Example #1
0
function store_doc_file($s)
{
    if (is_dir($s)) {
        return;
    }
    $item = array();
    $sys = get_sys_channel();
    $item['aid'] = 0;
    $item['uid'] = $sys['channel_id'];
    if (strpos($s, '.md')) {
        $mimetype = 'text/markdown';
    } elseif (strpos($s, '.html')) {
        $mimetype = 'text/html';
    } else {
        $mimetype = 'text/bbcode';
    }
    require_once 'include/html2plain.php';
    $item['body'] = html2plain(prepare_text(file_get_contents($s), $mimetype, true));
    $item['mimetype'] = 'text/plain';
    $item['plink'] = z_root() . '/' . str_replace('doc', 'help', $s);
    $item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
    $item['item_type'] = ITEM_TYPE_DOC;
    $r = q("select item.* from item left join item_id on item.id = item_id.iid where service = 'docfile' and\n\t\tsid = '%s' and item_type = %d limit 1", dbesc($s), intval(ITEM_TYPE_DOC));
    if ($r) {
        $item['id'] = $r[0]['id'];
        $item['mid'] = $item['parent_mid'] = $r[0]['mid'];
        $x = item_store_update($item);
    } else {
        $item['mid'] = $item['parent_mid'] = item_message_id();
        $x = item_store($item);
    }
    if ($x['success']) {
        update_remote_id($sys, $x['item_id'], ITEM_TYPE_DOC, $s, 'docfile', 0, $item['mid']);
    }
}
Example #2
0
 function init()
 {
     $result = array('success' => false);
     $mindate = $_REQUEST['mindate'] ? datetime_convert('UTC', 'UTC', $_REQUEST['mindate']) : '';
     if (!$mindate) {
         $mindate = datetime_convert('UTC', 'UTC', 'now - 14 days');
     }
     if (observer_prohibited()) {
         $result['message'] = 'Public access denied';
         json_return_and_die($result);
     }
     $observer = \App::get_observer();
     $channel_address = argc() > 1 ? argv(1) : '';
     if ($channel_address) {
         $r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1", dbesc(argv(1)));
     } else {
         $x = get_sys_channel();
         if ($x) {
             $r = array($x);
         }
         $mindate = datetime_convert('UTC', 'UTC', 'now - 14 days');
     }
     if (!$r) {
         $result['message'] = 'Channel not found.';
         json_return_and_die($result);
     }
     logger('zotfeed request: ' . $r[0]['channel_name'], LOGGER_DEBUG);
     $result['messages'] = zot_feed($r[0]['channel_id'], $observer['xchan_hash'], array('mindate' => $mindate));
     $result['success'] = true;
     json_return_and_die($result);
 }
Example #3
0
function zotfeed_init(&$a)
{
    $result = array('success' => false);
    $mindate = $_REQUEST['mindate'] ? datetime_convert('UTC', 'UTC', $_REQUEST['mindate']) : '';
    if (!$mindate) {
        $mindate = datetime_convert('UTC', 'UTC', 'now - 1 month');
    }
    if (get_config('system', 'block_public') && !get_account_id() && !remote_user()) {
        $result['message'] = 'Public access denied';
        json_return_and_die($result);
    }
    $observer = $a->get_observer();
    $channel_address = argc() > 1 ? argv(1) : '';
    if ($channel_address) {
        $r = q("select channel_id, channel_name from channel where channel_address = '%s' and not (channel_pageflags & %d) limit 1", dbesc(argv(1)), intval(PAGE_REMOVED));
    } else {
        $x = get_sys_channel();
        if ($x) {
            $r = array($x);
        }
    }
    if (!$r) {
        $result['message'] = 'Channel not found.';
        json_return_and_die($result);
    }
    logger('zotfeed request: ' . $r[0]['channel_name'], LOGGER_DEBUG);
    $result['messages'] = zot_feed($r[0]['channel_id'], $observer['xchan_hash'], $mindate);
    $result['success'] = true;
    json_return_and_die($result);
}
Example #4
0
 function __construct($req)
 {
     $this->ret = array('success' => false);
     $this->success = false;
     $this->test = array_key_exists('test', $req) ? intval($req['test']) : 0;
     $this->address = $req['auth'];
     $this->desturl = $req['dest'];
     $this->sec = $req['sec'];
     $this->version = $req['version'];
     $this->delegate = $req['delegate'];
     $c = get_sys_channel();
     if (!$c) {
         logger('unable to obtain response (sys) channel');
         reply_die('no local channels found.');
     }
     $x = $this->GetHublocs($this->address);
     if ($x) {
         foreach ($x as $xx) {
             if ($this->Verify($c, $xx)) {
                 break;
             }
         }
     }
     /**
      * @FIXME we really want to save the return_url in the session before we
      * visit rmagic. This does however prevent a recursion if you visit
      * rmagic directly, as it would otherwise send you back here again.
      * But z_root() probably isn't where you really want to go.
      */
     if (strstr($this->desturl, z_root() . '/rmagic')) {
         goaway(z_root());
     }
     $this->reply_die();
 }
Example #5
0
function diaspora_dispatch_public($msg)
{
    $sys_disabled = true;
    if (!get_config('system', 'disable_discover_tab')) {
        $sys_disabled = get_config('system', 'disable_diaspora_discover_tab');
    }
    $sys = $sys_disabled ? null : get_sys_channel();
    // find everybody following or allowing this author
    $r = q("SELECT * from channel where channel_id in ( SELECT abook_channel from abook left join xchan on abook_xchan = xchan_hash WHERE xchan_network like '%%diaspora%%' and xchan_addr = '%s' ) and channel_removed = 0 ", dbesc($msg['author']));
    // look for those following tags - we'll check tag validity for each specific channel later
    $y = q("select * from channel where channel_id in ( SELECT uid from pconfig where cat = 'diaspora' and k = 'followed_tags' and v != '') and channel_removed = 0 ");
    if (is_array($y) && is_array($r)) {
        $r = array_merge($r, $y);
    }
    // @FIXME we should also enumerate channels that allow postings by anybody
    if ($r) {
        foreach ($r as $rr) {
            logger('diaspora_public: delivering to: ' . $rr['channel_name'] . ' (' . $rr['channel_address'] . ') ');
            diaspora_dispatch($rr, $msg);
        }
    } else {
        if (!$sys) {
            logger('diaspora_public: no subscribers');
        }
    }
    if ($sys) {
        $sys['system'] = true;
        logger('diaspora_public: delivering to sys.');
        diaspora_dispatch($sys, $msg);
    }
}
Example #6
0
function viewsrc_content(&$a)
{
    $o = '';
    $sys = get_sys_channel();
    $item_id = argc() > 1 ? intval(argv(1)) : 0;
    $json = argc() > 2 && argv(2) === 'json' ? true : false;
    if (!local_channel()) {
        notice(t('Permission denied.') . EOL);
    }
    if (!$item_id) {
        App::$error = 404;
        notice(t('Item not found.') . EOL);
    }
    $item_normal = item_normal();
    if (local_channel() && $item_id) {
        $r = q("select id, item_flags, item_obscured, body from item where uid in (%d , %d) and id = %d {$item_normal} limit 1", intval(local_channel()), intval($sys['channel_id']), intval($item_id));
        if ($r) {
            if (intval($r[0]['item_obscured'])) {
                $r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'], true), get_config('system', 'prvkey'));
            }
            $o = $json ? json_encode($r[0]['body']) : str_replace("\n", '<br />', $r[0]['body']);
        }
    }
    if (is_ajax()) {
        print '<div><i class="icon-pencil"> ' . t('Source of Item') . ' ' . $r[0]['id'] . '</i></div>';
        echo $o;
        killme();
    }
    return $o;
}
Example #7
0
function viewsrc_content(&$a)
{
    $o = '';
    $sys = get_sys_channel();
    $item_id = argc() > 1 ? intval(argv(1)) : 0;
    $json = argc() > 2 && argv(2) === 'json' ? true : false;
    if (!local_channel()) {
        notice(t('Permission denied.') . EOL);
    }
    if (!$item_id) {
        $a->error = 404;
        notice(t('Item not found.') . EOL);
    }
    if (local_channel() && $item_id) {
        $r = q("select item_flags, body from item where item_restrict = 0 and uid in (%d , %d) and id = %d limit 1", intval(local_channel()), intval($sys['channel_id']), intval($item_id));
        if ($r) {
            if ($r[0]['item_flags'] & ITEM_OBSCURED) {
                $r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'], true), get_config('system', 'prvkey'));
            }
            $o = $json ? json_encode($r[0]['body']) : str_replace("\n", '<br />', $r[0]['body']);
        }
    }
    if (is_ajax()) {
        echo $o;
        killme();
    }
    return $o;
}
 function get()
 {
     if (!\App::$profile) {
         notice(t('Requested profile is not available.') . EOL);
         \App::$error = 404;
         return;
     }
     $which = argv(1);
     $uid = local_channel();
     $owner = 0;
     $channel = null;
     $observer = \App::get_observer();
     $channel = \App::get_channel();
     if (\App::$is_sys && is_site_admin()) {
         $sys = get_sys_channel();
         if ($sys && intval($sys['channel_id'])) {
             $uid = $owner = intval($sys['channel_id']);
             $channel = $sys;
             $observer = $sys;
         }
     }
     if (!$owner) {
         // Figure out who the page owner is.
         $r = q("select channel_id from channel where channel_address = '%s'", dbesc($which));
         if ($r) {
             $owner = intval($r[0]['channel_id']);
         }
     }
     $ob_hash = $observer ? $observer['xchan_hash'] : '';
     if (!perm_is_allowed($owner, $ob_hash, 'write_pages')) {
         notice(t('Permission denied.') . EOL);
         return;
     }
     $is_owner = $uid && $uid == $owner ? true : false;
     $o = '';
     // Figure out which post we're editing
     $post_id = argc() > 2 ? intval(argv(2)) : 0;
     if (!$post_id) {
         notice(t('Item not found') . EOL);
         return;
     }
     // Now we've got a post and an owner, let's find out if we're allowed to edit it
     $ob_hash = $observer ? $observer['xchan_hash'] : '';
     $perms = get_all_perms($owner, $ob_hash);
     if (!$perms['write_pages']) {
         notice(t('Permission denied.') . EOL);
         return;
     }
     $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", intval($post_id), intval($owner));
     $item_id = q("select * from item_id where service = 'PDL' and iid = %d limit 1", intval($itm[0]['id']));
     if ($item_id) {
         $layout_title = $item_id[0]['sid'];
     }
     $rp = 'layouts/' . $which;
     $x = array('webpage' => ITEM_TYPE_PDL, 'nickname' => $channel['channel_address'], 'editor_autocomplete' => true, 'bbco_autocomplete' => 'comanche', 'return_path' => $rp, 'button' => t('Edit'), 'hide_voting' => true, 'hide_future' => true, 'hide_expire' => true, 'hide_location' => true, 'hide_weblink' => true, 'hide_attach' => true, 'hide_preview' => true, 'ptyp' => $itm[0]['obj_type'], 'body' => undo_post_tagging($itm[0]['body']), 'post_id' => $post_id, 'title' => htmlspecialchars($itm[0]['title'], ENT_COMPAT, 'UTF-8'), 'pagetitle' => $layout_title, 'ptlabel' => t('Layout Name'), 'placeholdertitle' => t('Layout Description (Optional)'), 'showacl' => false, 'profile_uid' => intval($owner));
     $editor = status_editor($a, $x);
     $o .= replace_macros(get_markup_template('edpost_head.tpl'), array('$title' => t('Edit Layout'), '$delete' => $itm[0]['author_xchan'] === $ob_hash || $itm[0]['owner_xchan'] === $ob_hash ? t('Delete') : false, '$id' => $itm[0]['id'], '$editor' => $editor));
     return $o;
 }
