aboutsummaryrefslogtreecommitdiffstats
path: root/include/items.php
diff options
context:
space:
mode:
Diffstat (limited to 'include/items.php')
-rwxr-xr-xinclude/items.php193
1 files changed, 104 insertions, 89 deletions
diff --git a/include/items.php b/include/items.php
index 139c637e5..933b9ef81 100755
--- a/include/items.php
+++ b/include/items.php
@@ -328,25 +328,14 @@ function post_activity_item($arr,$allow_code = false,$deliver = true) {
return $ret;
}
- $arr['public_policy'] = ((x($_REQUEST,'public_policy')) ? escape_tags($_REQUEST['public_policy']) : map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
+ $arr['public_policy'] = ((array_key_exists('public_policy',$arr)) ? escape_tags($arr['public_policy']) : map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
+
if($arr['public_policy'])
$arr['item_private'] = 1;
if(! array_key_exists('mimetype',$arr))
$arr['mimetype'] = 'text/bbcode';
- if(array_key_exists('item_private',$arr) && $arr['item_private']) {
-
- $arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
-
- if($channel) {
- if($channel['channel_hash'] === $arr['author_xchan']) {
- $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
- $arr['item_verified'] = 1;
- }
- }
- }
-
$arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : item_message_id());
$arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']);
$arr['thr_parent'] = ((x($arr,'thr_parent')) ? $arr['thr_parent'] : $arr['mid']);
@@ -359,10 +348,13 @@ function post_activity_item($arr,$allow_code = false,$deliver = true) {
if(($is_comment) && ($arr['obj_type'] === ACTIVITY_OBJ_NOTE))
$arr['obj_type'] = ACTIVITY_OBJ_COMMENT;
- $arr['allow_cid'] = ((x($arr,'allow_cid')) ? $arr['allow_cid'] : $channel['channel_allow_cid']);
- $arr['allow_gid'] = ((x($arr,'allow_gid')) ? $arr['allow_gid'] : $channel['channel_allow_gid']);
- $arr['deny_cid'] = ((x($arr,'deny_cid')) ? $arr['deny_cid'] : $channel['channel_deny_cid']);
- $arr['deny_gid'] = ((x($arr,'deny_gid')) ? $arr['deny_gid'] : $channel['channel_deny_gid']);
+ if(! ( array_key_exists('allow_cid',$arr) || array_key_exists('allow_gid',$arr)
+ || array_key_exists('deny_cid',$arr) || array_key_exists('deny_gid',$arr))) {
+ $arr['allow_cid'] = $channel['channel_allow_cid'];
+ $arr['allow_gid'] = $channel['channel_allow_gid'];
+ $arr['deny_cid'] = $channel['channel_deny_cid'];
+ $arr['deny_gid'] = $channel['channel_deny_gid'];
+ }
$arr['comment_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'));
@@ -424,7 +416,7 @@ function validate_item_elements($message,$arr) {
/**
- * @brief Limit lenght on imported system messages.
+ * @brief Limit length on imported system messages.
*
* The purpose of this function is to apply system message length limits to
* imported messages without including any embedded photos in the length.
@@ -538,12 +530,7 @@ function get_item_elements($x,$allow_code = false) {
$arr = array();
- if($allow_code)
- $arr['body'] = $x['body'];
- else
- $arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : '');
-
- $key = get_config('system','pubkey');
+ $arr['body'] = $x['body'];
$maxlen = get_max_import_size();
@@ -655,7 +642,17 @@ function get_item_elements($x,$allow_code = false) {
return array();
}
+ // Check signature on the body text received.
+ // This presents an issue that we aren't verifying the text that is actually displayed
+ // on this site. We are however verifying the received text was exactly as received.
+ // We have every right to strip content that poses a security risk. You are welcome to
+ // create a plugin to verify the content after filtering if this offends you.
+
if($arr['sig']) {
+
+ // check the supplied signature against the supplied content.
+ // Note that we will purify the content which could change it.
+
$r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['author_xchan'])
);
@@ -665,6 +662,14 @@ function get_item_elements($x,$allow_code = false) {
logger('get_item_elements: message verification failed.');
}
+ // if the input is markdown, remove one level of html escaping.
+ // It will be re-applied in item_store() and/or item_store_update().
+ // Do this after signature checking as the original signature
+ // was generated on the escaped content.
+
+ if($arr['mimetype'] === 'text/markdown')
+ $arr['body'] = \Zotlabs\Lib\MarkdownSoap::unescape($arr['body']);
+
if(array_key_exists('revision',$x)) {
// extended export encoding
@@ -764,6 +769,8 @@ function import_author_xchan($x) {
if($arr['xchan_hash'])
return $arr['xchan_hash'];
+ $y = false;
+
if((! array_key_exists('network', $x)) || ($x['network'] === 'zot')) {
$y = import_author_zot($x);
}
@@ -774,11 +781,11 @@ function import_author_xchan($x) {
$y = import_author_rss($x);
}
- if($x['network'] === 'unknown') {
+ if(! $y) {
$y = import_author_unknown($x);
}
- return(($y) ? $y : false);
+ return($y);
}
/**
@@ -1452,6 +1459,26 @@ function get_profile_elements($x) {
}
+
+
+function item_sign(&$item) {
+
+ if(array_key_exists('sig',$item) && $item['sig'])
+ return;
+
+ $r = q("select channel_prvkey from channel where channel_id = %d and channel_hash = '%s' ",
+ intval($item['uid']),
+ dbesc($item['author_xchan'])
+ );
+ if(! $r)
+ return;
+
+ $item['sig'] = base64url_encode(rsa_sign($item['body'],$r[0]['channel_prvkey']));
+ $item['item_verified'] = 1;
+
+}
+
+
/**
* @brief
*
@@ -1529,35 +1556,30 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
// obsolete, but needed so as not to throw not-null constraints on some database driveres
$arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 );
- // only detect language if we have text content, and if the post is private but not yet
- // obscured, make it so.
- if((! array_key_exists('item_obscured',$arr)) || $arr['item_obscured'] == 0) {
- $arr['lang'] = detect_language($arr['body']);
- // apply the input filter here - if it is obscured it has been filtered already
- $arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
+ $arr['lang'] = detect_language($arr['body']);
- if(local_channel() && (local_channel() == $arr['uid']) && (! $arr['sig'])) {
- $channel = App::get_channel();
- if($channel['channel_hash'] === $arr['author_xchan']) {
- $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
- $arr['item_verified'] = 1;
- }
- }
+ // apply the input filter here
- $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
+ $arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec));
- if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
- $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
- call_hooks('item_translate', $translate);
- if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
- logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
- $ret['message'] = 'language not accepted';
- return $ret;
- }
- $arr = $translate['item'];
+ item_sign($arr);
+
+ if(! array_key_exists('sig',$arr))
+ $arr['sig'] = '';
+
+ $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
+
+ if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
+ $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
+ call_hooks('item_translate', $translate);
+ if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
+ logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
+ $ret['message'] = 'language not accepted';
+ return $ret;
}
+ $arr = $translate['item'];
}
if((x($arr,'obj')) && is_array($arr['obj'])) {
@@ -1804,9 +1826,12 @@ logger('revision: ' . $arr['revision']);
intval($arr['revision'])
);
- if($r && count($r)) {
+ if($r) {
+ // This will gives us a fresh copy of what's now in the DB and undo the db escaping,
+ // which really messes up the notifications
+
$current_post = $r[0]['id'];
- $arr = $r[0]; // This will gives us a fresh copy of what's now in the DB and undo the db escaping, which really messes up the notifications
+ $arr = $r[0];
logger('item_store: created item ' . $current_post, LOGGER_DEBUG);
}
else {
@@ -1953,33 +1978,25 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
return $ret;
}
- if((! array_key_exists('item_obscured', $arr)) || $arr['item_obscured'] == 0) {
+ $arr['lang'] = detect_language($arr['body']);
- $arr['lang'] = detect_language($arr['body']);
+ // apply the input filter here
- // apply the input filter here - if it is obscured it has been filtered already
- $arr['body'] = trim(z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']));
+ $arr['body'] = trim(z_input_filter($arr['body'],$arr['mimetype'],$allow_exec));
- if(local_channel() && (local_channel() == $arr['uid']) && (! $arr['sig'])) {
- $channel = App::get_channel();
- if($channel['channel_hash'] === $arr['author_xchan']) {
- $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey']));
- $arr['item_verified'] = 1;
- }
- }
+ item_sign($arr);
- $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
+ $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
- if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
- $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
- call_hooks('item_translate', $translate);
- if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
- logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
- $ret['message'] = 'language not accepted';
- return $ret;
- }
- $arr = $translate['item'];
+ if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
+ $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
+ call_hooks('item_translate', $translate);
+ if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
+ logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
+ $ret['message'] = 'language not accepted';
+ return $ret;
}
+ $arr = $translate['item'];
}
if((x($arr,'obj')) && is_array($arr['obj'])) {
@@ -3769,7 +3786,7 @@ function zot_feed($uid,$observer_hash,$arr) {
if(! is_sys_channel($uid))
$sql_extra = item_permissions_sql($uid,$observer_hash);
- $limit = " LIMIT 100 ";
+ $limit = " LIMIT 5000 ";
if($mindate > NULL_DATE) {
$sql_extra .= " and ( created > '$mindate' or changed > '$mindate' ) ";
@@ -3781,15 +3798,7 @@ function zot_feed($uid,$observer_hash,$arr) {
}
- $items = array();
-
- /** @FIXME re-unite these SQL statements. There is no need for them to be separate. The mySQL is convoluted with misuse of group by. As it stands, there is a slight difference where the postgres version doesn't remove the duplicate parents up to 100. In practice this doesn't matter. It could be made to match behavior by adding "distinct on (parent) " to the front of the selection list, at a not-worth-it performance penalty (page temp results to disk). duplicates are still ignored in the in() clause, you just get less than 100 parents if there are many children. */
-
- if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
- $groupby = '';
- } else {
- $groupby = 'GROUP BY parent';
- }
+ $items = [];
$item_normal = item_normal();
@@ -3798,7 +3807,7 @@ function zot_feed($uid,$observer_hash,$arr) {
WHERE uid != %d
$item_normal
AND item_wall = 1
- and item_private = 0 $sql_extra $groupby ORDER BY created ASC $limit",
+ and item_private = 0 $sql_extra ORDER BY created ASC $limit",
intval($uid)
);
}
@@ -3806,19 +3815,25 @@ function zot_feed($uid,$observer_hash,$arr) {
$r = q("SELECT parent, created, postopts from item
WHERE uid = %d $item_normal
AND item_wall = 1
- $sql_extra $groupby ORDER BY created ASC $limit",
+ $sql_extra ORDER BY created ASC $limit",
intval($uid)
);
}
+ $parents = [];
+
if($r) {
- for($x = 0; $x < count($r); $x ++) {
- if(strpos($r[$x]['postopts'],'nodeliver') !== false) {
- unset($r[$x]);
- }
+ foreach($r as $rv) {
+ if(array_key_exists($rv['parent'],$parents))
+ continue;
+ if(strpos($rv['postopts'],'nodeliver') !== false)
+ continue;
+ $parents[$rv['parent']] = $rv;
+ if(count($parents) > 200)
+ break;
}
- $parents_str = ids_to_querystr($r,'parent');
+ $parents_str = ids_to_querystr($parents,'parent');
$sys_query = ((is_sys_channel($uid)) ? $sql_extra : '');
$item_normal = item_normal();