function contactgroup_content(&$a) { if (!local_user()) { killme(); } if (argc() > 2 && intval(argv(1)) && argv(2)) { $r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and not ( abook_flags & %d ) limit 1", dbesc(argv(2)), intval(local_user()), intval(ABOOK_FLAG_SELF)); if ($r) { $change = $r[0]['abook_xchan']; } } if (argc() > 1 && intval(argv(1))) { $r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval(argv(1)), intval(local_user())); if (!$r) { killme(); } $group = $r[0]; $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['xchan_hash']; } } if ($change) { if (in_array($change, $preselected)) { group_rmv_member(local_user(), $group['name'], $change); } else { group_add_member(local_user(), $group['name'], $change); } } } killme(); }
function get() { if (!local_channel()) { killme(); } if (argc() > 2 && intval(argv(1)) && argv(2)) { $r = q("SELECT abook_xchan from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc(base64url_decode(argv(2))), intval(local_channel())); if ($r) { $change = $r[0]['abook_xchan']; } } if (argc() > 1 && intval(argv(1))) { $r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval(argv(1)), intval(local_channel())); if (!$r) { killme(); } $group = $r[0]; $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['xchan_hash']; } } if ($change) { if (in_array($change, $preselected)) { group_rmv_member(local_channel(), $group['gname'], $change); } else { group_add_member(local_channel(), $group['gname'], $change); } } } killme(); }
function contactgroup_content(&$a) { if (!local_user()) { killme(); } if ($a->argc > 2 && intval($a->argv[1]) && intval($a->argv[2])) { $r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1", intval($a->argv[2]), intval(local_user())); if (count($r)) { $change = intval($a->argv[2]); } } if ($a->argc > 1 && intval($a->argv[1])) { $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval($a->argv[1]), intval(local_user())); if (!count($r)) { killme(); } $group = $r[0]; $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['id']; } } if ($change) { if (in_array($change, $preselected)) { group_rmv_member(local_user(), $group['name'], $change); } else { group_add_member(local_user(), $group['name'], $change); } } } killme(); }
function get() { $change = false; logger('mod_group: ' . \App::$cmd, LOGGER_DEBUG); if (!local_channel()) { notice(t('Permission denied') . EOL); return; } // Switch to text mode interface if we have more than 'n' contacts or group members $switchtotext = get_pconfig(local_channel(), 'system', 'groupedit_image_limit'); if ($switchtotext === false) { $switchtotext = get_config('system', 'groupedit_image_limit'); } if ($switchtotext === false) { $switchtotext = 400; } $tpl = get_markup_template('group_edit.tpl'); $context = array('$submit' => t('Submit')); if (argc() == 2 && argv(1) === 'new') { return replace_macros($tpl, $context + array('$title' => t('Create a group of channels.'), '$gname' => array('groupname', t('Privacy group name: '), '', ''), '$gid' => 'new', '$public' => array('public', t('Members are visible to other channels'), false, ''), '$form_security_token' => get_form_security_token("group_edit"))); } if (argc() == 3 && argv(1) === 'drop') { check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); if (intval(argv(2))) { $r = q("SELECT `name` FROM `groups` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(argv(2)), intval(local_channel())); if ($r) { $result = group_rmv(local_channel(), $r[0]['gname']); } if ($result) { info(t('Privacy group removed.') . EOL); } else { notice(t('Unable to remove privacy group.') . EOL); } } goaway(z_root() . '/group'); // NOTREACHED } if (argc() > 2 && intval(argv(1)) && argv(2)) { check_form_security_token_ForbiddenOnErr('group_member_change', 't'); $r = q("SELECT abook_xchan from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 limit 1", dbesc(base64url_decode(argv(2))), intval(local_channel())); if (count($r)) { $change = base64url_decode(argv(2)); } } if (argc() > 1 && intval(argv(1))) { require_once 'include/acl_selectors.php'; $r = q("SELECT * FROM `groups` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval(argv(1)), intval(local_channel())); if (!$r) { notice(t('Privacy group not found.') . EOL); goaway(z_root() . '/connections'); } $group = $r[0]; $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { if (!in_array($member['xchan_hash'], $preselected)) { $preselected[] = $member['xchan_hash']; } } } if ($change) { if (in_array($change, $preselected)) { group_rmv_member(local_channel(), $group['gname'], $change); } else { group_add_member(local_channel(), $group['gname'], $change); } $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['xchan_hash']; } } } $drop_tpl = get_markup_template('group_drop.tpl'); $drop_txt = replace_macros($drop_tpl, array('$id' => $group['id'], '$delete' => t('Delete'), '$form_security_token' => get_form_security_token("group_drop"))); $context = $context + array('$title' => t('Privacy group editor'), '$gname' => array('groupname', t('Privacy group name: '), $group['gname'], ''), '$gid' => $group['id'], '$drop' => $drop_txt, '$public' => array('public', t('Members are visible to other channels'), $group['visible'], ''), '$form_security_token' => get_form_security_token('group_edit')); } if (!isset($group)) { return; } $groupeditor = array('label_members' => t('Members'), 'members' => array(), 'label_contacts' => t('All Connected Channels'), 'contacts' => array()); $sec_token = addslashes(get_form_security_token('group_member_change')); $textmode = $switchtotext && count($members) > $switchtotext ? true : false; foreach ($members as $member) { if ($member['xchan_url']) { $member['archived'] = intval($member['abook_archived']) ? true : false; $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;'; $groupeditor['members'][] = micropro($member, true, 'mpgroup', $textmode); } else { group_rmv_member(local_channel(), $group['gname'], $member['xchan_hash']); } } $r = q("SELECT abook.*, xchan.* FROM `abook` left join xchan on abook_xchan = xchan_hash WHERE `abook_channel` = %d AND abook_self = 0 and abook_blocked = 0 and abook_pending = 0 and xchan_deleted = 0 order by xchan_name asc", intval(local_channel())); if (count($r)) { $textmode = $switchtotext && count($r) > $switchtotext ? true : false; foreach ($r as $member) { if (!in_array($member['xchan_hash'], $preselected)) { $member['archived'] = intval($member['abook_archived']) ? true : false; $member['click'] = 'groupChangeMember(' . $group['id'] . ',\'' . base64url_encode($member['xchan_hash']) . '\',\'' . $sec_token . '\'); return false;'; $groupeditor['contacts'][] = micropro($member, true, 'mpall', $textmode); } } } $context['$groupeditor'] = $groupeditor; $context['$desc'] = t('Click on a channel to add or remove.'); if ($change) { $tpl = get_markup_template('groupeditor.tpl'); echo replace_macros($tpl, $context); killme(); } return replace_macros($tpl, $context); }
function items_fetch($arr, $channel = null, $observer_hash = null, $client_mode = CLIENT_MODE_NORMAL, $module = 'network') { $result = array('success' => false); $a = get_app(); $sql_extra = ''; $sql_nets = ''; $sql_options = ''; $sql_extra2 = ''; $sql_extra3 = ''; $def_acl = ''; $item_uids = ' true '; if ($arr['uid']) { $uid = $arr['uid']; } if ($channel) { $uid = $channel['channel_id']; $uidhash = $channel['channel_hash']; $item_uids = " item.uid = " . intval($uid) . " "; } if ($arr['star']) { $sql_options .= " and (item_flags & " . intval(ITEM_STARRED) . ")>0 "; } if ($arr['wall']) { $sql_options .= " and (item_flags & " . intval(ITEM_WALL) . ")>0 "; } $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ")>0 {$sql_options} ) "; if ($arr['since_id']) { $sql_extra .= " and item.id > " . $since_id . " "; } if ($arr['gid'] && $uid) { $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1", intval($arr['group']), intval($uid)); if (!$r) { $result['message'] = t('Collection not found.'); return $result; } $contact_str = ''; /** @FIXME $group is undefined */ $contacts = group_get_members($group); if ($contacts) { foreach ($contacts as $c) { if ($contact_str) { $contact_str .= ','; } $contact_str .= "'" . $c['xchan'] . "'"; } } else { $contact_str = ' 0 '; $result['message'] = t('Collection is empty.'); return $result; } $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true {$sql_options} AND (( author_xchan IN ( {$contact_str} ) OR owner_xchan in ( {$contact_str})) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent and item_restrict = 0 ) "; $x = group_rec_byhash($uid, $r[0]['hash']); $result['headline'] = sprintf(t('Collection: %s'), $x['name']); } elseif ($arr['cid'] && $uid) { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ")>0 limit 1", intval($arr['cid']), intval(local_channel())); if ($r) { $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true {$sql_options} AND uid = " . intval($arr['uid']) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; $result['headline'] = sprintf(t('Connection: %s'), $r[0]['xchan_name']); } else { $result['message'] = t('Connection not found.'); return $result; } } if ($arr['datequery']) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $arr['datequery'])))); } if ($arr['datequery2']) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $arr['datequery2'])))); } if (!array_key_exists('nouveau', $arr)) { $sql_extra2 = " AND item.parent = item.id "; $sql_extra3 = ''; } if ($arr['search']) { if (strpos($arr['search'], '#') === 0) { $sql_extra .= term_query('item', substr($arr['search'], 1), TERM_HASHTAG); } else { $sql_extra .= sprintf(" AND item.body like '%s' ", dbesc(protect_sprintf('%' . $arr['search'] . '%'))); } } if (strlen($arr['file'])) { $sql_extra .= term_query('item', $arr['files'], TERM_FILE); } if ($arr['conv'] && $channel) { $sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or ( item_flags & %d )>0)) ", dbesc(protect_sprintf($uidhash)), intval(ITEM_MENTIONSME)); } if ($client_mode & CLIENT_MODE_UPDATE && !($client_mode & CLIENT_MODE_LOAD)) { // only setup pagination on initial page view $pager_sql = ''; } else { $itemspage = $channel ? get_pconfig($uid, 'system', 'itemspage') : 20; $a->set_pager_itemspage(intval($itemspage) ? $itemspage : 20); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(get_app()->pager['itemspage']), intval(get_app()->pager['start'])); } if (isset($arr['start']) && isset($arr['records'])) { $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($arr['records']), intval($arr['start'])); } if (array_key_exists('cmin', $arr) || array_key_exists('cmax', $arr)) { if ($arr['cmin'] != 0 || $arr['cmax'] != 99) { // Not everybody who shows up in the network stream will be in your address book. // By default those that aren't are assumed to have closeness = 99; but this isn't // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in // the stream with a NULL address book entry. $sql_nets .= " AND "; if ($arr['cmax'] == 99) { $sql_nets .= " ( "; } $sql_nets .= "( abook.abook_closeness >= " . intval($arr['cmin']) . " "; $sql_nets .= " AND abook.abook_closeness <= " . intval($arr['cmax']) . " ) "; /** @fixme dead code, $cmax is undefined */ if ($cmax == 99) { $sql_nets .= " OR abook.abook_closeness IS NULL ) "; } } } $simple_update = $client_mode & CLIENT_MODE_UPDATE ? " and ( item.item_unseen = 1 ) " : ''; if ($client_mode & CLIENT_MODE_LOAD) { $simple_update = ''; } //$start = dba_timer(); require_once 'include/security.php'; $sql_extra .= item_permissions_sql($channel['channel_id'], $observer_hash); if ($arr['pages']) { $item_restrict = " AND (item_restrict & " . ITEM_WEBPAGE . ") "; } else { $item_restrict = " AND item_restrict = 0 "; } if ($arr['nouveau'] && $client_mode & CLIENT_MODE_LOAD && $channel) { // "New Item View" - show all items unthreaded in reverse created date order $items = q("SELECT item.*, item.id AS item_id FROM item\n\t\t\t\tWHERE {$item_uids} {$item_restrict}\n\t\t\t\t{$simple_update}\n\t\t\t\t{$sql_extra} {$sql_nets}\n\t\t\t\tORDER BY item.received DESC {$pager_sql}"); require_once 'include/items.php'; xchan_query($items); $items = fetch_post_tags($items, true); } else { // Normal conversation view if ($arr['order'] === 'post') { $ordering = "created"; } else { $ordering = "commented"; } if ($client_mode & CLIENT_MODE_LOAD || $client_mode == CLIENT_MODE_NORMAL) { // Fetch a page full of parent items for this page $r = q("SELECT distinct item.id AS item_id, item.{$ordering} FROM item\n left join abook on item.author_xchan = abook.abook_xchan\n WHERE {$item_uids} {$item_restrict}\n AND item.parent = item.id\n and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null)\n {$sql_extra3} {$sql_extra} {$sql_nets}\n ORDER BY item.{$ordering} DESC {$pager_sql} ", intval(ABOOK_FLAG_BLOCKED)); } else { // update $r = q("SELECT item.parent AS item_id FROM item\n left join abook on item.author_xchan = abook.abook_xchan\n WHERE {$item_uids} {$item_restrict} {$simple_update}\n and ((abook.abook_flags & %d) = 0 or abook.abook_flags is null)\n {$sql_extra3} {$sql_extra} {$sql_nets} ", intval(ABOOK_FLAG_BLOCKED)); } //$first = dba_timer(); // Then fetch all the children of the parents that are on this page if ($r) { $parents_str = ids_to_querystr($r, 'item_id'); if ($arr['top']) { $sql_extra = ' and id = parent ' . $sql_extra; } $items = q("SELECT item.*, item.id AS item_id FROM item\n\t\t\t\tWHERE {$item_uids} {$item_restrict}\n\t\t\t\tAND item.parent IN ( %s )\n\t\t\t\t{$sql_extra} ", dbesc($parents_str)); //$second = dba_timer(); xchan_query($items); //$third = dba_timer(); $items = fetch_post_tags($items, true); //$fourth = dba_timer(); require_once 'include/conversation.php'; $items = conv_sort($items, $ordering); //logger('items: ' . print_r($items,true)); } else { $items = array(); } if ($parents_str && $arr['mark_seen']) { $update_unseen = ' AND parent IN ( ' . dbesc($parents_str) . ' )'; } /** @FIXME finish mark unseen sql */ } return $items; }
function get($update = 0, $load = false) { if (!local_channel()) { $_SESSION['return_url'] = \App::$query_string; return login(false); } if ($load) { $_SESSION['loadtime'] = datetime_convert(); } $arr = array('query' => \App::$query_string); call_hooks('network_content_init', $arr); $channel = \App::get_channel(); $item_normal = item_normal(); $datequery = $datequery2 = ''; $group = 0; $nouveau = false; $datequery = x($_GET, 'dend') && is_a_date_arg($_GET['dend']) ? notags($_GET['dend']) : ''; $datequery2 = x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin']) ? notags($_GET['dbegin']) : ''; $nouveau = x($_GET, 'new') ? intval($_GET['new']) : 0; $gid = x($_GET, 'gid') ? intval($_GET['gid']) : 0; $category = x($_REQUEST, 'cat') ? $_REQUEST['cat'] : ''; $hashtags = x($_REQUEST, 'tag') ? $_REQUEST['tag'] : ''; $verb = x($_REQUEST, 'verb') ? $_REQUEST['verb'] : ''; $search = $_GET['search'] ? $_GET['search'] : ''; if ($search) { if (strpos($search, '@') === 0) { $r = q("select abook_id from abook left join xchan on abook_xchan = xchan_hash where xchan_name = '%s' and abook_channel = %d limit 1", dbesc(substr($search, 1)), intval(local_channel())); if ($r) { $_GET['cid'] = $r[0]['abook_id']; $search = $_GET['search'] = ''; } } elseif (strpos($search, '#') === 0) { $hashtags = substr($search, 1); $search = $_GET['search'] = ''; } } if ($datequery) { $_GET['order'] = 'post'; } // filter by collection (e.g. group) if ($gid) { $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1", intval($gid), intval(local_channel())); if (!$r) { if ($update) { killme(); } notice(t('No such group') . EOL); goaway(z_root() . '/network'); // NOTREACHED } $group = $gid; $group_hash = $r[0]['hash']; $def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>'); } $o = ''; // if no tabs are selected, defaults to comments $cid = x($_GET, 'cid') ? intval($_GET['cid']) : 0; $star = x($_GET, 'star') ? intval($_GET['star']) : 0; $order = x($_GET, 'order') ? notags($_GET['order']) : 'comment'; $liked = x($_GET, 'liked') ? intval($_GET['liked']) : 0; $conv = x($_GET, 'conv') ? intval($_GET['conv']) : 0; $spam = x($_GET, 'spam') ? intval($_GET['spam']) : 0; $cmin = x($_GET, 'cmin') ? intval($_GET['cmin']) : 0; $cmax = x($_GET, 'cmax') ? intval($_GET['cmax']) : 99; $firehose = x($_GET, 'fh') ? intval($_GET['fh']) : 0; $file = x($_GET, 'file') ? $_GET['file'] : ''; $deftag = ''; if (x($_GET, 'search') || x($_GET, 'file')) { $nouveau = true; } if ($cid) { $r = q("SELECT abook_xchan FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", intval($cid), intval(local_channel())); if (!$r) { if ($update) { killme(); } notice(t('No such channel') . EOL); goaway(z_root() . '/network'); // NOTREACHED } if ($_GET['pf'] === '1') { $deftag = '@' . t('forum') . '+' . intval($cid) . '+'; } else { $def_acl = array('allow_cid' => '<' . $r[0]['abook_xchan'] . '>'); } } if (!$update) { $tabs = network_tabs(); $o .= $tabs; // search terms header if ($search) { $o .= replace_macros(get_markup_template("section_title.tpl"), array('$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT, 'UTF-8'))); } nav_set_selected('network'); $channel_acl = array('allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], 'deny_cid' => $channel['channel_deny_cid'], 'deny_gid' => $channel['channel_deny_gid']); $private_editing = ($group || $cid) && !intval($_GET['pf']) ? true : false; $x = array('is_owner' => true, 'allow_location' => intval(get_pconfig($channel['channel_id'], 'system', 'use_browser_location')) ? '1' : '', 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], 'lockstate' => $private_editing || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid'] ? 'lock' : 'unlock', 'acl' => populate_acl($private_editing ? $def_acl : $channel_acl, true, \PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'bang' => $private_editing ? '!' : '', 'visitor' => true, 'profile_uid' => local_channel(), 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true); if ($deftag) { $x['pretext'] = $deftag; } $status_editor = status_editor($a, $x); $o .= $status_editor; } // We don't have to deal with ACL's on this page. You're looking at everything // that belongs to you, hence you can see all of it. We will filter by group if // desired. $sql_options = $star ? " and item_starred = 1 " : ''; $sql_nets = ''; $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE item_thread_top = 1 {$sql_options} ) "; if ($group) { $contact_str = ''; $contacts = group_get_members($group); if ($contacts) { foreach ($contacts as $c) { if ($contact_str) { $contact_str .= ','; } $contact_str .= "'" . $c['xchan'] . "'"; } } else { $contact_str = ' 0 '; info(t('Privacy group is empty')); } $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true {$sql_options} AND (( author_xchan IN ( {$contact_str} ) OR owner_xchan in ( {$contact_str} )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent {$item_normal} ) "; $x = group_rec_byhash(local_channel(), $group_hash); if ($x) { $title = replace_macros(get_markup_template("section_title.tpl"), array('$title' => t('Privacy group: ') . $x['name'])); } $o = $tabs; $o .= $title; $o .= $status_editor; } elseif ($cid) { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1", intval($cid), intval(local_channel())); if ($r) { $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true {$sql_options} AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) {$item_normal} ) "; $title = replace_macros(get_markup_template("section_title.tpl"), array('$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>')); $o = $tabs; $o .= $title; $o .= $status_editor; } else { notice(t('Invalid connection.') . EOL); goaway(z_root() . '/network'); } } if (x($category)) { $sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY)); } if (x($hashtags)) { $sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG)); } if (!$update) { // The special div is needed for liveUpdate to kick in for this page. // We only launch liveUpdate if you aren't filtering in some incompatible // way and also you aren't writing a comment (discovered in javascript). if ($gid || $cid || $cmin || $cmax != 99 || $star || $liked || $conv || $spam || $nouveau || $list) { $firehose = 0; } $maxheight = get_pconfig(local_channel(), 'system', 'network_divmore_height'); if (!$maxheight) { $maxheight = 400; } $o .= '<div id="live-network"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . local_channel() . "; var profile_page = " . \App::$pager['page'] . "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"), array('$baseurl' => z_root(), '$pgtype' => 'network', '$uid' => local_channel() ? local_channel() : '0', '$gid' => $gid ? $gid : '0', '$cid' => $cid ? $cid : '0', '$cmin' => $cmin ? $cmin : '0', '$cmax' => $cmax ? $cmax : '0', '$star' => $star ? $star : '0', '$liked' => $liked ? $liked : '0', '$conv' => $conv ? $conv : '0', '$spam' => $spam ? $spam : '0', '$fh' => $firehose ? $firehose : '0', '$nouveau' => $nouveau ? $nouveau : '0', '$wall' => '0', '$list' => x($_REQUEST, 'list') ? intval($_REQUEST['list']) : 0, '$page' => \App::$pager['page'] != 1 ? \App::$pager['page'] : 1, '$search' => $search ? $search : '', '$order' => $order, '$file' => $file, '$cats' => $category, '$tags' => $hashtags, '$dend' => $datequery, '$mid' => '', '$verb' => $verb, '$dbegin' => $datequery2)); } $sql_extra3 = ''; if ($datequery) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery)))); } if ($datequery2) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2)))); } $sql_extra2 = $nouveau ? '' : " AND item.parent = item.id "; $sql_extra3 = $nouveau ? '' : $sql_extra3; if (x($_GET, 'search')) { $search = escape_tags($_GET['search']); if (strpos($search, '#') === 0) { $sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG, TERM_COMMUNITYTAG); } else { $sql_extra .= sprintf(" AND item.body like '%s' ", dbesc(protect_sprintf('%' . $search . '%'))); } } if ($verb) { $sql_extra .= sprintf(" AND item.verb like '%s' ", dbesc(protect_sprintf('%' . $verb . '%'))); } if (strlen($file)) { $sql_extra .= term_query('item', $file, TERM_FILE); } if ($conv) { $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ", dbesc(protect_sprintf($channel['channel_hash']))); } if ($update && !$load) { // only setup pagination on initial page view $pager_sql = ''; } else { $itemspage = get_pconfig(local_channel(), 'system', 'itemspage'); \App::set_pager_itemspage(intval($itemspage) ? $itemspage : 20); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); } if ($cmin != 0 || $cmax != 99) { // Not everybody who shows up in the network stream will be in your address book. // By default those that aren't are assumed to have closeness = 99; but this isn't // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in // the stream with a NULL address book entry. $sql_nets .= " AND "; if ($cmax == 99) { $sql_nets .= " ( "; } $sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " "; $sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) "; if ($cmax == 99) { $sql_nets .= " OR abook.abook_closeness IS NULL ) "; } } $abook_uids = " and abook.abook_channel = " . local_channel() . " "; if ($firehose && !get_config('system', 'disable_discover_tab')) { require_once 'include/identity.php'; $sys = get_sys_channel(); $uids = " and item.uid = " . intval($sys['channel_id']) . " "; \App::$data['firehose'] = intval($sys['channel_id']); } else { $uids = " and item.uid = " . local_channel() . " "; } if (get_pconfig(local_channel(), 'system', 'network_list_mode')) { $page_mode = 'list'; } else { $page_mode = 'client'; } $simple_update = $update ? " and item_unseen = 1 " : ''; // This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day // or three and look at your matrix page - after opening up your browser. The first page loads just as it // should. All of a sudden a few seconds later, page 2 will get inserted at the beginning of the page // (before the page 1 content). The update code is actually doing just what it's supposed // to, it's fetching posts that have the ITEM_UNSEEN bit set. But the reason that page 2 content is being // returned in an UPDATE is because you hadn't gotten that far yet - you're still on page 1 and everything // that we loaded for page 1 is now marked as seen. But the stuff on page 2 hasn't been. So... it's being // treated as "new fresh" content because it is unseen. We need to distinguish it somehow from content // which "arrived as you were reading page 1". We're going to do this // by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items // which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers... if ($update && $_SESSION['loadtime']) { $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) "; } if ($load) { $simple_update = ''; } if ($nouveau && $load) { // "New Item View" - show all items unthreaded in reverse created date order $items = q("SELECT item.*, item.id AS item_id, received FROM item\n\t\t\t\tleft join abook on ( item.owner_xchan = abook.abook_xchan {$abook_uids} )\n\t\t\t\tWHERE true {$uids} {$item_normal}\n\t\t\t\tand (abook.abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t{$simple_update}\n\t\t\t\t{$sql_extra} {$sql_nets}\n\t\t\t\tORDER BY item.received DESC {$pager_sql} "); require_once 'include/items.php'; xchan_query($items); $items = fetch_post_tags($items, true); } elseif ($update) { // Normal conversation view if ($order === 'post') { $ordering = "created"; } else { $ordering = "commented"; } if ($load) { // Fetch a page full of parent items for this page $r = q("SELECT distinct item.id AS item_id, {$ordering} FROM item\n\t\t\t\t\tleft join abook on ( item.owner_xchan = abook.abook_xchan {$abook_uids} )\n\t\t\t\t\tWHERE true {$uids} {$item_normal}\n\t\t\t\t\tAND item.parent = item.id\n\t\t\t\t\tand (abook.abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t\t{$sql_extra3} {$sql_extra} {$sql_nets}\n\t\t\t\t\tORDER BY {$ordering} DESC {$pager_sql} "); } else { // this is an update $r = q("SELECT item.parent AS item_id FROM item\n\t\t\t\t\tleft join abook on ( item.owner_xchan = abook.abook_xchan {$abook_uids} )\n\t\t\t\t\tWHERE true {$uids} {$item_normal} {$simple_update}\n\t\t\t\t\tand (abook.abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t\t{$sql_extra3} {$sql_extra} {$sql_nets} "); $_SESSION['loadtime'] = datetime_convert(); } // Then fetch all the children of the parents that are on this page $parents_str = ''; $update_unseen = ''; if ($r) { $parents_str = ids_to_querystr($r, 'item_id'); $items = q("SELECT item.*, item.id AS item_id FROM item\n\t\t\t\t\tWHERE true {$uids} {$item_normal}\n\t\t\t\t\tAND item.parent IN ( %s )\n\t\t\t\t\t{$sql_extra} ", dbesc($parents_str)); xchan_query($items, true, $firehose ? local_channel() : 0); $items = fetch_post_tags($items, true); $items = conv_sort($items, $ordering); } else { $items = array(); } if ($page_mode === 'list') { /** * in "list mode", only mark the parent item and any like activities as "seen". * We won't distinguish between comment likes and post likes. The important thing * is that the number of unseen comments will be accurate. The SQL to separate the * comment likes could also get somewhat hairy. */ if ($parents_str) { $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; } } else { if ($parents_str) { $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; } } } if ($update_unseen && !$firehose) { $r = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d {$update_unseen} ", intval(local_channel())); } $mode = $nouveau ? 'network-new' : 'network'; $o .= conversation($a, $items, $mode, $update, $page_mode); if ($items && !$update) { $o .= alt_pager($a, count($items)); } return $o; }
/** * @brief Returns array of channels which have recursive permission for a file * * @param $arr_allow_cid * @param $arr_allow_gid * @param $arr_deny_cid * @param $arr_deny_gid * @param $folder_hash */ function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash) { $ret = array(); $parent_arr = array(); $count_values = array(); $poster = App::get_observer(); //turn allow_gid into allow_cid's foreach ($arr_allow_gid as $gid) { $in_group = group_get_members($gid); $arr_allow_cid = array_unique(array_merge($arr_allow_cid, $in_group)); } $count = 0; while ($folder_hash) { $x = q("SELECT allow_cid, allow_gid, deny_cid, deny_gid, folder FROM attach WHERE hash = '%s' LIMIT 1", dbesc($folder_hash)); //only process private folders if ($x[0]['allow_cid'] || $x[0]['allow_gid'] || $x[0]['deny_cid'] || $x[0]['deny_gid']) { $parent_arr['allow_cid'][] = expand_acl($x[0]['allow_cid']); $parent_arr['allow_gid'][] = expand_acl($x[0]['allow_gid']); /** * @TODO should find a much better solution for the allow_cid <-> allow_gid problem. * Do not use allow_gid for now. Instead lookup the members of the group directly and add them to allow_cid. * */ if ($parent_arr['allow_gid']) { foreach ($parent_arr['allow_gid'][$count] as $gid) { $in_group = group_get_members($gid); $parent_arr['allow_cid'][$count] = array_unique(array_merge($parent_arr['allow_cid'][$count], $in_group)); } } $parent_arr['deny_cid'][] = expand_acl($x[0]['deny_cid']); $parent_arr['deny_gid'][] = expand_acl($x[0]['deny_gid']); $count++; } $folder_hash = $x[0]['folder']; } //if none of the parent folders is private just return file perms if (!$parent_arr['allow_cid'] && !$parent_arr['allow_gid'] && !$parent_arr['deny_cid'] && !$parent_arr['deny_gid']) { $ret['allow_gid'] = $arr_allow_gid; $ret['allow_cid'] = $arr_allow_cid; $ret['deny_gid'] = $arr_deny_gid; $ret['deny_cid'] = $arr_deny_cid; return $ret; } //if there are no perms on the file we get them from the first parent folder if (!$arr_allow_cid && !$arr_allow_gid && !$arr_deny_cid && !$arr_deny_gid) { $arr_allow_cid = $parent_arr['allow_cid'][0]; $arr_allow_gid = $parent_arr['allow_gid'][0]; $arr_deny_cid = $parent_arr['deny_cid'][0]; $arr_deny_gid = $parent_arr['deny_gid'][0]; } //allow_cid $r_arr_allow_cid = false; foreach ($parent_arr['allow_cid'] as $folder_arr_allow_cid) { foreach ($folder_arr_allow_cid as $ac_hash) { $count_values[$ac_hash]++; } } foreach ($arr_allow_cid as $fac_hash) { if ($count_values[$fac_hash] == $count) { $r_arr_allow_cid[] = $fac_hash; } } //allow_gid $r_arr_allow_gid = false; foreach ($parent_arr['allow_gid'] as $folder_arr_allow_gid) { foreach ($folder_arr_allow_gid as $ag_hash) { $count_values[$ag_hash]++; } } foreach ($arr_allow_gid as $fag_hash) { if ($count_values[$fag_hash] == $count) { $r_arr_allow_gid[] = $fag_hash; } } //deny_gid foreach ($parent_arr['deny_gid'] as $folder_arr_deny_gid) { $r_arr_deny_gid = array_merge($arr_deny_gid, $folder_arr_deny_gid); } $r_arr_deny_gid = array_unique($r_arr_deny_gid); //deny_cid foreach ($parent_arr['deny_cid'] as $folder_arr_deny_cid) { $r_arr_deny_cid = array_merge($arr_deny_cid, $folder_arr_deny_cid); } $r_arr_deny_cid = array_unique($r_arr_deny_cid); //if none is allowed restrict to self if ($r_arr_allow_gid === false && $r_arr_allow_cid === false) { $ret['allow_cid'] = $poster['xchan_hash']; } else { $ret['allow_gid'] = $r_arr_allow_gid; $ret['allow_cid'] = $r_arr_allow_cid; $ret['deny_gid'] = $r_arr_deny_gid; $ret['deny_cid'] = $r_arr_deny_cid; } return $ret; }
function group_content(&$a) { $change = false; if (!local_user()) { notice(t('Permission denied') . EOL); return; } // Switch to text mode interface if we have more than 'n' contacts or group members $switchtotext = get_pconfig(local_user(), 'system', 'groupedit_image_limit'); if ($switchtotext === false) { $switchtotext = get_config('system', 'groupedit_image_limit'); } if ($switchtotext === false) { $switchtotext = 400; } $tpl = get_markup_template('group_edit.tpl'); $context = array('$submit' => t('Submit')); if ($a->argc == 2 && $a->argv[1] === 'new') { return replace_macros($tpl, $context + array('$title' => t('Create a group of contacts/friends.'), '$gname' => array('groupname', t('Group Name: '), '', ''), '$gid' => 'new', '$form_security_token' => get_form_security_token("group_edit"))); } if ($a->argc == 3 && $a->argv[1] === 'drop') { check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); if (intval($a->argv[2])) { $r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[2]), intval(local_user())); if (count($r)) { $result = group_rmv(local_user(), $r[0]['name']); } if ($result) { info(t('Group removed.') . EOL); } else { notice(t('Unable to remove group.') . EOL); } } goaway($a->get_baseurl() . '/group'); // NOTREACHED } if ($a->argc > 2 && intval($a->argv[1]) && intval($a->argv[2])) { check_form_security_token_ForbiddenOnErr('group_member_change', 't'); $r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1", intval($a->argv[2]), intval(local_user())); if (count($r)) { $change = intval($a->argv[2]); } } if ($a->argc > 1 && intval($a->argv[1])) { require_once 'include/acl_selectors.php'; $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval($a->argv[1]), intval(local_user())); if (!count($r)) { notice(t('Group not found.') . EOL); goaway($a->get_baseurl() . '/contacts'); } $group = $r[0]; $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['id']; } } if ($change) { if (in_array($change, $preselected)) { group_rmv_member(local_user(), $group['name'], $change); } else { group_add_member(local_user(), $group['name'], $change); } $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['id']; } } } $drop_tpl = get_markup_template('group_drop.tpl'); $drop_txt = replace_macros($drop_tpl, array('$id' => $group['id'], '$delete' => t('Delete'), '$form_security_token' => get_form_security_token("group_drop"))); $celeb = $a->user['page-flags'] == PAGE_SOAPBOX || $a->user['page-flags'] == PAGE_COMMUNITY ? true : false; $context = $context + array('$title' => t('Group Editor'), '$gname' => array('groupname', t('Group Name: '), $group['name'], ''), '$gid' => $group['id'], '$drop' => $drop_txt, '$form_security_token' => get_form_security_token('group_edit')); } if (!isset($group)) { return; } $groupeditor = array('label_members' => t('Members'), 'members' => array(), 'label_contacts' => t('All Contacts'), 'contacts' => array()); $sec_token = addslashes(get_form_security_token('group_member_change')); $textmode = $switchtotext && count($members) > $switchtotext ? true : false; foreach ($members as $member) { if ($member['url']) { $member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . ',\'' . $sec_token . '\'); return true;'; $groupeditor['members'][] = micropro($member, true, 'mpgroup', $textmode); } else { group_rmv_member(local_user(), $group['name'], $member['id']); } } $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 and `pending` = 0 and `self` = 0 ORDER BY `name` ASC", intval(local_user())); if (count($r)) { $textmode = $switchtotext && count($r) > $switchtotext ? true : false; foreach ($r as $member) { if (!in_array($member['id'], $preselected)) { $member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . ',\'' . $sec_token . '\'); return true;'; $groupeditor['contacts'][] = micropro($member, true, 'mpall', $textmode); } } } $context['$groupeditor'] = $groupeditor; $context['$desc'] = t('Click on a contact to add or remove.'); if ($change) { $tpl = get_markup_template('groupeditor.tpl'); echo replace_macros($tpl, $context); killme(); } return replace_macros($tpl, $context); }
function network_content(&$a, $update = 0, $load = false) { if (!local_user()) { $_SESSION['return_url'] = $a->query_string; return login(false); } $arr = array('query' => $a->query_string); call_hooks('network_content_init', $arr); $channel = $a->get_channel(); $search = $_GET['search'] ? $_GET['search'] : ''; if ($search) { if (strpos($search, '@') === 0) { $r = q("select abook_id from abook left join xchan on abook_xchan = xchan_hash where xchan_name = '%s' and abook_channel = %d limit 1", dbesc(substr($search, 1)), intval(local_user())); if ($r) { $_GET['cid'] = $r[0]['abook_id']; $search = $_GET['search'] = ''; } } elseif (strpos($search, '#') === 0) { $search = $_GET['search'] = substr($search, 1); } } $datequery = $datequery2 = ''; $group = 0; $nouveau = false; $datequery = x($_GET, 'dend') && is_a_date_arg($_GET['dend']) ? notags($_GET['dend']) : ''; $datequery2 = x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin']) ? notags($_GET['dbegin']) : ''; $nouveau = x($_GET, 'new') ? intval($_GET['new']) : 0; $gid = x($_GET, 'gid') ? intval($_GET['gid']) : 0; if ($datequery) { $_GET['order'] = 'post'; } if ($gid) { $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1", intval($gid), intval(local_user())); if (!$r) { if ($update) { killme(); } notice(t('No such group') . EOL); goaway($a->get_baseurl(true) . '/network'); // NOTREACHED } $group = $gid; $group_hash = $r[0]['hash']; $def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>'); } $o = ''; // if no tabs are selected, defaults to comments $cid = x($_GET, 'cid') ? intval($_GET['cid']) : 0; $star = x($_GET, 'star') ? intval($_GET['star']) : 0; $order = x($_GET, 'order') ? notags($_GET['order']) : 'comment'; $liked = x($_GET, 'liked') ? intval($_GET['liked']) : 0; $conv = x($_GET, 'conv') ? intval($_GET['conv']) : 0; $spam = x($_GET, 'spam') ? intval($_GET['spam']) : 0; $cmin = x($_GET, 'cmin') ? intval($_GET['cmin']) : 0; $cmax = x($_GET, 'cmax') ? intval($_GET['cmax']) : 99; $firehose = x($_GET, 'fh') ? intval($_GET['fh']) : 0; $file = x($_GET, 'file') ? $_GET['file'] : ''; if (x($_GET, 'search') || x($_GET, 'file')) { $nouveau = true; } if ($cid) { $def_acl = array('allow_cid' => '<' . intval($cid) . '>'); } if (!$update) { $o .= network_tabs(); // search terms header if ($search) { $o .= '<h2>' . t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT, 'UTF-8') . '</h2>'; } nav_set_selected('network'); $channel_acl = array('allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], 'deny_cid' => $channel['channel_deny_cid'], 'deny_gid' => $channel['channel_deny_gid']); $x = array('is_owner' => true, 'allow_location' => intval(get_pconfig($channel['channel_id'], 'system', 'use_browser_location')) ? '1' : '', 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], 'lockstate' => $group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid'] ? 'lock' : 'unlock', 'acl' => populate_acl($group || $cid ? $def_acl : $channel_acl), 'bang' => $group || $cid ? '!' : '', 'visitor' => true, 'profile_uid' => local_user()); $o .= status_editor($a, $x); } // We don't have to deal with ACL's on this page. You're looking at everything // that belongs to you, hence you can see all of it. We will filter by group if // desired. $sql_options = $star ? " and (item_flags & " . intval(ITEM_STARRED) . ")" : ''; $sql_nets = ''; $sql_extra = " AND `item`.`parent` IN ( SELECT `parent` FROM `item` WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ") {$sql_options} ) "; if ($group) { $contact_str = ''; $contacts = group_get_members($group); if ($contacts) { foreach ($contacts as $c) { if ($contact_str) { $contact_str .= ','; } $contact_str .= "'" . $c['xchan'] . "'"; } } else { $contact_str = ' 0 '; info(t('Collection is empty')); } $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true {$sql_options} AND (( author_xchan IN ( {$contact_str} ) OR owner_xchan in ( {$contact_str} )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent and item_restrict = 0 ) "; $x = group_rec_byhash(local_user(), $group_hash); if ($x) { $o = '<h2>' . t('Collection: ') . $x['name'] . '</h2>' . $o; } } elseif ($cid) { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ") limit 1", intval($cid), intval(local_user())); if ($r) { $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true {$sql_options} AND uid = " . intval(local_user()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; $o = '<h2>' . t('Connection: ') . $r[0]['xchan_name'] . '</h2>' . $o; } else { notice(t('Invalid connection.') . EOL); goaway($a->get_baseurl(true) . '/network'); } } if (!$update) { // The special div is needed for liveUpdate to kick in for this page. // We only launch liveUpdate if you aren't filtering in some incompatible // way and also you aren't writing a comment (discovered in javascript). if ($gid || $cid || $cmin || $cmax != 99 || $star || $liked || $conv || $spam || $nouveau || $list) { $firehose = 0; } $o .= '<div id="live-network"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . $_SESSION['uid'] . "; var profile_page = " . $a->pager['page'] . ";</script>"; $a->page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"), array('$baseurl' => z_root(), '$pgtype' => 'network', '$uid' => local_user() ? local_user() : '0', '$gid' => $gid ? $gid : '0', '$cid' => $cid ? $cid : '0', '$cmin' => $cmin ? $cmin : '0', '$cmax' => $cmax ? $cmax : '0', '$star' => $star ? $star : '0', '$liked' => $liked ? $liked : '0', '$conv' => $conv ? $conv : '0', '$spam' => $spam ? $spam : '0', '$fh' => $firehose ? $firehose : '0', '$nouveau' => $nouveau ? $nouveau : '0', '$wall' => '0', '$list' => x($_REQUEST, 'list') ? intval($_REQUEST['list']) : 0, '$page' => $a->pager['page'] != 1 ? $a->pager['page'] : 1, '$search' => $search ? $search : '', '$order' => $order, '$file' => $file, '$cats' => '', '$dend' => $datequery, '$mid' => '', '$dbegin' => $datequery2)); } $sql_extra3 = ''; if ($datequery) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery)))); } if ($datequery2) { $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2)))); } $sql_extra2 = $nouveau ? '' : " AND `item`.`parent` = `item`.`id` "; $sql_extra3 = $nouveau ? '' : $sql_extra3; if (x($_GET, 'search')) { $search = escape_tags($_GET['search']); if (strpos($search, '#') === 0) { $sql_extra .= term_query('item', substr($search, 1), TERM_HASHTAG); } else { $sql_extra .= sprintf(" AND `item`.`body` like '%s' ", dbesc(protect_sprintf('%' . $search . '%'))); } } if (strlen($file)) { $sql_extra .= term_query('item', $file, TERM_FILE); } if ($conv) { $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or ( item_flags & %d ))) ", dbesc(protect_sprintf($channel['channel_hash'])), intval(ITEM_MENTIONSME)); } if ($update && !$load) { // only setup pagination on initial page view $pager_sql = ''; } else { $itemspage = get_pconfig(local_user(), 'system', 'itemspage'); $a->set_pager_itemspage(intval($itemspage) ? $itemspage : 20); $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage'])); } if ($cmin != 0 || $cmax != 99) { // Not everybody who shows up in the network stream will be in your address book. // By default those that aren't are assumed to have closeness = 99; but this isn't // recorded anywhere. So if cmax is 99, we'll open the search up to anybody in // the stream with a NULL address book entry. $sql_nets .= " AND "; if ($cmax == 99) { $sql_nets .= " ( "; } $sql_nets .= "( abook.abook_closeness >= " . intval($cmin) . " "; $sql_nets .= " AND abook.abook_closeness <= " . intval($cmax) . " ) "; if ($cmax == 99) { $sql_nets .= " OR abook.abook_closeness IS NULL ) "; } } if ($firehose && !get_config('system', 'disable_discover_tab')) { require_once 'include/identity.php'; $sys = get_sys_channel(); $uids = " and item.uid = " . intval($sys['channel_id']) . " "; $a->data['firehose'] = intval($sys['channel_id']); } else { $uids = " and item.uid = " . local_user() . " "; } $simple_update = $update ? " and ( item.item_flags & " . intval(ITEM_UNSEEN) . " ) " : ''; // This fixes a very subtle bug so I'd better explain it. You wake up in the morning or return after a day // or three and look at your matrix page - after opening up your browser. The first page loads just as it // should. All of a sudden a few seconds later, page 2 will get inserted at the beginning of the page // (before the page 1 content). The update code is actually doing just what it's supposed // to, it's fetching posts that have the ITEM_UNSEEN bit set. But the reason that page 2 content is being // returned in an UPDATE is because you hadn't gotten that far yet - you're still on page 1 and everything // that we loaded for page 1 is now marked as seen. But the stuff on page 2 hasn't been. So... it's being // treated as "new fresh" content because it is unseen. We need to distinguish it somehow from content // which "arrived as you were reading page 1". We're going to do this // by storing in your session the current UTC time whenever you LOAD a network page, and only UPDATE items // which are both ITEM_UNSEEN and have "changed" since that time. Cross fingers... if ($update && $_SESSION['loadtime']) { $simple_update .= " and item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' "; } if ($load) { $simple_update = ''; } if ($nouveau && $load) { // "New Item View" - show all items unthreaded in reverse created date order $items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` \n\t\t\tWHERE true {$uids} AND item_restrict = 0 \n\t\t\t{$simple_update}\n\t\t\t{$sql_extra} {$sql_nets}\n\t\t\tORDER BY `item`.`received` DESC {$pager_sql} "); require_once 'include/items.php'; xchan_query($items); $items = fetch_post_tags($items, true); } elseif ($update) { // Normal conversation view if ($order === 'post') { $ordering = "`created`"; } else { $ordering = "`commented`"; } if ($load) { $_SESSION['loadtime'] = datetime_convert(); // Fetch a page full of parent items for this page $r = q("SELECT distinct item.id AS item_id FROM item \n\t\t\t\tleft join abook on item.author_xchan = abook.abook_xchan\n\t\t\t\tWHERE true {$uids} AND item.item_restrict = 0\n\t\t\t\tAND item.parent = item.id\n\t\t\t\tand ((abook.abook_flags & %d) = 0 or abook.abook_flags is null)\n\t\t\t\t{$sql_extra3} {$sql_extra} {$sql_nets}\n\t\t\t\tORDER BY item.{$ordering} DESC {$pager_sql} ", intval(ABOOK_FLAG_BLOCKED)); } else { if (!$firehose) { // update $r = q("SELECT item.parent AS item_id FROM item\n\t\t\t\t\tleft join abook on item.author_xchan = abook.abook_xchan\n\t\t\t\t\tWHERE true {$uids} AND item.item_restrict = 0 {$simple_update}\n\t\t\t\t\tand ((abook.abook_flags & %d) = 0 or abook.abook_flags is null)\n\t\t\t\t\t{$sql_extra3} {$sql_extra} {$sql_nets} ", intval(ABOOK_FLAG_BLOCKED)); } } // Then fetch all the children of the parents that are on this page $parents_str = ''; $update_unseen = ''; if ($r) { $parents_str = ids_to_querystr($r, 'item_id'); $items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` \n\t\t\t\tWHERE true {$uids} AND `item`.`item_restrict` = 0\n\t\t\t\tAND `item`.`parent` IN ( %s )\n\t\t\t\t{$sql_extra} ", dbesc($parents_str)); xchan_query($items); $items = fetch_post_tags($items, true); $items = conv_sort($items, $ordering); } else { $items = array(); } if ($parents_str) { $update_unseen = ' AND parent IN ( ' . dbesc($parents_str) . ' )'; } } if ($update_unseen && !$firehose) { $r = q("UPDATE `item` SET item_flags = ( item_flags ^ %d)\n\t\t\tWHERE (item_flags & %d) AND `uid` = %d {$update_unseen} ", intval(ITEM_UNSEEN), intval(ITEM_UNSEEN), intval(local_user())); } $mode = $nouveau ? 'network-new' : 'network'; $o .= conversation($a, $items, $mode, $update, 'client'); if ($items && !$update) { $o .= alt_pager($a, count($items)); } return $o; }
function group_content(&$a) { if (!local_user()) { notice(t('Permission denied') . EOL); return; } // Switch to text mod interface if we have more than 'n' contacts or group members $switchtotext = get_pconfig(local_user(), 'system', 'groupedit_image_limit'); if ($switchtotext === false) { $switchtotext = get_config('system', 'groupedit_image_limit'); } if ($switchtotext === false) { $switchtotext = 400; } if ($a->argc == 2 && $a->argv[1] === 'new') { $tpl = get_markup_template('group_new.tpl'); $o .= replace_macros($tpl, array('$desc' => t('Create a group of contacts/friends.'), '$name' => t('Group Name: '), '$submit' => t('Submit'))); return $o; } if ($a->argc == 3 && $a->argv[1] === 'drop') { if (intval($a->argv[2])) { $r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[2]), intval(local_user())); if (count($r)) { $result = group_rmv(local_user(), $r[0]['name']); } if ($result) { info(t('Group removed.') . EOL); } else { notice(t('Unable to remove group.') . EOL); } } goaway($a->get_baseurl() . '/group'); // NOTREACHED } if ($a->argc > 2 && intval($a->argv[1]) && intval($a->argv[2])) { $r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1", intval($a->argv[2]), intval(local_user())); if (count($r)) { $change = intval($a->argv[2]); } } if ($a->argc > 1 && intval($a->argv[1])) { require_once 'include/acl_selectors.php'; $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval($a->argv[1]), intval(local_user())); if (!count($r)) { notice(t('Group not found.') . EOL); goaway($a->get_baseurl() . '/contacts'); } $group = $r[0]; $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['id']; } } if ($change) { if (in_array($change, $preselected)) { group_rmv_member(local_user(), $group['name'], $change); } else { group_add_member(local_user(), $group['name'], $change); } $members = group_get_members($group['id']); $preselected = array(); if (count($members)) { foreach ($members as $member) { $preselected[] = $member['id']; } } } $drop_tpl = get_markup_template('group_drop.tpl'); $drop_txt = replace_macros($drop_tpl, array('$id' => $group['id'], '$delete' => t('Delete'))); $celeb = $a->user['page-flags'] == PAGE_SOAPBOX || $a->user['page-flags'] == PAGE_COMMUNITY ? true : false; $tpl = get_markup_template('group_edit.tpl'); $o .= replace_macros($tpl, array('$gid' => $group['id'], '$name' => $group['name'], '$drop' => $drop_txt, '$desc' => t('Click on a contact to add or remove.'), '$title' => t('Group Editor'), '$gname' => t('Group Name: '), '$submit' => t('Submit'))); } if (!isset($group)) { return; } $o .= '<div id="group-update-wrapper">'; if ($change) { $o = ''; } $o .= '<h3>' . t('Members') . '</h3>'; $o .= '<div id="group-members">'; $textmode = $switchtotext && count($members) > $switchtotext ? true : false; foreach ($members as $member) { if ($member['url']) { $member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . '); return true;'; $o .= micropro($member, true, 'mpgroup', $textmode); } else { group_rmv_member(local_user(), $group['name'], $member['id']); } } $o .= '</div><div id="group-members-end"></div>'; $o .= '<hr id="group-separator" />'; $o .= '<h3>' . t('All Contacts') . '</h3>'; $o .= '<div id="group-all-contacts">'; $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 and `pending` = 0 and `self` = 0 ORDER BY `name` ASC", intval(local_user())); if (count($r)) { $textmode = $switchtotext && count($r) > $switchtotext ? true : false; foreach ($r as $member) { if (!in_array($member['id'], $preselected)) { $member['click'] = 'groupChangeMember(' . $group['id'] . ',' . $member['id'] . '); return true;'; $o .= micropro($member, true, 'mpall', $textmode); } } } $o .= '</div><div id="group-all-contacts-end"></div>'; if ($change) { echo $o; killme(); } $o .= '</div>'; return $o; }
function group_content(&$a) { if (!local_user()) { notice(t('Permission denied.') . EOL); return; } if ($a->argc == 2 && $a->argv[1] == 'new') { $tpl = file_get_contents('view/group_new.tpl'); $o .= replace_macros($tpl, array()); } if ($a->argc == 3 && $a->argv[1] == 'drop') { if (intval($a->argv[2])) { $r = q("SELECT `name` FROM `group` WHERE `id` = %d LIMIT 1", intval($a->argv[2])); if (count($r)) { $result = group_rmv($r[0]['name']); } if ($result) { notice(t('Group removed.') . EOL); } else { notice(t('Unable to remove group.') . EOL); } } goaway($a->get_baseurl() . '/group'); return; // NOTREACHED } if ($a->argc == 2 && intval($a->argv[1])) { require_once 'view/acl_selectors.php'; $r = q("SELECT * FROM `group` WHERE `id` = %d LIMIT 1", intval($a->argv[1])); if (!count($r)) { notice(t('Group not found.') . EOL); goaway($a->get_baseurl() . '/contacts'); } $group = $r[0]; $ret = group_get_members($group['id']); $preselected = array(); if (count($ret)) { foreach ($ret as $p) { $preselected[] = $p['id']; } } $drop_tpl = file_get_contents('view/group_drop.tpl'); $drop_txt = replace_macros($drop_tpl, array('$id' => $group['id'], '$delete' => t('Delete'))); $tpl = file_get_contents('view/group_edit.tpl'); $o .= replace_macros($tpl, array('$gid' => $group['id'], '$name' => $group['name'], '$drop' => $drop_txt, '$selector' => contact_select('group_members_select', 'group_members_select', $preselected, 25))); } return $o; }