Example #9
0
 function get()
 {
     if (!\App::$profile) {
         notice(t('Requested profile is not available.') . EOL);
         \App::$error = 404;
         return;
     }
     $which = argv(1);
     $uid = local_channel();
     $owner = 0;
     $channel = null;
     $observer = \App::get_observer();
     $channel = \App::get_channel();
     if (\App::$is_sys && is_site_admin()) {
         $sys = get_sys_channel();
         if ($sys && intval($sys['channel_id'])) {
             $uid = $owner = intval($sys['channel_id']);
             $channel = $sys;
             $observer = $sys;
         }
     }
     if (!$owner) {
         // Figure out who the page owner is.
         $r = q("select channel_id from channel where channel_address = '%s'", dbesc($which));
         if ($r) {
             $owner = intval($r[0]['channel_id']);
         }
     }
     $ob_hash = $observer ? $observer['xchan_hash'] : '';
     if (!perm_is_allowed($owner, $ob_hash, 'write_pages')) {
         notice(t('Permission denied.') . EOL);
         return;
     }
     $is_owner = $uid && $uid == $owner ? true : false;
     $o = '';
     // Figure out which post we're editing
     $post_id = argc() > 2 ? intval(argv(2)) : 0;
     if (!($post_id && $owner)) {
         notice(t('Item not found') . EOL);
         return;
     }
     $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s LIMIT 1", intval($post_id), intval($owner));
     if ($itm) {
         $item_id = q("select * from item_id where service = 'BUILDBLOCK' and iid = %d limit 1", intval($itm[0]['id']));
         if ($item_id) {
             $block_title = $item_id[0]['sid'];
         }
     } else {
         notice(t('Item not found') . EOL);
         return;
     }
     $mimetype = $itm[0]['mimetype'];
     $rp = 'blocks/' . $channel['channel_address'];
     $x = array('nickname' => $channel['channel_address'], 'bbco_autocomplete' => $mimetype == 'text/bbcode' ? 'bbcode' : 'comanche-block', 'return_path' => $rp, 'webpage' => ITEM_TYPE_BLOCK, 'ptlabel' => t('Block Name'), 'button' => t('Edit'), 'writefiles' => $mimetype == 'text/bbcode' ? perm_is_allowed($owner, get_observer_hash(), 'write_storage') : false, 'weblink' => $mimetype == 'text/bbcode' ? t('Insert web link') : false, 'hide_voting' => true, 'hide_future' => true, 'hide_location' => true, 'hide_expire' => true, 'showacl' => false, 'ptyp' => $itm[0]['type'], 'mimeselect' => true, 'mimetype' => $itm[0]['mimetype'], 'body' => undo_post_tagging($itm[0]['body']), 'post_id' => $post_id, 'visitor' => true, 'title' => htmlspecialchars($itm[0]['title'], ENT_COMPAT, 'UTF-8'), 'placeholdertitle' => t('Title (optional)'), 'pagetitle' => $block_title, 'profile_uid' => intval($channel['channel_id']), 'bbcode' => $mimetype == 'text/bbcode' ? true : false);
     $editor = status_editor($a, $x);
     $o .= replace_macros(get_markup_template('edpost_head.tpl'), array('$title' => t('Edit Block'), '$delete' => $itm[0]['author_xchan'] === $ob_hash || $itm[0]['owner_xchan'] === $ob_hash ? t('Delete') : false, '$id' => $itm[0]['id'], '$editor' => $editor));
     return $o;
 }
