aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Module/Item.php
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs/Module/Item.php')
-rw-r--r--Zotlabs/Module/Item.php747
1 files changed, 396 insertions, 351 deletions
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 3d13655d2..83e8d609e 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -44,253 +44,30 @@ class Item extends Controller {
function init() {
if (Libzot::is_zot_request()) {
-
- $item_id = argv(1);
-
- if (!$item_id)
- http_status_exit(404, 'Not found');
-
- $portable_id = EMPTY_STR;
-
- $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
- dbesc(ACTIVITY_FOLLOW),
- dbesc(ACTIVITY_UNFOLLOW)
- );
-
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
-
- $i = null;
-
- // do we have the item (at all)?
-
- $r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
- dbesc($item_id)
- );
-
- if (!$r) {
- http_status_exit(404, 'Not found');
- }
-
- // process an authenticated fetch
-
- $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
- if ($sigdata['portable_id'] && $sigdata['header_valid']) {
- $portable_id = $sigdata['portable_id'];
- if (!check_channelallowed($portable_id)) {
- http_status_exit(403, 'Permission denied');
- }
- if (!check_siteallowed($sigdata['signer'])) {
- http_status_exit(403, 'Permission denied');
- }
- observer_auth($portable_id);
-
- $i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
- dbesc($r[0]['parent_mid']),
- dbesc($portable_id)
- );
- }
- elseif (Config::get('system', 'require_authenticated_fetch', false)) {
- http_status_exit(403, 'Permission denied');
- }
-
- // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
- // with a bias towards those items owned by channels on this site (item_wall = 1)
-
- $sql_extra = item_permissions_sql(0);
-
- if (!$i) {
- $i = q("select id as item_id, uid, item_private from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
- dbesc($r[0]['parent_mid'])
- );
- }
-
- if (!$i) {
- http_status_exit(403, 'Forbidden');
- }
-
- $chan = channelx_by_n($i[0]['uid']);
-
- if (!$chan) {
- http_status_exit(404, 'Not found');
- }
-
- if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
- http_status_exit(403, 'Forbidden');
- }
-
- $parents_str = ids_to_querystr($i, 'item_id');
-
- // We won't need to check for privacy mismatches if the verified observer is also owner
- $parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : '');
-
- $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ",
- intval($parents_str)
- );
-
- App::set_pager_total($total[0]['count']);
- App::set_pager_itemspage(30);
-
- if (App::$pager['total'] > App::$pager['itemspage']) {
- // let mod conversation handle this request
- App::$query_string = str_replace('item', 'conversation', App::$query_string);
- $i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
- as_return_and_die($i ,$chan);
- }
- else {
- $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id",
- intval($parents_str)
- );
-
- xchan_query($items, true);
- $items = fetch_post_tags($items, true);
-
- $i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
- }
-
- if ($portable_id && (!intval($items[0]['item_private']))) {
- $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
- intval($items[0]['uid']),
- dbesc($portable_id)
- );
- if (!$c) {
- ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
- }
- }
-
- as_return_and_die($i ,$chan);
+ $this->init_zot_request();
}
if (ActivityStreams::is_as_request()) {
-
- $item_id = argv(1);
- if (!$item_id)
- http_status_exit(404, 'Not found');
-
- $portable_id = EMPTY_STR;
-
- $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
- dbesc(ACTIVITY_FOLLOW),
- dbesc(ACTIVITY_UNFOLLOW)
- );
-
- $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 $item_normal_extra ";
-
- $i = null;
-
- // do we have the item (at all)?
- // add preferential bias to item owners (item_wall = 1)
-
- $r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
- dbesc($item_id)
- );
-
- if (!$r) {
- http_status_exit(404, 'Not found');
- }
-
- // process an authenticated fetch
-
- $sigdata = HTTPSig::verify(EMPTY_STR);
- if ($sigdata['portable_id'] && $sigdata['header_valid']) {
- $portable_id = $sigdata['portable_id'];
- if (!check_channelallowed($portable_id)) {
- http_status_exit(403, 'Permission denied');
- }
- if (!check_siteallowed($sigdata['signer'])) {
- http_status_exit(403, 'Permission denied');
- }
- observer_auth($portable_id);
-
- $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1 ",
- dbesc($r[0]['parent_mid']),
- dbesc($portable_id)
- );
- }
- elseif (Config::get('system', 'require_authenticated_fetch', false)) {
- http_status_exit(403, 'Permission denied');
- }
-
- // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
- // with a bias towards those items owned by channels on this site (item_wall = 1)
-
- $sql_extra = item_permissions_sql(0);
-
- if (!$i) {
- $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
- dbesc($r[0]['parent_mid'])
- );
- }
-
- $bear = Activity::token_from_request();
- if ($bear) {
- logger('bear: ' . $bear, LOGGER_DEBUG);
- if (!$i) {
- $t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
- dbesc($bear)
- );
- if ($t) {
- $i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
- dbesc($item_id),
- intval($t[0]['iid'])
- );
- }
- }
- }
-
- if (!$i) {
- http_status_exit(403, 'Forbidden');
- }
-
- // If we get to this point we have determined we can access the original in $r (fetched much further above), so use it.
-
- xchan_query($r, true);
- $items = fetch_post_tags($r, false);
-
- $chan = channelx_by_n($items[0]['uid']);
-
- if (!$chan)
- http_status_exit(404, 'Not found');
-
- if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
- http_status_exit(403, 'Forbidden');
-
- $i = Activity::encode_item($items[0]);
-
- if (!$i)
- http_status_exit(404, 'Not found');
-
- if ($portable_id && (!intval($items[0]['item_private']))) {
- $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
- intval($items[0]['uid']),
- dbesc($portable_id)
- );
- if (!$c) {
- ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
- }
- }
-
- as_return_and_die($i ,$chan);
-
+ $this->init_as_request();
}
if (argc() > 1 && argv(1) !== 'drop') {
- $x = q("select uid, item_wall, llink, mid, uuid from item where mid = '%s' or mid = '%s' or uuid = '%s'",
- dbesc(z_root() . '/item/' . argv(1)),
- dbesc(z_root() . '/activity/' . argv(1)),
+ $x = q("select uid, item_wall, llink, uuid from item where uuid = '%s' order by item_wall desc",
dbesc(argv(1))
);
+
if ($x) {
- foreach ($x as $xv) {
- if (intval($xv['item_wall'])) {
- $c = channelx_by_n($xv['uid']);
- if ($c) {
- goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $xv['uuid']);
- }
+ if ($x[0]['item_wall']) {
+ $c = channelx_by_n($x[0]['uid']);
+ if ($c) {
+ goaway(z_root() . '/channel/' . $c['channel_address'] . '?mid=' . $x[0]['uuid']);
}
}
+
goaway($x[0]['llink']);
}
+
http_status_exit(404, 'Not found');
}
@@ -301,7 +78,7 @@ class Item extends Controller {
// This will change. Figure out who the observer is and whether or not
// they have permission to post here. Else ignore the post.
- if ((!local_channel()) && (!remote_channel()) && (!x($_REQUEST, 'anonname')))
+ if ((!local_channel()) && (!remote_channel()) && (empty($_POST['anonname'])))
return;
$uid = local_channel();
@@ -323,7 +100,6 @@ class Item extends Controller {
$item_deleted = false;
$item_hidden = false;
$item_unpublished = false;
- $item_delayed = false;
$item_pending_remove = false;
$item_blocked = false;
@@ -331,12 +107,13 @@ class Item extends Controller {
* Is this a reply to something?
*/
- $parent = ((x($_REQUEST, 'parent')) ? intval($_REQUEST['parent']) : 0);
- $parent_mid = ((x($_REQUEST, 'parent_mid')) ? trim($_REQUEST['parent_mid']) : '');
- $mode = ((isset($_REQUEST['conv_mode']) && $_REQUEST['conv_mode'] === 'channel') ? 'channel' : 'network');
+ $parent = ((!empty($_POST['parent'])) ? intval($_POST['parent']) : 0);
+ $thr_parent_id = $parent;
+ $parent_mid = ((!empty($_POST['parent_mid'])) ? trim($_POST['parent_mid']) : '');
+ $mode = ((isset($_POST['conv_mode']) && $_POST['conv_mode'] === 'channel') ? 'channel' : 'network');
- $remote_xchan = ((x($_REQUEST, 'remote_xchan')) ? trim($_REQUEST['remote_xchan']) : false);
- $r = q("select * from xchan where xchan_hash = '%s' limit 1",
+ $remote_xchan = ((!empty($_POST['remote_xchan'])) ? trim($_POST['remote_xchan']) : false);
+ $r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($remote_xchan)
);
if ($r)
@@ -344,7 +121,7 @@ class Item extends Controller {
else
$remote_xchan = $remote_observer = false;
- $profile_uid = ((x($_REQUEST, 'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
+ $profile_uid = ((!empty($_POST['profile_uid'])) ? intval($_POST['profile_uid']) : 0);
require_once('include/channel.php');
$sys = get_sys_channel();
@@ -354,25 +131,25 @@ class Item extends Controller {
$observer = $sys;
}
- if (x($_REQUEST, 'dropitems')) {
+ if (!empty($_POST['dropitems'])) {
require_once('include/items.php');
- $arr_drop = explode(',', $_REQUEST['dropitems']);
+ $arr_drop = explode(',', $_POST['dropitems']);
drop_items($arr_drop);
$json = ['success' => 1];
echo json_encode($json);
killme();
}
- call_hooks('post_local_start', $_REQUEST);
+ call_hooks('post_local_start', $_POST);
- // logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
+ // logger('postvars ' . print_r($_POST,true), LOGGER_DATA);
- $api_source = ((x($_REQUEST, 'api_source') && $_REQUEST['api_source']) ? true : false);
+ $api_source = ((!empty($_POST['api_source'])) ? true : false);
- $consensus = $_REQUEST['consensus'] ?? 0;
- $nocomment = $_REQUEST['nocomment'] ?? 0;
+ $consensus = $_POST['consensus'] ?? 0;
+ $nocomment = $_POST['nocomment'] ?? 0;
- $is_poll = ((isset($_REQUEST['poll_answers'][0]) && $_REQUEST['poll_answers'][0]) && (isset($_REQUEST['poll_answers'][1]) && $_REQUEST['poll_answers'][1]));
+ $is_poll = ((isset($_POST['poll_answers'][0]) && $_POST['poll_answers'][0]) && (isset($_POST['poll_answers'][1]) && $_POST['poll_answers'][1]));
// 'origin' (if non-zero) indicates that this network is where the message originated,
// for the purpose of relaying comments to other conversation members.
@@ -383,42 +160,43 @@ class Item extends Controller {
// If you are unsure, it is prudent (and important) to leave it unset.
- $origin = (($api_source && array_key_exists('origin', $_REQUEST)) ? intval($_REQUEST['origin']) : 1);
+ $origin = (($api_source && array_key_exists('origin', $_POST)) ? intval($_REQU_POSTEST['origin']) : 1);
// To represent message-ids on other networks - this will create an iconfig record
- $namespace = (($api_source && array_key_exists('namespace', $_REQUEST)) ? strip_tags($_REQUEST['namespace']) : '');
- $remote_id = (($api_source && array_key_exists('remote_id', $_REQUEST)) ? strip_tags($_REQUEST['remote_id']) : '');
+ $namespace = (($api_source && array_key_exists('namespace', $_POST)) ? strip_tags($_POST['namespace']) : '');
+ $remote_id = (($api_source && array_key_exists('remote_id', $_POST)) ? strip_tags($_POST['remote_id']) : '');
$owner_hash = null;
- $message_id = ((x($_REQUEST, 'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : null);
- $created = ((x($_REQUEST, 'created')) ? datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['created']) : datetime_convert());
- $post_id = ((x($_REQUEST, 'post_id')) ? intval($_REQUEST['post_id']) : 0);
- $app = ((x($_REQUEST, 'source')) ? strip_tags($_REQUEST['source']) : '');
- $return_path = ((x($_REQUEST, 'return')) ? $_REQUEST['return'] : '');
- $preview = ((x($_REQUEST, 'preview')) ? intval($_REQUEST['preview']) : 0);
- $categories = ((x($_REQUEST, 'category')) ? escape_tags($_REQUEST['category']) : '');
- $webpage = ((x($_REQUEST, 'webpage')) ? intval($_REQUEST['webpage']) : 0);
- $item_obscured = ((x($_REQUEST, 'obscured')) ? intval($_REQUEST['obscured']) : 0);
- $pagetitle = ((x($_REQUEST, 'pagetitle')) ? escape_tags($_REQUEST['pagetitle']) : '');
- $layout_mid = ((x($_REQUEST, 'layout_mid')) ? escape_tags($_REQUEST['layout_mid']) : '');
- $plink = ((x($_REQUEST, 'permalink')) ? escape_tags($_REQUEST['permalink']) : '');
- $obj_type = ((x($_REQUEST, 'obj_type')) ? escape_tags($_REQUEST['obj_type']) : 'Note');
+ $message_id = ((!empty($_POST['message_id']) && $api_source) ? strip_tags($_POST['message_id']) : null);
+ $created = ((!empty($_POST['created'])) ? datetime_convert(date_default_timezone_get(), 'UTC', $_POST['created']) : datetime_convert());
+ $post_id = ((!empty($_POST['post_id'])) ? intval($_POST['post_id']) : 0);
+ $app = ((!empty($_POST['source'])) ? strip_tags($_POST['source']) : '');
+ $return_path = ((!empty($_POST['return'])) ? $_POST['return'] : '');
+ $preview = ((!empty($_POST['preview'])) ? intval($_POST['preview']) : 0);
+ $categories = ((!empty($_POST['category'])) ? escape_tags($_POST['category']) : '');
+ $item_type = ((!empty($_POST['webpage'])) ? intval($_POST['webpage']) : ITEM_TYPE_POST);
+ $item_obscured = ((!empty($_POST['obscured'])) ? intval($_POST['obscured']) : 0);
+ $item_delayed = ((!empty($_POST['delayed'])) ? intval($_POST['delayed']) : 0);
+ $pagetitle = ((!empty($_POST['pagetitle'])) ? escape_tags($_POST['pagetitle']) : '');
+ $layout_mid = ((!empty($_POST['layout_mid'])) ? escape_tags($_POST['layout_mid']) : '');
+ $plink = ((!empty($_POST['permalink'])) ? escape_tags($_POST['permalink']) : null);
+ $obj_type = ((!empty($_POST['obj_type'])) ? escape_tags($_POST['obj_type']) : 'Note');
// allow API to bulk load a bunch of imported items with sending out a bunch of posts.
- $nopush = ((x($_REQUEST, 'nopush')) ? intval($_REQUEST['nopush']) : 0);
+ $nopush = ((!empty($_POST['nopush'])) ? intval($_POST['nopush']) : 0);
/*
* Check service class limits
*/
- if ($uid && !(x($_REQUEST, 'parent')) && !(x($_REQUEST, 'post_id'))) {
- $ret = $this->item_check_service_class($uid, (($_REQUEST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false));
+ if ($uid && empty($_POST['parent']) && empty($_POST['post_id'])) {
+ $ret = $this->item_check_service_class($uid, (($_POST['webpage'] == ITEM_TYPE_WEBPAGE) ? true : false));
if (!$ret['success']) {
notice(t($ret['message']) . EOL);
if ($api_source)
return (['success' => false, 'message' => 'service class exception']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -430,7 +208,6 @@ class Item extends Controller {
$expires = NULL_DATE;
- $comments_closed = NULL_DATE;
$route = '';
$parent_item = null;
@@ -440,8 +217,8 @@ class Item extends Controller {
if ($parent || $parent_mid) {
- if (!x($_REQUEST, 'type'))
- $_REQUEST['type'] = 'net-comment';
+ if (empty($_POST['type']))
+ $_POST['type'] = 'net-comment';
if ($parent) {
$r = q("SELECT * FROM item WHERE id = %d LIMIT 1",
@@ -477,7 +254,7 @@ class Item extends Controller {
notice(t('Unable to locate original post.') . EOL);
if ($api_source)
return (['success' => false, 'message' => 'invalid post id']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -500,7 +277,7 @@ class Item extends Controller {
if (!$observer) {
$observer = App::get_observer();
if (!$observer) {
- $observer = anon_identity_init($_REQUEST);
+ $observer = anon_identity_init($_POST);
if ($observer) {
$moderated = true;
$remote_xchan = $remote_observer = $observer;
@@ -512,7 +289,7 @@ class Item extends Controller {
notice(t('Permission denied.') . EOL);
if ($api_source)
return (['success' => false, 'message' => 'permission denied']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -531,17 +308,17 @@ class Item extends Controller {
notice(t('Permission denied.') . EOL);
if ($api_source)
return (['success' => false, 'message' => 'permission denied']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
}
else {
- if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], ($webpage) ? 'write_pages' : 'post_wall')) {
+ if (!perm_is_allowed($profile_uid, $observer['xchan_hash'], (intval($item_type) === ITEM_TYPE_POST) ? 'post_wall' : 'write_pages')) {
notice(t('Permission denied.') . EOL);
if ($api_source)
return (['success' => false, 'message' => 'permission denied']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -597,7 +374,7 @@ class Item extends Controller {
logger("mod_item: no channel.");
if ($api_source)
return (['success' => false, 'message' => 'no channel']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -607,6 +384,7 @@ class Item extends Controller {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($channel['channel_hash'])
);
+
if ($r && count($r)) {
$owner_xchan = $r[0];
}
@@ -614,7 +392,7 @@ class Item extends Controller {
logger("mod_item: no owner.");
if ($api_source)
return (['success' => false, 'message' => 'no owner']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -648,17 +426,21 @@ class Item extends Controller {
$view_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'view_stream');
$comment_policy = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'], 'post_comments');
- $public_policy = ((x($_REQUEST, 'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope($view_policy, true));
- if ($webpage)
- $public_policy = '';
- if ($public_policy)
+ $public_policy = '';
+
+ if (intval($item_type) === ITEM_TYPE_POST) {
+ $public_policy = ((!empty($_POST['public_policy'])) ? escape_tags($_POST['public_policy']) : map_scope($view_policy, true));
+ }
+
+ if ($public_policy) {
$private = 1;
+ }
if ($orig_post) {
$private = 0;
- // webpages are allowed to change ACLs after the fact. Normal conversation items aren't.
- if ($webpage) {
- $acl->set_from_array($_REQUEST);
+ // Normal conversation items are not allowed to change ACL.
+ if (intval($item_type) !== ITEM_TYPE_POST) {
+ $acl->set_from_array($_POST);
}
else {
$acl->set($orig_post);
@@ -674,10 +456,10 @@ class Item extends Controller {
$coord = $orig_post['coord'];
$verb = $orig_post['verb'];
$app = $orig_post['app'];
- $title = escape_tags(trim($_REQUEST['title']));
- $summary = escape_tags(trim($_REQUEST['summary']));
- $body = trim($_REQUEST['body']);
- $item_flags = $orig_post['item_flags'];
+ $title = escape_tags(trim($_POST['title']));
+ $summary = escape_tags(trim($_POST['summary']));
+ $body = trim($_POST['body']);
+ $item_flags = $orig_post['item_flags'];
$item_origin = $orig_post['item_origin'];
$item_unseen = $orig_post['item_unseen'];
$item_starred = $orig_post['item_starred'];
@@ -691,7 +473,7 @@ class Item extends Controller {
$item_mentionsme = $orig_post['item_mentionsme'];
$item_nocomment = $orig_post['item_nocomment'];
$item_obscured = $orig_post['item_obscured'];
- $item_verified = $orig_post['item_verified'];
+ $item_verified = $orig_post['item_verified'];
$item_retained = $orig_post['item_retained'];
$item_rss = $orig_post['item_rss'];
$item_deleted = $orig_post['item_deleted'];
@@ -710,14 +492,15 @@ class Item extends Controller {
$thr_parent = $orig_post['thr_parent'];
$parent_mid = $orig_post['parent_mid'];
$plink = $orig_post['plink'];
+ $owner_hash = $orig_post['owner_xchan'];
}
else {
if (!$walltowall) {
- if ((array_key_exists('contact_allow', $_REQUEST))
- || (array_key_exists('group_allow', $_REQUEST))
- || (array_key_exists('contact_deny', $_REQUEST))
- || (array_key_exists('group_deny', $_REQUEST))) {
- $acl->set_from_array($_REQUEST);
+ if ((array_key_exists('contact_allow', $_POST))
+ || (array_key_exists('group_allow', $_POST))
+ || (array_key_exists('contact_deny', $_POST))
+ || (array_key_exists('group_deny', $_POST))) {
+ $acl->set_from_array($_POST);
}
elseif (!$api_source) {
@@ -732,16 +515,16 @@ class Item extends Controller {
}
- $location = ((isset($_REQUEST['location'])) ? notags(trim($_REQUEST['location'])) : '');
- $coord = ((isset($_REQUEST['coord'])) ? notags(trim($_REQUEST['coord'])) : '');
- $verb = ((isset($_REQUEST['verb'])) ? notags(trim($_REQUEST['verb'])) : '');
- $title = ((isset($_REQUEST['title'])) ? escape_tags(trim($_REQUEST['title'])) : '');
- $summary = ((isset($_REQUEST['summary'])) ? escape_tags(trim($_REQUEST['summary'])) : '');
- $body = ((isset($_REQUEST['body'])) ? trim($_REQUEST['body']) : '');
- $body .= ((isset($_REQUEST['attachment'])) ? trim($_REQUEST['attachment']) : '');
+ $location = ((isset($_POST['location'])) ? notags(trim($_POST['location'])) : '');
+ $coord = ((isset($_POST['coord'])) ? notags(trim($_POST['coord'])) : '');
+ $verb = ((isset($_POST['verb'])) ? notags(trim($_POST['verb'])) : '');
+ $title = ((isset($_POST['title'])) ? escape_tags(trim($_POST['title'])) : '');
+ $summary = ((isset($_POST['summary'])) ? escape_tags(trim($_POST['summary'])) : '');
+ $body = ((isset($_POST['body'])) ? trim($_POST['body']) : '');
+ $body .= ((isset($_POST['attachment'])) ? trim($_POST['attachment']) : '');
$postopts = '';
- $allow_empty = ((array_key_exists('allow_empty', $_REQUEST)) ? intval($_REQUEST['allow_empty']) : 0);
+ $allow_empty = ((array_key_exists('allow_empty', $_POST)) ? intval($_POST['allow_empty']) : 0);
$private = ((isset($private) && $private) ? $private : intval($acl->is_private() || ($public_policy)));
@@ -752,7 +535,7 @@ class Item extends Controller {
$private = intval($parent_item['item_private']);
$public_policy = $parent_item['public_policy'];
$owner_hash = $parent_item['owner_xchan'];
- $webpage = $parent_item['item_type'];
+ $item_type = $parent_item['item_type'];
}
@@ -763,7 +546,7 @@ class Item extends Controller {
info(t('Empty post discarded.') . EOL);
if ($api_source)
return (['success' => false, 'message' => 'no content']);
- if (x($_REQUEST, 'return'))
+ if (!empty($_POST['return']))
goaway(z_root() . "/" . $return_path);
killme();
}
@@ -771,15 +554,15 @@ class Item extends Controller {
if (feature_enabled($profile_uid, 'content_expire')) {
- if (x($_REQUEST, 'expire')) {
- $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_REQUEST['expire']);
+ if (!empty($_POST['expire'])) {
+ $expires = datetime_convert(date_default_timezone_get(), 'UTC', $_POST['expire']);
if ($expires <= datetime_convert())
$expires = NULL_DATE;
}
}
- $mimetype = ((isset($_REQUEST['mimetype'])) ? notags(trim($_REQUEST['mimetype'])) : '');
+ $mimetype = ((isset($_POST['mimetype'])) ? notags(trim($_POST['mimetype'])) : '');
if (!$mimetype)
$mimetype = 'text/bbcode';
@@ -813,7 +596,7 @@ class Item extends Controller {
$is_group = get_pconfig($profile_uid, 'system', 'group_actor');
- if ($is_group && $walltowall && !$walltowall_comment && !$webpage) {
+ if ($is_group && $walltowall && !$walltowall_comment && (intval($item_type) === ITEM_TYPE_POST)) {
$groupww = true;
$str_contact_allow = $owner_xchan['xchan_hash'];
$str_group_allow = '';
@@ -837,8 +620,10 @@ class Item extends Controller {
if ($results) {
- // Set permissions based on tag replacements
- set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
+ // Set permissions based on tag replacements only if not editing an existing post
+ if (!$orig_post) {
+ set_linkified_perms($results, $str_contact_allow, $str_group_allow, $profile_uid, $private, $parent_item);
+ }
foreach ($results as $result) {
$success = $result['success'];
@@ -1010,42 +795,65 @@ class Item extends Controller {
}
$item_unseen = ((local_channel() != $profile_uid) ? 1 : 0);
- $item_wall = ((isset($_REQUEST['type']) && ($_REQUEST['type'] === 'wall' || $_REQUEST['type'] === 'wall-comment')) ? 1 : 0);
+ $item_wall = ((isset($_POST['type']) && ($_POST['type'] === 'wall' || $_POST['type'] === 'wall-comment')) ? 1 : 0);
$item_origin = (($origin) ? 1 : 0);
$item_consensus = (($consensus) ? 1 : 0);
$item_nocomment = (($nocomment) ? 1 : 0);
+ $comments_closed = (($nocomment) ? $comments_closed : NULL_DATE);
// determine if this is a wall post
+ if (in_array($item_type, [ITEM_TYPE_POST, ITEM_TYPE_CARD, ITEM_TYPE_ARTICLE])) {
+ $item_wall = 1;
+ }
+
if ($parent) {
$item_wall = $parent_item['item_wall'];
}
- else {
- if (!$webpage) {
- $item_wall = 1;
- }
- }
-
- if ($moderated)
+ if ($moderated) {
$item_blocked = ITEM_MODERATED;
+ }
- if (!strlen($verb))
+ if (!strlen($verb)) {
$verb = 'Create';
+ }
$notify_type = (($parent) ? 'comment-new' : 'wall-new');
$uuid = $uuid ?? $message_id ?? item_message_id();
$mid = $mid ?? z_root() . '/item/' . $uuid;
+
+ if (empty($owner_hash)) {
+ $owner_hash = $owner_xchan['xchan_hash'];
+ }
+
+ // Set the conversation target.
+ if ($owner_hash === $channel['channel_hash']) {
+ $attributedTo = z_root() . '/channel/' . $channel['channel_address'];
+
+ $conversation = isset($parent_item) ? $parent_item['mid'] : $mid;
+ $datarray['target'] = [
+ 'id' => str_replace('/item/', '/conversation/', $conversation),
+ 'type' => 'Collection',
+ 'attributedTo' => $attributedTo,
+ ];
+ $datarray['tgt_type'] = 'Collection';
+ }
+ elseif (!empty($parent_item['target'])) {
+ $datarray['target'] = $parent_item['target'];
+ $datarray['tgt_type'] = $parent_item['tgt_type'];
+ }
+
if ($is_poll) {
$poll = [
'question' => $body,
- 'answers' => $_REQUEST['poll_answers'],
- 'multiple_answers' => $_REQUEST['poll_multiple_answers'],
- 'expire_value' => $_REQUEST['poll_expire_value'],
- 'expire_unit' => $_REQUEST['poll_expire_unit']
+ 'answers' => $_POST['poll_answers'],
+ 'multiple_answers' => $_POST['poll_multiple_answers'],
+ 'expire_value' => $_POST['poll_expire_value'],
+ 'expire_unit' => $_POST['poll_expire_unit']
];
$obj = $this->extract_poll_data($poll, ['item_private' => $private, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_contact_deny]);
}
@@ -1058,7 +866,7 @@ class Item extends Controller {
$obj['id'] = $mid;
$obj['diaspora:guid'] = $uuid;
$obj['attributedTo'] = channel_url($channel);
- $obj['published'] = $created;
+ $obj['published'] = datetime_convert('UTC', 'UTC', $created, ATOM_TIME);
$obj['name'] = $title;
$datarray['obj'] = $obj;
@@ -1080,19 +888,13 @@ class Item extends Controller {
if ($parent_item)
$parent_mid = $parent_item['mid'];
-
// Fallback so that we always have a thr_parent
if (!$thr_parent)
$thr_parent = $mid;
-
$item_thread_top = ((!$parent) ? 1 : 0);
- if ((!$plink) && ($item_thread_top)) {
- $plink = $mid;
- }
-
if (isset($datarray['obj']) && $datarray['obj']) {
$datarray['obj']['id'] = $mid;
}
@@ -1130,7 +932,7 @@ class Item extends Controller {
$datarray['item_unseen'] = intval($item_unseen);
$datarray['item_wall'] = intval($item_wall);
$datarray['item_origin'] = intval($item_origin);
- $datarray['item_type'] = $webpage;
+ $datarray['item_type'] = $item_type;
$datarray['item_private'] = intval($private);
$datarray['item_thread_top'] = intval($item_thread_top);
$datarray['item_starred'] = intval($item_starred);
@@ -1155,7 +957,7 @@ class Item extends Controller {
$datarray['public_policy'] = $public_policy;
$datarray['comment_policy'] = map_scope($comment_policy);
$datarray['term'] = array_unique($post_tags, SORT_REGULAR);
- $datarray['plink'] = $plink;
+ $datarray['plink'] = $plink ?? $mid;
$datarray['route'] = $route;
// A specific ACL over-rides public_policy completely
@@ -1209,14 +1011,14 @@ class Item extends Controller {
call_hooks('post_local', $datarray);
- if (x($datarray, 'cancel')) {
+ if (!empty($datarray['cancel'])) {
logger('mod_item: post cancelled by plugin or duplicate suppressed.');
if ($return_path)
goaway(z_root() . "/" . $return_path);
if ($api_source)
return (['success' => false, 'message' => 'operation cancelled']);
$json = ['cancel' => 1];
- $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
+ $json['reload'] = z_root() . '/' . $_POST['jsreload'];
echo json_encode($json);
killme();
}
@@ -1225,8 +1027,8 @@ class Item extends Controller {
if (mb_strlen($datarray['title']) > 191)
$datarray['title'] = mb_substr($datarray['title'], 0, 191);
- if ($webpage) {
- IConfig::Set($datarray, 'system', webpage_to_namespace($webpage),
+ if (intval($item_type) !== ITEM_TYPE_POST) {
+ IConfig::Set($datarray, 'system', item_type_to_namespace($item_type),
(($pagetitle) ? $pagetitle : basename($datarray['mid'])), true);
}
elseif ($namespace) {
@@ -1243,6 +1045,7 @@ class Item extends Controller {
$this->add_listeners($datarray);
}
+ /* sync this is done in item_store_update()
if (!$parent) {
$r = q("select * from item where id = %d",
intval($post_id)
@@ -1253,14 +1056,19 @@ class Item extends Controller {
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
}
- if (!$nopush)
- Master::Summon(['Notifier', 'edit_post', $post_id]);
+ */
+ if (!$nopush) {
+ Master::Summon(['Notifier', 'edit_post', $post_id]);
+ if (intval($x['approval_id'])) {
+ Master::Summon(['Notifier', 'edit_post', $x['approval_id']]);
+ }
+ }
if ($api_source)
return ($x);
- if ((x($_REQUEST, 'return')) && strlen($return_path)) {
+ if ((!empty($_POST['return'])) && strlen($return_path)) {
logger('return: ' . $return_path);
if ($return_path === 'hq') {
@@ -1279,6 +1087,7 @@ class Item extends Controller {
}
$post_id = $post['item_id'];
+ $approval_id = $post['approval_id'] ?? 0;
$datarray = $post['item'];
@@ -1353,6 +1162,7 @@ class Item extends Controller {
killme();
}
+ /* sync this is done in item_store_update()
if ($parent || $datarray['item_private'] == 1) {
$r = q("select * from item where id = %d",
intval($post_id)
@@ -1363,6 +1173,7 @@ class Item extends Controller {
Libsync::build_sync_packet($profile_uid, ['item' => [encode_item($sync_item[0], true)]]);
}
}
+ */
$datarray['id'] = $post_id;
$datarray['llink'] = z_root() . '/display/' . $datarray['uuid'];
@@ -1373,8 +1184,12 @@ class Item extends Controller {
$nopush = false;
}
- if (!$nopush)
+ if (!$nopush) {
Master::Summon(['Notifier', $notify_type, $post_id]);
+ if ($approval_id) {
+ Master::Summon(['Notifier', $notify_type, $approval_id]);
+ }
+ }
logger('post_complete');
@@ -1406,11 +1221,12 @@ class Item extends Controller {
$json = [
'success' => 1,
'id' => $post_id,
+ 'thr_parent_id' => $thr_parent_id,
'html' => conversation($item, $mode, true, 'r_preview'),
];
- if (x($_REQUEST, 'jsreload') && strlen($_REQUEST['jsreload']))
- $json['reload'] = z_root() . '/' . $_REQUEST['jsreload'];
+ if (!empty($_POST['jsreload']))
+ $json['reload'] = z_root() . '/' . $_POST['jsreload'];
logger('post_json: ' . print_r($json, true), LOGGER_DEBUG);
@@ -1427,10 +1243,7 @@ class Item extends Controller {
if ((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) {
- require_once('include/items.php');
-
-
- $i = q("select id, uid, item_origin, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1",
+ $i = q("select * from item where id = %d limit 1",
intval(argv(2))
);
@@ -1457,7 +1270,6 @@ class Item extends Controller {
$can_delete = true;
}
-
if (!($can_delete || $local_delete)) {
notice(t('Permission denied.') . EOL);
return;
@@ -1473,13 +1285,14 @@ class Item extends Controller {
}
else {
// complex deletion that needs to propagate and be performed in phases
- drop_item($i[0]['id'], true, DROPITEM_PHASE1);
+ drop_item($i[0]['id'], DROPITEM_PHASE1);
$complex = true;
}
$r = q("select * from item where id = %d",
intval($i[0]['id'])
);
+
if ($r) {
xchan_query($r);
$sync_item = fetch_post_tags($r);
@@ -1488,6 +1301,9 @@ class Item extends Controller {
if ($complex) {
tag_deliver($i[0]['uid'], $i[0]['id']);
+ if (intval($i[0]['item_wall']) || $i[0]['mid'] !== $i[0]['parent_mid']) {
+ Master::Summon(['Notifier', 'drop', $i[0]['id']]);
+ }
}
}
@@ -1671,5 +1487,234 @@ class Item extends Controller {
}
}
+ private function init_zot_request() {
+
+ $item_id = argv(1);
+
+ if (!$item_id)
+ http_status_exit(404, 'Not found');
+
+ $portable_id = EMPTY_STR;
+
+ $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
+ dbesc(ACTIVITY_FOLLOW),
+ dbesc(ACTIVITY_UNFOLLOW)
+ );
+
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
+
+ $i = null;
+
+ // do we have the item (at all)?
+
+ $r = q("select parent_mid from item where uuid = '%s' $item_normal limit 1",
+ dbesc($item_id)
+ );
+
+ if (!$r) {
+ http_status_exit(404, 'Not found');
+ }
+
+ // process an authenticated fetch
+
+ $sigdata = HTTPSig::verify(($_SERVER['REQUEST_METHOD'] === 'POST') ? file_get_contents('php://input') : EMPTY_STR);
+ if ($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ if (!check_channelallowed($portable_id)) {
+ http_status_exit(403, 'Permission denied');
+ }
+ if (!check_siteallowed($sigdata['signer'])) {
+ http_status_exit(403, 'Permission denied');
+ }
+ observer_auth($portable_id);
+
+ $i = q("select id as item_id, uid from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1",
+ dbesc($r[0]['parent_mid']),
+ dbesc($portable_id)
+ );
+ }
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
+ }
+
+ // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
+ // with a bias towards those items owned by channels on this site (item_wall = 1)
+
+ $sql_extra = item_permissions_sql(0);
+
+ if (!$i) {
+ $i = q("select id as item_id, uid, item_private from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
+ dbesc($r[0]['parent_mid'])
+ );
+ }
+
+ if (!$i) {
+ http_status_exit(403, 'Forbidden');
+ }
+
+ $chan = channelx_by_n($i[0]['uid']);
+
+ if (!$chan) {
+ http_status_exit(404, 'Not found');
+ }
+
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream')) {
+ http_status_exit(403, 'Forbidden');
+ }
+
+ $parents_str = ids_to_querystr($i, 'item_id');
+
+ // We won't need to check for privacy mismatches if the verified observer is also owner
+ $parent_item_private = ((isset($i[0]['item_private'])) ? " and item_private = " . intval($i[0]['item_private']) . " " : '');
+
+ $total = q("SELECT count(*) AS count FROM item WHERE parent = %d $parent_item_private $item_normal ",
+ intval($parents_str)
+ );
+
+ App::set_pager_total($total[0]['count']);
+ App::set_pager_itemspage(30);
+
+ if (App::$pager['total'] > App::$pager['itemspage']) {
+ // let mod conversation handle this request
+ App::$query_string = str_replace('item', 'conversation', App::$query_string);
+ $i = Activity::paged_collection_init(App::$pager['total'], App::$query_string);
+ as_return_and_die($i ,$chan);
+ }
+ else {
+ $items = q("SELECT item.*, item.id AS item_id FROM item WHERE item.parent = %d $parent_item_private $item_normal ORDER BY item.id",
+ intval($parents_str)
+ );
+
+ xchan_query($items, true);
+ $items = fetch_post_tags($items, true);
+
+ $i = Activity::encode_item_collection($items, App::$query_string, 'OrderedCollection', App::$pager['total']);
+ }
+
+ if ($portable_id && (!intval($items[0]['item_private']))) {
+ $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
+ intval($items[0]['uid']),
+ dbesc($portable_id)
+ );
+ if (!$c) {
+ ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ }
+ }
+
+ as_return_and_die($i ,$chan);
+ }
+
+ private function init_as_request() {
+
+ $item_id = argv(1);
+ if (!$item_id)
+ http_status_exit(404, 'Not found');
+
+ $portable_id = EMPTY_STR;
+
+ $item_normal_extra = sprintf(" and not verb in ('Follow', 'Ignore', '%s', '%s') ",
+ dbesc(ACTIVITY_FOLLOW),
+ dbesc(ACTIVITY_UNFOLLOW)
+ );
+
+ $item_normal = " and item.item_hidden = 0 and item.item_type = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_blocked = 0 and item.item_uplink = 0 $item_normal_extra ";
+
+ $i = null;
+
+ // do we have the item (at all)?
+ // add preferential bias to item owners (item_wall = 1)
+
+ $r = q("select * from item where uuid = '%s' $item_normal order by item_wall desc limit 1",
+ dbesc($item_id)
+ );
+
+ if (!$r) {
+ http_status_exit(404, 'Not found');
+ }
+
+ // process an authenticated fetch
+
+ $sigdata = HTTPSig::verify(EMPTY_STR);
+ if ($sigdata['portable_id'] && $sigdata['header_valid']) {
+ $portable_id = $sigdata['portable_id'];
+ if (!check_channelallowed($portable_id)) {
+ http_status_exit(403, 'Permission denied');
+ }
+ if (!check_siteallowed($sigdata['signer'])) {
+ http_status_exit(403, 'Permission denied');
+ }
+ observer_auth($portable_id);
+
+ $i = q("select id as item_id from item where mid = '%s' $item_normal and owner_xchan = '%s' limit 1 ",
+ dbesc($r[0]['parent_mid']),
+ dbesc($portable_id)
+ );
+ }
+ elseif (Config::get('system', 'require_authenticated_fetch', false)) {
+ http_status_exit(403, 'Permission denied');
+ }
+
+ // if we don't have a parent id belonging to the signer see if we can obtain one as a visitor that we have permission to access
+ // with a bias towards those items owned by channels on this site (item_wall = 1)
+
+ $sql_extra = item_permissions_sql(0);
+
+ if (!$i) {
+ $i = q("select id as item_id from item where mid = '%s' $item_normal $sql_extra order by item_wall desc limit 1",
+ dbesc($r[0]['parent_mid'])
+ );
+ }
+
+ $bear = Activity::token_from_request();
+ if ($bear) {
+ logger('bear: ' . $bear, LOGGER_DEBUG);
+ if (!$i) {
+ $t = q("select * from iconfig where cat = 'ocap' and k = 'relay' and v = '%s'",
+ dbesc($bear)
+ );
+ if ($t) {
+ $i = q("select id as item_id from item where uuid = '%s' and id = %d $item_normal limit 1",
+ dbesc($item_id),
+ intval($t[0]['iid'])
+ );
+ }
+ }
+ }
+
+ if (!$i) {
+ http_status_exit(403, 'Forbidden');
+ }
+
+ // If we get to this point we have determined we can access the original in $r (fetched much further above), so use it.
+
+ xchan_query($r, true);
+ $items = fetch_post_tags($r, false);
+
+ $chan = channelx_by_n($items[0]['uid']);
+
+ if (!$chan)
+ http_status_exit(404, 'Not found');
+
+ if (!perm_is_allowed($chan['channel_id'], get_observer_hash(), 'view_stream'))
+ http_status_exit(403, 'Forbidden');
+
+ $i = Activity::encode_item($items[0]);
+
+ if (!$i)
+ http_status_exit(404, 'Not found');
+
+ if ($portable_id && (!intval($items[0]['item_private']))) {
+ $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s'",
+ intval($items[0]['uid']),
+ dbesc($portable_id)
+ );
+ if (!$c) {
+ ThreadListener::store(z_root() . '/item/' . $item_id, $portable_id);
+ }
+ }
+
+ as_return_and_die($i ,$chan);
+
+ }
}