function get($update = 0, $load = false) { $checkjs = new \Zotlabs\Web\CheckJS(1); if ($load) { $_SESSION['loadtime'] = datetime_convert(); } if (observer_prohibited()) { notice(t('Public access denied.') . EOL); return; } require_once "include/bbcode.php"; require_once 'include/security.php'; require_once 'include/conversation.php'; require_once 'include/acl_selectors.php'; require_once 'include/items.php'; \App::$page['htmlhead'] .= replace_macros(get_markup_template('display-head.tpl'), array()); if (argc() > 1 && argv(1) !== 'load') { $item_hash = argv(1); } if ($_REQUEST['mid']) { $item_hash = $_REQUEST['mid']; } if (!$item_hash) { \App::$error = 404; notice(t('Item not found.') . EOL); return; } $observer_is_owner = false; if (local_channel() && !$update) { $channel = \App::get_channel(); $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($channel_acl), 'permissions' => $channel_acl, 'bang' => '', 'visitor' => true, 'profile_uid' => local_channel(), 'return_path' => 'channel/' . $channel['channel_address'], 'expanded' => true, 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true); $o = '<div id="jot-popup">'; $o .= status_editor($a, $x); $o .= '</div>'; } // This page can be viewed by anybody so the query could be complicated // First we'll see if there is a copy of the item which is owned by us - if we're logged in locally. // If that fails (or we aren't logged in locally), // query an item in which the observer (if logged in remotely) has cid or gid rights // and if that fails, look for a copy of the post that has no privacy restrictions. // If we find the post, but we don't find a copy that we're allowed to look at, this fact needs to be reported. // find a copy of the item somewhere $target_item = null; $r = q("select id, uid, mid, parent_mid, item_type, item_deleted from item where mid like '%s' limit 1", dbesc($item_hash . '%')); if ($r) { $target_item = $r[0]; } $r = null; if ($target_item['item_type'] == ITEM_TYPE_WEBPAGE) { $x = q("select * from channel where channel_id = %d limit 1", intval($target_item['uid'])); $y = q("select * from iconfig left join item on iconfig.iid = item.id \n\t\t\t\twhere item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1", intval($target_item['uid']), intval($target_item['id'])); if ($x && $y) { goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['v']); } else { notice(t('Page not found.') . EOL); return ''; } } $simple_update = $update ? " AND item_unseen = 1 " : ''; 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 (!$update && !$load) { $o .= '<div id="live-display"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . (intval(local_channel()) ? local_channel() : -1) . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; </script>\r\n"; \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"), array('$baseurl' => z_root(), '$pgtype' => 'display', '$uid' => '0', '$gid' => '0', '$cid' => '0', '$cmin' => '0', '$cmax' => '99', '$star' => '0', '$liked' => '0', '$conv' => '0', '$spam' => '0', '$fh' => '0', '$nouveau' => '0', '$wall' => '0', '$page' => \App::$pager['page'] != 1 ? \App::$pager['page'] : 1, '$list' => x($_REQUEST, 'list') ? intval($_REQUEST['list']) : 0, '$search' => '', '$order' => '', '$file' => '', '$cats' => '', '$tags' => '', '$dend' => '', '$dbegin' => '', '$verb' => '', '$mid' => $item_hash)); } $observer_hash = get_observer_hash(); $item_normal = item_normal(); $sql_extra = public_permissions_sql($observer_hash); if ($update && $load || $checkjs->disabled()) { $updateable = false; $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); if ($load || $checkjs->disabled()) { $r = null; require_once 'include/channel.php'; $sys = get_sys_channel(); $sysid = $sys['channel_id']; if (local_channel()) { $r = q("SELECT * from item\n\t\t\t\t\t\tWHERE uid = %d\n\t\t\t\t\t\tand mid = '%s'\n\t\t\t\t\t\t{$item_normal}\n\t\t\t\t\t\tlimit 1", intval(local_channel()), dbesc($target_item['parent_mid'])); if ($r) { $updateable = true; } } if ($r === null) { // in case somebody turned off public access to sys channel content using permissions // make that content unsearchable by ensuring the owner_xchan can't match if (!perm_is_allowed($sysid, $observer_hash, 'view_stream')) { $sysid = 0; } $r = q("SELECT * from item\n\t\t\t\t\t\tWHERE mid = '%s'\n\t\t\t\t\t\tAND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' \n\t\t\t\t\t\tAND `item`.`deny_gid` = '' AND item_private = 0 ) \n\t\t\t\t\t\tand owner_xchan in ( " . stream_perms_xchans($observer_hash ? PERMS_NETWORK | PERMS_PUBLIC : PERMS_PUBLIC) . " ))\n\t\t\t\t\t\tOR uid = %d )\n\t\t\t\t\t\t{$sql_extra} )\n\t\t\t\t\t\t{$item_normal}\n\t\t\t\t\t\tlimit 1", dbesc($target_item['parent_mid']), intval($sysid)); } } } elseif ($update && !$load) { $r = null; require_once 'include/channel.php'; $sys = get_sys_channel(); $sysid = $sys['channel_id']; if (local_channel()) { $r = q("SELECT * from item\n\t\t\t\t\tWHERE uid = %d\n\t\t\t\t\tand mid = '%s'\n\t\t\t\t\t{$item_normal}\n\t\t\t\t\t{$simple_update}\n\t\t\t\t\tlimit 1", intval(local_channel()), dbesc($target_item['parent_mid'])); if ($r) { $updateable = true; } } if ($r === null) { // in case somebody turned off public access to sys channel content using permissions // make that content unsearchable by ensuring the owner_xchan can't match if (!perm_is_allowed($sysid, $observer_hash, 'view_stream')) { $sysid = 0; } $r = q("SELECT * from item\n\t\t\t\t\tWHERE mid = '%s'\n\t\t\t\t\tAND (((( `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' \n\t\t\t\t\tAND `item`.`deny_gid` = '' AND item_private = 0 ) \n\t\t\t\t\tand owner_xchan in ( " . stream_perms_xchans($observer_hash ? PERMS_NETWORK | PERMS_PUBLIC : PERMS_PUBLIC) . " ))\n\t\t\t\t\tOR uid = %d )\n\t\t\t\t\t{$sql_extra} )\n\t\t\t\t\t{$item_normal}\n\t\t\t\t\t{$simple_update}\n\t\t\t\t\tlimit 1", dbesc($target_item['parent_mid']), intval($sysid)); } $_SESSION['loadtime'] = datetime_convert(); } else { $r = array(); } if ($r) { $parents_str = ids_to_querystr($r, 'id'); if ($parents_str) { $items = q("SELECT `item`.*, `item`.`id` AS `item_id` \n\t\t\t\t\tFROM `item`\n\t\t\t\t\tWHERE parent in ( %s ) {$item_normal} ", dbesc($parents_str)); xchan_query($items); $items = fetch_post_tags($items, true); $items = conv_sort($items, 'created'); } } else { $items = array(); } if ($checkjs->disabled()) { $o .= conversation($a, $items, 'display', $update, 'traditional'); if ($items[0]['title']) { \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; } } else { $o .= conversation($a, $items, 'display', $update, 'client'); } if ($updateable) { $x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ", intval(local_channel()), intval($r[0]['parent'])); } $o .= '<div id="content-complete"></div>'; return $o; /* elseif((! $update) && (! { $r = q("SELECT `id`, item_flags FROM `item` WHERE `id` = '%s' OR `mid` = '%s' LIMIT 1", dbesc($item_hash), dbesc($item_hash) ); if($r) { if(intval($r[0]['item_deleted'])) { notice( t('Item has been removed.') . EOL ); } else { notice( t('Permission denied.') . EOL ); } } else { notice( t('Item not found.') . EOL ); } } */ }
function get($update = 0, $load = false) { if ($load) { $_SESSION['loadtime'] = datetime_convert(); } $checkjs = new \Zotlabs\Web\CheckJS(1); $category = $datequery = $datequery2 = ''; $mid = x($_REQUEST, 'mid') ? $_REQUEST['mid'] : ''; $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']) : ''; if (observer_prohibited(true)) { return login(); } $category = x($_REQUEST, 'cat') ? $_REQUEST['cat'] : ''; $hashtags = x($_REQUEST, 'tag') ? $_REQUEST['tag'] : ''; $groups = array(); $o = ''; if ($update) { // Ensure we've got a profile owner if updating. \App::$profile['profile_uid'] = \App::$profile_uid = $update; } else { if (\App::$profile['profile_uid'] == local_channel()) { nav_set_selected('home'); } } $is_owner = local_channel() && \App::$profile['profile_uid'] == local_channel() ? true : false; $channel = \App::get_channel(); $observer = \App::get_observer(); $ob_hash = $observer ? $observer['xchan_hash'] : ''; $perms = get_all_perms(\App::$profile['profile_uid'], $ob_hash); if (!$perms['view_stream']) { // We may want to make the target of this redirect configurable if ($perms['view_profile']) { notice(t('Insufficient permissions. Request redirected to profile page.') . EOL); goaway(z_root() . "/profile/" . \App::$profile['channel_address']); } notice(t('Permission denied.') . EOL); return; } if (!$update) { $o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); $o .= common_friends_visitor_widget(\App::$profile['profile_uid']); if ($channel && $is_owner) { $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']); } else { $channel_acl = array(); } if ($perms['post_wall']) { $x = array('is_owner' => $is_owner, 'allow_location' => ($is_owner || $observer) && intval(get_pconfig(\App::$profile['profile_uid'], 'system', 'use_browser_location')) ? true : false, 'default_location' => $is_owner ? \App::$profile['channel_location'] : '', 'nickname' => \App::$profile['channel_address'], 'lockstate' => strlen(\App::$profile['channel_allow_cid']) || strlen(\App::$profile['channel_allow_gid']) || strlen(\App::$profile['channel_deny_cid']) || strlen(\App::$profile['channel_deny_gid']) ? 'lock' : 'unlock', 'acl' => $is_owner ? populate_acl($channel_acl, true, \PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : '', 'showacl' => $is_owner ? 'yes' : '', 'bang' => '', 'visitor' => $is_owner || $observer ? true : false, 'profile_uid' => \App::$profile['profile_uid'], 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true); $o .= status_editor($a, $x); } } /** * Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups */ $item_normal = item_normal(); $sql_extra = item_permissions_sql(\App::$profile['profile_uid']); if (get_pconfig(\App::$profile['profile_uid'], 'system', 'channel_list_mode') && !$mid) { $page_mode = 'list'; } else { $page_mode = 'client'; } $abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " "; $simple_update = $update ? " AND item_unseen = 1 " : ''; \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n"; 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 ($update && !$load) { if ($mid) { $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d {$item_normal}\n\t\t\t\t\tAND item_wall = 1 AND item_unseen = 1 {$sql_extra} limit 1", dbesc($mid . '%'), intval(\App::$profile['profile_uid'])); } else { $r = q("SELECT distinct parent AS `item_id`, created 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 uid = %d {$item_normal}\n\t\t\t\t\tAND item_wall = 1 {$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_extra}\n\t\t\t\t\tORDER BY created DESC", intval(\App::$profile['profile_uid'])); $_SESSION['loadtime'] = datetime_convert(); } } else { 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 ($datequery) { $sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery)))); } if ($datequery2) { $sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2)))); } $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 ($load || $checkjs->disabled()) { if ($mid) { $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d {$item_normal}\n\t\t\t\t\t\tAND item_wall = 1 {$sql_extra} limit 1", dbesc($mid), intval(\App::$profile['profile_uid'])); if (!$r) { notice(t('Permission denied.') . EOL); } } else { $r = q("SELECT distinct id AS item_id, created FROM item \n\t\t\t\t\t\tleft join abook on item.author_xchan = abook.abook_xchan\n\t\t\t\t\t\tWHERE uid = %d {$item_normal}\n\t\t\t\t\t\tAND item_wall = 1 and item_thread_top = 1\n\t\t\t\t\t\tAND (abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t\t\t{$sql_extra} {$sql_extra2}\n\t\t\t\t\t\tORDER BY created DESC {$pager_sql} ", intval(\App::$profile['profile_uid'])); } } else { $r = array(); } } if ($r) { $parents_str = ids_to_querystr($r, 'item_id'); $items = q("SELECT `item`.*, `item`.`id` AS `item_id` \n\t\t\t\tFROM `item`\n\t\t\t\tWHERE `item`.`uid` = %d {$item_normal}\n\t\t\t\tAND `item`.`parent` IN ( %s )\n\t\t\t\t{$sql_extra} ", intval(\App::$profile['profile_uid']), dbesc($parents_str)); xchan_query($items); $items = fetch_post_tags($items, true); $items = conv_sort($items, 'created'); if ($load && $mid && !count($items)) { // This will happen if we don't have sufficient permissions // to view the parent item (or the item itself if it is toplevel) notice(t('Permission denied.') . EOL); } } else { $items = array(); } if (!$update && !$load) { // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. $maxheight = get_pconfig(\App::$profile['profile_uid'], 'system', 'channel_divmore_height'); if (!$maxheight) { $maxheight = 400; } $o .= '<div id="live-channel"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . \App::$profile['profile_uid'] . "; var netargs = '?f='; 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' => 'channel', '$uid' => \App::$profile['profile_uid'] ? \App::$profile['profile_uid'] : '0', '$gid' => '0', '$cid' => '0', '$cmin' => '0', '$cmax' => '0', '$star' => '0', '$liked' => '0', '$conv' => '0', '$spam' => '0', '$nouveau' => '0', '$wall' => '1', '$fh' => '0', '$page' => \App::$pager['page'] != 1 ? \App::$pager['page'] : 1, '$search' => '', '$order' => '', '$list' => x($_REQUEST, 'list') ? intval($_REQUEST['list']) : 0, '$file' => '', '$cats' => $category ? $category : '', '$tags' => $hashtags ? $hashtags : '', '$mid' => $mid, '$verb' => '', '$dend' => $datequery, '$dbegin' => $datequery2)); } $update_unseen = ''; 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 ($is_owner && $update_unseen) { $r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d {$update_unseen}", intval(local_channel())); } if ($checkjs->disabled()) { $o .= conversation($a, $items, 'channel', $update, 'traditional'); } else { $o .= conversation($a, $items, 'channel', $update, $page_mode); } if (!$update || $checkjs->disabled()) { $o .= alt_pager($a, count($items)); if ($mid && $items[0]['title']) { \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; } } if ($mid) { $o .= '<div id="content-complete"></div>'; } return $o; }