Example #10
0
function mitem_content(&$a)
{
    $uid = local_channel();
    $channel = $a->get_channel();
    $observer = $a->get_observer();
    $ob_hash = $observer ? $observer['xchan_hash'] : '';
    if ($a->is_sys && is_site_admin()) {
        $sys = get_sys_channel();
        $uid = intval($sys['channel_id']);
        $channel = $sys;
        $ob_hash = $sys['xchan_hash'];
    }
    if (!$uid) {
        notice(t('Permission denied.') . EOL);
        return '';
    }
    if (argc() < 2 || !$a->data['menu']) {
        notice(t('Not found.') . EOL);
        return '';
    }
    $m = menu_fetch($a->data['menu']['menu_name'], $uid, $ob_hash);
    $a->data['menu_item'] = $m;
    if (argc() == 2) {
        $r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc", intval($a->data['menu']['menu_id']), intval($uid));
        $o .= replace_macros(get_markup_template('mitemlist.tpl'), array('$title' => t('Manage Menu Elements'), '$menuname' => $a->data['menu']['menu_name'], '$menudesc' => $a->data['menu']['menu_desc'], '$edmenu' => t('Edit menu'), '$menu_id' => $a->data['menu']['menu_id'], '$mlist' => $r, '$edit' => t('Edit element'), '$drop' => t('Drop element'), '$new' => t('New element'), '$hintmenu' => t('Edit this menu container'), '$hintnew' => t('Add menu element'), '$hintdrop' => t('Delete this menu item'), '$hintedit' => t('Edit this menu item')));
        return $o;
    }
    if (argc() > 2) {
        if (argv(2) === 'new') {
            $perm_defaults = 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']);
            $o = replace_macros(get_markup_template('mitemedit.tpl'), array('$header' => t('New Menu Element'), '$menu_id' => $a->data['menu']['menu_id'], '$permissions' => t('Menu Item Permissions'), '$permdesc' => t("(click to open/close)"), '$aclselect' => populate_acl($perm_defaults, false), '$mitem_desc' => array('mitem_desc', t('Link text'), '', '', '*'), '$mitem_link' => array('mitem_link', t('URL of link'), '', '', '*'), '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), true, ''), '$newwin' => array('newwin', t('Open link in new window'), false, ''), '$mitem_order' => array('mitem_order', t('Order in list'), '0', t('Higher numbers will sink to bottom of listing')), '$submit' => t('Create')));
            return $o;
        } elseif (intval(argv(2))) {
            $m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1", intval(argv(2)), intval($uid));
            if (!$m) {
                notice(t('Menu item not found.') . EOL);
                goaway(z_root() . '/menu' . ($a->is_sys ? '?f=&sys=1' : ''));
            }
            $mitem = $m[0];
            if (argc() == 4 && argv(3) == 'drop') {
                $r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2)));
                if ($r) {
                    info(t('Menu item deleted.') . EOL);
                } else {
                    notice(t('Menu item could not be deleted.') . EOL);
                }
                goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . ($a->is_sys ? '?f=&sys=1' : ''));
            } else {
                // edit menu item
                $o = replace_macros(get_markup_template('mitemedit.tpl'), array('$header' => t('Edit Menu Element'), '$menu_id' => $a->data['menu']['menu_id'], '$permissions' => t('Menu Item Permissions'), '$permdesc' => t("(click to open/close)"), '$aclselect' => populate_acl($mitem, false), '$mitem_id' => intval(argv(2)), '$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '', '*'), '$mitem_link' => array('mitem_link', t('URL of link'), $mitem['mitem_link'], '', '*'), '$usezid' => array('usezid', t('Use RedMatrix magic-auth if available'), $mitem['mitem_flags'] & MENU_ITEM_ZID ? 1 : 0, ''), '$newwin' => array('newwin', t('Open link in new window'), $mitem['mitem_flags'] & MENU_ITEM_NEWWIN ? 1 : 0, ''), '$mitem_order' => array('mitem_order', t('Order in list'), $mitem['mitem_order'], t('Higher numbers will sink to bottom of listing')), '$submit' => t('Modify')));
                return $o;
            }
        }
    }
}
Example #11
0
 function get()
 {
     $uid = local_channel();
     if (\App::$is_sys && is_site_admin()) {
         $sys = get_sys_channel();
         $uid = intval($sys['channel_id']);
     }
     if (!$uid) {
         notice(t('Permission denied.') . EOL);
         return '';
     }
     if (argc() == 1) {
         $channel = $sys ? $sys : \App::get_channel();
         // list menus
         $x = menu_list($uid);
         if ($x) {
             for ($y = 0; $y < count($x); $y++) {
                 $m = menu_fetch($x[$y]['menu_name'], $uid, get_observer_hash());
                 if ($m) {
                     $x[$y]['element'] = '[element]' . base64url_encode(json_encode(menu_element($channel, $m))) . '[/element]';
                 }
                 $x[$y]['bookmark'] = $x[$y]['menu_flags'] & MENU_BOOKMARK ? true : false;
             }
         }
         $create = replace_macros(get_markup_template('menuedit.tpl'), array('$menu_name' => array('menu_name', t('Menu Name'), '', t('Unique name (not visible on webpage) - required'), '*'), '$menu_desc' => array('menu_desc', t('Menu Title'), '', t('Visible on webpage - leave empty for no title'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow Bookmarks'), 0, t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), '$submit' => t('Submit and proceed'), '$sys' => \App::$is_sys, '$display' => 'none'));
         $o = replace_macros(get_markup_template('menulist.tpl'), array('$title' => t('Menus'), '$create' => $create, '$menus' => $x, '$nametitle' => t('Menu Name'), '$desctitle' => t('Menu Title'), '$edit' => t('Edit'), '$drop' => t('Drop'), '$created' => t('Created'), '$edited' => t('Edited'), '$new' => t('New'), '$bmark' => t('Bookmarks allowed'), '$hintnew' => t('Create'), '$hintdrop' => t('Delete this menu'), '$hintcontent' => t('Edit menu contents'), '$hintedit' => t('Edit this menu'), '$sys' => \App::$is_sys));
         return $o;
     }
     if (argc() > 1) {
         if (intval(argv(1))) {
             if (argc() == 3 && argv(2) == 'drop') {
                 menu_sync_packet($uid, get_observer_hash(), intval(argv(1)), true);
                 $r = menu_delete_id(intval(argv(1)), $uid);
                 if (!$r) {
                     notice(t('Menu could not be deleted.') . EOL);
                 }
                 goaway(z_root() . '/menu' . (\App::$is_sys ? '?f=&sys=1' : ''));
             }
             $m = menu_fetch_id(intval(argv(1)), $uid);
             if (!$m) {
                 notice(t('Menu not found.') . EOL);
                 return '';
             }
             $o = replace_macros(get_markup_template('menuedit.tpl'), array('$header' => t('Edit Menu'), '$sys' => \App::$is_sys, '$menu_id' => intval(argv(1)), '$menu_edit_link' => 'mitem/' . intval(argv(1)) . (\App::$is_sys ? '?f=&sys=1' : ''), '$hintedit' => t('Add or remove entries to this menu'), '$editcontents' => t('Edit menu contents'), '$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'), '$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), $m['menu_flags'] & MENU_BOOKMARK ? 1 : 0, t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), '$menu_system' => $m['menu_flags'] & MENU_SYSTEM ? 1 : 0, '$submit' => t('Submit and proceed')));
             return $o;
         } else {
             notice(t('Not found.') . EOL);
             return;
         }
     }
 }
Example #12
0
function diaspora_get_contact_by_handle($uid, $handle)
{
    if (diaspora_is_blacklisted($handle)) {
        return false;
    }
    require_once 'include/channel.php';
    $sys = get_sys_channel();
    if ($sys && $sys['channel_id'] == $uid) {
        $r = q("SELECT * FROM xchan where xchan_addr = '%s' limit 1", dbesc($handle));
    } else {
        $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where xchan_addr = '%s' and abook_channel = %d limit 1", dbesc($handle), intval($uid));
    }
    return $r ? $r[0] : false;
}
Example #13
0
function menu_content(&$a)
{
    $uid = local_channel();
    if ($a->is_sys && is_site_admin()) {
        $sys = get_sys_channel();
        $uid = intval($sys['channel_id']);
    }
    if (!$uid) {
        notice(t('Permission denied.') . EOL);
        return '';
    }
    if (argc() == 1) {
        // list menus
        $x = menu_list($uid);
        if ($x) {
            for ($y = 0; $y < count($x); $y++) {
                $x[$y]['bookmark'] = $x[$y]['menu_flags'] & MENU_BOOKMARK ? true : false;
            }
        }
        $o = replace_macros(get_markup_template('menulist.tpl'), array('$title' => t('Manage Menus'), '$menus' => $x, '$edit' => t('Edit'), '$drop' => t('Drop'), '$new' => t('New'), '$bmark' => t('Bookmarks allowed'), '$hintnew' => t('Create a new menu'), '$hintdrop' => t('Delete this menu'), '$hintcontent' => t('Edit menu contents'), '$hintedit' => t('Edit this menu')));
        return $o;
    }
    if (argc() > 1) {
        if (argv(1) === 'new') {
            $o = replace_macros(get_markup_template('menuedit.tpl'), array('$header' => t('New Menu'), '$menu_name' => array('menu_name', t('Menu name'), '', t('Must be unique, only seen by you'), '*'), '$menu_desc' => array('menu_desc', t('Menu title'), '', t('Menu title as seen by others'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), 0, t('Menu may be used to store saved bookmarks'), ''), '$submit' => t('Create')));
            return $o;
        } elseif (intval(argv(1))) {
            $m = menu_fetch_id(intval(argv(1)), $uid);
            if (!$m) {
                notice(t('Menu not found.') . EOL);
                return '';
            }
            if (argc() == 3 && argv(2) == 'drop') {
                $r = menu_delete_id(intval(argv(1)), $uid);
                if ($r) {
                    info(t('Menu deleted.') . EOL);
                } else {
                    notice(t('Menu could not be deleted.') . EOL);
                }
                goaway(z_root() . '/menu' . ($a->is_sys ? '?f=&sys=1' : ''));
            } else {
                $o = replace_macros(get_markup_template('menuedit.tpl'), array('$header' => t('Edit Menu'), '$menu_id' => intval(argv(1)), '$hintedit' => t('Add or remove entries to this menu'), '$editcontents' => t('Edit menu contents'), '$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'), '$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), $m['menu_flags'] & MENU_BOOKMARK ? 1 : 0, t('Menu may be used to store saved bookmarks'), ''), '$menu_system' => $m['menu_flags'] & MENU_SYSTEM ? 1 : 0, '$submit' => t('Modify')));
                return $o;
            }
        } else {
            notice(t('Not found.') . EOL);
            return;
        }
    }
}
Example #14
0
function pubsub_post(&$a)
{
    $sys_disabled = true;
    if (!get_config('system', 'disable_discover_tab')) {
        $sys_disabled = get_config('system', 'disable_diaspora_discover_tab');
    }
    $sys = $sys_disabled ? null : get_sys_channel();
    if ($sys) {
        $sys['system'] = true;
    }
    $xml = file_get_contents('php://input');
    logger('pubsub: feed arrived from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . App::$cmd);
    logger('pubsub: user-agent: ' . $_SERVER['HTTP_USER_AGENT']);
    logger('pubsub: data: ' . $xml, LOGGER_DATA);
    $nick = argc() > 1 ? escape_tags(trim(argv(1))) : '';
    $contact_id = argc() > 2 ? intval(argv(2)) : 0;
    $channel = channelx_by_nick($nick);
    if (!$channel) {
        http_status_exit(200, 'OK');
    }
    $importer_arr = array($channel);
    if ($sys) {
        $importer_arr[] = $sys;
    }
    foreach ($importer_arr as $channel) {
        if (!$channel['system']) {
            $connections = abook_connections($channel['channel_id'], ' and abook_id = ' . $contact_id);
        } else {
            $connections = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d", intval($contact_id));
        }
        if ($connections) {
            $xchan = $connections[0];
        } else {
            logger('connection ' . $contact_id . ' not found.');
            continue;
        }
        if (!perm_is_allowed($channel['channel_id'], $xchan['xchan_hash'], 'send_stream') && !$channel['system']) {
            logger('permission denied.');
            continue;
        }
        consume_feed($xml, $channel, $xchan, 1);
        consume_feed($xml, $channel, $xchan, 2);
    }
    http_status_exit(200, 'OK');
}
Example #15
0
File: expire.php Project: Mauru/red
function expire_run($argv, $argc)
{
    cli_startup();
    $r = q("select id from item where (item_restrict & %d) and not (item_restrict & %d) and changed < UTC_TIMESTAMP() - INTERVAL 10 DAY", intval(ITEM_DELETED), intval(ITEM_PENDING_REMOVE));
    if ($r) {
        foreach ($r as $rr) {
            drop_item($rr['id'], false, DROPITEM_PHASE2);
        }
    }
    // physically remove anything that has been deleted for more than two months
    $r = q("delete from item where ( item_restrict & %d ) and changed < UTC_TIMESTAMP() - INTERVAL 36 DAY", intval(ITEM_PENDING_REMOVE));
    // make this optional as it could have a performance impact on large sites
    if (intval(get_config('system', 'optimize_items'))) {
        q("optimize table item");
    }
    logger('expire: start', LOGGER_DEBUG);
    $r = q("SELECT channel_id, channel_address, channel_expire_days from channel where channel_expire_days != 0");
    if ($r && count($r)) {
        foreach ($r as $rr) {
            logger('Expire: ' . $rr['channel_address'] . ' interval: ' . $rr['channel_expire_days'], LOGGER_DEBUG);
            item_expire($rr['channel_id'], $rr['channel_expire_days']);
        }
    }
    $x = get_sys_channel();
    if ($x) {
        // this should probably just fetch the channel_expire_days from the sys channel,
        // but there's no convenient way to set it.
        $expire_days = get_config('externals', 'expire_days');
        if ($expire_days === false) {
            $expire_days = 30;
        }
        if ($expire_days) {
            item_expire($x['channel_id'], $expire_days);
        }
    }
    return;
}
Example #16
0
 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 );
     		}
     
     	}
     */
 }
Example #17
0
/**
 * @brief "Render" a conversation or list of items for HTML display.
 *
 * There are two major forms of display:
 *  - Sequential or unthreaded ("New Item View" or search results)
 *  - conversation view
 *
 * The $mode parameter decides between the various renderings and also
 * figures out how to determine page owner and other contextual items
 * that are based on unique features of the calling module.
 *
 * @param App &$a
 * @param array $items
 * @param string $mode
 * @param boolean $update
 * @param string $page_mode default traditional
 * @param string $prepared_item
 * @return string
 */
function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional', $prepared_item = '')
{
    $content_html = '';
    $o = '';
    require_once 'bbcode.php';
    $ssl_state = local_channel() ? true : false;
    if (local_channel()) {
        load_pconfig(local_channel(), '');
    }
    $arr_blocked = null;
    if (local_channel()) {
        $str_blocked = get_pconfig(local_channel(), 'system', 'blocked');
    }
    if (!local_channel() && $mode == 'network') {
        $sys = get_sys_channel();
        $id = $sys['channel_id'];
        $str_blocked = get_pconfig($id, 'system', 'blocked');
    }
    if ($str_blocked) {
        $arr_blocked = explode(',', $str_blocked);
        for ($x = 0; $x < count($arr_blocked); $x++) {
            $arr_blocked[$x] = trim($arr_blocked[$x]);
        }
    }
    $profile_owner = 0;
    $page_writeable = false;
    $live_update_div = '';
    $preview = $page_mode === 'preview' ? true : false;
    $previewing = $preview ? ' preview ' : '';
    if ($mode === 'network') {
        $profile_owner = local_channel();
        $page_writeable = true;
        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).
            $live_update_div = '<div id="live-network"></div>' . "\r\n" . "<script> var profile_uid = " . $_SESSION['uid'] . "; var netargs = '" . substr($a->cmd, 8) . '?f=' . (x($_GET, 'cid') ? '&cid=' . $_GET['cid'] : '') . (x($_GET, 'search') ? '&search=' . $_GET['search'] : '') . (x($_GET, 'star') ? '&star=' . $_GET['star'] : '') . (x($_GET, 'order') ? '&order=' . $_GET['order'] : '') . (x($_GET, 'bmark') ? '&bmark=' . $_GET['bmark'] : '') . (x($_GET, 'liked') ? '&liked=' . $_GET['liked'] : '') . (x($_GET, 'conv') ? '&conv=' . $_GET['conv'] : '') . (x($_GET, 'spam') ? '&spam=' . $_GET['spam'] : '') . (x($_GET, 'nets') ? '&nets=' . $_GET['nets'] : '') . (x($_GET, 'cmin') ? '&cmin=' . $_GET['cmin'] : '') . (x($_GET, 'cmax') ? '&cmax=' . $_GET['cmax'] : '') . (x($_GET, 'file') ? '&file=' . $_GET['file'] : '') . (x($_GET, 'uri') ? '&uri=' . $_GET['uri'] : '') . "'; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
        }
    } elseif ($mode === 'channel') {
        $profile_owner = $a->profile['profile_uid'];
        $page_writeable = $profile_owner == local_channel();
        if (!$update) {
            $tab = notags(trim($_GET['tab']));
            if ($tab === 'posts') {
                // 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.
                $live_update_div = '<div id="live-channel"></div>' . "\r\n" . "<script> var profile_uid = " . $a->profile['profile_uid'] . "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
            }
        }
    } elseif ($mode === 'display') {
        $profile_owner = local_channel();
        $page_writeable = false;
        $live_update_div = '<div id="live-display"></div>' . "\r\n";
    } elseif ($mode === 'page') {
        $profile_owner = $a->profile['uid'];
        $page_writeable = $profile_owner == local_channel();
        $live_update_div = '<div id="live-page"></div>' . "\r\n";
    } elseif ($mode === 'search') {
        $live_update_div = '<div id="live-search"></div>' . "\r\n";
    } elseif ($mode === 'photos') {
        $profile_onwer = $a->profile['profile_uid'];
        $page_writeable = $profile_owner == local_channel();
        $live_update_div = '<div id="live-photos"></div>' . "\r\n";
        // for photos we've already formatted the top-level item (the photo)
        $content_html = $a->data['photo_html'];
    }
    $page_dropping = local_channel() && local_channel() == $profile_owner ? true : false;
    if (!feature_enabled($profile_owner, 'multi_delete')) {
        $page_dropping = false;
    }
    $channel = $a->get_channel();
    $observer = $a->get_observer();
    if ($update) {
        $return_url = $_SESSION['return_url'];
    } else {
        $return_url = $_SESSION['return_url'] = $a->query_string;
    }
    load_contact_links(local_channel());
    $cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
    call_hooks('conversation_start', $cb);
    $items = $cb['items'];
    $conv_responses = array('like' => array('title' => t('Likes', 'title')), 'dislike' => array('title' => t('Dislikes', 'title')), 'agree' => array('title' => t('Agree', 'title')), 'disagree' => array('title' => t('Disagree', 'title')), 'abstain' => array('title' => t('Abstain', 'title')), 'attendyes' => array('title' => t('Attending', 'title')), 'attendno' => array('title' => t('Not attending', 'title')), 'attendmaybe' => array('title' => t('Might attend', 'title')));
    // array with html for each thread (parent+comments)
    $threads = array();
    $threadsid = -1;
    $page_template = get_markup_template("conversation.tpl");
    if ($items) {
        if ($mode === 'network-new' || $mode === 'search' || $mode === 'community') {
            // "New Item View" on network page or search page results
            // - just loop through the items and format them minimally for display
            //$tpl = get_markup_template('search_item.tpl');
            $tpl = 'search_item.tpl';
            foreach ($items as $item) {
                if ($arr_blocked) {
                    $blocked = false;
                    foreach ($arr_blocked as $b) {
                        if ($b && $item['author_xchan'] == $b) {
                            $blocked = true;
                            break;
                        }
                    }
                    if ($blocked) {
                        continue;
                    }
                }
                $threadsid++;
                $comment = '';
                $owner_url = '';
                $owner_photo = '';
                $owner_name = '';
                $sparkle = '';
                if ($mode === 'search' || $mode === 'community') {
                    if ((activity_match($item['verb'], ACTIVITY_LIKE) || activity_match($item['verb'], ACTIVITY_DISLIKE)) && $item['id'] != $item['parent']) {
                        continue;
                    }
                    $nickname = $item['nickname'];
                } else {
                    $nickname = $a->user['nickname'];
                }
                $profile_name = strlen($item['author-name']) ? $item['author-name'] : $item['name'];
                if ($item['author-link'] && !$item['author-name']) {
                    $profile_name = $item['author-link'];
                }
                $tags = array();
                $hashtags = array();
                $mentions = array();
                $sp = false;
                $profile_link = best_link_url($item, $sp);
                if ($sp) {
                    $sparkle = ' sparkle';
                } else {
                    $profile_link = zid($profile_link);
                }
                $normalised = normalise_link(strlen($item['author-link']) ? $item['author-link'] : $item['url']);
                $profile_name = $item['author']['xchan_name'];
                $profile_link = $item['author']['xchan_url'];
                $profile_avatar = $item['author']['xchan_photo_m'];
                $location = format_location($item);
                localize_item($item);
                if ($mode === 'network-new') {
                    $dropping = true;
                } else {
                    $dropping = false;
                }
                $drop = array('pagedropping' => $page_dropping, 'dropping' => $dropping, 'select' => t('Select'), 'delete' => t('Delete'));
                $star = false;
                $isstarred = "unstarred icon-star-empty";
                $lock = $item['item_private'] || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']) ? t('Private Message') : false;
                $likebuttons = false;
                $shareable = false;
                $verified = $item['item_flags'] & ITEM_VERIFIED ? t('Message signature validated') : '';
                $forged = $item['sig'] && !($item['item_flags'] & ITEM_VERIFIED) ? t('Message signature incorrect') : '';
                $unverified = '';
                $tags = array();
                $terms = get_terms_oftype($item['term'], array(TERM_HASHTAG, TERM_MENTION, TERM_UNKNOWN));
                if (count($terms)) {
                    foreach ($terms as $tag) {
                        $tags[] = format_term_for_display($tag);
                    }
                }
                $body = prepare_body($item, true);
                $tmp_item = array('template' => $tpl, 'toplevel' => 'toplevel_item', 'mode' => $mode, 'id' => $preview ? 'P0' : $item['item_id'], 'linktitle' => sprintf(t('View %s\'s profile @ %s'), $profile_name, $profile_url), 'profile_url' => $profile_link, 'item_photo_menu' => item_photo_menu($item), 'name' => $profile_name, 'sparkle' => $sparkle, 'lock' => $lock, 'thumb' => $profile_avatar, 'title' => $item['title'], 'body' => $body, 'tags' => $tags, 'hashtags' => $hashtags, 'mentions' => $mentions, 'verified' => $verified, 'unverified' => $unverified, 'forged' => $forged, 'txt_cats' => t('Categories:'), 'txt_folders' => t('Filed under:'), 'has_cats' => count($categories) ? 'true' : '', 'has_folders' => count($folders) ? 'true' : '', 'categories' => $categories, 'folders' => $folders, 'text' => strip_tags($body), 'ago' => relative_date($item['created']), 'app' => $item['app'], 'str_app' => sprintf(t(' from %s'), $item['app']), 'isotime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'c'), 'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'), 'editedtime' => $item['edited'] != $item['created'] ? sprintf(t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : '', 'expiretime' => $item['expires'] !== NULL_DATE ? sprintf(t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')) : '', 'location' => $location, 'indent' => '', 'owner_name' => $owner_name, 'owner_url' => $owner_url, 'owner_photo' => $owner_photo, 'plink' => get_plink($item, false), 'edpost' => false, 'isstarred' => $isstarred, 'star' => $star, 'drop' => $drop, 'vote' => $likebuttons, 'like' => '', 'dislike' => '', 'comment' => '', 'conv' => $preview ? '' : array('href' => z_root() . '/display/' . $item['mid'], 'title' => t('View in context')), 'previewing' => $previewing, 'wait' => t('Please wait'), 'thread_level' => 1);
                $arr = array('item' => $item, 'output' => $tmp_item);
                call_hooks('display_item', $arr);
                //				$threads[$threadsid]['id'] = $item['item_id'];
                $threads[] = $arr['output'];
            }
        } else {
            // Normal View
            //			logger('conv: items: ' . print_r($items,true));
            require_once 'include/ConversationObject.php';
            require_once 'include/ItemObject.php';
            $conv = new Conversation($mode, $preview, $prepared_item);
            // In the display mode we don't have a profile owner.
            if ($mode === 'display' && $items) {
                $conv->set_profile_owner($items[0]['uid']);
            }
            // get all the topmost parents
            // this shouldn't be needed, as we should have only them in our array
            // But for now, this array respects the old style, just in case
            $threads = array();
            foreach ($items as $item) {
                // Check for any blocked authors
                if ($arr_blocked) {
                    $blocked = false;
                    foreach ($arr_blocked as $b) {
                        if ($b && $item['author_xchan'] == $b) {
                            $blocked = true;
                            break;
                        }
                    }
                    if ($blocked) {
                        continue;
                    }
                }
                // Check all the kids too
                if ($arr_blocked && $item['children']) {
                    for ($d = 0; $d < count($item['children']); $d++) {
                        foreach ($arr_blocked as $b) {
                            if ($b && $item['children'][$d]['author_xchan'] == $b) {
                                $item['children'][$d]['author_blocked'] = true;
                            }
                        }
                    }
                }
                builtin_activity_puller($item, $conv_responses);
                if (!visible_activity($item)) {
                    continue;
                }
                $item['pagedrop'] = $page_dropping;
                if ($item['id'] == $item['parent']) {
                    $item_object = new Item($item);
                    $conv->add_thread($item_object);
                    if ($page_mode === 'list') {
                        $item_object->set_template('conv_list.tpl');
                        $item_object->set_display_mode('list');
                    }
                }
            }
            $threads = $conv->get_template_data($conv_responses);
            if (!$threads) {
                logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG);
                $threads = array();
            }
        }
    }
    if ($page_mode === 'traditional' || $page_mode === 'preview') {
        $page_template = get_markup_template("threaded_conversation.tpl");
    } elseif ($update) {
        $page_template = get_markup_template("convobj.tpl");
    } else {
        $page_template = get_markup_template("conv_frame.tpl");
        $threads = null;
    }
    //	if($page_mode === 'preview')
    //		logger('preview: ' . print_r($threads,true));
    //  Do not un-comment if smarty3 is in use
    //	logger('page_template: ' . $page_template);
    //	logger('nouveau: ' . print_r($threads,true));
    $o .= replace_macros($page_template, array('$baseurl' => $a->get_baseurl($ssl_state), '$photo_item' => $content_html, '$live_update' => $live_update_div, '$remove' => t('remove'), '$mode' => $mode, '$user' => $a->user, '$threads' => $threads, '$wait' => t('Loading...'), '$dropping' => $page_dropping ? t('Delete Selected Items') : False));
    return $o;
}
Example #18
0
function mitem_content(&$a)
{
    $uid = local_channel();
    $channel = $a->get_channel();
    $observer = $a->get_observer();
    $ob_hash = $observer ? $observer['xchan_hash'] : '';
    if ($a->is_sys && is_site_admin()) {
        $sys = get_sys_channel();
        $uid = intval($sys['channel_id']);
        $channel = $sys;
        $ob_hash = $sys['xchan_hash'];
    }
    if (!$uid) {
        notice(t('Permission denied.') . EOL);
        return '';
    }
    if (argc() < 2 || !$a->data['menu']) {
        notice(t('Not found.') . EOL);
        return '';
    }
    $m = menu_fetch($a->data['menu']['menu_name'], $uid, $ob_hash);
    $a->data['menu_item'] = $m;
    $menu_list = menu_list($uid);
    foreach ($menu_list as $menus) {
        if ($menus['menu_name'] != $m['menu']['menu_name']) {
            $menu_names[] = $menus['menu_name'];
        }
    }
    $acl = new AccessList($channel);
    $lockstate = $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid'] ? 'lock' : 'unlock';
    if (argc() == 2) {
        $r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc", intval($a->data['menu']['menu_id']), intval($uid));
        if ($_GET['display']) {
            $display = $_GET['display'];
        } else {
            $display = $r ? 'none' : 'block';
        }
        $create = replace_macros(get_markup_template('mitemedit.tpl'), array('$menu_id' => $a->data['menu']['menu_id'], '$permissions' => t('Menu Item Permissions'), '$permdesc' => t("(click to open/close)"), '$aclselect' => populate_acl($acl->get(), false), '$mitem_desc' => array('mitem_desc', t('Link Name'), '', 'Visible name of the link', '*'), '$mitem_link' => array('mitem_link', t('Link or Submenu Target'), '', t('Enter URL of the link or select a menu name to create a submenu'), '*', 'list="menu-names"'), '$usezid' => array('usezid', t('Use magic-auth if available'), true, '', array(t('No'), t('Yes'))), '$newwin' => array('newwin', t('Open link in new window'), false, '', array(t('No'), t('Yes'))), '$mitem_order' => array('mitem_order', t('Order in list'), '0', t('Higher numbers will sink to bottom of listing')), '$submit' => t('Submit and finish'), '$submit_more' => t('Submit and continue'), '$display' => $display, '$lockstate' => $lockstate, '$menu_names' => $menu_names, '$sys' => $a->is_sys));
        $o .= replace_macros(get_markup_template('mitemlist.tpl'), array('$title' => t('Menu:'), '$create' => $create, '$nametitle' => t('Link Name'), '$targettitle' => t('Link Target'), '$menuname' => $a->data['menu']['menu_name'], '$menudesc' => $a->data['menu']['menu_desc'], '$edmenu' => t('Edit menu'), '$menu_id' => $a->data['menu']['menu_id'], '$mlist' => $r, '$edit' => t('Edit element'), '$drop' => t('Drop element'), '$new' => t('New element'), '$hintmenu' => t('Edit this menu container'), '$hintnew' => t('Add menu element'), '$hintdrop' => t('Delete this menu item'), '$hintedit' => t('Edit this menu item')));
        return $o;
    }
    if (argc() > 2) {
        if (intval(argv(2))) {
            $m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1", intval(argv(2)), intval($uid));
            if (!$m) {
                notice(t('Menu item not found.') . EOL);
                goaway(z_root() . '/menu' . ($a->is_sys ? '?f=&sys=1' : ''));
            }
            $mitem = $m[0];
            $lockstate = $mitem['allow_cid'] || $mitem['allow_gid'] || $mitem['deny_cid'] || $mitem['deny_gid'] ? 'lock' : 'unlock';
            if (argc() == 4 && argv(3) == 'drop') {
                menu_sync_packet($uid, get_observer_hash(), $mitem['mitem_menu_id']);
                $r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2)));
                menu_sync_packet($uid, get_observer_hash(), $mitem['mitem_menu_id']);
                if ($r) {
                    info(t('Menu item deleted.') . EOL);
                } else {
                    notice(t('Menu item could not be deleted.') . EOL);
                }
                goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . ($a->is_sys ? '?f=&sys=1' : ''));
            }
            // edit menu item
            $o = replace_macros(get_markup_template('mitemedit.tpl'), array('$header' => t('Edit Menu Element'), '$menu_id' => $a->data['menu']['menu_id'], '$permissions' => t('Menu Item Permissions'), '$permdesc' => t("(click to open/close)"), '$aclselect' => populate_acl($mitem, false), '$mitem_id' => intval(argv(2)), '$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '', '*'), '$mitem_link' => array('mitem_link', t('Link or Submenu Target'), $mitem['mitem_link'], 'Enter URL of the link or select a menu name to create a submenu', '*', 'list="menu-names"'), '$usezid' => array('usezid', t('Use magic-auth if available'), $mitem['mitem_flags'] & MENU_ITEM_ZID ? 1 : 0, '', array(t('No'), t('Yes'))), '$newwin' => array('newwin', t('Open link in new window'), $mitem['mitem_flags'] & MENU_ITEM_NEWWIN ? 1 : 0, '', array(t('No'), t('Yes'))), '$mitem_order' => array('mitem_order', t('Order in list'), $mitem['mitem_order'], t('Higher numbers will sink to bottom of listing')), '$submit' => t('Submit'), '$lockstate' => $lockstate, '$menu_names' => $menu_names));
            return $o;
        }
    }
}
Example #19
0
 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;
 }
