function dirstats_content(&$a) { $hubcount = get_config('dirstats', 'hubcount'); $zotcount = get_config('dirstats', 'zotcount'); $friendicacount = get_config('dirstats', 'friendicacount'); $diasporacount = get_config('dirstats', 'diasporacount'); $channelcount = get_config('dirstats', 'channelcount'); $friendicachannelcount = get_config('dirstats', 'friendicachannelcount'); $diasporachannelcount = get_config('dirstats', 'diasporachannelcount'); $over35s = get_config('dirstats', 'over35s'); $under35s = get_config('dirstats', 'under35s'); $average = get_config('dirstats', 'averageage'); $chatrooms = get_config('dirstats', 'chatrooms'); $tags = get_config('dirstats', 'tags'); $ob = App::get_observer(); $observer = $ob['xchan_hash']; // Requested by Martin $fountainofyouth = get_xconfig($observer, 'dirstats', 'averageage'); if (intval($fountainofyouth)) { $average = $fountainofyouth; } if (argv(1) == 'json') { $dirstats = array('hubcount' => $hubcount, 'zotcount' => $zotcount, 'friendicacount' => $friendicacount, 'diasporacount' => $diasporacount, 'channelcount' => $channelcount, 'friendicachannelcount' => $friendicachannelcount, 'diasporachannelcount' => $diasporachannelcount, 'over35s' => $over35s, 'under35s' => $under35s, 'average' => $average, 'chatrooms' => $chatrooms, 'tags' => $tags); echo json_return_and_die($dirstats); } elseif (argv(1) == 'genpost' && get_config('dirstats', 'allowfiledump')) { $result = '[b]Hub count[/b] : ' . $hubcount . "\n" . '[b]Hubzilla Hubs[/b] : ' . $zotcount . "\n" . '[b]Friendica Hubs[/b] : ' . $friendicacount . "\n" . '[b]Diaspora Pods[/b] : ' . $diasporacount . "\n" . '[b]Hubzilla Channels[/b] : ' . $channelcount . "\n" . '[b]Friendica Profiles[/b] : ' . $friendicachannelcount . "\n" . '[b]Diaspora Profiles[/b] : ' . $diasporachannelcount . "\n" . '[b]People aged 35 and above[/b] : ' . $over35s . "\n" . '[b]People aged 34 and below[/b] : ' . $under35s . "\n" . '[b]Average Age[/b] : ' . $average . "\n" . '[b]Known Chatrooms[/b] : ' . $chatrooms . "\n" . '[b]Unique Profile Tags[/b] : ' . $tags . "\n"; file_put_contents('genpost', $result); } else { $tpl = get_markup_template("dirstats.tpl", "addon/dirstats/"); return replace_macros($tpl, array('$title' => t('Hubzilla Directory Stats'), '$hubtitle' => t('Total Hubs'), '$hubcount' => $hubcount, '$zotlabel' => t('Hubzilla Hubs'), '$zotcount' => $zotcount, '$friendicalabel' => t('Friendica Hubs'), '$friendicacount' => $friendicacount, '$diasporalabel' => t('Diaspora Pods'), '$diasporacount' => $diasporacount, '$zotchanlabel' => t('Hubzilla Channels'), '$channelcount' => $channelcount, '$friendicachanlabel' => t('Friendica Channels'), '$friendicachannelcount' => $friendicachannelcount, '$diasporachanlabel' => t('Diaspora Channels'), '$diasporachannelcount' => $diasporachannelcount, '$over35label' => t('Aged 35 and above'), '$over35s' => $over35s, '$under35label' => t('Aged 34 and under'), '$under35s' => $under35s, '$averageagelabel' => t('Average Age'), '$average' => $average, '$chatlabel' => t('Known Chatrooms'), '$chatrooms' => $chatrooms, '$tagslabel' => t('Known Tags'), '$tags' => $tags, '$disclaimer' => t('Please note Diaspora and Friendica statistics are merely those **this directory** is aware of, and not all those known in the network. This also applies to chatrooms,'))); } }
/** * Set the mode we'll be displayed on */ private function set_mode($mode) { if ($this->get_mode() == $mode) { return; } $a = $this->get_app(); $this->observer = App::get_observer(); $ob_hash = $this->observer ? $this->observer['xchan_hash'] : ''; switch ($mode) { case 'network': $this->profile_owner = local_channel(); $this->writable = true; break; case 'channel': $this->profile_owner = App::$profile['profile_uid']; $this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments'); break; case 'display': // in this mode we set profile_owner after initialisation (from conversation()) and then // pull some trickery which allows us to re-invoke this function afterward // it's an ugly hack so FIXME $this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments'); break; case 'page': $this->profile_owner = App::$profile['uid']; $this->writable = perm_is_allowed($this->profile_owner, $ob_hash, 'post_comments'); break; default: logger('[ERROR] Conversation::set_mode : Unhandled mode (' . $mode . ').', LOGGER_DEBUG); return false; break; } $this->mode = $mode; }
function post() { $using_api = false; if (\App::$data['api_info'] && array_key_exists('media', $_FILES)) { $using_api = true; $user_info = \App::$data['api_info']; $nick = $user_info['screen_name']; $channel = get_channel_by_nick($user_info['screen_name']); } elseif (argc() > 1) { $channel = get_channel_by_nick(argv(1)); } if (!$channel) { killme(); } $observer = \App::get_observer(); $def_album = get_pconfig($channel['channel_id'], 'system', 'photo_path'); $def_attach = get_pconfig($channel['channel_id'], 'system', 'attach_path'); $r = attach_store($channel, $observer ? $observer['xchan_hash'] : '', '', array('source' => 'editor', 'visible' => 0, 'album' => $def_album, 'directory' => $def_attach, 'allow_cid' => '<' . $channel['channel_hash'] . '>')); if (!$r['success']) { notice($r['message'] . EOL); killme(); } if (intval($r['data']['is_photo'])) { $s = "\n\n" . $r['body'] . "\n\n"; } else { $s = "\n\n" . '[attachment]' . $r['data']['hash'] . ',' . $r['data']['revision'] . '[/attachment]' . "\n"; } if ($using_api) { return $s; } echo $s; killme(); }
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); }
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; }
function get() { // This doesn't work, so if (!is_developer()) { return; } if (argc() > 1) { $which = argv(1); } else { notice(t('Requested profile is not available.') . EOL); return; } $profile = 0; $profile = argv(1); profile_load($which, $profile); $r = q("select channel_id from channel where channel_address = '%s'", dbesc($which)); if ($r) { $owner = intval($r[0]['channel_id']); } $observer = \App::get_observer(); $ob_hash = $observer ? $observer['xchan_hash'] : ''; $perms = get_all_perms($owner, $ob_hash); if (!$perms['view_profile']) { notice(t('Permission denied.') . EOL); return; } $newmembertext = t('Some blurb about what to do when you\'re new here'); // By default, all badges are false $contactbadge = false; $profilebadge = false; $keywordsbadge = false; // Check number of contacts. Award a badge if over 10 // We'll figure these out on each page load instead of // writing them to the DB because that will mean one needs // to retain their achievements - eg, you can't add // a bunch of channels just to get your badge, and then // delete them all again. If these become popular or // used in profiles or something, we may need to reconsider // and add a table for this - because this won't scale. $r = q("select * from abook where abook_channel = %d", intval($owner)); if (count($r)) { $contacts = count($r); } // We're checking for 11 to adjust for the abook record for self if ($contacts >= 11) { $contactbadge = true; } // Check if an about field in the profile has been created. $r = q("select * from profile where uid = %d and about <> ''", intval($owner)); if ($r) { $profilebadge = 1; } // Check if keywords have been set $r = q("select * from profile where uid = %d and keywords <> ''", intval($owner)); if ($r) { $keywordsbadge = 1; } return replace_macros(get_markup_template("achievements.tpl"), array('$newmembertext' => $newmembertext, '$profilebadge' => $profilebadge, '$contactbadge' => $contactbadge, '$keywordsbadge' => $keywordsbadge, '$channelsbadge' => $channelsbadge)); }
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; }
function get() { if (!local_channel()) { if (remote_channel()) { $observer = \App::get_observer(); if ($observer && $observer['xchan_url']) { $parsed = @parse_url($observer['xchan_url']); if (!$parsed) { notice(t('Unable to find your hub.') . EOL); return; } $url = $parsed['scheme'] . '://' . $parsed['host'] . ($parsed['port'] ? ':' . $parsed['port'] : ''); $url .= '/oexchange'; $result = z_post_url($url, $_REQUEST); json_return_and_die($result); } } return login(false); } if (argc() > 1 && argv(1) === 'done') { info(t('Post successful.') . EOL); return; } $url = x($_REQUEST, 'url') && strlen($_REQUEST['url']) ? urlencode(notags(trim($_REQUEST['url']))) : ''; $title = x($_REQUEST, 'title') && strlen($_REQUEST['title']) ? '&title=' . urlencode(notags(trim($_REQUEST['title']))) : ''; $description = x($_REQUEST, 'description') && strlen($_REQUEST['description']) ? '&description=' . urlencode(notags(trim($_REQUEST['description']))) : ''; $tags = x($_REQUEST, 'tags') && strlen($_REQUEST['tags']) ? '&tags=' . urlencode(notags(trim($_REQUEST['tags']))) : ''; $ret = z_fetch_url(z_root() . '/urlinfo?f=&url=' . $url . $title . $description . $tags); if ($ret['success']) { $s = $ret['body']; } if (!strlen($s)) { return; } $post = array(); $post['profile_uid'] = local_channel(); $post['return'] = '/oexchange/done'; $post['body'] = $s; $post['type'] = 'wall'; $_REQUEST = $post; $mod = new Item(); $mod->post(); }
function connect_content(&$a) { $edit = local_channel() && local_channel() == App::$data['channel']['channel_id'] ? true : false; $text = get_pconfig(App::$data['channel']['channel_id'], 'system', 'selltext'); if ($edit) { $o = replace_macros(get_markup_template('sellpage_edit.tpl'), array('$header' => t('Premium Channel Setup'), '$address' => App::$data['channel']['channel_address'], '$premium' => array('premium', t('Enable premium channel connection restrictions'), App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM ? '1' : '', ''), '$lbl_about' => t('Please enter your restrictions or conditions, such as paypal receipt, usage guidelines, etc.'), '$text' => $text, '$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'), '$lbl2' => t('Potential connections will then see the following text before proceeding:'), '$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'), '$submit' => t('Submit'))); return $o; } else { if (!$text) { $text = t('(No specific instructions have been provided by the channel owner.)'); } $submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array('$continue' => t('Continue'), '$address' => App::$data['channel']['channel_address'])); $o = replace_macros(get_markup_template('sellpage_view.tpl'), array('$header' => t('Restricted or Premium Channel'), '$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'), '$text' => prepare_text($text), '$desc2' => t('By continuing, I certify that I have complied with any instructions provided on this page.'), '$submit' => $submit)); $arr = array('channel' => App::$data['channel'], 'observer' => App::get_observer(), 'sellpage' => $o, 'submit' => $submit); call_hooks('connect_premium', $arr); $o = $arr['sellpage']; } return $o; }
function init() { if (get_config('system', 'block_public') && !local_channel() && !remote_channel()) { return; } $o = ''; if (argc() > 1) { $nick = argv(1); profile_load($a, $nick); $channelx = channelx_by_nick($nick); if (!$channelx) { return; } \App::$data['channel'] = $channelx; $observer = \App::get_observer(); \App::$data['observer'] = $observer; $observer_xchan = $observer ? $observer['xchan_hash'] : ''; head_set_icon(\App::$data['channel']['xchan_photo_s']); \App::$page['htmlhead'] .= "<script> var profile_uid = " . (\App::$data['channel'] ? \App::$data['channel']['channel_id'] : 0) . "; </script>"; } return; }
function init() { if (observer_prohibited()) { return; } $o = ''; if (argc() > 1) { $nick = argv(1); profile_load($nick); $channelx = channelx_by_nick($nick); if (!$channelx) { return; } \App::$data['channel'] = $channelx; $observer = \App::get_observer(); \App::$data['observer'] = $observer; $observer_xchan = $observer ? $observer['xchan_hash'] : ''; head_set_icon(\App::$data['channel']['xchan_photo_s']); \App::$page['htmlhead'] .= "<script> var profile_uid = " . (\App::$data['channel'] ? \App::$data['channel']['channel_id'] : 0) . "; </script>"; } return; }
function post() { $using_api = x($_FILES, 'media') ? true : false; if ($using_api) { require_once 'include/api.php'; $user_info = api_get_user($a); $nick = $user_info['screen_name']; } else { if (argc() > 1) { $nick = argv(1); } } $channel = $nick ? get_channel_by_nick($nick) : false; if (!$channel) { if ($using_api) { return; } notice(t('Channel not found.') . EOL); killme(); } $observer = \App::get_observer(); $args = array('source' => 'editor', 'visible' => 0, 'contact_allow' => array($channel['channel_hash'])); $ret = photo_upload($channel, $observer, $args); if (!$ret['success']) { if ($using_api) { return; } notice($ret['message']); killme(); } if ($using_api) { return "\n\n" . $ret['body'] . "\n\n"; } else { echo "\n\n" . $ret['body'] . "\n\n"; } killme(); }
function get($update = 0, $load = false) { if ($load) { $_SESSION['loadtime'] = datetime_convert(); } $checkjs = new \Zotlabs\Web\CheckJS(1); $category = $datequery = $datequery2 = ''; $mid = x($_REQUEST, 'mid') ? $_REQUEST['mid'] : ''; $datequery = x($_GET, 'dend') && is_a_date_arg($_GET['dend']) ? notags($_GET['dend']) : ''; $datequery2 = x($_GET, 'dbegin') && is_a_date_arg($_GET['dbegin']) ? notags($_GET['dbegin']) : ''; if (observer_prohibited(true)) { return login(); } $category = x($_REQUEST, 'cat') ? $_REQUEST['cat'] : ''; $hashtags = x($_REQUEST, 'tag') ? $_REQUEST['tag'] : ''; $groups = array(); $o = ''; if ($update) { // Ensure we've got a profile owner if updating. \App::$profile['profile_uid'] = \App::$profile_uid = $update; } else { if (\App::$profile['profile_uid'] == local_channel()) { nav_set_selected('home'); } } $is_owner = local_channel() && \App::$profile['profile_uid'] == local_channel() ? true : false; $channel = \App::get_channel(); $observer = \App::get_observer(); $ob_hash = $observer ? $observer['xchan_hash'] : ''; $perms = get_all_perms(\App::$profile['profile_uid'], $ob_hash); if (!$perms['view_stream']) { // We may want to make the target of this redirect configurable if ($perms['view_profile']) { notice(t('Insufficient permissions. Request redirected to profile page.') . EOL); goaway(z_root() . "/profile/" . \App::$profile['channel_address']); } notice(t('Permission denied.') . EOL); return; } if (!$update) { $o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); $o .= common_friends_visitor_widget(\App::$profile['profile_uid']); if ($channel && $is_owner) { $channel_acl = array('allow_cid' => $channel['channel_allow_cid'], 'allow_gid' => $channel['channel_allow_gid'], 'deny_cid' => $channel['channel_deny_cid'], 'deny_gid' => $channel['channel_deny_gid']); } else { $channel_acl = array(); } if ($perms['post_wall']) { $x = array('is_owner' => $is_owner, 'allow_location' => ($is_owner || $observer) && intval(get_pconfig(\App::$profile['profile_uid'], 'system', 'use_browser_location')) ? true : false, 'default_location' => $is_owner ? \App::$profile['channel_location'] : '', 'nickname' => \App::$profile['channel_address'], 'lockstate' => strlen(\App::$profile['channel_allow_cid']) || strlen(\App::$profile['channel_allow_gid']) || strlen(\App::$profile['channel_deny_cid']) || strlen(\App::$profile['channel_deny_gid']) ? 'lock' : 'unlock', 'acl' => $is_owner ? populate_acl($channel_acl, true, \PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : '', 'showacl' => $is_owner ? 'yes' : '', 'bang' => '', 'visitor' => $is_owner || $observer ? true : false, 'profile_uid' => \App::$profile['profile_uid'], 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true); $o .= status_editor($a, $x); } } /** * Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups */ $item_normal = item_normal(); $sql_extra = item_permissions_sql(\App::$profile['profile_uid']); if (get_pconfig(\App::$profile['profile_uid'], 'system', 'channel_list_mode') && !$mid) { $page_mode = 'list'; } else { $page_mode = 'client'; } $abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " "; $simple_update = $update ? " AND item_unseen = 1 " : ''; \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n"; if ($update && $_SESSION['loadtime']) { $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC', 'UTC', $_SESSION['loadtime']) . "' ) "; } if ($load) { $simple_update = ''; } if ($update && !$load) { if ($mid) { $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d {$item_normal}\n\t\t\t\t\tAND item_wall = 1 AND item_unseen = 1 {$sql_extra} limit 1", dbesc($mid . '%'), intval(\App::$profile['profile_uid'])); } else { $r = q("SELECT distinct parent AS `item_id`, created from item\n\t\t\t\t\tleft join abook on ( item.owner_xchan = abook.abook_xchan {$abook_uids} )\n\t\t\t\t\tWHERE uid = %d {$item_normal}\n\t\t\t\t\tAND item_wall = 1 {$simple_update}\n\t\t\t\t\tAND (abook.abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t\t{$sql_extra}\n\t\t\t\t\tORDER BY created DESC", intval(\App::$profile['profile_uid'])); $_SESSION['loadtime'] = datetime_convert(); } } else { if (x($category)) { $sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY)); } if (x($hashtags)) { $sql_extra .= protect_sprintf(term_query('item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG)); } if ($datequery) { $sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery)))); } if ($datequery2) { $sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(), '', $datequery2)))); } $itemspage = get_pconfig(local_channel(), 'system', 'itemspage'); \App::set_pager_itemspage(intval($itemspage) ? $itemspage : 20); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); if ($load || $checkjs->disabled()) { if ($mid) { $r = q("SELECT parent AS item_id from item where mid = '%s' and uid = %d {$item_normal}\n\t\t\t\t\t\tAND item_wall = 1 {$sql_extra} limit 1", dbesc($mid), intval(\App::$profile['profile_uid'])); if (!$r) { notice(t('Permission denied.') . EOL); } } else { $r = q("SELECT distinct id AS item_id, created FROM item \n\t\t\t\t\t\tleft join abook on item.author_xchan = abook.abook_xchan\n\t\t\t\t\t\tWHERE uid = %d {$item_normal}\n\t\t\t\t\t\tAND item_wall = 1 and item_thread_top = 1\n\t\t\t\t\t\tAND (abook_blocked = 0 or abook.abook_flags is null)\n\t\t\t\t\t\t{$sql_extra} {$sql_extra2}\n\t\t\t\t\t\tORDER BY created DESC {$pager_sql} ", intval(\App::$profile['profile_uid'])); } } else { $r = array(); } } if ($r) { $parents_str = ids_to_querystr($r, 'item_id'); $items = q("SELECT `item`.*, `item`.`id` AS `item_id` \n\t\t\t\tFROM `item`\n\t\t\t\tWHERE `item`.`uid` = %d {$item_normal}\n\t\t\t\tAND `item`.`parent` IN ( %s )\n\t\t\t\t{$sql_extra} ", intval(\App::$profile['profile_uid']), dbesc($parents_str)); xchan_query($items); $items = fetch_post_tags($items, true); $items = conv_sort($items, 'created'); if ($load && $mid && !count($items)) { // This will happen if we don't have sufficient permissions // to view the parent item (or the item itself if it is toplevel) notice(t('Permission denied.') . EOL); } } else { $items = array(); } if (!$update && !$load) { // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. $maxheight = get_pconfig(\App::$profile['profile_uid'], 'system', 'channel_divmore_height'); if (!$maxheight) { $maxheight = 400; } $o .= '<div id="live-channel"></div>' . "\r\n"; $o .= "<script> var profile_uid = " . \App::$profile['profile_uid'] . "; var netargs = '?f='; var profile_page = " . \App::$pager['page'] . "; divmore_height = " . intval($maxheight) . "; </script>\r\n"; \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"), array('$baseurl' => z_root(), '$pgtype' => 'channel', '$uid' => \App::$profile['profile_uid'] ? \App::$profile['profile_uid'] : '0', '$gid' => '0', '$cid' => '0', '$cmin' => '0', '$cmax' => '0', '$star' => '0', '$liked' => '0', '$conv' => '0', '$spam' => '0', '$nouveau' => '0', '$wall' => '1', '$fh' => '0', '$page' => \App::$pager['page'] != 1 ? \App::$pager['page'] : 1, '$search' => '', '$order' => '', '$list' => x($_REQUEST, 'list') ? intval($_REQUEST['list']) : 0, '$file' => '', '$cats' => $category ? $category : '', '$tags' => $hashtags ? $hashtags : '', '$mid' => $mid, '$verb' => '', '$dend' => $datequery, '$dbegin' => $datequery2)); } $update_unseen = ''; if ($page_mode === 'list') { /** * in "list mode", only mark the parent item and any like activities as "seen". * We won't distinguish between comment likes and post likes. The important thing * is that the number of unseen comments will be accurate. The SQL to separate the * comment likes could also get somewhat hairy. */ if ($parents_str) { $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; } } else { if ($parents_str) { $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; } } if ($is_owner && $update_unseen) { $r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d {$update_unseen}", intval(local_channel())); } if ($checkjs->disabled()) { $o .= conversation($a, $items, 'channel', $update, 'traditional'); } else { $o .= conversation($a, $items, 'channel', $update, $page_mode); } if (!$update || $checkjs->disabled()) { $o .= alt_pager($a, count($items)); if ($mid && $items[0]['title']) { \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; } } if ($mid) { $o .= '<div id="content-complete"></div>'; } return $o; }
/** * API: map_shareUserLocation * Share real-time location data by generating an access token and posting it. * $data contains the ACL specified by the user. The access token is returned * @param type $data */ function map_shareUserLocation($data) { $resource_type = 'locserv'; $token = random_string(); //Extract the ACL for permissions $args = array(); $args['allow_cid'] = perms2str($data['contact_allow']); $args['allow_gid'] = perms2str($data['group_allow']); $args['deny_cid'] = perms2str($data['contact_deny']); $args['deny_gid'] = perms2str($data['group_deny']); $args['token'] = $token; array_key_exists('token', $args) ? $token = $args['token'] : ($token = ''); $channel = App::get_channel(); $observer = App::get_observer(); $acl = new Zotlabs\Access\AccessList($channel); if (array_key_exists('allow_cid', $args)) { $acl->set($args); } $ac = $acl->get(); $mid = item_message_id(); // Generate a unique message ID $arr = array(); // Initialize the array of parameters for the post // If this were an actual location, ACTIVITY_OBJ_LOCATION would make sense, // but since this is actually an access token to retrieve location data, we'll // have to use something more vague $objtype = ACTIVITY_OBJ_THING; //check if item for this object exists $y = q("SELECT mid FROM item WHERE obj_type = '%s' AND resource_type = '%s' AND resource_id = '%s' AND uid = %d LIMIT 1", dbesc(ACTIVITY_POST), dbesc($resource_type), dbesc($token), intval($channel['channel_id'])); if ($y) { notice('Error posting access token. Item already exists.'); logger('map plugin: Error posting access token. item already exists: ' . json_encode($y)); die; } $body = $channel['channel_name'] . ' shared their location with you. '; $link = z_root() . '/map/?action=getLatestLocation&token=' . $token; /* * The local map plugin link for the receiver only needs the token. The plugin * will look up the stored item table record and use the object->locationDataType * to determine what kind of location data has been shared. This will allow it * to make the proper request for data to the sharer's hub. For example, if the * object->locationDataType is a dynamicMarker, then the receiver will request * only the most recent location associated with that token */ $body .= '[url=' . z_root() . '/map?action=getLatestLocation&token=' . $token . ']Click here to view[/url]'; // Encode object according to Activity Streams: http://activitystrea.ms/specs/json/1.0/ $object = json_encode(array('type' => $objtype, 'title' => 'location data access token', 'locationDataType' => 'dynamicMarker', 'id' => $token, 'url' => $link)); if (intval($data['visible']) || $data['visible'] === 'true') { $visible = 1; } else { $visible = 0; } $item_hidden = $visible ? 0 : 1; $arr['aid'] = $channel['channel_account_id']; $arr['uid'] = $channel['channel_id']; $arr['mid'] = $mid; $arr['parent_mid'] = $mid; $arr['item_hidden'] = $item_hidden; $arr['resource_type'] = $resource_type; $arr['resource_id'] = $token; $arr['owner_xchan'] = $channel['channel_hash']; $arr['author_xchan'] = $observer['xchan_hash']; $arr['title'] = 'Shared Location'; $arr['allow_cid'] = $ac['allow_cid']; $arr['allow_gid'] = $ac['allow_gid']; $arr['deny_cid'] = $ac['deny_cid']; $arr['deny_gid'] = $ac['deny_gid']; $arr['item_wall'] = 0; $arr['item_origin'] = 1; $arr['item_thread_top'] = 1; $arr['item_private'] = intval($acl->is_private()); $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid']; $arr['verb'] = ACTIVITY_POST; $arr['obj_type'] = $objtype; $arr['object'] = $object; $arr['body'] = $body; $post = item_store($arr); $item_id = $post['item_id']; if ($item_id) { proc_run('php', "include/notifier.php", "activity", $item_id); echo json_encode(array('item' => $arr, 'status' => true)); } else { echo json_encode(array('item' => null, 'status' => false)); } die; }
/** * @brief Returns array of channels which have recursive permission for a file * * @param $arr_allow_cid * @param $arr_allow_gid * @param $arr_deny_cid * @param $arr_deny_gid * @param $folder_hash */ function recursive_activity_recipients($arr_allow_cid, $arr_allow_gid, $arr_deny_cid, $arr_deny_gid, $folder_hash) { $ret = array(); $parent_arr = array(); $count_values = array(); $poster = App::get_observer(); //turn allow_gid into allow_cid's foreach ($arr_allow_gid as $gid) { $in_group = group_get_members($gid); $arr_allow_cid = array_unique(array_merge($arr_allow_cid, $in_group)); } $count = 0; while ($folder_hash) { $x = q("SELECT allow_cid, allow_gid, deny_cid, deny_gid, folder FROM attach WHERE hash = '%s' LIMIT 1", dbesc($folder_hash)); //only process private folders if ($x[0]['allow_cid'] || $x[0]['allow_gid'] || $x[0]['deny_cid'] || $x[0]['deny_gid']) { $parent_arr['allow_cid'][] = expand_acl($x[0]['allow_cid']); $parent_arr['allow_gid'][] = expand_acl($x[0]['allow_gid']); /** * @TODO should find a much better solution for the allow_cid <-> allow_gid problem. * Do not use allow_gid for now. Instead lookup the members of the group directly and add them to allow_cid. * */ if ($parent_arr['allow_gid']) { foreach ($parent_arr['allow_gid'][$count] as $gid) { $in_group = group_get_members($gid); $parent_arr['allow_cid'][$count] = array_unique(array_merge($parent_arr['allow_cid'][$count], $in_group)); } } $parent_arr['deny_cid'][] = expand_acl($x[0]['deny_cid']); $parent_arr['deny_gid'][] = expand_acl($x[0]['deny_gid']); $count++; } $folder_hash = $x[0]['folder']; } //if none of the parent folders is private just return file perms if (!$parent_arr['allow_cid'] && !$parent_arr['allow_gid'] && !$parent_arr['deny_cid'] && !$parent_arr['deny_gid']) { $ret['allow_gid'] = $arr_allow_gid; $ret['allow_cid'] = $arr_allow_cid; $ret['deny_gid'] = $arr_deny_gid; $ret['deny_cid'] = $arr_deny_cid; return $ret; } //if there are no perms on the file we get them from the first parent folder if (!$arr_allow_cid && !$arr_allow_gid && !$arr_deny_cid && !$arr_deny_gid) { $arr_allow_cid = $parent_arr['allow_cid'][0]; $arr_allow_gid = $parent_arr['allow_gid'][0]; $arr_deny_cid = $parent_arr['deny_cid'][0]; $arr_deny_gid = $parent_arr['deny_gid'][0]; } //allow_cid $r_arr_allow_cid = false; foreach ($parent_arr['allow_cid'] as $folder_arr_allow_cid) { foreach ($folder_arr_allow_cid as $ac_hash) { $count_values[$ac_hash]++; } } foreach ($arr_allow_cid as $fac_hash) { if ($count_values[$fac_hash] == $count) { $r_arr_allow_cid[] = $fac_hash; } } //allow_gid $r_arr_allow_gid = false; foreach ($parent_arr['allow_gid'] as $folder_arr_allow_gid) { foreach ($folder_arr_allow_gid as $ag_hash) { $count_values[$ag_hash]++; } } foreach ($arr_allow_gid as $fag_hash) { if ($count_values[$fag_hash] == $count) { $r_arr_allow_gid[] = $fag_hash; } } //deny_gid foreach ($parent_arr['deny_gid'] as $folder_arr_deny_gid) { $r_arr_deny_gid = array_merge($arr_deny_gid, $folder_arr_deny_gid); } $r_arr_deny_gid = array_unique($r_arr_deny_gid); //deny_cid foreach ($parent_arr['deny_cid'] as $folder_arr_deny_cid) { $r_arr_deny_cid = array_merge($arr_deny_cid, $folder_arr_deny_cid); } $r_arr_deny_cid = array_unique($r_arr_deny_cid); //if none is allowed restrict to self if ($r_arr_allow_gid === false && $r_arr_allow_cid === false) { $ret['allow_cid'] = $poster['xchan_hash']; } else { $ret['allow_gid'] = $r_arr_allow_gid; $ret['allow_cid'] = $r_arr_allow_cid; $ret['deny_gid'] = $r_arr_deny_gid; $ret['deny_cid'] = $r_arr_deny_cid; } return $ret; }
/** * @brief Creates a new file in the directory. * * Data will either be supplied as a stream resource, or in certain cases * as a string. Keep in mind that you may have to support either. * * After successful creation of the file, you may choose to return the ETag * of the new file here. * * @throw \Sabre\DAV\Exception\Forbidden * @param string $name Name of the file * @param resource|string $data Initial payload * @return null|string ETag */ public function createFile($name, $data = null) { logger('create file in directory ' . $name, LOGGER_DEBUG); if (!$this->auth->owner_id) { logger('permission denied ' . $name); throw new DAV\Exception\Forbidden('Permission denied.'); } if (!perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'write_storage')) { logger('permission denied ' . $name); throw new DAV\Exception\Forbidden('Permission denied.'); } $mimetype = z_mime_content_type($name); $c = q("SELECT * FROM channel WHERE channel_id = %d AND channel_removed = 0 LIMIT 1", intval($this->auth->owner_id)); if (!$c) { logger('no channel'); throw new DAV\Exception\Forbidden('Permission denied.'); } $filesize = 0; $hash = random_string(); $f = 'store/' . $this->auth->owner_nick . '/' . ($this->os_path ? $this->os_path . '/' : '') . $hash; $direct = null; if ($this->folder_hash) { $r = q("select * from attach where hash = '%s' and is_dir = 1 and uid = %d limit 1", dbesc($this->folder_hash), intval($c[0]['channel_id'])); if ($r) { $direct = $r[0]; } } if ($direct && ($direct['allow_cid'] || $direct['allow_gid'] || $direct['deny_cid'] || $direct['deny_gid'])) { $allow_cid = $direct['allow_cid']; $allow_gid = $direct['allow_gid']; $deny_cid = $direct['deny_cid']; $deny_gid = $direct['deny_gid']; } else { $allow_cid = $c[0]['channel_allow_cid']; $allow_gid = $c[0]['channel_allow_gid']; $deny_cid = $c[0]['channel_deny_cid']; $deny_gid = $c[0]['channel_deny_gid']; } $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, folder, os_storage, filetype, filesize, revision, is_photo, content, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($c[0]['channel_account_id']), intval($c[0]['channel_id']), dbesc($hash), dbesc($this->auth->observer), dbesc($name), dbesc($this->folder_hash), intval(1), dbesc($mimetype), intval($filesize), intval(0), intval($is_photo), dbesc($f), dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid)); // returns the number of bytes that were written to the file, or FALSE on failure $size = file_put_contents($f, $data); // delete attach entry if file_put_contents() failed if ($size === false) { logger('file_put_contents() failed to ' . $f); attach_delete($c[0]['channel_id'], $hash); return; } // returns now $edited = datetime_convert(); $is_photo = 0; $x = @getimagesize($f); logger('getimagesize: ' . print_r($x, true), LOGGER_DATA); if ($x && ($x[2] === IMAGETYPE_GIF || $x[2] === IMAGETYPE_JPEG || $x[2] === IMAGETYPE_PNG)) { $is_photo = 1; } // updates entry with filesize and timestamp $d = q("UPDATE attach SET filesize = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d", dbesc($size), intval($is_photo), dbesc($edited), dbesc($hash), intval($c[0]['channel_id'])); // update the folder's lastmodified timestamp $e = q("UPDATE attach SET edited = '%s' WHERE hash = '%s' AND uid = %d", dbesc($edited), dbesc($this->folder_hash), intval($c[0]['channel_id'])); $maxfilesize = get_config('system', 'maxfilesize'); if ($maxfilesize && $size > $maxfilesize) { attach_delete($c[0]['channel_id'], $hash); return; } // check against service class quota $limit = engr_units_to_bytes(service_class_fetch($c[0]['channel_id'], 'attach_upload_limit')); if ($limit !== false) { $x = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d ", intval($c[0]['channel_account_id'])); if ($x && $x[0]['total'] + $size > $limit) { logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . userReadableSize($limit)); attach_delete($c[0]['channel_id'], $hash); return; } } if ($is_photo) { $album = ''; if ($this->folder_hash) { $f1 = q("select filename from attach WHERE hash = '%s' AND uid = %d", dbesc($this->folder_hash), intval($c[0]['channel_id'])); if ($f1) { $album = $f1[0]['filename']; } } require_once 'include/photos.php'; $args = array('resource_id' => $hash, 'album' => $album, 'os_path' => $f, 'filename' => $name, 'getimagesize' => $x, 'directory' => $direct); $p = photo_upload($c[0], \App::get_observer(), $args); } $sync = attach_export_data($c[0], $hash); if ($sync) { build_sync_packet($c[0]['channel_id'], array('file' => array($sync))); } }
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; }
function init() { $prvcachecontrol = false; $streaming = null; $channel = null; switch (argc()) { case 4: $person = argv(3); $res = argv(2); $type = argv(1); break; case 2: $photo = argv(1); break; case 1: default: killme(); // NOTREACHED } $observer_xchan = get_observer_hash(); $default = get_default_profile_photo(); if (isset($type)) { /** * Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites. * */ if ($type === 'profile') { switch ($res) { case 'm': $resolution = 5; $default = get_default_profile_photo(80); break; case 's': $resolution = 6; $default = get_default_profile_photo(48); break; case 'l': default: $resolution = 4; break; } } $uid = $person; $d = ['imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '']; call_hooks('get_profile_photo', $d); $resolution = $d['imgscale']; $uid = $d['channel_id']; $default = $d['default']; $data = $d['data']; $mimetype = $d['mimetype']; if (!$data) { $r = q("SELECT * FROM photo WHERE imgscale = %d AND uid = %d AND photo_usage = %d LIMIT 1", intval($resolution), intval($uid), intval(PHOTO_PROFILE)); if ($r) { $data = dbunescbin($r[0]['content']); $mimetype = $r[0]['mimetype']; } if (intval($r[0]['os_storage'])) { $data = file_get_contents($data); } } if (!$data) { $data = file_get_contents($default); } if (!$mimetype) { $mimetype = 'image/png'; } } else { /** * Other photos */ /* Check for a cookie to indicate display pixel density, in order to detect high-resolution displays. This procedure was derived from the "Retina Images" by Jeremey Worboys, used in accordance with the Creative Commons Attribution 3.0 Unported License. Project link: https://github.com/Retina-Images/Retina-Images License link: http://creativecommons.org/licenses/by/3.0/ */ $cookie_value = false; if (isset($_COOKIE['devicePixelRatio'])) { $cookie_value = intval($_COOKIE['devicePixelRatio']); } else { // Force revalidation of cache on next request $cache_directive = 'no-cache'; $status = 'no cookie'; } $resolution = 0; if (strpos($photo, '.') !== false) { $photo = substr($photo, 0, strpos($photo, '.')); } if (substr($photo, -2, 1) == '-') { $resolution = intval(substr($photo, -1, 1)); $photo = substr($photo, 0, -2); // If viewing on a high-res screen, attempt to serve a higher resolution image: if ($resolution == 2 && $cookie_value > 1) { $resolution = 1; } } // If using resolution 1, make sure it exists before proceeding: if ($resolution == 1) { $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution)); if (!$r) { $resolution = 2; } } $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution)); if ($r) { $allowed = $r[0]['uid'] ? perm_is_allowed($r[0]['uid'], $observer_xchan, 'view_storage') : true; $sql_extra = permissions_sql($r[0]['uid']); if (!$sql_extra) { $sql_extra = ' and true '; } // Only check permissions on normal photos. Those photos we don't check includes // profile photos, xchan photos (which are also profile photos), 'thing' photos, // and cover photos $sql_extra = " and (( photo_usage = 0 {$sql_extra} ) or photo_usage != 0 )"; $channel = channelx_by_n($r[0]['uid']); // Now we'll see if we can access the photo $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d {$sql_extra} LIMIT 1", dbesc($photo), intval($resolution)); if ($r && $allowed) { $data = dbunescbin($r[0]['content']); $mimetype = $r[0]['mimetype']; if (intval($r[0]['os_storage'])) { $streaming = $data; } } else { // Does the picture exist? It may be a remote person with no credentials, // but who should otherwise be able to view it. Show a default image to let // them know permissions was denied. It may be possible to view the image // through an authenticated profile visit. // There won't be many completely unauthorised people seeing this because // they won't have the photo link, so there's a reasonable chance that the person // might be able to obtain permission to view it. $r = q("SELECT * FROM `photo` WHERE `resource_id` = '%s' AND `imgscale` = %d LIMIT 1", dbesc($photo), intval($resolution)); if ($r) { logger('mod_photo: forbidden. ' . \App::$query_string); $observer = \App::get_observer(); logger('mod_photo: observer = ' . ($observer ? $observer['xchan_addr'] : '(not authenticated)')); $data = file_get_contents('images/nosign.png'); $mimetype = 'image/png'; $prvcachecontrol = true; } } } } if (!isset($data)) { if (isset($resolution)) { switch ($resolution) { case 4: $data = file_get_contents(get_default_profile_photo()); $mimetype = 'image/png'; break; case 5: $data = file_get_contents(get_default_profile_photo(80)); $mimetype = 'image/png'; break; case 6: $data = file_get_contents(get_default_profile_photo(48)); $mimetype = 'image/png'; break; default: killme(); // NOTREACHED break; } } } if (isset($res) && intval($res) && $res < 500) { $ph = photo_factory($data, $mimetype); if ($ph->is_valid()) { $ph->scaleImageSquare($res); $data = $ph->imageString(); $mimetype = $ph->getType(); } } // Writing in cachefile if (isset($cachefile) && $cachefile != '') { file_put_contents($cachefile, $data); } if (function_exists('header_remove')) { header_remove('Pragma'); header_remove('pragma'); } header("Content-type: " . $mimetype); if ($prvcachecontrol) { // it is a private photo that they have no permission to view. // tell the browser not to cache it, in case they authenticate // and subsequently have permission to see it header("Cache-Control: no-store, no-cache, must-revalidate"); } else { // The photo cache default is 1 day to provide a privacy trade-off, // as somebody reducing photo permissions on a photo that is already // "in the wild" won't be able to stop the photo from being viewed // for this amount amount of time once it is in the browser cache. // The privacy expectations of your site members and their perception // of privacy where it affects the entire project may be affected. // This has performance considerations but we highly recommend you // leave it alone. $cache = get_config('system', 'photo_cache_time'); if (!$cache) { $cache = 3600 * 24; } // 1 day header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT"); header("Cache-Control: max-age=" . $cache); } // If it's a file resource, stream it. if ($streaming && $channel) { if (strpos($streaming, 'store') !== false) { $istream = fopen($streaming, 'rb'); } else { $istream = fopen('store/' . $channel['channel_address'] . '/' . $streaming, 'rb'); } $ostream = fopen('php://output', 'wb'); if ($istream && $ostream) { pipe_streams($istream, $ostream); fclose($istream); fclose($ostream); } } else { echo $data; } killme(); // NOTREACHED }
function init() { // We need this to make sure the channel theme is always loaded. $which = argv(1); $profile = 0; profile_load($a, $which, $profile); if (\App::$profile['profile_uid']) { head_set_icon(\App::$profile['thumb']); } // load the item here in the init function because we need to extract // the page layout and initialise the correct theme. $observer = \App::get_observer(); $ob_hash = $observer ? $observer['xchan_hash'] : ''; // perm_is_allowed is denied unconditionally when 'site blocked to unauthenticated members'. // This bypasses that restriction for sys channel (public) content if (!perm_is_allowed(\App::$profile['profile_uid'], $ob_hash, 'view_pages') && !is_sys_channel(\App::$profile['profile_uid'])) { notice(t('Permission denied.') . EOL); return; } if (argc() < 3) { notice(t('Invalid item.') . EOL); return; } $channel_address = argv(1); // The page link title was stored in a urlencoded format // php or the browser may/will have decoded it, so re-encode it for our search $page_id = urlencode(argv(2)); $u = q("select channel_id from channel where channel_address = '%s' limit 1", dbesc($channel_address)); if (!$u) { notice(t('Channel not found.') . EOL); return; } if ($_REQUEST['rev']) { $revision = " and revision = " . intval($_REQUEST['rev']) . " "; } else { $revision = " order by revision desc "; } require_once 'include/security.php'; $sql_options = item_permissions_sql($u[0]['channel_id']); $r = q("select item.* from item left join item_id on item.id = item_id.iid\n\t\t\twhere item.uid = %d and sid = '%s' and item.item_delayed = 0 and (( service = 'WEBPAGE' and item_type = %d ) \n\t\t\tOR ( service = 'PDL' AND item_type = %d )) {$sql_options} {$revision} limit 1", intval($u[0]['channel_id']), dbesc($page_id), intval(ITEM_TYPE_WEBPAGE), intval(ITEM_TYPE_PDL)); if (!$r) { // Check again with no permissions clause to see if it is a permissions issue $x = q("select item.* from item left join item_id on item.id = item_id.iid\n\t\t\twhere item.uid = %d and sid = '%s' and item.item_delayed = 0 and service = 'WEBPAGE' and \n\t\t\titem_type = %d {$revision} limit 1", intval($u[0]['channel_id']), dbesc($page_id), intval(ITEM_TYPE_WEBPAGE)); if ($x) { // Yes, it's there. You just aren't allowed to see it. notice(t('Permission denied.') . EOL); } else { notice(t('Page not found.') . EOL); } return; } if ($r[0]['title']) { \App::$page['title'] = escape_tags($r[0]['title']); } if ($r[0]['item_type'] == ITEM_TYPE_PDL) { \App::$comanche = new \Zotlabs\Render\Comanche(); \App::$comanche->parse($r[0]['body']); \App::$pdl = $r[0]['body']; } elseif ($r[0]['layout_mid']) { $l = q("select body from item where mid = '%s' and uid = %d limit 1", dbesc($r[0]['layout_mid']), intval($u[0]['channel_id'])); if ($l) { \App::$comanche = new \Zotlabs\Render\Comanche(); \App::$comanche->parse($l[0]['body']); \App::$pdl = $l[0]['body']; } } \App::$data['webpage'] = $r; }
function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) { // Hide all [noparse] contained bbtags by spacefying them if (strpos($Text, '[noparse]') !== false) { $Text = preg_replace_callback("/\\[noparse\\](.*?)\\[\\/noparse\\]/ism", 'bb_spacefy', $Text); } if (strpos($Text, '[nobb]') !== false) { $Text = preg_replace_callback("/\\[nobb\\](.*?)\\[\\/nobb\\]/ism", 'bb_spacefy', $Text); } if (strpos($Text, '[pre]') !== false) { $Text = preg_replace_callback("/\\[pre\\](.*?)\\[\\/pre\\]/ism", 'bb_spacefy', $Text); } // If we find any event code, turn it into an event. // After we're finished processing the bbcode we'll // replace all of the event code with a reformatted version. $ev = bbtoevent($Text); // process [observer] tags before we do anything else because we might // be stripping away stuff that then doesn't need to be worked on anymore if ($cache) { $observer = false; } else { $observer = App::get_observer(); } if (strpos($Text, '[/observer]') !== false || strpos($Text, '[/rpost]') !== false) { if ($observer) { $Text = preg_replace("/\\[observer\\=1\\](.*?)\\[\\/observer\\]/ism", '$1', $Text); $Text = preg_replace("/\\[observer\\=0\\].*?\\[\\/observer\\]/ism", '', $Text); $Text = preg_replace_callback("/\\[rpost(=(.*?))?\\](.*?)\\[\\/rpost\\]/ism", 'rpost_callback', $Text); } else { $Text = preg_replace("/\\[observer\\=1\\].*?\\[\\/observer\\]/ism", '', $Text); $Text = preg_replace("/\\[observer\\=0\\](.*?)\\[\\/observer\\]/ism", '$1', $Text); $Text = preg_replace("/\\[rpost(=.*?)?\\](.*?)\\[\\/rpost\\]/ism", '', $Text); } } if ($cache) { $channel = false; } else { $channel = App::get_channel(); } if (strpos($Text, '[/channel]') !== false) { if ($channel) { $Text = preg_replace("/\\[channel\\=1\\](.*?)\\[\\/channel\\]/ism", '$1', $Text); $Text = preg_replace("/\\[channel\\=0\\].*?\\[\\/channel\\]/ism", '', $Text); } else { $Text = preg_replace("/\\[channel\\=1\\].*?\\[\\/channel\\]/ism", '', $Text); $Text = preg_replace("/\\[channel\\=0\\](.*?)\\[\\/channel\\]/ism", '$1', $Text); } } $x = bb_extract_images($Text); $Text = $x['body']; $saved_images = $x['images']; $Text = str_replace(array('[baseurl]', '[sitename]'), array(z_root(), get_config('system', 'sitename')), $Text); // Replace any html brackets with HTML Entities to prevent executing HTML or script // Don't use strip_tags here because it breaks [url] search by replacing & with amp $Text = str_replace("<", "<", $Text); $Text = str_replace(">", ">", $Text); // Convert new line chars to html <br /> tags // nlbr seems to be hopelessly messed up // $Text = nl2br($Text); // We'll emulate it. $Text = str_replace("\r\n", "\n", $Text); $Text = str_replace(array("\r", "\n"), array('<br />', '<br />'), $Text); if ($preserve_nl) { $Text = str_replace(array("\n", "\r"), array('', ''), $Text); } $Text = str_replace(array("\t", " "), array(" ", " "), $Text); // Set up the parameters for a URL search string $URLSearchString = "^\\[\\]"; // Set up the parameters for a MAIL search string $MAILSearchString = $URLSearchString; // replace [observer.baseurl] if ($observer) { $s1 = '<span class="bb_observer" title="' . t('Different viewers will see this text differently') . '">'; $s2 = '</span>'; $obsBaseURL = $observer['xchan_connurl']; $obsBaseURL = preg_replace("/\\/poco\\/.*\$/", '', $obsBaseURL); $Text = str_replace('[observer.baseurl]', $obsBaseURL, $Text); $Text = str_replace('[observer.url]', $observer['xchan_url'], $Text); $Text = str_replace('[observer.name]', $s1 . $observer['xchan_name'] . $s2, $Text); $Text = str_replace('[observer.address]', $s1 . $observer['xchan_addr'] . $s2, $Text); $Text = str_replace('[observer.webname]', substr($observer['xchan_addr'], 0, strpos($observer['xchan_addr'], '@')), $Text); $Text = str_replace('[observer.photo]', $s1 . '[zmg]' . $observer['xchan_photo_l'] . '[/zmg]' . $s2, $Text); } else { $Text = str_replace('[observer.baseurl]', '', $Text); $Text = str_replace('[observer.url]', '', $Text); $Text = str_replace('[observer.name]', '', $Text); $Text = str_replace('[observer.address]', '', $Text); $Text = str_replace('[observer.webname]', '', $Text); $Text = str_replace('[observer.photo]', '', $Text); } // Perform URL Search $urlchars = '[a-zA-Z0-9\\:\\/\\-\\?\\&\\;\\.\\=\\@\\_\\~\\#\\%\\$\\!\\+\\,\\@]'; if (strpos($Text, 'http') !== false) { $Text = preg_replace("/([^\\]\\='" . '"' . "\\/]|^|\\#\\^)(https?\\:\\/\\/{$urlchars}+)/ism", '$1<a href="$2" target="_blank" >$2</a>', $Text); } if (strpos($Text, '[/share]') !== false) { $Text = preg_replace_callback("/\\[share(.*?)\\](.*?)\\[\\/share\\]/ism", 'bb_ShareAttributes', $Text); } if ($tryoembed) { if (strpos($Text, '[/url]') !== false) { $Text = preg_replace_callback("/[^\\^]\\[url\\]([{$URLSearchString}]*)\\[\\/url\\]/ism", 'tryoembed', $Text); } } if (strpos($Text, '[/url]') !== false) { $Text = preg_replace("/\\#\\^\\[url\\]([{$URLSearchString}]*)\\[\\/url\\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_blank" >$1</a>', $Text); $Text = preg_replace("/\\#\\^\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" target="_blank" >$2</a>', $Text); $Text = preg_replace("/\\[url\\]([{$URLSearchString}]*)\\[\\/url\\]/ism", '<a href="$1" target="_blank" >$1</a>', $Text); $Text = preg_replace("/\\[url\\=([{$URLSearchString}]*)\\](.*?)\\[\\/url\\]/ism", '<a href="$1" target="_blank" >$2</a>', $Text); } if (strpos($Text, '[/zrl]') !== false) { $Text = preg_replace("/\\#\\^\\[zrl\\]([{$URLSearchString}]*)\\[\\/zrl\\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_blank" >$1</a>', $Text); $Text = preg_replace("/\\#\\^\\[zrl\\=([{$URLSearchString}]*)\\](.*?)\\[\\/zrl\\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" target="_blank" >$2</a>', $Text); $Text = preg_replace("/\\[zrl\\]([{$URLSearchString}]*)\\[\\/zrl\\]/ism", '<a class="zrl" href="$1" target="_blank" >$1</a>', $Text); $Text = preg_replace("/\\[zrl\\=([{$URLSearchString}]*)\\](.*?)\\[\\/zrl\\]/ism", '<a class="zrl" href="$1" target="_blank" >$2</a>', $Text); } // Remove bookmarks from UNO if (UNO) { $Text = str_replace('<span class="bookmark-identifier">#^</span>', '', $Text); } // Perform MAIL Search if (strpos($Text, '[/mail]') !== false) { $Text = preg_replace("/\\[mail\\]([{$MAILSearchString}]*)\\[\\/mail\\]/", '<a href="mailto:$1" target="_blank" >$1</a>', $Text); $Text = preg_replace("/\\[mail\\=([{$MAILSearchString}]*)\\](.*?)\\[\\/mail\\]/", '<a href="mailto:$1" target="_blank" >$2</a>', $Text); } // leave open the posibility of [map=something] // this is replaced in prepare_body() which has knowledge of the item location if (strpos($Text, '[/map]') !== false) { $Text = preg_replace_callback("/\\[map\\](.*?)\\[\\/map\\]/ism", 'bb_map_location', $Text); } if (strpos($Text, '[map=') !== false) { $Text = preg_replace_callback("/\\[map=(.*?)\\]/ism", 'bb_map_coords', $Text); } if (strpos($Text, '[map]') !== false) { $Text = preg_replace("/\\[map\\]/", '<div class="map"></div>', $Text); } // Check for bold text if (strpos($Text, '[b]') !== false) { $Text = preg_replace("(\\[b\\](.*?)\\[\\/b\\])ism", '<strong>$1</strong>', $Text); } // Check for Italics text if (strpos($Text, '[i]') !== false) { $Text = preg_replace("(\\[i\\](.*?)\\[\\/i\\])ism", '<em>$1</em>', $Text); } // Check for Underline text if (strpos($Text, '[u]') !== false) { $Text = preg_replace("(\\[u\\](.*?)\\[\\/u\\])ism", '<u>$1</u>', $Text); } // Check for strike-through text if (strpos($Text, '[s]') !== false) { $Text = preg_replace("(\\[s\\](.*?)\\[\\/s\\])ism", '<strike>$1</strike>', $Text); } // Check for over-line text if (strpos($Text, '[o]') !== false) { $Text = preg_replace("(\\[o\\](.*?)\\[\\/o\\])ism", '<span class="overline">$1</span>', $Text); } if (strpos($Text, '[sup]') !== false) { $Text = preg_replace("(\\[sup\\](.*?)\\[\\/sup\\])ism", '<sup>$1</sup>', $Text); } if (strpos($Text, '[sub]') !== false) { $Text = preg_replace("(\\[sub\\](.*?)\\[\\/sub\\])ism", '<sub>$1</sub>', $Text); } // Check for colored text if (strpos($Text, '[/color]') !== false) { $Text = preg_replace("(\\[color=(.*?)\\](.*?)\\[\\/color\\])ism", "<span style=\"color: \$1;\">\$2</span>", $Text); } // Check for sized text // [size=50] --> font-size: 50px (with the unit). if (strpos($Text, '[/size]') !== false) { $Text = preg_replace("(\\[size=(\\d*?)\\](.*?)\\[\\/size\\])ism", "<span style=\"font-size: \$1px;\">\$2</span>", $Text); $Text = preg_replace("(\\[size=(.*?)\\](.*?)\\[\\/size\\])ism", "<span style=\"font-size: \$1;\">\$2</span>", $Text); } // Check for h1 if (strpos($Text, '[h1]') !== false) { $Text = preg_replace("(\\[h1\\](.*?)\\[\\/h1\\])ism", '<h1>$1</h1>', $Text); } // Check for h2 if (strpos($Text, '[h2]') !== false) { $Text = preg_replace("(\\[h2\\](.*?)\\[\\/h2\\])ism", '<h2>$1</h2>', $Text); } // Check for h3 if (strpos($Text, '[h3]') !== false) { $Text = preg_replace("(\\[h3\\](.*?)\\[\\/h3\\])ism", '<h3>$1</h3>', $Text); } // Check for h4 if (strpos($Text, '[h4]') !== false) { $Text = preg_replace("(\\[h4\\](.*?)\\[\\/h4\\])ism", '<h4>$1</h4>', $Text); } // Check for h5 if (strpos($Text, '[h5]') !== false) { $Text = preg_replace("(\\[h5\\](.*?)\\[\\/h5\\])ism", '<h5>$1</h5>', $Text); } // Check for h6 if (strpos($Text, '[h6]') !== false) { $Text = preg_replace("(\\[h6\\](.*?)\\[\\/h6\\])ism", '<h6>$1</h6>', $Text); } // Check for table of content without params if (strpos($Text, '[toc]') !== false) { $Text = preg_replace("/\\[toc\\]/ism", '<ul id="toc"></ul>', $Text); } // Check for table of content with params if (strpos($Text, '[toc') !== false) { $Text = preg_replace("/\\[toc([^\\]]+?)\\]/ism", '<ul$1></ul>', $Text); } // Check for centered text if (strpos($Text, '[/center]') !== false) { $Text = preg_replace("(\\[center\\](.*?)\\[\\/center\\])ism", "<div style=\"text-align:center;\">\$1</div>", $Text); } // Check for footer if (strpos($Text, '[/footer]') !== false) { $Text = preg_replace("(\\[footer\\](.*?)\\[\\/footer\\])ism", "<div class=\"wall-item-footer\">\$1</div>", $Text); } // Check for list text $Text = str_replace("[*]", "<li>", $Text); // handle nested lists $endlessloop = 0; while ((strpos($Text, "[/list]") !== false && strpos($Text, "[list") !== false || strpos($Text, "[/ol]") !== false && strpos($Text, "[ol]") !== false || strpos($Text, "[/ul]") !== false && strpos($Text, "[ul]") !== false || strpos($Text, "[/dl]") !== false && strpos($Text, "[dl") !== false || strpos($Text, "[/li]") !== false && strpos($Text, "[li]") !== false) && ++$endlessloop < 20) { $Text = preg_replace("/\\[list\\](.*?)\\[\\/list\\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $Text); $Text = preg_replace("/\\[list=\\](.*?)\\[\\/list\\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>', $Text); $Text = preg_replace("/\\[list=1\\](.*?)\\[\\/list\\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $Text); $Text = preg_replace("/\\[list=((?-i)i)\\](.*?)\\[\\/list\\]/ism", '<ul class="listlowerroman" style="list-style-type: lower-roman;">$2</ul>', $Text); $Text = preg_replace("/\\[list=((?-i)I)\\](.*?)\\[\\/list\\]/ism", '<ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul>', $Text); $Text = preg_replace("/\\[list=((?-i)a)\\](.*?)\\[\\/list\\]/ism", '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul>', $Text); $Text = preg_replace("/\\[list=((?-i)A)\\](.*?)\\[\\/list\\]/ism", '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul>', $Text); $Text = preg_replace("/\\[ul\\](.*?)\\[\\/ul\\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $Text); $Text = preg_replace("/\\[ol\\](.*?)\\[\\/ol\\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $Text); $Text = preg_replace("/\\[li\\](.*?)\\[\\/li\\]/ism", '<li>$1</li>', $Text); // [dl] tags have an optional [dl terms="bi"] form where bold/italic/underline/mono/large // etc. style may be specified for the "terms" in the definition list. The quotation marks // are also optional. The regex looks intimidating, but breaks down as: // "[dl" <optional-whitespace> <optional-termStyles> "]" <matchGroup2> "[/dl]" // where optional-termStyles are: "terms=" <optional-quote> <matchGroup1> <optional-quote> $Text = preg_replace_callback('/\\[dl[[:space:]]*(?:terms=(?:"|")?([a-zA-Z]+)(?:"|")?)?\\](.*?)\\[\\/dl\\]/ism', 'bb_definitionList', $Text); } if (strpos($Text, '[th]') !== false) { $Text = preg_replace("/\\[th\\](.*?)\\[\\/th\\]/sm", '<th>$1</th>', $Text); } if (strpos($Text, '[td]') !== false) { $Text = preg_replace("/\\[td\\](.*?)\\[\\/td\\]/sm", '<td>$1</td>', $Text); } if (strpos($Text, '[tr]') !== false) { $Text = preg_replace("/\\[tr\\](.*?)\\[\\/tr\\]/sm", '<tr>$1</tr>', $Text); } if (strpos($Text, '[/table]') !== false) { $Text = preg_replace("/\\[table\\](.*?)\\[\\/table\\]/sm", '<table>$1</table>', $Text); $Text = preg_replace("/\\[table border=1\\](.*?)\\[\\/table\\]/sm", '<table border="1" >$1</table>', $Text); $Text = preg_replace("/\\[table border=0\\](.*?)\\[\\/table\\]/sm", '<table border="0" >$1</table>', $Text); } $Text = str_replace('</tr><br /><tr>', "</tr>\n<tr>", $Text); $Text = str_replace('[hr]', '<hr />', $Text); // This is actually executed in prepare_body() $Text = str_replace('[nosmile]', '', $Text); // Check for font change text if (strpos($Text, '[/font]') !== false) { $Text = preg_replace("/\\[font=(.*?)\\](.*?)\\[\\/font\\]/sm", "<span style=\"font-family: \$1;\">\$2</span>", $Text); } // Check for [code] text if (strpos($Text, '[code]') !== false) { $Text = preg_replace_callback("/\\[code\\](.*?)\\[\\/code\\]/ism", 'bb_code', $Text); } // Check for [spoiler] text $endlessloop = 0; while (strpos($Text, "[/spoiler]") !== false and strpos($Text, "[spoiler]") !== false and ++$endlessloop < 20) { $Text = preg_replace_callback("/\\[spoiler\\](.*?)\\[\\/spoiler\\]/ism", 'bb_spoilertag', $Text); } // Check for [spoiler=Author] text $endlessloop = 0; while (strpos($Text, "[/spoiler]") !== false and strpos($Text, "[spoiler=") !== false and ++$endlessloop < 20) { $Text = preg_replace_callback("/\\[spoiler=(.*?)\\](.*?)\\[\\/spoiler\\]/ism", 'bb_spoilertag', $Text); } // Check for [open] text $endlessloop = 0; while (strpos($Text, "[/open]") !== false and strpos($Text, "[open]") !== false and ++$endlessloop < 20) { $Text = preg_replace_callback("/\\[open\\](.*?)\\[\\/open\\]/ism", 'bb_opentag', $Text); } // Check for [open=Title] text $endlessloop = 0; while (strpos($Text, "[/open]") !== false and strpos($Text, "[open=") !== false and ++$endlessloop < 20) { $Text = preg_replace_callback("/\\[open=(.*?)\\](.*?)\\[\\/open\\]/ism", 'bb_opentag', $Text); } // Declare the format for [quote] layout $QuoteLayout = '<blockquote>$1</blockquote>'; // Check for [quote] text // handle nested quotes $endlessloop = 0; while (strpos($Text, "[/quote]") !== false and strpos($Text, "[quote]") !== false and ++$endlessloop < 20) { $Text = preg_replace("/\\[quote\\](.*?)\\[\\/quote\\]/ism", "{$QuoteLayout}", $Text); } // Check for [quote=Author] text $t_wrote = t('$1 wrote:'); // handle nested quotes $endlessloop = 0; while (strpos($Text, "[/quote]") !== false and strpos($Text, "[quote=") !== false and ++$endlessloop < 20) { $Text = preg_replace("/\\[quote=[\"\\']*(.*?)[\"\\']*\\](.*?)\\[\\/quote\\]/ism", "<span class=" . '"bb-quote"' . ">" . $t_wrote . "</span><blockquote>\$2</blockquote>", $Text); } // Images // [img]pathtoimage[/img] if (strpos($Text, '[/img]') !== false) { $Text = preg_replace("/\\[img\\](.*?)\\[\\/img\\]/ism", '<img style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/zmg]') !== false) { $Text = preg_replace("/\\[zmg\\](.*?)\\[\\/zmg\\]/ism", '<img class="zrl" style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text); } // [img float={left, right}]pathtoimage[/img] if (strpos($Text, '[/img]') !== false) { $Text = preg_replace("/\\[img float=left\\](.*?)\\[\\/img\\]/ism", '<img style="max-width=100%;" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/img]') !== false) { $Text = preg_replace("/\\[img float=right\\](.*?)\\[\\/img\\]/ism", '<img style="max-width=100%;" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/zmg]') !== false) { $Text = preg_replace("/\\[zmg float=left\\](.*?)\\[\\/zmg\\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/zmg]') !== false) { $Text = preg_replace("/\\[zmg float=right\\](.*?)\\[\\/zmg\\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text); } // [img=widthxheight]pathtoimage[/img] if (strpos($Text, '[/img]') !== false) { $Text = preg_replace("/\\[img\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/img\\]/ism", '<img src="$3" style="width: 100%; max-width: $1px;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/zmg]') !== false) { $Text = preg_replace("/\\[zmg\\=([0-9]*)x([0-9]*)\\](.*?)\\[\\/zmg\\]/ism", '<img class="zrl" src="$3" style="width: 100%; max-width: $1px;" alt="' . t('Image/photo') . '" />', $Text); } // [img=widthxheight float={left, right}]pathtoimage[/img] if (strpos($Text, '[/img]') !== false) { $Text = preg_replace("/\\[img\\=([0-9]*)x([0-9]*) float=left\\](.*?)\\[\\/img\\]/ism", '<img src="$3" style="width: 100%; max-width: $1px; float: left;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/img]') !== false) { $Text = preg_replace("/\\[img\\=([0-9]*)x([0-9]*) float=right\\](.*?)\\[\\/img\\]/ism", '<img src="$3" style="width: 100%; max-width: $1px; float: right;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/zmg]') !== false) { $Text = preg_replace("/\\[zmg\\=([0-9]*)x([0-9]*) float=left\\](.*?)\\[\\/zmg\\]/ism", '<img class="zrl" src="$3" style="width: 100%; max-width: $1px; float: left;" alt="' . t('Image/photo') . '" />', $Text); } if (strpos($Text, '[/zmg]') !== false) { $Text = preg_replace("/\\[zmg\\=([0-9]*)x([0-9]*) float=right\\](.*?)\\[\\/zmg\\]/ism", '<img class="zrl" src="$3" style="width: 100%; max-width: $1px; float: right;" alt="' . t('Image/photo') . '" />', $Text); } // style (sanitized) if (strpos($Text, '[/style]') !== false) { $Text = preg_replace_callback("(\\[style=(.*?)\\](.*?)\\[\\/style\\])ism", "bb_sanitize_style", $Text); } // crypt if (strpos($Text, '[/crypt]') !== false) { $x = random_string(); $Text = preg_replace("/\\[crypt\\](.*?)\\[\\/crypt\\]/ism", '<br /><div id="' . $x . '"><img src="' . z_root() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text); $Text = preg_replace_callback("/\\[crypt (.*?)\\](.*?)\\[\\/crypt\\]/ism", 'bb_parse_crypt', $Text); } if (strpos($Text, '[/app]') !== false) { $Text = preg_replace_callback("/\\[app\\](.*?)\\[\\/app\\]/ism", 'bb_parse_app', $Text); } if (strpos($Text, '[/element]') !== false) { $Text = preg_replace_callback("/\\[element\\](.*?)\\[\\/element\\]/ism", 'bb_parse_element', $Text); } // html5 video and audio if (strpos($Text, '[/video]') !== false) { $Text = preg_replace_callback("/\\[video\\](.*?\\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\\[\\/video\\]/ism", 'tryzrlvideo', $Text); } if (strpos($Text, '[/audio]') !== false) { $Text = preg_replace_callback("/\\[audio\\](.*?\\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\\[\\/audio\\]/ism", 'tryzrlaudio', $Text); } if (strpos($Text, '[/zvideo]') !== false) { $Text = preg_replace_callback("/\\[zvideo\\](.*?\\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\\[\\/zvideo\\]/ism", 'tryzrlvideo', $Text); } if (strpos($Text, '[/zaudio]') !== false) { $Text = preg_replace_callback("/\\[zaudio\\](.*?\\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\\[\\/zaudio\\]/ism", 'tryzrlaudio', $Text); } // Try to Oembed if ($tryoembed) { if (strpos($Text, '[/video]') !== false) { $Text = preg_replace_callback("/\\[video\\](.*?)\\[\\/video\\]/ism", 'tryoembed', $Text); } if (strpos($Text, '[/audio]') !== false) { $Text = preg_replace_callback("/\\[audio\\](.*?)\\[\\/audio\\]/ism", 'tryoembed', $Text); } if (strpos($Text, '[/zvideo]') !== false) { $Text = preg_replace_callback("/\\[zvideo\\](.*?)\\[\\/zvideo\\]/ism", 'tryoembed', $Text); } if (strpos($Text, '[/zaudio]') !== false) { $Text = preg_replace_callback("/\\[zaudio\\](.*?)\\[\\/zaudio\\]/ism", 'tryoembed', $Text); } } // if video couldn't be embedded, link to it instead. if (strpos($Text, '[/video]') !== false) { $Text = preg_replace("/\\[video\\](.*?)\\[\\/video\\]/", '<a href="$1" target="_blank" >$1</a>', $Text); } if (strpos($Text, '[/audio]') !== false) { $Text = preg_replace("/\\[audio\\](.*?)\\[\\/audio\\]/", '<a href="$1" target="_blank" >$1</a>', $Text); } if (strpos($Text, '[/zvideo]') !== false) { $Text = preg_replace("/\\[zvideo\\](.*?)\\[\\/zvideo\\]/", '<a class="zid" href="$1" target="_blank" >$1</a>', $Text); } if (strpos($Text, '[/zaudio]') !== false) { $Text = preg_replace("/\\[zaudio\\](.*?)\\[\\/zaudio\\]/", '<a class="zid" href="$1" target="_blank" >$1</a>', $Text); } if ($tryoembed) { if (strpos($Text, '[/iframe]') !== false) { $Text = preg_replace_callback("/\\[iframe\\](.*?)\\[\\/iframe\\]/ism", 'bb_iframe', $Text); } } else { if (strpos($Text, '[/iframe]') !== false) { $Text = preg_replace("/\\[iframe\\](.*?)\\[\\/iframe\\]/ism", '<a href="$1" target="_blank" >$1</a>', $Text); } } // oembed tag $Text = oembed_bbcode2html($Text); // Avoid triple linefeeds through oembed $Text = str_replace("<br style='clear:left'></span><br /><br />", "<br style='clear:left'></span><br />", $Text); // If we found an event earlier, strip out all the event code and replace with a reformatted version. // Replace the event-start section with the entire formatted event. The other bbcode is stripped. // Summary (e.g. title) is required, earlier revisions only required description (in addition to // start which is always required). Allow desc with a missing summary for compatibility. if ((x($ev, 'desc') || x($ev, 'summary')) && x($ev, 'start')) { $sub = format_event_html($ev); $sub = str_replace('$', "", $sub); $Text = preg_replace("/\\[event\\-start\\](.*?)\\[\\/event\\-start\\]/ism", $sub, $Text); $Text = preg_replace("/\\[event\\-summary\\](.*?)\\[\\/event\\-summary\\]/ism", '', $Text); $Text = preg_replace("/\\[event\\-description\\](.*?)\\[\\/event\\-description\\]/ism", '', $Text); $Text = preg_replace("/\\[event\\-finish\\](.*?)\\[\\/event\\-finish\\]/ism", '', $Text); $Text = preg_replace("/\\[event\\-id\\](.*?)\\[\\/event\\-id\\]/ism", '', $Text); $Text = preg_replace("/\\[event\\-location\\](.*?)\\[\\/event\\-location\\]/ism", '', $Text); $Text = preg_replace("/\\[event\\-adjust\\](.*?)\\[\\/event\\-adjust\\]/ism", '', $Text); $Text = str_replace("", '$', $Text); } // Unhide all [noparse] contained bbtags unspacefying them // and triming the [noparse] tag. if (strpos($Text, '[noparse]') !== false) { $Text = preg_replace_callback("/\\[noparse\\](.*?)\\[\\/noparse\\]/ism", 'bb_unspacefy_and_trim', $Text); } if (strpos($Text, '[nobb]') !== false) { $Text = preg_replace_callback("/\\[nobb\\](.*?)\\[\\/nobb\\]/ism", 'bb_unspacefy_and_trim', $Text); } if (strpos($Text, '[pre]') !== false) { $Text = preg_replace_callback("/\\[pre\\](.*?)\\[\\/pre\\]/ism", 'bb_unspacefy_and_trim', $Text); } $Text = preg_replace('/\\[\\&\\;([#a-z0-9]+)\\;\\]/', '&$1;', $Text); // fix any escaped ampersands that may have been converted into links if (strpos($Text, '&') !== false) { $Text = preg_replace("/\\<(.*?)(src|href)=(.*?)\\&\\;(.*?)\\>/ism", '<$1$2=$3&$4>', $Text); } // This is subtle - it's an XSS filter. It only accepts links with a protocol scheme and where // the scheme begins with z (zhttp), h (http(s)), f (ftp), m (mailto), and named anchors. $Text = preg_replace("/\\<(.*?)(src|href)=\"[^zhfm#](.*?)\\>/ism", '<$1$2="">', $Text); $Text = bb_replace_images($Text, $saved_images); call_hooks('bbcode', $Text); return $Text; }
function mood_init(&$a) { if (!local_channel()) { return; } $uid = local_channel(); $channel = App::get_channel(); $verb = notags(trim($_GET['verb'])); if (!$verb) { return; } $verbs = get_mood_verbs(); if (!array_key_exists($verb, $verbs)) { return; } $activity = ACTIVITY_MOOD . '#' . urlencode($verb); $parent = x($_GET, 'parent') ? intval($_GET['parent']) : 0; logger('mood: verb ' . $verb, LOGGER_DEBUG); if ($parent) { $r = q("select mid, owner_xchan, private, allow_cid, allow_gid, deny_cid, deny_gid \n\t\t\tfrom item where id = %d and parent = %d and uid = %d limit 1", intval($parent), intval($parent), intval($uid)); if (count($r)) { $parent_mid = $r[0]['mid']; $private = $r[0]['item_private']; $allow_cid = $r[0]['allow_cid']; $allow_gid = $r[0]['allow_gid']; $deny_cid = $r[0]['deny_cid']; $deny_gid = $r[0]['deny_gid']; } } else { $private = 0; $allow_cid = $channel['channel_allow_cid']; $allow_gid = $channel['channel_allow_gid']; $deny_cid = $channel['channel_deny_cid']; $deny_gid = $channel['channel_deny_gid']; } $poster = App::get_observer(); $mid = item_message_id(); $action = sprintf(t('%1$s is %2$s', 'mood'), '[zrl=' . $poster['xchan_url'] . ']' . $poster['xchan_name'] . '[/zrl]', $verbs[$verb]); $arr = array(); $arr['aid'] = get_account_id(); $arr['uid'] = $uid; $arr['mid'] = $mid; $arr['parent_mid'] = $parent_mid ? $parent_mid : $mid; $arr['author_xchan'] = $poster['xchan_hash']; $arr['owner_xchan'] = $parent_mid ? $r[0]['owner_xchan'] : $poster['xchan_hash']; $arr['title'] = ''; $arr['allow_cid'] = $allow_cid; $arr['allow_gid'] = $allow_gid; $arr['deny_cid'] = $deny_cid; $arr['deny_gid'] = $deny_gid; $arr['item_private'] = $private; $arr['verb'] = $activity; $arr['body'] = $action; $arr['item_origin'] = 1; $arr['item_wall'] = 1; $arr['item_unseen'] = 1; if (!$parent_mid) { $item['item_thread_top'] = 1; } if (!$arr['plink'] && intval($arr['item_thread_top'])) { $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid']; } $post = item_store($arr); $item_id = $post['item_id']; if ($item_id) { proc_run('php', "include/notifier.php", "activity", $item_id); } call_hooks('post_local_end', $arr); if ($_SESSION['return_url']) { goaway(z_root() . '/' . $_SESSION['return_url']); } return; }
function get() { if (!local_channel() && !remote_channel()) { return; } $item_id = argc() > 2 ? notags(trim(argv(2))) : 0; if (argv(1) === 'sub') { $activity = ACTIVITY_FOLLOW; } elseif (argv(1) === 'unsub') { $activity = ACTIVITY_UNFOLLOW; } $r = q("SELECT parent FROM item WHERE id = '%s'", dbesc($item_id)); if ($r) { $r = q("select * from item where id = parent and id = %d limit 1", dbesc($r[0]['parent'])); } if (!$item_id || !$r) { logger('subthread: no item ' . $item_id); return; } $item = $r[0]; $owner_uid = $item['uid']; $observer = \App::get_observer(); $ob_hash = $observer ? $observer['xchan_hash'] : ''; if (!perm_is_allowed($owner_uid, $ob_hash, 'post_comments')) { return; } $sys = get_sys_channel(); $owner_uid = $item['uid']; $owner_aid = $item['aid']; // 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(); } $mid = item_message_id(); $post_type = $item['resource_type'] === 'photo' ? t('photo') : t('status'); $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']; $obj = 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 (!intval($item['item_thread_top'])) { $post_type = 'comment'; } if ($activity === ACTIVITY_FOLLOW) { $bodyverb = t('%1$s is following %2$s\'s %3$s'); } if ($activity === ACTIVITY_UNFOLLOW) { $bodyverb = t('%1$s stopped following %2$s\'s %3$s'); } $arr = array(); $arr['mid'] = $mid; $arr['aid'] = $owner_aid; $arr['uid'] = $owner_uid; $arr['parent'] = $item['id']; $arr['parent_mid'] = $item['mid']; $arr['thr_parent'] = $item['mid']; $arr['owner_xchan'] = $thread_owner['xchan_hash']; $arr['author_xchan'] = $observer['xchan_hash']; $arr['item_origin'] = 1; $arr['item_notshown'] = 1; if (intval($item['item_wall'])) { $arr['item_wall'] = 1; } else { $arr['item_wall'] = 0; } $ulink = '[zrl=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/zrl]'; $alink = '[zrl=' . $observer['xchan_url'] . ']' . $observer['xchan_name'] . '[/zrl]'; $plink = '[zrl=' . z_root() . '/display/' . $item['mid'] . ']' . $post_type . '[/zrl]'; $arr['body'] = sprintf($bodyverb, $alink, $ulink, $plink); $arr['verb'] = $activity; $arr['obj_type'] = $objtype; $arr['object'] = $obj; $arr['allow_cid'] = $item['allow_cid']; $arr['allow_gid'] = $item['allow_gid']; $arr['deny_cid'] = $item['deny_cid']; $arr['deny_gid'] = $item['deny_gid']; $post = item_store($arr); $post_id = $post['item_id']; $arr['id'] = $post_id; call_hooks('post_local_end', $arr); killme(); }
function get() { $o = ''; if (!local_channel()) { if (remote_channel()) { // redirect to your own site. // We can only do this with a GET request so you'll need to keep the text short or risk getting truncated // by the wretched beast called 'suhosin'. All the browsers now allow long GET requests, but suhosin // blocks them. $url = get_rpost_path(\App::get_observer()); // make sure we're not looping to our own hub if ($url && !stristr($url, \App::get_hostname())) { foreach ($_REQUEST as $key => $arg) { $url .= '&' . $key . '=' . $arg; } goaway($url); } } // The login procedure is going to bugger our $_REQUEST variables // so save them in the session. if (array_key_exists('body', $_REQUEST)) { $_SESSION['rpost'] = $_REQUEST; } return login(); } // If we have saved rpost session variables, but nothing in the current $_REQUEST, recover the saved variables if (!array_key_exists('body', $_REQUEST) && array_key_exists('rpost', $_SESSION)) { $_REQUEST = $_SESSION['rpost']; unset($_SESSION['rpost']); } if (array_key_exists('channel', $_REQUEST)) { $r = q("select channel_id from channel where channel_account_id = %d and channel_address = '%s' limit 1", intval(get_account_id()), dbesc($_REQUEST['channel'])); if ($r) { require_once 'include/security.php'; $change = change_channel($r[0]['channel_id']); } } if ($_REQUEST['remote_return']) { $_SESSION['remote_return'] = $_REQUEST['remote_return']; } if (argc() > 1 && argv(1) === 'return') { if ($_SESSION['remote_return']) { goaway($_SESSION['remote_return']); } goaway(z_root() . '/network'); } $plaintext = true; // if(feature_enabled(local_channel(),'richtext')) // $plaintext = false; if (array_key_exists('type', $_REQUEST) && $_REQUEST['type'] === 'html') { require_once 'include/html2bbcode.php'; $_REQUEST['body'] = html2bbcode($_REQUEST['body']); } $channel = \App::get_channel(); $acl = new \Zotlabs\Access\AccessList($channel); $channel_acl = $acl->get(); if ($_REQUEST['url']) { $x = z_fetch_url(z_root() . '/linkinfo?f=&url=' . urlencode($_REQUEST['url'])); if ($x['success']) { $_REQUEST['body'] = $_REQUEST['body'] . $x['body']; } } $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' => $acl->is_private() ? 'lock' : 'unlock', 'acl' => populate_acl($channel_acl, true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'permissions' => $channel_acl, 'bang' => '', 'visitor' => true, 'profile_uid' => local_channel(), 'title' => $_REQUEST['title'], 'body' => $_REQUEST['body'], 'attachment' => $_REQUEST['attachment'], 'source' => x($_REQUEST, 'source') ? strip_tags($_REQUEST['source']) : '', 'return_path' => 'rpost/return', 'bbco_autocomplete' => 'bbcode', 'editor_autocomplete' => true, 'bbcode' => true); $editor = status_editor($a, $x); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array('$title' => t('Edit post'), '$editor' => $editor)); 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; } $ob_hash = $observer ? $observer['xchan_hash'] : ''; $perms = get_all_perms($owner, $ob_hash); if (!$perms['write_pages']) { notice(t('Permission denied.') . EOL); return; } // We've already figured out which item we want and whose copy we need, // so we don't need anything fancy here $sql_extra = item_permissions_sql($owner); $itm = q("SELECT * FROM `item` WHERE `id` = %d and uid = %s {$sql_extra} LIMIT 1", intval($post_id), intval($owner)); if (!$itm) { notice(t('Permission denied.') . EOL); return; } if (intval($itm[0]['item_obscured'])) { $key = get_config('system', 'prvkey'); if ($itm[0]['title']) { $itm[0]['title'] = crypto_unencapsulate(json_decode_plus($itm[0]['title']), $key); } if ($itm[0]['body']) { $itm[0]['body'] = crypto_unencapsulate(json_decode_plus($itm[0]['body']), $key); } } $item_id = q("select * from item_id where service = 'WEBPAGE' and iid = %d limit 1", intval($itm[0]['id'])); if ($item_id) { $page_title = $item_id[0]['sid']; } $mimetype = $itm[0]['mimetype']; if ($mimetype === 'application/x-php') { if (!$uid || $uid != $itm[0]['uid']) { notice(t('Permission denied.') . EOL); return; } } $layout = $itm[0]['layout_mid']; $tpl = get_markup_template("jot.tpl"); $rp = 'webpages/' . $which; $x = array('nickname' => $channel['channel_address'], 'bbco_autocomplete' => $mimetype == 'text/bbcode' ? 'bbcode' : '', 'return_path' => $rp, 'webpage' => ITEM_TYPE_WEBPAGE, 'ptlabel' => t('Page link'), 'pagetitle' => $page_title, 'writefiles' => $mimetype == 'text/bbcode' ? perm_is_allowed($owner, get_observer_hash(), 'write_storage') : false, 'button' => t('Edit'), 'weblink' => $mimetype == 'text/bbcode' ? t('Insert web link') : false, 'hide_location' => true, 'hide_voting' => true, 'ptyp' => $itm[0]['type'], 'body' => undo_post_tagging($itm[0]['body']), 'post_id' => $post_id, 'visitor' => $is_owner ? true : false, 'acl' => populate_acl($itm[0], false, \PermissionDescription::fromGlobalPermission('view_pages')), 'showacl' => $is_owner ? true : false, 'mimetype' => $mimetype, 'mimeselect' => true, 'layout' => $layout, 'layoutselect' => true, 'title' => htmlspecialchars($itm[0]['title'], ENT_COMPAT, 'UTF-8'), 'lockstate' => strlen($itm[0]['allow_cid']) || strlen($itm[0]['allow_gid']) || strlen($itm[0]['deny_cid']) || strlen($itm[0]['deny_gid']) ? 'lock' : 'unlock', 'profile_uid' => intval($owner), 'bbcode' => $mimetype == 'text/bbcode' ? true : false); $editor = status_editor($a, $x); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array('$title' => t('Edit Webpage'), '$delete' => $itm[0]['author_xchan'] === $ob_hash || $itm[0]['owner_xchan'] === $ob_hash ? t('Delete') : false, '$editor' => $editor, '$id' => $itm[0]['id'])); return $o; }
/** * @brief Returns xchan_hash from the observer. * * @return empty string if no observer, otherwise xchan_hash from observer */ function get_observer_hash() { $observer = App::get_observer(); if (is_array($observer)) { return $observer['xchan_hash']; } return ''; }
/** * @brief Formats a profile for display in the sidebar. * * It is very difficult to templatise the HTML completely * because of all the conditional logic. * * @param array $profile * @param int $block * @param boolean $show_connect * * @return HTML string suitable for sidebar inclusion * Exceptions: Returns empty string if passed $profile is wrong type or not populated */ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = false) { $observer = App::get_observer(); $o = ''; $location = false; $pdesc = true; $reddress = true; if (!perm_is_allowed($profile['uid'], is_array($observer) ? $observer['xchan_hash'] : '', 'view_profile')) { $block = true; } if (!is_array($profile) && !count($profile)) { return $o; } head_set_icon($profile['thumb']); if (is_sys_channel($profile['uid'])) { $show_connect = false; } $profile['picdate'] = urlencode($profile['picdate']); call_hooks('profile_sidebar_enter', $profile); if ($show_connect) { // This will return an empty string if we're already connected. $connect_url = rconnect_url($profile['uid'], get_observer_hash()); $connect = $connect_url ? t('Connect') : ''; if ($connect_url) { $connect_url = sprintf($connect_url, urlencode(channel_reddress($profile))); } // premium channel - over-ride if ($profile['channel_pageflags'] & PAGE_PREMIUM) { $connect_url = z_root() . '/connect/' . $profile['channel_address']; } } if (x($profile, 'address') == 1 || x($profile, 'locality') == 1 || x($profile, 'region') == 1 || x($profile, 'postal_code') == 1 || x($profile, 'country_name') == 1) { $location = t('Location:'); } $profile['homepage'] = linkify($profile['homepage'], true); $gender = x($profile, 'gender') == 1 ? t('Gender:') : False; $marital = x($profile, 'marital') == 1 ? t('Status:') : False; $homepage = x($profile, 'homepage') == 1 ? t('Homepage:') : False; $profile['online'] = $profile['online_status'] === 'online' ? t('Online Now') : False; // logger('online: ' . $profile['online']); if ($profile['hidewall'] && !local_channel() && !remote_channel() || $block) { $location = $reddress = $pdesc = $gender = $marital = $homepage = False; } $firstname = strpos($profile['channel_name'], ' ') ? trim(substr($profile['channel_name'], 0, strpos($profile['channel_name'], ' '))) : $profile['channel_name']; $lastname = $firstname === $profile['channel_name'] ? '' : trim(substr($profile['channel_name'], strlen($firstname))); $diaspora = array('podloc' => z_root(), 'guid' => $profile['channel_guid'] . str_replace('.', '', App::get_hostname()), 'pubkey' => pemtorsa($profile['channel_pubkey']), 'searchable' => $block ? 'false' : 'true', 'nickname' => $profile['channel_address'], 'fullname' => $profile['channel_name'], 'firstname' => $firstname, 'lastname' => $lastname, 'photo300' => z_root() . '/photo/profile/300/' . $profile['uid'] . '.jpg', 'photo100' => z_root() . '/photo/profile/100/' . $profile['uid'] . '.jpg', 'photo50' => z_root() . '/photo/profile/50/' . $profile['uid'] . '.jpg'); $contact_block = contact_block(); $channel_menu = false; $menu = get_pconfig($profile['uid'], 'system', 'channel_menu'); if ($menu && !$block) { require_once 'include/menu.php'; $m = menu_fetch($menu, $profile['uid'], $observer['xchan_hash']); if ($m) { $channel_menu = menu_render($m); } } $menublock = get_pconfig($profile['uid'], 'system', 'channel_menublock'); if ($menublock && !$block) { $comanche = new Zotlabs\Render\Comanche(); $channel_menu .= $comanche->block($menublock); } if ($zcard) { $tpl = get_markup_template('profile_vcard_short.tpl'); } else { $tpl = get_markup_template('profile_vcard.tpl'); } require_once 'include/widgets.php'; // if(! feature_enabled($profile['uid'],'hide_rating')) $z = widget_rating(array('target' => $profile['channel_hash'])); $o .= replace_macros($tpl, array('$zcard' => $zcard, '$profile' => $profile, '$connect' => $connect, '$connect_url' => $connect_url, '$location' => $location, '$gender' => $gender, '$pdesc' => $pdesc, '$marital' => $marital, '$homepage' => $homepage, '$chanmenu' => $channel_menu, '$diaspora' => $diaspora, '$reddress' => $reddress, '$rating' => $z, '$contact_block' => $contact_block, '$editmenu' => profile_edit_menu($profile['uid']))); $arr = array('profile' => &$profile, 'entry' => &$o); call_hooks('profile_sidebar', $arr); return $o; }
function get() { $observer = \App::get_observer(); $xchan = null; $r = null; if ($_REQUEST['hash']) { $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($_REQUEST['hash'])); } if ($_REQUEST['address']) { $r = q("select * from xchan where xchan_addr = '%s' limit 1", dbesc($_REQUEST['address'])); } elseif (local_channel() && intval($_REQUEST['cid'])) { $r = q("SELECT abook.*, xchan.* \n\t\t\t\tFROM abook left join xchan on abook_xchan = xchan_hash\n\t\t\t\tWHERE abook_channel = %d and abook_id = %d LIMIT 1", intval(local_channel()), intval($_REQUEST['cid'])); } elseif ($_REQUEST['url']) { // if somebody re-installed they will have more than one xchan, use the most recent name date as this is // the most useful consistently ascending table item we have. $r = q("select * from xchan where xchan_url = '%s' order by xchan_name_date desc limit 1", dbesc($_REQUEST['url'])); } if ($r) { \App::$poi = $r[0]; } // Here, let's see if we have an xchan. If we don't, how we proceed is determined by what // info we do have. If it's a URL, we can offer to visit it directly. If it's a webbie or // address, we can and should try to import it. If it's just a hash, we can't continue, but we // probably wouldn't have a hash if we don't already have an xchan for this channel. if (!\App::$poi) { logger('mod_chanview: fallback'); // This is hackish - construct a zot address from the url if ($_REQUEST['url']) { if (preg_match('/https?\\:\\/\\/(.*?)(\\/channel\\/|\\/profile\\/)(.*?)$/ism', $_REQUEST['url'], $matches)) { $_REQUEST['address'] = $matches[3] . '@' . $matches[1]; } logger('mod_chanview: constructed address ' . print_r($matches, true)); } if ($_REQUEST['address']) { $ret = zot_finger($_REQUEST['address'], null); if ($ret['success']) { $j = json_decode($ret['body'], true); if ($j) { import_xchan($j); } $r = q("select * from xchan where xchan_addr = '%s' limit 1", dbesc($_REQUEST['address'])); if ($r) { \App::$poi = $r[0]; } } } } if (!\App::$poi) { // We don't know who this is, and we can't figure it out from the URL // On the plus side, there's a good chance we know somebody else at that // hub so sending them there with a Zid will probably work anyway. $url = $_REQUEST['url']; if ($observer) { $url = zid($url); } } if (\App::$poi) { $url = \App::$poi['xchan_url']; if ($observer) { $url = zid($url); } } // let somebody over-ride the iframed viewport presentation // or let's just declare this a failed experiment. // if((! local_channel()) || (get_pconfig(local_channel(),'system','chanview_full'))) goaway($url); // $o = replace_macros(get_markup_template('chanview.tpl'),array( // '$url' => $url, // '$full' => t('toggle full screen mode') // )); // return $o; }
function drop_item($id, $interactive = true, $stage = DROPITEM_NORMAL, $force = false) { // locate item to be deleted $r = q("SELECT * FROM item WHERE id = %d LIMIT 1", intval($id)); if (!$r || intval($r[0]['item_deleted']) && $stage === DROPITEM_NORMAL) { if (!$interactive) { return 0; } notice(t('Item not found.') . EOL); goaway(z_root() . '/' . $_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 = App::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. if ($linked_item && !$force) { $r = q("UPDATE item SET item_hidden = 1 WHERE id = %d", intval($item['id'])); } else { $r = q("UPDATE item SET item_deleted = 1 WHERE id = %d", 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 (intval($item['item_wall']) && $stage != DROPITEM_PHASE2 || $stage == DROPITEM_PHASE1) { Zotlabs\Daemon\Master::Summon(array('Notifier', 'drop', $notify_id)); } goaway(z_root() . '/' . $_SESSION['return_url']); } else { if (!$interactive) { return 0; } notice(t('Permission denied.') . EOL); goaway(z_root() . '/' . $_SESSION['return_url']); } }
function get() { 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; } // Block design features from visitors if (!$uid || $uid != $owner) { notice(t('Permission denied.') . EOL); return; } $mimetype = $_REQUEST['mimetype'] ? $_REQUEST['mimetype'] : get_pconfig($owner, 'system', 'page_mimetype'); $x = array('webpage' => ITEM_TYPE_BLOCK, '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' => '', 'showacl' => false, 'visitor' => true, 'mimetype' => $mimetype, 'mimeselect' => true, 'hide_location' => true, 'ptlabel' => t('Block Name'), 'profile_uid' => intval($owner), '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); $r = q("select iid, sid, mid, title, body, mimetype, created, edited from item_id left join item on item_id.iid = item.id\n\t\t\twhere item_id.uid = %d and service = 'BUILDBLOCK' and item_type = %d order by item.created desc", intval($owner), intval(ITEM_TYPE_BLOCK)); $pages = null; if ($r) { $pages = array(); foreach ($r as $rr) { $element_arr = array('type' => 'block', 'title' => $rr['title'], 'body' => $rr['body'], 'created' => $rr['created'], 'edited' => $rr['edited'], 'mimetype' => $rr['mimetype'], 'pagetitle' => $rr['sid'], 'mid' => $rr['mid']); $pages[$rr['iid']][] = array('url' => $rr['iid'], 'name' => $rr['sid'], 'title' => $rr['title'], 'created' => $rr['created'], 'edited' => $rr['edited'], 'bb_element' => '[element]' . base64url_encode(json_encode($element_arr)) . '[/element]'); } } //Build the base URL for edit links $url = z_root() . '/editblock/' . $which; $o .= replace_macros(get_markup_template('blocklist.tpl'), array('$baseurl' => $url, '$title' => t('Blocks'), '$name' => t('Block Name'), '$blocktitle' => t('Block Title'), '$created' => t('Created'), '$edited' => t('Edited'), '$create' => t('Create'), '$edit' => t('Edit'), '$share' => t('Share'), '$delete' => t('Delete'), '$editor' => $editor, '$pages' => $pages, '$channel' => $which, '$view' => t('View'), '$preview' => '1')); return $o; }
function poco($a, $extended = false) { $system_mode = false; if (observer_prohibited()) { logger('mod_poco: block_public'); http_status_exit(401); } $observer = App::get_observer(); if (argc() > 1) { $user = notags(trim(argv(1))); } if (!x($user)) { $c = q("select * from pconfig where cat = 'system' and k = 'suggestme' and v = '1'"); if (!$c) { logger('mod_poco: system mode. No candidates.', LOGGER_DEBUG); http_status_exit(404); } $system_mode = true; } $format = $_REQUEST['format'] ? $_REQUEST['format'] : 'json'; $justme = false; if (argc() > 2 && argv(2) === '@me') { $justme = true; } if (argc() > 3) { if (argv(3) === '@all') { $justme = false; } elseif (argv(3) === '@self') { $justme = true; } } if (argc() > 4 && intval(argv(4)) && $justme == false) { $cid = intval(argv(4)); } if (!$system_mode) { $r = q("SELECT channel_id from channel where channel_address = '%s' limit 1", dbesc($user)); if (!$r) { logger('mod_poco: user mode. Account not found. ' . $user); http_status_exit(404); } $channel_id = $r[0]['channel_id']; $ohash = $observer ? $observer['xchan_hash'] : ''; if (!perm_is_allowed($channel_id, $ohash, 'view_contacts')) { logger('mod_poco: user mode. Permission denied for ' . $ohash . ' user: '******'system' and k = 'suggestme' and v = '1') "); } else { $r = q("SELECT count(*) as `total` from abook where abook_channel = %d \n\t\t\t{$sql_extra} ", intval($channel_id)); $rooms = q("select * from menu_item where ( mitem_flags & " . intval(MENU_ITEM_CHATROOM) . " )>0 and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' and mitem_channel_id = %d", intval($channel_id)); } if ($r) { $totalResults = intval($r[0]['total']); } else { $totalResults = 0; } $startIndex = intval($_GET['startIndex']); if (!$startIndex) { $startIndex = 0; } $itemsPerPage = x($_GET, 'count') && intval($_GET['count']) ? intval($_GET['count']) : $totalResults; if ($system_mode) { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_self = 1 \n\t\t\tand abook_channel in (select uid from pconfig where cat = 'system' and k = 'suggestme' and v = '1') \n\t\t\tlimit %d offset %d ", intval($itemsPerPage), intval($startIndex)); } else { $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d \n\t\t\t{$sql_extra} LIMIT %d OFFSET %d", intval($channel_id), intval($itemsPerPage), intval($startIndex)); } $ret = array(); if (x($_GET, 'sorted')) { $ret['sorted'] = 'false'; } if (x($_GET, 'filtered')) { $ret['filtered'] = 'false'; } if (x($_GET, 'updatedSince')) { $ret['updateSince'] = 'false'; } $ret['startIndex'] = (string) $startIndex; $ret['itemsPerPage'] = (string) $itemsPerPage; $ret['totalResults'] = (string) $totalResults; if ($rooms) { $ret['chatrooms'] = array(); foreach ($rooms as $room) { $ret['chatrooms'][] = array('url' => $room['mitem_link'], 'desc' => $room['mitem_desc']); } } $ret['entry'] = array(); $fields_ret = array('id' => false, 'guid' => false, 'guid_sig' => false, 'hash' => false, 'displayName' => false, 'urls' => false, 'preferredUsername' => false, 'photos' => false, 'rating' => false); if (!x($_GET, 'fields') || $_GET['fields'] === '@all') { foreach ($fields_ret as $k => $v) { $fields_ret[$k] = true; } } else { $fields_req = explode(',', $_GET['fields']); foreach ($fields_req as $f) { $fields_ret[trim($f)] = true; } } if (is_array($r)) { if (count($r)) { foreach ($r as $rr) { $entry = array(); if ($fields_ret['id']) { $entry['id'] = $rr['abook_id']; } if ($fields_ret['guid']) { $entry['guid'] = $rr['xchan_guid']; } if ($fields_ret['guid_sig']) { $entry['guid_sig'] = $rr['xchan_guid_sig']; } if ($fields_ret['hash']) { $entry['hash'] = $rr['xchan_hash']; } if ($fields_ret['displayName']) { $entry['displayName'] = $rr['xchan_name']; } if ($fields_ret['urls']) { $entry['urls'] = array(array('value' => $rr['xchan_url'], 'type' => 'profile')); $network = $rr['xchan_network']; if (strpos($network, 'friendica') !== false) { $network = 'friendica'; } if ($rr['xchan_addr']) { $entry['urls'][] = array('value' => 'acct:' . $rr['xchan_addr'], 'type' => $network); } } if ($fields_ret['preferredUsername']) { $entry['preferredUsername'] = substr($rr['xchan_addr'], 0, strpos($rr['xchan_addr'], '@')); } if ($fields_ret['photos']) { $entry['photos'] = array(array('value' => $rr['xchan_photo_l'], 'mimetype' => $rr['xchan_photo_mimetype'], 'type' => 'profile')); } $ret['entry'][] = $entry; } } else { $ret['entry'][] = array(); } } else { http_status_exit(500); } if ($format === 'xml') { header('Content-type: text/xml'); echo replace_macros(get_markup_template('poco_xml.tpl'), array_xmlify(array('$response' => $ret))); http_status_exit(500); } if ($format === 'json') { header('Content-type: application/json'); echo json_encode($ret); killme(); } else { http_status_exit(500); } }