+function construct_acl_data(&$a, $user) {
+
+ // Get group and contact information for html ACL selector
+ $acl_data = acl_lookup($a, 'html');
+
+ $user_defaults = get_acl_permissions($user);
+
+ if($acl_data['groups']) {
+ foreach($acl_data['groups'] as $key=>$group) {
+ // Add a "selected" flag to groups that are posted to by default
+ if($user_defaults['allow_gid'] &&
+ in_array($group['id'], $user_defaults['allow_gid']) && !in_array($group['id'], $user_defaults['deny_gid']) )
+ $acl_data['groups'][$key]['selected'] = 1;
+ else
+ $acl_data['groups'][$key]['selected'] = 0;
+ }
+ }
+ if($acl_data['contacts']) {
+ foreach($acl_data['contacts'] as $key=>$contact) {
+ // Add a "selected" flag to groups that are posted to by default
+ if($user_defaults['allow_cid'] &&
+ in_array($contact['id'], $user_defaults['allow_cid']) && !in_array($contact['id'], $user_defaults['deny_cid']) )
+ $acl_data['contacts'][$key]['selected'] = 1;
+ else
+ $acl_data['contacts'][$key]['selected'] = 0;
+ }
+ }
+
+ return $acl_data;
+
+}
+
+function acl_lookup(&$a, $out_type = 'json') {
+
+ if(!local_user())
+ return "";
+
+ $start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
+ $count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
+ $search = (x($_REQUEST,'search') ? $_REQUEST['search'] : "");
+ $type = (x($_REQUEST,'type') ? $_REQUEST['type'] : "");
+ $mode = (x($_REQUEST,'smode') ? $_REQUEST['smode'] : "");
+ $conv_id = (x($_REQUEST,'conversation') ? $_REQUEST['conversation'] : null);
+
+ // For use with jquery.textcomplete for private mail completion
+
+ if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
+ if(! $type)
+ $type = 'm';
+ $search = $_REQUEST['query'];
+ }
+
+ logger("Searching for ".$search." - type ".$type, LOGGER_DEBUG);
+
+ if ($search!=""){
+ $sql_extra = "AND `name` LIKE '%%".dbesc($search)."%%'";
+ $sql_extra2 = "AND (`attag` LIKE '%%".dbesc($search)."%%' OR `name` LIKE '%%".dbesc($search)."%%' OR `nick` LIKE '%%".dbesc($search)."%%')";
+ } else {
+ $sql_extra = $sql_extra2 = "";
+ }
+
+ // count groups and contacts
+ if ($type=='' || $type=='g'){
+ $r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
+ intval(local_user())
+ );
+ $group_count = (int)$r[0]['g'];
+ } else {
+ $group_count = 0;
+ }
+
+ $sql_extra2 .= " ".unavailable_networks();
+
+ // autocomplete for editor mentions
+ if ($type=='' || $type=='c'){
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND `self` = 0
+ AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0
+ AND `notify` != '' $sql_extra2" ,
+ intval(local_user())
+ );
+ $contact_count = (int)$r[0]['c'];
+ }
+ elseif ($type == 'm') {
+
+ // autocomplete for Private Messages
+
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND `self` = 0
+ AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0
+ AND `network` IN ('%s','%s','%s') $sql_extra2" ,
+ intval(local_user()),
+ dbesc(NETWORK_DFRN),
+ dbesc(NETWORK_ZOT),
+ dbesc(NETWORK_DIASPORA)
+ );
+ $contact_count = (int)$r[0]['c'];
+
+ }
+ elseif ($type == 'a') {
+
+ // autocomplete for Contacts
+
+ $r = q("SELECT COUNT(*) AS c FROM `contact`
+ WHERE `uid` = %d AND `self` = 0
+ AND `pending` = 0 $sql_extra2" ,
+ intval(local_user())
+ );
+ $contact_count = (int)$r[0]['c'];
+
+ } else {
+ $contact_count = 0;
+ }
+
+
+ $tot = $group_count+$contact_count;
+
+ $groups = array();
+ $contacts = array();
+
+ if ($type=='' || $type=='g'){
+
+ $r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
+ FROM `group`
+ INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id` AND `group_member`.`uid` = `group`.`uid`
+ WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
+ $sql_extra
+ GROUP BY `group`.`name`
+ ORDER BY `group`.`name`
+ LIMIT %d,%d",
+ intval(local_user()),
+ intval($start),
+ intval($count)
+ );
+
+ foreach($r as $g){
+// logger('acl: group: ' . $g['name'] . ' members: ' . $g['uids']);
+ $groups[] = array(
+ "type" => "g",
+ "photo" => "images/twopeople.png",
+ "name" => htmlentities($g['name']),
+ "id" => intval($g['id']),
+ "uids" => array_map("intval", explode(",",$g['uids'])),
+ "link" => '',
+ "forum" => '0'
+ );
+ }
+ }
+
+ if ($type==''){
+
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
+ WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != ''
+ AND NOT (`network` IN ('%s', '%s'))
+ $sql_extra2
+ ORDER BY `name` ASC ",
+ intval(local_user()),
+ dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET)
+ );
+ }
+ elseif ($type=='c'){
+
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
+ WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != ''
+ AND NOT (`network` IN ('%s'))
+ $sql_extra2
+ ORDER BY `name` ASC ",
+ intval(local_user()),
+ dbesc(NETWORK_STATUSNET)
+ );
+ }
+ elseif($type == 'm') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag` FROM `contact`
+ WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0
+ AND `network` IN ('%s','%s','%s')
+ $sql_extra2
+ ORDER BY `name` ASC ",
+ intval(local_user()),
+ dbesc(NETWORK_DFRN),
+ dbesc(NETWORK_ZOT),
+ dbesc(NETWORK_DIASPORA)
+ );
+ }
+ elseif($type == 'a') {
+ $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
+ WHERE `uid` = %d AND `pending` = 0
+ $sql_extra2
+ ORDER BY `name` ASC ",
+ intval(local_user())
+ );
+ }
+ elseif($type == 'x') {
+ // autocomplete for global contact search (e.g. navbar search)
+ $r = navbar_complete($a);
+ $contacts = array();
+ if($r) {
+ foreach($r as $g) {
+ $contacts[] = array(
+ "photo" => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
+ "name" => $g['name'],
+ "nick" => (x($g['addr']) ? $g['addr'] : $g['url']),
+ "network" => $g['network'],
+ "link" => $g['url'],
+ "forum" => (x($g['community']) ? 1 : 0),
+ );
+ }
+ }
+ $o = array(
+ 'start' => $start,
+ 'count' => $count,
+ 'items' => $contacts,
+ );
+ echo json_encode($o);
+ killme();
+ }
+ else
+ $r = array();
+
+
+ if(count($r)) {
+ foreach($r as $g){
+ $contacts[] = array(
+ "type" => "c",
+ "photo" => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
+ "name" => htmlentities($g['name']),
+ "id" => intval($g['id']),
+ "network" => $g['network'],
+ "link" => $g['url'],
+ "nick" => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
+ "forum" => ((x($g['forum']) || x($g['prv'])) ? 1 : 0),
+ );
+ }
+ }
+
+ $items = array_merge($groups, $contacts);
+
+ if ($conv_id) {
+ /* if $conv_id is set, get unknow contacts in thread */
+ /* but first get know contacts url to filter them out */
+ function _contact_link($i){ return dbesc($i['link']); }
+ $known_contacts = array_map(_contact_link, $contacts);
+ $unknow_contacts=array();
+ $r = q("SELECT `author-avatar`,`author-name`,`author-link`
+ FROM `item` WHERE `parent` = %d
+ AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
+ AND `author-link` NOT IN ('%s')
+ GROUP BY `author-link`
+ ORDER BY `author-name` ASC
+ ",
+ intval($conv_id),
+ dbesc($search),
+ dbesc($search),
+ implode("','", $known_contacts)
+ );
+ if (is_array($r) && count($r)){
+ foreach($r as $row) {
+ // nickname..
+ $up = parse_url($row['author-link']);
+ $nick = explode("/",$up['path']);
+ $nick = $nick[count($nick)-1];
+ $nick .= "@".$up['host'];
+ // /nickname
+ $unknow_contacts[] = array(
+ "type" => "c",
+ "photo" => proxy_url($row['author-avatar'], false, PROXY_SIZE_MICRO),
+ "name" => htmlentities($row['author-name']),
+ "id" => '',
+ "network" => "unknown",
+ "link" => $row['author-link'],
+ "nick" => htmlentities($nick),
+ "forum" => false
+ );
+ }
+ }
+
+ $items = array_merge($items, $unknow_contacts);
+ $tot += count($unknow_contacts);
+ }
+
+ $results = array(
+ "tot" => $tot,
+ "start" => $start,
+ "count" => $count,
+ "groups" => $groups,
+ "contacts" => $contacts,
+ "items" => $items,
+ "type" => $type,
+ "search" => $search,
+ );
+
+ call_hooks('acl_lookup_end', $results);
+
+ if($out_type === 'html') {
+ $o = array(
+ 'tot' => $results["tot"],
+ 'start' => $results["start"],
+ 'count' => $results["count"],
+ 'groups' => $results["groups"],
+ 'contacts' => $results["contacts"],
+ );
+ return $o;
+ }
+
+ $o = array(
+ 'tot' => $results["tot"],
+ 'start' => $results["start"],
+ 'count' => $results["count"],
+ 'items' => $results["items"],
+ );
+
+ echo json_encode($o);
+
+ killme();
+}
+/**
+ * @brief Searching for global contacts for autocompletion
+ *
+ * @param App $a
+ * @return array with the search results
+ */
+function navbar_complete(&$a) {
+
+// logger('navbar_complete');
+
+ if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
+ return;
+ }
+
+ // check if searching in the local global contact table is enabled
+ $localsearch = get_config('system','poco_local_search');
+
+ $search = $prefix.notags(trim($_REQUEST['search']));
+ $mode = $_REQUEST['smode'];
+
+ // don't search if search term has less than 2 characters
+ if(! $search || mb_strlen($search) < 2)
+ return array();
+
+ if(substr($search,0,1) === '@')
+ $search = substr($search,1);
+
+ if($localsearch) {
+ $x = DirSearch::global_search_by_name($search, $mode);
+ return $x;
+ }
+
+ if(! $localsearch) {
+ $p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : '');
+
+ $x = z_fetch_url(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search));
+ if($x['success']) {
+ $t = 0;
+ $j = json_decode($x['body'],true);
+ if($j && $j['results']) {
+ return $j['results'];
+ }
+ }
+ }
+ return;
+}