Example #20
0
function item_content(&$a)
{
    if (!local_channel() && !remote_channel()) {
        return;
    }
    require_once 'include/security.php';
    if (argc() == 3 && argv(1) === 'drop' && intval(argv(2))) {
        require_once 'include/items.php';
        $i = q("select id, uid, author_xchan, owner_xchan, source_xchan, item_restrict from item where id = %d limit 1", intval(argv(2)));
        if ($i) {
            $can_delete = false;
            $local_delete = false;
            if (local_channel() && local_channel() == $i[0]['uid']) {
                $local_delete = true;
            }
            $sys = get_sys_channel();
            if (is_site_admin() && $sys['channel_id'] == $i[0]['uid']) {
                $can_delete = true;
            }
            $ob_hash = get_observer_hash();
            if ($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
                $can_delete = true;
            }
            if (!($can_delete || $local_delete)) {
                notice(t('Permission denied.') . EOL);
                return;
            }
            // if this is a different page type or it's just a local delete
            // but not by the item author or owner, do a simple deletion
            if ($i[0]['item_restrict'] || $local_delete && !$can_delete) {
                drop_item($i[0]['id']);
            } else {
                // complex deletion that needs to propagate and be performed in phases
                drop_item($i[0]['id'], true, DROPITEM_PHASE1);
                tag_deliver($i[0]['uid'], $i[0]['id']);
            }
        }
    }
}
Example #21
0
/**
 * @brief Creates navigation menu for webpage, layout, blocks, menu sites.
 *
 * @return string
 */
