Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

760 lines
20 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
6 years ago
6 years ago
6 years ago
6 years ago
11 years ago
6 years ago
4 years ago
  1. <?php
  2. /**
  3. * @file include/acl_selectors.php
  4. */
  5. use Friendica\App;
  6. require_once "include/contact_selectors.php";
  7. require_once "include/contact_widgets.php";
  8. require_once "include/DirSearch.php";
  9. require_once "include/features.php";
  10. require_once "mod/proxy.php";
  11. /**
  12. * @package acl_selectors
  13. */
  14. function group_select($selname,$selclass,$preselected = false,$size = 4) {
  15. $a = get_app();
  16. $o = '';
  17. $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n";
  18. $r = q("SELECT `id`, `name` FROM `group` WHERE NOT `deleted` AND `uid` = %d ORDER BY `name` ASC",
  19. intval(local_user())
  20. );
  21. $arr = array('group' => $r, 'entry' => $o);
  22. // e.g. 'network_pre_group_deny', 'profile_pre_group_allow'
  23. call_hooks($a->module . '_pre_' . $selname, $arr);
  24. if (dbm::is_result($r)) {
  25. foreach ($r as $rr) {
  26. if ((is_array($preselected)) && in_array($rr['id'], $preselected)) {
  27. $selected = " selected=\"selected\" ";
  28. } else {
  29. $selected = '';
  30. }
  31. $trimmed = mb_substr($rr['name'],0,12);
  32. $o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}\" >$trimmed</option>\r\n";
  33. }
  34. }
  35. $o .= "</select>\r\n";
  36. call_hooks($a->module . '_post_' . $selname, $o);
  37. return $o;
  38. }
  39. /// @TODO after an optional parameter, no mandadory parameter can follow
  40. /// @TODO find proper type-hints
  41. function contact_selector($selname, $selclass, $preselected = false, $options) {
  42. $a = get_app();
  43. $mutual = false;
  44. $networks = null;
  45. $single = false;
  46. $exclude = false;
  47. $size = 4;
  48. if (is_array($options)) {
  49. if (x($options, 'size'))
  50. $size = $options['size'];
  51. if (x($options, 'mutual_friends')) {
  52. $mutual = true;
  53. }
  54. if (x($options, 'single')) {
  55. $single = true;
  56. }
  57. if (x($options, 'multiple')) {
  58. $single = false;
  59. }
  60. if (x($options, 'exclude')) {
  61. $exclude = $options['exclude'];
  62. }
  63. if (x($options, 'networks')) {
  64. switch ($options['networks']) {
  65. case 'DFRN_ONLY':
  66. $networks = array(NETWORK_DFRN);
  67. break;
  68. case 'PRIVATE':
  69. if (is_array($a->user) && $a->user['prvnets']) {
  70. $networks = array(NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA);
  71. } else {
  72. $networks = array(NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA);
  73. }
  74. break;
  75. case 'TWO_WAY':
  76. if (is_array($a->user) && $a->user['prvnets']) {
  77. $networks = array(NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA);
  78. } else {
  79. $networks = array(NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA, NETWORK_OSTATUS);
  80. }
  81. break;
  82. default: /// @TODO Maybe log this call?
  83. break;
  84. }
  85. }
  86. }
  87. $x = array('options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks);
  88. call_hooks('contact_select_options', $x);
  89. $o = '';
  90. $sql_extra = '';
  91. if (x($x, 'mutual')) {
  92. $sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
  93. }
  94. if (x($x, 'exclude')) {
  95. $sql_extra .= sprintf(" AND `id` != %d ", intval($x['exclude']));
  96. }
  97. if (is_array($x['networks']) && count($x['networks'])) {
  98. /// @TODO rewrite to foreach()
  99. for ($y = 0; $y < count($x['networks']) ; $y ++) {
  100. $x['networks'][$y] = "'" . dbesc($x['networks'][$y]) . "'";
  101. }
  102. $str_nets = implode(',', $x['networks']);
  103. $sql_extra .= " AND `network` IN ( $str_nets ) ";
  104. }
  105. $tabindex = (x($options, 'tabindex') ? "tabindex=\"" . $options["tabindex"] . "\"" : "");
  106. if ($x['single']) {
  107. $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"" . $x['size'] . "\" $tabindex >\r\n";
  108. } else {
  109. $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"" . $x['size'] . "$\" $tabindex >\r\n";
  110. }
  111. $r = q("SELECT `id`, `name`, `url`, `network` FROM `contact`
  112. WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
  113. $sql_extra
  114. ORDER BY `name` ASC ",
  115. intval(local_user())
  116. );
  117. $arr = array('contact' => $r, 'entry' => $o);
  118. // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
  119. call_hooks($a->module . '_pre_' . $selname, $arr);
  120. if (dbm::is_result($r)) {
  121. foreach ($r as $rr) {
  122. if ((is_array($preselected)) && in_array($rr['id'], $preselected)) {
  123. $selected = " selected=\"selected\" ";
  124. } else {
  125. $selected = '';
  126. }
  127. $trimmed = mb_substr($rr['name'],0,20);
  128. $o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}|{$rr['url']}\" >$trimmed</option>\r\n";
  129. }
  130. }
  131. $o .= "</select>\r\n";
  132. call_hooks($a->module . '_post_' . $selname, $o);
  133. return $o;
  134. }
  135. function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false, $privatenet = false, $tabindex = null) {
  136. require_once "include/bbcode.php";
  137. $a = get_app();
  138. $o = '';
  139. // When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector
  140. // to one recipient. By default our selector allows multiple selects amongst all contacts.
  141. $sql_extra = '';
  142. if ($privmail || $celeb) {
  143. $sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
  144. }
  145. if ($privmail) {
  146. $sql_extra .= sprintf(" AND `network` IN ('%s' , '%s') ",
  147. NETWORK_DFRN, NETWORK_DIASPORA);
  148. } elseif ($privatenet) {
  149. $sql_extra .= sprintf(" AND `network` IN ('%s' , '%s', '%s', '%s') ",
  150. NETWORK_DFRN, NETWORK_MAIL, NETWORK_FACEBOOK, NETWORK_DIASPORA);
  151. }
  152. $tabindex = ($tabindex > 0 ? "tabindex=\"$tabindex\"" : "");
  153. if ($privmail AND $preselected) {
  154. $sql_extra .= " AND `id` IN (".implode(",", $preselected).")";
  155. $hidepreselected = ' style="display: none;"';
  156. } else {
  157. $hidepreselected = "";
  158. }
  159. if ($privmail) {
  160. $o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\" $tabindex $hidepreselected>\r\n";
  161. } else {
  162. $o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" $tabindex >\r\n";
  163. }
  164. $r = q("SELECT `id`, `name`, `url`, `network` FROM `contact`
  165. WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
  166. $sql_extra
  167. ORDER BY `name` ASC ",
  168. intval(local_user())
  169. );
  170. $arr = array('contact' => $r, 'entry' => $o);
  171. // e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
  172. call_hooks($a->module . '_pre_' . $selname, $arr);
  173. $receiverlist = array();
  174. if (dbm::is_result($r)) {
  175. foreach ($r as $rr) {
  176. if ((is_array($preselected)) && in_array($rr['id'], $preselected)) {
  177. $selected = " selected=\"selected\" ";
  178. } else {
  179. $selected = '';
  180. }
  181. if ($privmail) {
  182. $trimmed = GetProfileUsername($rr['url'], $rr['name'], false);
  183. } else {
  184. $trimmed = mb_substr($rr['name'],0,20);
  185. }
  186. $receiverlist[] = $trimmed;
  187. $o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}|{$rr['url']}\" >$trimmed</option>\r\n";
  188. }
  189. }
  190. $o .= "</select>\r\n";
  191. if ($privmail AND $preselected) {
  192. $o .= implode(", ", $receiverlist);
  193. }
  194. call_hooks($a->module . '_post_' . $selname, $o);
  195. return $o;
  196. }
  197. function fixacl(&$item) {
  198. $item = intval(str_replace(array('<', '>'), array('', ''), $item));
  199. }
  200. function prune_deadguys($arr) {
  201. if (! $arr) {
  202. return $arr;
  203. }
  204. $str = dbesc(implode(',', $arr));
  205. $r = q("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 ");
  206. if (dbm::is_result($r)) {
  207. $ret = array();
  208. foreach ($r as $rr) {
  209. $ret[] = intval($rr['id']);
  210. }
  211. return $ret;
  212. }
  213. return array();
  214. }
  215. function get_acl_permissions($user = null) {
  216. $allow_cid = $allow_gid = $deny_cid = $deny_gid = false;
  217. if (is_array($user)) {
  218. $allow_cid = ((strlen($user['allow_cid']))
  219. ? explode('><', $user['allow_cid']) : array() );
  220. $allow_gid = ((strlen($user['allow_gid']))
  221. ? explode('><', $user['allow_gid']) : array() );
  222. $deny_cid = ((strlen($user['deny_cid']))
  223. ? explode('><', $user['deny_cid']) : array() );
  224. $deny_gid = ((strlen($user['deny_gid']))
  225. ? explode('><', $user['deny_gid']) : array() );
  226. array_walk($allow_cid,'fixacl');
  227. array_walk($allow_gid,'fixacl');
  228. array_walk($deny_cid,'fixacl');
  229. array_walk($deny_gid,'fixacl');
  230. }
  231. $allow_cid = prune_deadguys($allow_cid);
  232. return array(
  233. 'allow_cid' => $allow_cid,
  234. 'allow_gid' => $allow_gid,
  235. 'deny_cid' => $deny_cid,
  236. 'deny_gid' => $deny_gid,
  237. );
  238. }
  239. function populate_acl($user = null, $show_jotnets = false) {
  240. $perms = get_acl_permissions($user);
  241. $jotnets = '';
  242. if ($show_jotnets) {
  243. $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
  244. $mail_enabled = false;
  245. $pubmail_enabled = false;
  246. if (! $mail_disabled) {
  247. $r = q("SELECT `pubmail` FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
  248. intval(local_user())
  249. );
  250. if (dbm::is_result($r)) {
  251. $mail_enabled = true;
  252. if (intval($r[0]['pubmail'])) {
  253. $pubmail_enabled = true;
  254. }
  255. }
  256. }
  257. if (!$user['hidewall']) {
  258. if ($mail_enabled) {
  259. $selected = (($pubmail_enabled) ? ' checked="checked" ' : '');
  260. $jotnets .= '<div class="profile-jot-net"><input type="checkbox" name="pubmail_enable"' . $selected . ' value="1" /> ' . t("Post to Email") . '</div>';
  261. }
  262. call_hooks('jot_networks', $jotnets);
  263. } else {
  264. $jotnets .= sprintf(t('Connectors disabled, since "%s" is enabled.'),
  265. t('Hide your profile details from unknown viewers?'));
  266. }
  267. }
  268. $tpl = get_markup_template("acl_selector.tpl");
  269. $o = replace_macros($tpl, array(
  270. '$showall'=> t("Visible to everybody"),
  271. '$show' => t("show"),
  272. '$hide' => t("don't show"),
  273. '$allowcid' => json_encode($perms['allow_cid']),
  274. '$allowgid' => json_encode($perms['allow_gid']),
  275. '$denycid' => json_encode($perms['deny_cid']),
  276. '$denygid' => json_encode($perms['deny_gid']),
  277. '$networks' => $show_jotnets,
  278. '$emailcc' => t('CC: email addresses'),
  279. '$emtitle' => t('Example: bob@example.com, mary@example.com'),
  280. '$jotnets' => $jotnets,
  281. '$aclModalTitle' => t('Permissions'),
  282. '$aclModalDismiss' => t('Close'),
  283. '$features' => array(
  284. 'aclautomention' => (feature_enabled($user['uid'], "aclautomention") ? "true" : "false")
  285. ),
  286. ));
  287. return $o;
  288. }
  289. function construct_acl_data(App $a, $user) {
  290. // Get group and contact information for html ACL selector
  291. $acl_data = acl_lookup($a, 'html');
  292. $user_defaults = get_acl_permissions($user);
  293. if ($acl_data['groups']) {
  294. foreach ($acl_data['groups'] as $key => $group) {
  295. // Add a "selected" flag to groups that are posted to by default
  296. if ($user_defaults['allow_gid'] &&
  297. in_array($group['id'], $user_defaults['allow_gid']) && !in_array($group['id'], $user_defaults['deny_gid']) ) {
  298. $acl_data['groups'][$key]['selected'] = 1;
  299. } else {
  300. $acl_data['groups'][$key]['selected'] = 0;
  301. }
  302. }
  303. }
  304. if ($acl_data['contacts']) {
  305. foreach ($acl_data['contacts'] as $key => $contact) {
  306. // Add a "selected" flag to groups that are posted to by default
  307. if ($user_defaults['allow_cid'] &&
  308. in_array($contact['id'], $user_defaults['allow_cid']) && !in_array($contact['id'], $user_defaults['deny_cid']) ) {
  309. $acl_data['contacts'][$key]['selected'] = 1;
  310. } else {
  311. $acl_data['contacts'][$key]['selected'] = 0;
  312. }
  313. }
  314. }
  315. return $acl_data;
  316. }
  317. function acl_lookup(App $a, $out_type = 'json') {
  318. if (!local_user()) {
  319. return '';
  320. }
  321. $start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
  322. $count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
  323. $search = (x($_REQUEST,'search') ? $_REQUEST['search'] : "");
  324. $type = (x($_REQUEST,'type') ? $_REQUEST['type'] : "");
  325. $mode = (x($_REQUEST,'smode') ? $_REQUEST['smode'] : "");
  326. $conv_id = (x($_REQUEST,'conversation') ? $_REQUEST['conversation'] : null);
  327. // For use with jquery.textcomplete for private mail completion
  328. if (x($_REQUEST, 'query') && strlen($_REQUEST['query'])) {
  329. if (! $type) {
  330. $type = 'm';
  331. }
  332. $search = $_REQUEST['query'];
  333. }
  334. logger("Searching for ".$search." - type ".$type, LOGGER_DEBUG);
  335. if ($search != "") {
  336. $sql_extra = "AND `name` LIKE '%%".dbesc($search)."%%'";
  337. $sql_extra2 = "AND (`attag` LIKE '%%".dbesc($search)."%%' OR `name` LIKE '%%".dbesc($search)."%%' OR `nick` LIKE '%%".dbesc($search)."%%')";
  338. } else {
  339. /// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
  340. $sql_extra = $sql_extra2 = "";
  341. }
  342. // count groups and contacts
  343. if ($type == '' || $type == 'g') {
  344. $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
  345. intval(local_user())
  346. );
  347. $group_count = (int)$r[0]['g'];
  348. } else {
  349. $group_count = 0;
  350. }
  351. $sql_extra2 .= " ".unavailable_networks();
  352. if ($type == '' || $type == 'c') {
  353. // autocomplete for editor mentions
  354. $r = q("SELECT COUNT(*) AS c FROM `contact`
  355. WHERE `uid` = %d AND NOT `self`
  356. AND NOT `blocked` AND NOT `pending` AND NOT `archive`
  357. AND `notify` != '' $sql_extra2" ,
  358. intval(local_user())
  359. );
  360. $contact_count = (int)$r[0]['c'];
  361. }
  362. elseif ($type == 'm') {
  363. // autocomplete for Private Messages
  364. $r = q("SELECT COUNT(*) AS c FROM `contact`
  365. WHERE `uid` = %d AND NOT `self`
  366. AND NOT `blocked` AND NOT `pending` AND NOT `archive`
  367. AND `network` IN ('%s','%s','%s') $sql_extra2" ,
  368. intval(local_user()),
  369. dbesc(NETWORK_DFRN),
  370. dbesc(NETWORK_ZOT),
  371. dbesc(NETWORK_DIASPORA)
  372. );
  373. $contact_count = (int)$r[0]['c'];
  374. }
  375. elseif ($type == 'a') {
  376. // autocomplete for Contacts
  377. $r = q("SELECT COUNT(*) AS c FROM `contact`
  378. WHERE `uid` = %d AND NOT `self`
  379. AND NOT `pending` $sql_extra2" ,
  380. intval(local_user())
  381. );
  382. $contact_count = (int)$r[0]['c'];
  383. } else {
  384. $contact_count = 0;
  385. }
  386. $tot = $group_count+$contact_count;
  387. $groups = array();
  388. $contacts = array();
  389. if ($type == '' || $type == 'g') {
  390. /// @todo We should cache this query.
  391. // This can be done when we can delete cache entries via wildcard
  392. $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
  393. FROM `group`
  394. INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id` AND `group_member`.`uid` = `group`.`uid`
  395. WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
  396. $sql_extra
  397. GROUP BY `group`.`name`, `group`.`id`
  398. ORDER BY `group`.`name`
  399. LIMIT %d,%d",
  400. intval(local_user()),
  401. intval($start),
  402. intval($count)
  403. );
  404. foreach ($r as $g) {
  405. // logger('acl: group: ' . $g['name'] . ' members: ' . $g['uids']);
  406. $groups[] = array(
  407. "type" => "g",
  408. "photo" => "images/twopeople.png",
  409. "name" => htmlentities($g['name']),
  410. "id" => intval($g['id']),
  411. "uids" => array_map("intval", explode(",",$g['uids'])),
  412. "link" => '',
  413. "forum" => '0'
  414. );
  415. }
  416. }
  417. if ($type == '') {
  418. $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
  419. WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
  420. AND NOT (`network` IN ('%s', '%s'))
  421. $sql_extra2
  422. ORDER BY `name` ASC ",
  423. intval(local_user()),
  424. dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET)
  425. );
  426. } elseif ($type == 'c') {
  427. $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
  428. WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
  429. AND NOT (`network` IN ('%s'))
  430. $sql_extra2
  431. ORDER BY `name` ASC ",
  432. intval(local_user()),
  433. dbesc(NETWORK_STATUSNET)
  434. );
  435. }
  436. elseif ($type == 'm') {
  437. $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag` FROM `contact`
  438. WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
  439. AND `network` IN ('%s','%s','%s')
  440. $sql_extra2
  441. ORDER BY `name` ASC ",
  442. intval(local_user()),
  443. dbesc(NETWORK_DFRN),
  444. dbesc(NETWORK_ZOT),
  445. dbesc(NETWORK_DIASPORA)
  446. );
  447. } elseif ($type == 'a') {
  448. $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
  449. WHERE `uid` = %d AND `pending` = 0
  450. $sql_extra2
  451. ORDER BY `name` ASC ",
  452. intval(local_user())
  453. );
  454. } elseif ($type == 'x') {
  455. // autocomplete for global contact search (e.g. navbar search)
  456. $r = navbar_complete($a);
  457. $contacts = array();
  458. if ($r) {
  459. foreach ($r as $g) {
  460. $contacts[] = array(
  461. 'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
  462. 'name' => $g['name'],
  463. 'nick' => (x($g['addr']) ? $g['addr'] : $g['url']),
  464. 'network' => $g['network'],
  465. 'link' => $g['url'],
  466. 'forum' => (x($g['community']) ? 1 : 0),
  467. );
  468. }
  469. }
  470. $o = array(
  471. 'start' => $start,
  472. 'count' => $count,
  473. 'items' => $contacts,
  474. );
  475. echo json_encode($o);
  476. killme();
  477. } else {
  478. $r = array();
  479. }
  480. if (dbm::is_result($r)) {
  481. foreach ($r as $g) {
  482. $contacts[] = array(
  483. 'type' => 'c',
  484. 'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
  485. 'name' => htmlentities($g['name']),
  486. 'id' => intval($g['id']),
  487. 'network' => $g['network'],
  488. 'link' => $g['url'],
  489. 'nick' => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
  490. 'forum' => ((x($g, 'forum') || x($g, 'prv')) ? 1 : 0),
  491. );
  492. }
  493. }
  494. $items = array_merge($groups, $contacts);
  495. if ($conv_id) {
  496. /*
  497. * if $conv_id is set, get unknown contacts in thread
  498. * but first get known contacts url to filter them out
  499. */
  500. $known_contacts = array_map(
  501. function ($i) {
  502. return dbesc($i['link']);
  503. }
  504. , $contacts);
  505. $unknown_contacts = array();
  506. $r = q("SELECT `author-link`
  507. FROM `item` WHERE `parent` = %d
  508. AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
  509. AND `author-link` NOT IN ('%s')
  510. GROUP BY `author-link`, `author-avatar`, `author-name`
  511. ORDER BY `author-name` ASC
  512. ",
  513. intval($conv_id),
  514. dbesc($search),
  515. dbesc($search),
  516. implode("', '", $known_contacts)
  517. );
  518. if (dbm::is_result($r)) {
  519. foreach ($r as $row) {
  520. $contact = get_contact_details_by_url($row['author-link']);
  521. if (count($contact) > 0) {
  522. $unknown_contacts[] = array(
  523. 'type' => 'c',
  524. 'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
  525. 'name' => htmlentities($contact['name']),
  526. 'id' => intval($contact['cid']),
  527. 'network' => $contact['network'],
  528. 'link' => $contact['url'],
  529. 'nick' => htmlentities($contact['nick'] ? : $contact['addr']),
  530. 'forum' => $contact['forum']
  531. );
  532. }
  533. }
  534. }
  535. $items = array_merge($items, $unknown_contacts);
  536. $tot += count($unknown_contacts);
  537. }
  538. $results = array(
  539. 'tot' => $tot,
  540. 'start' => $start,
  541. 'count' => $count,
  542. 'groups' => $groups,
  543. 'contacts' => $contacts,
  544. 'items' => $items,
  545. 'type' => $type,
  546. 'search' => $search,
  547. );
  548. call_hooks('acl_lookup_end', $results);
  549. if ($out_type === 'html') {
  550. $o = array(
  551. 'tot' => $results['tot'],
  552. 'start' => $results['start'],
  553. 'count' => $results['count'],
  554. 'groups' => $results['groups'],
  555. 'contacts' => $results['contacts'],
  556. );
  557. return $o;
  558. }
  559. $o = array(
  560. 'tot' => $results['tot'],
  561. 'start' => $results['start'],
  562. 'count' => $results['count'],
  563. 'items' => $results['items'],
  564. );
  565. echo json_encode($o);
  566. killme();
  567. }
  568. /**
  569. * @brief Searching for global contacts for autocompletion
  570. *
  571. * @param App $a
  572. * @return array with the search results
  573. */
  574. function navbar_complete(App $a) {
  575. // logger('navbar_complete');
  576. if ((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
  577. return;
  578. }
  579. // check if searching in the local global contact table is enabled
  580. $localsearch = get_config('system','poco_local_search');
  581. $search = $prefix.notags(trim($_REQUEST['search']));
  582. $mode = $_REQUEST['smode'];
  583. // don't search if search term has less than 2 characters
  584. if (! $search || mb_strlen($search) < 2) {
  585. return array();
  586. }
  587. if (substr($search,0,1) === '@') {
  588. $search = substr($search,1);
  589. }
  590. if ($localsearch) {
  591. $x = DirSearch::global_search_by_name($search, $mode);
  592. return $x;
  593. }
  594. if (! $localsearch) {
  595. $p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : '');
  596. $x = z_fetch_url(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search));
  597. if ($x['success']) {
  598. $t = 0;
  599. $j = json_decode($x['body'],true);
  600. if ($j && $j['results']) {
  601. return $j['results'];
  602. }
  603. }
  604. }
  605. /// @TODO Not needed here?
  606. return;
  607. }