function design_tools()
{
    $channel = get_app()->get_channel();
    $sys = false;
    if (get_app()->is_sys && is_site_admin()) {
        require_once 'include/identity.php';
        $channel = get_sys_channel();
        $sys = true;
    }
    $who = $channel['channel_address'];
    return replace_macros(get_markup_template('design_tools.tpl'), array('$title' => t('Design Tools'), '$who' => $who, '$sys' => $sys, '$blocks' => t('Blocks'), '$menus' => t('Menus'), '$layout' => t('Layouts'), '$pages' => t('Pages')));
}
Example #22
0
function check_config(&$a)
{
    $build = get_config('system', 'db_version');
    if (!intval($build)) {
        $build = set_config('system', 'db_version', DB_UPDATE_VERSION);
    }
    $saved = get_config('system', 'urlverify');
    if (!$saved) {
        set_config('system', 'urlverify', bin2hex(z_root()));
    }
    if ($saved && $saved != bin2hex(z_root())) {
        // our URL changed. Do something.
        $oldurl = hex2bin($saved);
        logger('Baseurl changed!');
        $oldhost = substr($oldurl, strpos($oldurl, '//') + 2);
        $host = substr(z_root(), strpos(z_root(), '//') + 2);
        $is_ip_addr = preg_match("/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\$/", $host) ? true : false;
        $was_ip_addr = preg_match("/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\$/", $oldhost) ? true : false;
        // only change the url to an ip address if it was already an ip and not a dns name
        if (!$is_ip_addr || $is_ip_addr && $was_ip_addr) {
            fix_system_urls($oldurl, z_root());
            set_config('system', 'urlverify', bin2hex(z_root()));
        } else {
            logger('Attempt to change baseurl from a DNS name to an IP address was refused.');
        }
    }
    // This will actually set the url to the one stored in .htconfig, and ignore what
    // we're passing - unless we are installing and it has never been set.
    $a->set_baseurl($a->get_baseurl());
    // Make sure each site has a system channel.  This is now created on install
    // so we just need to keep this around a couple of weeks until the hubs that
    // already exist have one
    $syschan_exists = get_sys_channel();
    if (!$syschan_exists) {
        create_sys_channel();
    }
    if ($build != DB_UPDATE_VERSION) {
        $stored = intval($build);
        if (!$stored) {
            logger('Critical: check_config unable to determine database schema version');
            return;
        }
        $current = intval(DB_UPDATE_VERSION);
        if ($stored < $current && file_exists('install/update.php')) {
            load_config('database');
            // We're reporting a different version than what is currently installed.
            // Run any existing update scripts to bring the database up to current.
            require_once 'install/update.php';
            // make sure that boot.php and update.php are the same release, we might be
            // updating right this very second and the correct version of the update.php
            // file may not be here yet. This can happen on a very busy site.
            if (DB_UPDATE_VERSION == UPDATE_VERSION) {
                for ($x = $stored; $x < $current; $x++) {
                    if (function_exists('update_r' . $x)) {
                        // There could be a lot of processes running or about to run.
                        // We want exactly one process to run the update command.
                        // So store the fact that we're taking responsibility
                        // after first checking to see if somebody else already has.
                        // If the update fails or times-out completely you may need to
                        // delete the config entry to try again.
                        if (get_config('database', 'update_r' . $x)) {
                            break;
                        }
                        set_config('database', 'update_r' . $x, '1');
                        // call the specific update
                        $func = 'update_r' . $x;
                        $retval = $func();
                        if ($retval) {
                            // Prevent sending hundreds of thousands of emails by creating
                            // a lockfile.
                            $lockfile = 'store/[data]/mailsent';
                            if (file_exists($lockfile) && filemtime($lockfile) > time() - 86400) {
                                return;
                            }
                            @unlink($lockfile);
                            //send the administrator an e-mail
                            file_put_contents($lockfile, $x);
                            $email_tpl = get_intltext_template("update_fail_eml.tpl");
                            $email_msg = replace_macros($email_tpl, array('$sitename' => $a->config['system']['sitename'], '$siteurl' => $a->get_baseurl(), '$update' => $x, '$error' => sprintf(t('Update %s failed. See error logs.'), $x)));
                            $subject = email_header_encode(sprintf(t('Update Error at %s'), $a->get_baseurl()));
                            mail($a->config['system']['admin_email'], $subject, $email_msg, 'From: Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit');
                            //try the logger
                            logger('CRITICAL: Update Failed: ' . $x);
                        } else {
                            set_config('database', 'update_r' . $x, 'success');
                        }
                    }
                }
                set_config('system', 'db_version', DB_UPDATE_VERSION);
            }
        }
    }
    /**
     *
     * Synchronise plugins:
     *
     * $a->config['system']['addon'] contains a comma-separated list of names
     * of plugins/addons which are used on this system.
     * Go through the database list of already installed addons, and if we have
     * an entry, but it isn't in the config list, call the unload procedure
     * and mark it uninstalled in the database (for now we'll remove it).
     * Then go through the config list and if we have a plugin that isn't installed,
     * call the install procedure and add it to the database.
     *
     */
    $r = q("SELECT * FROM `addon` WHERE `installed` = 1");
    if ($r) {
        $installed = $r;
    } else {
        $installed = array();
    }
    $plugins = get_config('system', 'addon');
    $plugins_arr = array();
    if ($plugins) {
        $plugins_arr = explode(',', str_replace(' ', '', $plugins));
    }
    $a->plugins = $plugins_arr;
    $installed_arr = array();
    if (count($installed)) {
        foreach ($installed as $i) {
            if (!in_array($i['name'], $plugins_arr)) {
                unload_plugin($i['name']);
            } else {
                $installed_arr[] = $i['name'];
            }
        }
    }
    if (count($plugins_arr)) {
        foreach ($plugins_arr as $p) {
            if (!in_array($p, $installed_arr)) {
                load_plugin($p);
            }
        }
    }
    load_hooks();
}
Example #23
0
function store_doc_file($s)
{
    if (is_dir($s)) {
        return;
    }
    $item = array();
    $sys = get_sys_channel();
    $item['aid'] = 0;
    $item['uid'] = $sys['channel_id'];
    if (strpos($s, '.md')) {
        $mimetype = 'text/markdown';
    } elseif (strpos($s, '.html')) {
        $mimetype = 'text/html';
    } else {
        $mimetype = 'text/bbcode';
    }
    require_once 'include/html2plain.php';
    $item['body'] = html2plain(prepare_text(file_get_contents($s), $mimetype, true));
    $item['mimetype'] = 'text/plain';
    $item['plink'] = z_root() . '/' . str_replace('doc', 'help', $s);
    $item['owner_xchan'] = $item['author_xchan'] = $sys['channel_hash'];
    $item['item_type'] = ITEM_TYPE_DOC;
    $r = q("select item.* from item left join iconfig on item.id = iconfig.iid \n\t\twhere iconfig.cat = 'system' and iconfig.k = 'docfile' and\n\t\ticonfig.v = '%s' and item_type = %d limit 1", dbesc($s), intval(ITEM_TYPE_DOC));
    \Zotlabs\Lib\IConfig::Set($item, 'system', 'docfile', $s);
    if ($r) {
        $item['id'] = $r[0]['id'];
        $item['mid'] = $item['parent_mid'] = $r[0]['mid'];
        $x = item_store_update($item);
    } else {
        $item['mid'] = $item['parent_mid'] = item_message_id();
        $x = item_store($item);
    }
    return $x;
}
Example #24
0
function like_content(&$a)
{
    $o = '';
    $observer = $a->get_observer();
    $interactive = $_REQUEST['interactive'];
    if ($interactive) {
        $o .= '<h1>' . t('Like/Dislike') . '</h1>';
        $o .= EOL . EOL;
        if (!$observer) {
            $_SESSION['return_url'] = $a->query_string;
            $o .= t('This action is restricted to members.') . EOL;
            $o .= t('Please <a href="rmagic">login with your RedMatrix ID</a> or <a href="register">register as a new RedMatrix member</a> to continue.') . EOL;
            return $o;
        }
    }
    $verb = notags(trim($_GET['verb']));
    if (!$verb) {
        $verb = 'like';
    }
    switch ($verb) {
        case 'like':
        case 'unlike':
            $activity = ACTIVITY_LIKE;
            break;
        case 'dislike':
        case 'undislike':
            $activity = ACTIVITY_DISLIKE;
            break;
        case 'agree':
        case 'unagree':
            $activity = ACTIVITY_AGREE;
            break;
        case 'disagree':
        case 'undisagree':
            $activity = ACTIVITY_DISAGREE;
            break;
        case 'abstain':
        case 'unabstain':
            $activity = ACTIVITY_ABSTAIN;
            break;
        case 'attendyes':
        case 'unattendyes':
            $activity = ACTIVITY_ATTEND;
            break;
        case 'attendno':
        case 'unattendno':
            $activity = ACTIVITY_ATTENDNO;
            break;
        case 'attendmaybe':
        case 'unattendmaybe':
            $activity = ACTIVITY_ATTENDMAYBE;
            break;
        default:
            return;
            break;
    }
    $extended_like = false;
    $object = $target = null;
    $post_type = '';
    $objtype = '';
    if (argc() == 3) {
        if (!$observer) {
            killme();
        }
        $extended_like = true;
        $obj_type = argv(1);
        $obj_id = argv(2);
        $public = true;
        if ($obj_type == 'profile') {
            $r = q("select * from profile where profile_guid = '%s' limit 1", dbesc(argv(2)));
            if (!$r) {
                killme();
            }
            $owner_uid = $r[0]['uid'];
            if ($r[0]['is_default']) {
                $public = true;
            }
            if (!$public) {
                $d = q("select abook_xchan from abook where abook_profile = '%s' and abook_channel = %d", dbesc($r[0]['profile_guid']), intval($owner_uid));
                if (!$d) {
                    // forgery - illegal
                    if ($interactive) {
                        notice(t('Invalid request.') . EOL);
                        return $o;
                    }
                    killme();
                }
                // $d now contains a list of those who can see this profile - only send the status notification
                // to them.
                $allow_cid = $allow_gid = $deny_cid = $deny_gid = '';
                foreach ($d as $dd) {
                    $allow_gid .= '<' . $dd['abook_xchan'] . '>';
                }
            }
            $post_type = t('channel');
            $objtype = ACTIVITY_OBJ_PROFILE;
        } elseif ($obj_type == 'thing') {
            $r = q("select * from obj left join term on obj_obj = term_hash where term_hash != '' \n\t\t\t\tand obj_type = %d and term_hash = '%s' limit 1", intval(TERM_OBJ_THING), dbesc(argv(2)));
            if (!$r) {
                if ($interactive) {
                    notice(t('Invalid request.') . EOL);
                    return $o;
                }
                killme();
            }
            $owner_uid = $r[0]['obj_channel'];
            $allow_cid = $r[0]['allow_cid'];
            $allow_gid = $r[0]['allow_gid'];
            $deny_cid = $r[0]['deny_cid'];
            $deny_gid = $r[0]['deny_gid'];
            if ($allow_cid || $allow_gid || $deny_cid || $deny_gid) {
                $public = false;
            }
            $post_type = t('thing');
            $objtype = ACTIVITY_OBJ_PROFILE;
            $tgttype = ACTIVITY_OBJ_THING;
            $links = array();
            $links[] = array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/thing/' . $r[0]['term_hash']);
            if ($r[0]['imgurl']) {
                $links[] = array('rel' => 'photo', 'href' => $r[0]['imgurl']);
            }
            $target = json_encode(array('type' => $tgttype, 'title' => $r[0]['term'], 'id' => z_root() . '/thing/' . $r[0]['term_hash'], 'link' => $links));
            $plink = '[zrl=' . z_root() . '/thing/' . $r[0]['term_hash'] . ']' . $r[0]['term'] . '[/zrl]';
        }
        if (!($owner_uid && $r)) {
            if ($interactive) {
                notice(t('Invalid request.') . EOL);
                return $o;
            }
            killme();
        }
        // The resultant activity is going to be a wall-to-wall post, so make sure this is allowed
        $perms = get_all_perms($owner_uid, $observer['xchan_hash']);
        if (!($perms['post_like'] && $perms['view_profile'])) {
            if ($interactive) {
                notice(t('Permission denied.') . EOL);
                return $o;
            }
            killme();
        }
        $ch = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_id = %d limit 1", intval($owner_uid));
        if (!$ch) {
            if ($interactive) {
                notice(t('Channel unavailable.') . EOL);
                return $o;
            }
            killme();
        }
        if (!$plink) {
            $plink = '[zrl=' . z_root() . '/profile/' . $ch[0]['channel_address'] . ']' . $post_type . '[/zrl]';
        }
        $links = array();
        $links[] = array('rel' => 'alternate', 'type' => 'text/html', 'href' => z_root() . '/profile/' . $ch[0]['channel_address']);
        $links[] = array('rel' => 'photo', 'type' => $ch[0]['xchan_photo_mimetype'], 'href' => $ch[0]['xchan_photo_l']);
        $object = json_encode(array('type' => ACTIVITY_OBJ_PROFILE, 'title' => $ch[0]['channel_name'], 'id' => $ch[0]['xchan_url'] . '/' . $ch[0]['xchan_hash'], 'link' => $links));
        // second like of the same thing is "undo" for the first like
        $z = q("select * from likes where channel_id = %d and liker = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' limit 1", intval($ch[0]['channel_id']), dbesc($observer['xchan_hash']), dbesc($activity), dbesc($tgttype ? $tgttype : $objtype), dbesc($obj_id));
        if ($z) {
            q("delete from likes where id = %d limit 1", intval($z[0]['id']));
            drop_item($z[0]['iid'], false);
            if ($interactive) {
                notice(t('Previous action reversed.') . EOL);
                return $o;
            }
            killme();
        }
    } else {
        // this is used to like an item or comment
        $item_id = argc() == 2 ? notags(trim(argv(1))) : 0;
        logger('like: verb ' . $verb . ' item ' . $item_id, LOGGER_DEBUG);
        // get the item. Allow linked photos (which are normally hidden) to be liked
        $r = q("SELECT * FROM item WHERE id = %d and (item_restrict = 0 or item_restrict = %d) LIMIT 1", intval($item_id), intval(ITEM_HIDDEN));
        if (!$item_id || !$r) {
            logger('like: no item ' . $item_id);
            killme();
        }
        $item = $r[0];
        $owner_uid = $item['uid'];
        $owner_aid = $item['aid'];
        $sys = get_sys_channel();
        // if this is a "discover" item, (item['uid'] is the sys channel),
        // fallback to the item comment policy, which should've been
        // respected when generating the conversation thread.
        // Even if the activity is rejected by the item owner, it should still get attached
        // to the local discover conversation on this site.
        if ($owner_uid != $sys['channel_id'] && !perm_is_allowed($owner_uid, $observer['xchan_hash'], 'post_comments')) {
            notice(t('Permission denied') . EOL);
            killme();
        }
        $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($item['owner_xchan']));
        if ($r) {
            $thread_owner = $r[0];
        } else {
            killme();
        }
        $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($item['author_xchan']));
        if ($r) {
            $item_author = $r[0];
        } else {
            killme();
        }
        $verbs = " '" . dbesc($activity) . "' ";
        $multi_undo = 0;
        // event participation and consensus items are essentially radio toggles. If you make a subsequent choice,
        // we need to eradicate your first choice.
        if ($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
            $verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
            $multi_undo = 1;
        }
        if ($activity === ACTIVITY_AGREE || $activity === ACTIVITY_DISAGREE || $activity === ACTIVITY_ABSTAIN) {
            $verbs = " '" . dbesc(ACTIVITY_AGREE) . "','" . dbesc(ACTIVITY_DISAGREE) . "','" . dbesc(ACTIVITY_ABSTAIN) . "' ";
            $multi_undo = 1;
        }
        $r = q("SELECT id, parent, uid, verb FROM item WHERE verb in ( {$verbs} ) AND item_restrict = 0 \n\t\t\tAND author_xchan = '%s' AND ( parent = %d OR thr_parent = '%s') and uid = %d ", dbesc($observer['xchan_hash']), intval($item_id), dbesc($item['mid']), intval($owner_uid));
        if ($r) {
            // already liked it. Drop that item.
            require_once 'include/items.php';
            foreach ($r as $rr) {
                drop_item($rr['id'], false, DROPITEM_PHASE1);
                // set the changed timestamp on the parent so we'll see the update without a page reload
                $z = q("update item set changed = '%s' where id = %d and uid = %d", dbesc(datetime_convert()), intval($rr['parent']), intval($rr['uid']));
                // Prior activity was a duplicate of the one we're submitting, just undo it;
                // don't fall through and create another
                if (activity_match($rr['verb'], $activity)) {
                    $multi_undo = false;
                }
            }
            if ($interactive) {
                return;
            }
            if (!$multi_undo) {
                killme();
            }
        }
    }
    $mid = item_message_id();
    if ($extended_like) {
        $item_flags = ITEM_THREAD_TOP | ITEM_ORIGIN | ITEM_WALL;
    } else {
        $post_type = $item['resource_type'] === 'photo' ? t('photo') : t('status');
        if ($item['obj_type'] === ACTIVITY_OBJ_EVENT) {
            $post_type = t('event');
        }
        $links = array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item['plink']));
        $objtype = $item['resource_type'] === 'photo' ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE;
        $body = $item['body'];
        $object = json_encode(array('type' => $objtype, 'id' => $item['mid'], 'parent' => $item['thr_parent'] ? $item['thr_parent'] : $item['parent_mid'], 'link' => $links, 'title' => $item['title'], 'content' => $item['body'], 'created' => $item['created'], 'edited' => $item['edited'], 'author' => array('name' => $item_author['xchan_name'], 'address' => $item_author['xchan_addr'], 'guid' => $item_author['xchan_guid'], 'guid_sig' => $item_author['xchan_guid_sig'], 'link' => array(array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']), array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])))));
        if (!($item['item_flags'] & ITEM_THREAD_TOP)) {
            $post_type = 'comment';
        }
        $item_flags = ITEM_ORIGIN | ITEM_NOTSHOWN;
        if ($item['item_flags'] & ITEM_WALL) {
            $item_flags |= ITEM_WALL;
        }
        // if this was a linked photo and was hidden, unhide it.
        if ($item['item_restrict'] & ITEM_HIDDEN) {
            $r = q("update item set item_restrict = (item_restrict ^ %d) where id = %d", intval(ITEM_HIDDEN), intval($item['id']));
        }
    }
    if ($verb === 'like') {
        $bodyverb = t('%1$s likes %2$s\'s %3$s');
    }
    if ($verb === 'dislike') {
        $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
    }
    if ($verb === 'agree') {
        $bodyverb = t('%1$s agrees with %2$s\'s %3$s');
    }
    if ($verb === 'disagree') {
        $bodyverb = t('%1$s doesn\'t agree with %2$s\'s %3$s');
    }
    if ($verb === 'abstain') {
        $bodyverb = t('%1$s abstains from a decision on %2$s\'s %3$s');
    }
    if ($verb === 'attendyes') {
        $bodyverb = t('%1$s is attending %2$s\'s %3$s');
    }
    if ($verb === 'attendno') {
        $bodyverb = t('%1$s is not attending %2$s\'s %3$s');
    }
    if ($verb === 'attendmaybe') {
        $bodyverb = t('%1$s may attend %2$s\'s %3$s');
    }
    if (!isset($bodyverb)) {
        killme();
    }
    $arr = array();
    if ($extended_like) {
        $ulink = '[zrl=' . $ch[0]['xchan_url'] . ']' . $ch[0]['xchan_name'] . '[/zrl]';
        $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
        $private = $public ? 0 : 1;
    } else {
        $arr['parent'] = $item['id'];
        $arr['thr_parent'] = $item['mid'];
        $ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]';
        $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]';
        $plink = '[zrl=' . $a->get_baseurl() . '/display/' . $item['mid'] . ']' . $post_type . '[/zrl]';
        $allow_cid = $item['allow_cid'];
        $allow_gid = $item['allow_gid'];
        $deny_cid = $item['deny_cid'];
        $deny_gid = $item['deny_gid'];
        $private = $item['private'];
    }
    $arr['mid'] = $mid;
    $arr['aid'] = $extended_like ? $ch[0]['channel_account_id'] : $owner_aid;
    $arr['uid'] = $owner_uid;
    $arr['item_flags'] = $item_flags;
    $arr['parent_mid'] = $extended_like ? $mid : $item['mid'];
    $arr['owner_xchan'] = $extended_like ? $ch[0]['xchan_hash'] : $thread_owner['xchan_hash'];
    $arr['author_xchan'] = $observer['xchan_hash'];
    $arr['body'] = sprintf($bodyverb, $alink, $ulink, $plink);
    if ($obj_type === 'thing' && $r[0]['imgurl']) {
        $arr['body'] .= "\n\n[zmg=80x80]" . $r[0]['imgurl'] . '[/zmg]';
    }
    $arr['verb'] = $activity;
    $arr['obj_type'] = $objtype;
    $arr['object'] = $object;
    if ($target) {
        $arr['tgt_type'] = $tgttype;
        $arr['target'] = $target;
    }
    $arr['allow_cid'] = $allow_cid;
    $arr['allow_gid'] = $allow_gid;
    $arr['deny_cid'] = $deny_cid;
    $arr['deny_gid'] = $deny_gid;
    $arr['item_private'] = $private;
    $post = item_store($arr);
    $post_id = $post['item_id'];
    $arr['id'] = $post_id;
    call_hooks('post_local_end', $arr);
    if ($extended_like) {
        $r = q("insert into likes (channel_id,liker,likee,iid,verb,target_type,target_id,target) values (%d,'%s','%s',%d,'%s','%s','%s','%s')", intval($ch[0]['channel_id']), dbesc($observer['xchan_hash']), dbesc($ch[0]['channel_hash']), intval($post_id), dbesc($activity), dbesc($tgttype ? $tgttype : $objtype), dbesc($obj_id), dbesc(json_encode($target ? $target : $object)));
    }
    proc_run('php', "include/notifier.php", "like", "{$post_id}");
    if ($interactive) {
        notice(t('Action completed.') . EOL);
        $o .= t('Thank you.');
        return $o;
    }
    killme();
}
Example #25
0
function get_theme_uid()
{
    $uid = $_REQUEST['puid'] ? intval($_REQUEST['puid']) : 0;
    if (local_channel()) {
        if (get_pconfig(local_channel(), 'system', 'always_my_theme') || !$uid) {
            return local_channel();
        }
    }
    if (!$uid) {
        $x = get_sys_channel();
        if ($x) {
            return $x['channel_id'];
        }
    }
    return $uid;
}
Example #26
0
File: zot.php Project: 23n/hubzilla
/**
 * @brief
 *
 * A public message with no listed recipients can be delivered to anybody who
 * has PERMS_NETWORK for that type of post, PERMS_AUTHED (in-network senders are
 * by definition authenticated) or PERMS_SITE and is one the same site,
 * or PERMS_SPECIFIC and the sender is a contact who is granted permissions via
 * their connection permissions in the address book.
 * Here we take a given message and construct a list of hashes of everybody
 * on the site that we should try and deliver to.
 * Some of these will be rejected, but this gives us a place to start.
 *
 * @param array $msg
 * @return NULL|array
 */
function public_recips($msg)
{
    require_once 'include/identity.php';
    $check_mentions = false;
    $include_sys = false;
    if ($msg['message']['type'] === 'activity') {
        if (!get_config('system', 'disable_discover_tab')) {
            $include_sys = true;
        }
        $col = 'channel_w_stream';
        $field = PERMS_W_STREAM;
        if (array_key_exists('flags', $msg['message']) && in_array('thread_parent', $msg['message']['flags'])) {
            // check mention recipient permissions on top level posts only
            $check_mentions = true;
        } else {
            // This doesn't look like it works so I have to explain what happened. These are my
            // notes (below) from when I got this section of code working. You would think that
            // we only have to find those with the requisite stream or comment permissions,
            // depending on whether this is a top-level post or a comment - but you would be wrong.
            // ... so public_recips and allowed_public_recips is working so much better
            // than before, but was still not quite right. We seem to be getting all the right
            // results for top-level posts now, but comments aren't getting through on channels
            // for which we've allowed them to send us their stream, but not comment on our posts.
            // The reason is we were seeing if they could comment - and we only need to do that if
            // we own the post. If they own the post, we only need to check if they can send us their stream.
            // if this is a comment and it wasn't sent by the post owner, check to see who is allowing them to comment.
            // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up
            // their software. We may need this step to protect us from bad guys intentionally stuffing up their software.
            // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the
            // owner's stream (which was already set above) - as they control the comment permissions, not us.
            // Note that by doing this we introduce another bug because some public forums have channel_w_stream
            // permissions set to themselves only. We also need in this function to add these public forums to the
            // public recipient list based on if they are tagged or not and have tag permissions. This is complicated
            // by the fact that this activity doesn't have the public forum tag. It's the parent activity that
            // contains the tag. we'll solve that further below.
            if ($msg['notify']['sender']['guid_sig'] != $msg['message']['owner']['guid_sig']) {
                $col = 'channel_w_comment';
                $field = PERMS_W_COMMENT;
            }
        }
    } elseif ($msg['message']['type'] === 'mail') {
        $col = 'channel_w_mail';
        $field = PERMS_W_MAIL;
    }
    if (!$col) {
        return NULL;
    }
    $col = dbesc($col);
    // First find those channels who are accepting posts from anybody, or at least
    // something greater than just their connections.
    if ($msg['notify']['sender']['url'] === z_root()) {
        $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0\n\t\t\t\t\tor (  " . $col . " & " . intval(PERMS_SITE) . " ) > 0\n\t\t\t\t\tor (  " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0\n\t\t\t\t\tor (  " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) ";
    } else {
        $sql = " where ( " . $col . " = " . intval(PERMS_NETWORK) . " \n\t\t\t\t\tor " . $col . " = " . intval(PERMS_PUBLIC) . "\n\t\t\t\t\tor " . $col . " = " . intval(PERMS_AUTHED) . " ) ";
    }
    $r = q("select channel_hash as hash from channel {$sql} or channel_hash = '%s'\n\t\tand channel_removed = 0 ", dbesc($msg['notify']['sender']['hash']));
    if (!$r) {
        $r = array();
    }
    // Now we have to get a bit dirty. Find every channel that has the sender in their connections (abook)
    // and is allowing this sender at least at a high level.
    $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id\n\t\twhere abook_xchan = '%s' and channel_removed = 0\n\t\tand (( " . $col . " = " . intval(PERMS_SPECIFIC) . " and ( abook_my_perms & " . intval($field) . " ) > 0 )\n\t\tOR   " . $col . " = " . intval(PERMS_PENDING) . " \n\t\tOR  ( " . $col . " = " . intval(PERMS_CONTACTS) . " and abook_pending = 0 )) ", dbesc($msg['notify']['sender']['hash']));
    if (!$x) {
        $x = array();
    }
    $r = array_merge($r, $x);
    //logger('message: ' . print_r($msg['message'],true));
    if ($include_sys && array_key_exists('public_scope', $msg['message']) && $msg['message']['public_scope'] === 'public') {
        $sys = get_sys_channel();
        if ($sys) {
            $r[] = array('hash' => $sys['channel_hash']);
        }
    }
    // look for any public mentions on this site
    // They will get filtered by tgroup_check() so we don't need to check permissions now
    if ($check_mentions) {
        // It's a top level post. Look at the tags. See if any of them are mentions and are on this hub.
        if ($msg['message']['tags']) {
            if (is_array($msg['message']['tags']) && $msg['message']['tags']) {
                foreach ($msg['message']['tags'] as $tag) {
                    if ($tag['type'] === 'mention' && strpos($tag['url'], z_root()) !== false) {
                        $address = basename($tag['url']);
                        if ($address) {
                            $z = q("select channel_hash as hash from channel where channel_address = '%s' \n\t\t\t\t\t\t\t\tand channel_removed = 0 limit 1", dbesc($address));
                            if ($z) {
                                $r = array_merge($r, $z);
                            }
                        }
                    }
                }
            }
        }
    } else {
        // This is a comment. We need to find any parent with ITEM_UPLINK set. But in fact, let's just return
        // everybody that stored a copy of the parent. This way we know we're covered. We'll check the
        // comment permissions when we deliver them.
        if ($msg['message']['message_top']) {
            $z = q("select owner_xchan as hash from item where parent_mid = '%s' ", dbesc($msg['message']['message_top']));
            if ($z) {
                $r = array_merge($r, $z);
            }
        }
    }
    // There are probably a lot of duplicates in $r at this point. We need to filter those out.
    // It's a bit of work since it's a multi-dimensional array
    if ($r) {
        $uniq = array();
        foreach ($r as $rr) {
            if (!in_array($rr['hash'], $uniq)) {
                $uniq[] = $rr['hash'];
            }
        }
        $r = array();
        foreach ($uniq as $rr) {
            $r[] = array('hash' => $rr);
        }
    }
    logger('public_recips: ' . print_r($r, true), LOGGER_DATA);
    return $r;
}
Example #27
0
function drop_item($id, $interactive = true, $stage = DROPITEM_NORMAL, $force = false)
{
    $a = get_app();
    // locate item to be deleted
    $r = q("SELECT * FROM item WHERE id = %d LIMIT 1", intval($id));
    if (!$r || $r[0]['item_restrict'] & ITEM_DELETED && $stage === DROPITEM_NORMAL) {
        if (!$interactive) {
            return 0;
        }
        notice(t('Item not found.') . EOL);
        goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
    }
    $item = $r[0];
    $linked_item = $item['resource_id'] ? true : false;
    $ok_to_delete = false;
    // system deletion
    if (!$interactive) {
        $ok_to_delete = true;
    }
    // owner deletion
    if (local_channel() && local_channel() == $item['uid']) {
        $ok_to_delete = true;
    }
    // sys owned item, requires site admin to delete
    $sys = get_sys_channel();
    if (is_site_admin() && $sys['channel_id'] == $item['uid']) {
        $ok_to_delete = true;
    }
    // author deletion
    $observer = $a->get_observer();
    if ($observer && $observer['xchan_hash'] && $observer['xchan_hash'] === $item['author_xchan']) {
        $ok_to_delete = true;
    }
    if ($ok_to_delete) {
        // set the deleted flag immediately on this item just in case the
        // hook calls a remote process which loops. We'll delete it properly in a second.
        $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ) WHERE id = %d", intval($linked_item && !$force ? ITEM_HIDDEN : ITEM_DELETED), intval($item['id']));
        $arr = array('item' => $item, 'interactive' => $interactive, 'stage' => $stage);
        call_hooks('drop_item', $arr);
        $notify_id = intval($item['id']);
        $items = q("select * from item where parent = %d and uid = %d", intval($item['id']), intval($item['uid']));
        if ($items) {
            foreach ($items as $i) {
                delete_item_lowlevel($i, $stage, $force);
            }
        } else {
            delete_item_lowlevel($item, $stage, $force);
        }
        if (!$interactive) {
            return 1;
        }
        // send the notification upstream/downstream as the case may be
        // only send notifications to others if this is the owner's wall item.
        // This isn't optimal. We somehow need to pass to this function whether or not
        // to call the notifier, or we need to call the notifier from the calling function.
        // We'll rely on the undocumented behaviour that DROPITEM_PHASE1 is (hopefully) only
        // set if we know we're going to send delete notifications out to others.
        if ($item['item_flags'] & ITEM_WALL && $stage != DROPITEM_PHASE2 || $stage == DROPITEM_PHASE1) {
            proc_run('php', 'include/notifier.php', 'drop', $notify_id);
        }
        goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
    } else {
        if (!$interactive) {
            return 0;
        }
        notice(t('Permission denied.') . EOL);
        goaway($a->get_baseurl() . '/' . $_SESSION['return_url']);
    }
}
Example #28
0
function webpages_content(&$a)
{
    if (!App::$profile) {
        notice(t('Requested profile is not available.') . EOL);
        App::$error = 404;
        return;
    }
    $which = argv(1);
    $_SESSION['return_url'] = App::$query_string;
    $uid = local_channel();
    $owner = 0;
    $channel = null;
    $observer = App::get_observer();
    $channel = App::get_channel();
    if (App::$is_sys && is_site_admin()) {
        $sys = get_sys_channel();
        if ($sys && intval($sys['channel_id'])) {
            $uid = $owner = intval($sys['channel_id']);
            $channel = $sys;
            $observer = $sys;
        }
    }
    if (!$owner) {
        // Figure out who the page owner is.
        $r = q("select channel_id from channel where channel_address = '%s'", dbesc($which));
        if ($r) {
            $owner = intval($r[0]['channel_id']);
        }
    }
    $ob_hash = $observer ? $observer['xchan_hash'] : '';
    $perms = get_all_perms($owner, $ob_hash);
    if (!$perms['write_pages']) {
        notice(t('Permission denied.') . EOL);
        return;
    }
    $mimetype = $_REQUEST['mimetype'] ? $_REQUEST['mimetype'] : get_pconfig($owner, 'system', 'page_mimetype');
    if (!$mimetype) {
        $mimetype = 'choose';
    }
    $layout = $_REQUEST['layout'] ? $_REQUEST['layout'] : get_pconfig($owner, 'system', 'page_layout');
    if (!$layout) {
        $layout = 'choose';
    }
    // Create a status editor (for now - we'll need a WYSIWYG eventually) to create pages
    // Nickname is set to the observers xchan, and profile_uid to the owner's.
    // This lets you post pages at other people's channels.
    if (!$channel && $uid && $uid == App::$profile_uid) {
        $channel = App::get_channel();
    }
    if ($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']);
    } else {
        $channel_acl = array();
    }
    $is_owner = $uid && $uid == $owner;
    $o = profile_tabs($a, $is_owner, App::$profile['channel_address']);
    $x = array('webpage' => ITEM_TYPE_WEBPAGE, 'is_owner' => true, 'nickname' => App::$profile['channel_address'], 'lockstate' => $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid'] ? 'lock' : 'unlock', 'bang' => '', 'acl' => $is_owner ? populate_acl($channel_acl, false) : '', 'showacl' => $is_owner ? true : false, 'visitor' => true, 'profile_uid' => intval($owner), 'mimetype' => $mimetype, 'layout' => $layout, 'expanded' => true, 'novoting' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true);
    if ($_REQUEST['title']) {
        $x['title'] = $_REQUEST['title'];
    }
    if ($_REQUEST['body']) {
        $x['body'] = $_REQUEST['body'];
    }
    if ($_REQUEST['pagetitle']) {
        $x['pagetitle'] = $_REQUEST['pagetitle'];
    }
    $editor = status_editor($a, $x);
    // Get a list of webpages.  We can't display all them because endless scroll makes that unusable,
    // so just list titles and an edit link.
    /** @TODO - this should be replaced with pagelist_widget */
    $sql_extra = item_permissions_sql($owner);
    $r = q("select * from item_id left join item on item_id.iid = item.id \n\t\twhere item_id.uid = %d and service = 'WEBPAGE' and item_type = %d {$sql_extra} order by item.created desc", intval($owner), intval(ITEM_TYPE_WEBPAGE));
    $pages = null;
    if ($r) {
        $pages = array();
        foreach ($r as $rr) {
            unobscure($rr);
            $lockstate = $rr['allow_cid'] || $rr['allow_gid'] || $rr['deny_cid'] || $rr['deny_gid'] ? 'lock' : 'unlock';
            $element_arr = array('type' => 'webpage', 'title' => $rr['title'], 'body' => $rr['body'], 'created' => $rr['created'], 'edited' => $rr['edited'], 'mimetype' => $rr['mimetype'], 'pagetitle' => $rr['sid'], 'mid' => $rr['mid'], 'layout_mid' => $rr['layout_mid']);
            $pages[$rr['iid']][] = array('url' => $rr['iid'], 'pagetitle' => $rr['sid'], 'title' => $rr['title'], 'created' => datetime_convert('UTC', date_default_timezone_get(), $rr['created']), 'edited' => datetime_convert('UTC', date_default_timezone_get(), $rr['edited']), 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]', 'lockstate' => $lockstate);
        }
    }
    //Build the base URL for edit links
    $url = z_root() . '/editwebpage/' . $which;
    $o .= replace_macros(get_markup_template('webpagelist.tpl'), array('$listtitle' => t('Webpages'), '$baseurl' => $url, '$create' => t('Create'), '$edit' => t('Edit'), '$share' => t('Share'), '$delete' => t('Delete'), '$pages' => $pages, '$channel' => $which, '$editor' => $editor, '$view' => t('View'), '$preview' => t('Preview'), '$actions_txt' => t('Actions'), '$pagelink_txt' => t('Page Link'), '$title_txt' => t('Page Title'), '$created_txt' => t('Created'), '$edited_txt' => t('Edited')));
    return $o;
}
Example #29
0
function api_statuses_public_timeline(&$a, $type)
{
    if (api_user() === false) {
        return false;
    }
    $user_info = api_get_user($a);
    $sys = get_sys_channel();
    // params
    $count = x($_REQUEST, 'count') ? $_REQUEST['count'] : 20;
    $page = x($_REQUEST, 'page') ? $_REQUEST['page'] - 1 : 0;
    if ($page < 0) {
        $page = 0;
    }
    $since_id = x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0;
    $max_id = x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0;
    //$since_id = 0;//$since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0);
    $start = $page * $count;
    //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false);
    if ($max_id > 0) {
        $sql_extra = 'AND `item`.`id` <= ' . intval($max_id);
    }
    require_once 'include/security.php';
    $item_normal = item_normal();
    $r = q("select * from item where allow_cid = ''  and allow_gid = ''\n\t\t\tand deny_cid  = ''  and deny_gid  = ''\n            and item_private = 0\n\t\t\t{$item_normal}\n\t\t\tand uid = " . $sys['channel_id'] . "\n\t\t\t{$sql_extra}\n\t\t\tAND id > %d group by mid\n\t\t\torder by received desc LIMIT %d OFFSET %d ", intval($since_id), intval($count), intval($start));
    xchan_query($r, true);
    $ret = api_format_items($r, $user_info);
    $data = array('$statuses' => $ret);
    switch ($type) {
        case "atom":
        case "rss":
            $data = api_rss_extra($a, $data, $user_info);
            break;
        case "as":
            $as = api_format_as($a, $ret, $user_info);
            $as['title'] = $a->config['sitename'] . " " . t('Public Timeline');
            $as['link']['url'] = $a->get_baseurl() . "/";
            return $as;
            break;
    }
    return api_apply_template("timeline", $type, $data);
}
Example #30
0
function public_content(&$a, $update = 0, $load = false)
{
    if ($load) {
        $_SESSION['loadtime'] = datetime_convert();
    }
    if (get_config('system', 'block_public') && !get_account_id() && !remote_channel()) {
        return login();
    }
    if (get_config('system', 'disable_discover_tab')) {
        return;
    }
    $item_normal = item_normal();
    if (!$update) {
        $maxheight = get_config('system', 'home_divmore_height');
        if (!$maxheight) {
            $maxheight = 400;
        }
        $o .= '<div id="live-public"></div>' . "\r\n";
        $o .= "<script> var profile_uid = " . (intval(local_channel()) ? local_channel() : -1) . "; 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' => 'public', '$uid' => local_channel() ? local_channel() : '0', '$gid' => '0', '$cid' => '0', '$cmin' => '0', '$cmax' => '99', '$star' => '0', '$liked' => '0', '$conv' => '0', '$spam' => '0', '$fh' => '1', '$nouveau' => '0', '$wall' => '0', '$list' => '0', '$page' => App::$pager['page'] != 1 ? App::$pager['page'] : 1, '$search' => '', '$order' => 'comment', '$file' => '', '$cats' => '', '$tags' => '', '$dend' => '', '$mid' => '', '$verb' => '', '$dbegin' => ''));
    }
    if ($update && !$load) {
        // only setup pagination on initial page view
        $pager_sql = '';
    } else {
        App::set_pager_itemspage(20);
        $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
    }
    require_once 'include/identity.php';
    require_once 'include/security.php';
    if (get_config('system', 'site_firehose')) {
        $uids = " and item.uid in ( " . stream_perms_api_uids(PERMS_PUBLIC) . " ) and item_private = 0  and item_wall = 1 ";
    } else {
        $sys = get_sys_channel();
        $uids = " and item.uid  = " . intval($sys['channel_id']) . " ";
        $sql_extra = item_permissions_sql($sys['channel_id']);
        App::$data['firehose'] = intval($sys['channel_id']);
    }
    if (get_config('system', 'public_list_mode')) {
        $page_mode = 'list';
    } else {
        $page_mode = 'client';
    }
    $simple_update = $update ? " and item.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 = '';
    }
    //logger('update: ' . $update . ' load: ' . $load);
    if ($update) {
        $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\tleft join abook on item.author_xchan = abook.abook_xchan\n\t\t\t\tWHERE true {$uids} {$item_normal}\n\t\t\t\tAND item.parent = item.id\n\t\t\t\tand (abook.abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t{$sql_extra3} {$sql_extra} {$sql_nets}\n\t\t\t\tORDER BY {$ordering} DESC {$pager_sql} ");
        } elseif ($update) {
            $r = q("SELECT distinct item.id AS item_id, {$ordering} FROM item\n\t\t\t\tleft join abook on item.author_xchan = abook.abook_xchan\n\t\t\t\tWHERE true {$uids} {$item_normal}\n\t\t\t\tAND item.parent = item.id {$simple_update}\n\t\t\t\tand (abook.abook_blocked = 0 or abook.abook_flags is null)\n\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\tWHERE true {$uids} {$item_normal}\n\t\t\t\tAND item.parent IN ( %s )\n\t\t\t\t{$sql_extra} ", dbesc($parents_str));
            xchan_query($items, true, -1);
            $items = fetch_post_tags($items, true);
            $items = conv_sort($items, $ordering);
        } else {
            $items = array();
        }
    }
    // fake it
    $mode = 'network';
    $o .= conversation($a, $items, $mode, $update, $page_mode);
    if ($items && !$update) {
        $o .= alt_pager($a, count($items));
    }
    return $o;
}