X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FItem.php;h=a39093d78546303ffd156babc22e2e13fd511845;hb=348e0300a6365770f62daec2bbbc01ceaca3740f;hp=2c9be633a9ae8083e1c2178d140bfac0895ed5a9;hpb=82987d018ae680cd937c5bdf4ffe71143644988d;p=friendica.git diff --git a/src/Model/Item.php b/src/Model/Item.php index 2c9be633a9..a39093d785 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -24,6 +24,7 @@ use Friendica\Protocol\Diaspora; use Friendica\Protocol\OStatus; use Friendica\Util\DateTimeFormat; use Friendica\Util\XML; +use Friendica\Util\Security; use Text_LanguageDetect; require_once 'boot.php'; @@ -80,7 +81,7 @@ class Item extends BaseObject // All fields in the item table const ITEM_FIELDLIST = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', 'guid', 'contact-id', 'type', 'wall', 'gravity', 'extid', 'icid', 'iaid', 'psid', - 'uri-hash', 'created', 'edited', 'commented', 'received', 'changed', 'verb', + 'created', 'edited', 'commented', 'received', 'changed', 'verb', 'postopts', 'plink', 'resource-id', 'event-id', 'tag', 'attach', 'inform', 'file', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'post-type', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', @@ -231,6 +232,10 @@ class Item extends BaseObject } } + if (array_key_exists('signed_text', $row) && array_key_exists('interaction', $row) && !is_null($row['interaction'])) { + $row['signed_text'] = $row['interaction']; + } + if (array_key_exists('ignored', $row) && array_key_exists('internal-user-ignored', $row) && !is_null($row['internal-user-ignored'])) { $row['ignored'] = $row['internal-user-ignored']; } @@ -242,6 +247,7 @@ class Item extends BaseObject unset($row['internal-iaid']); unset($row['internal-icid']); unset($row['internal-user-ignored']); + unset($row['interaction']); return $row; } @@ -375,7 +381,7 @@ class Item extends BaseObject $usermode = true; } - $fields = self::fieldlist($selected, $usermode); + $fields = self::fieldlist($usermode); $select_fields = self::constructSelectFields($fields, $selected); @@ -482,7 +488,7 @@ class Item extends BaseObject $usermode = true; } - $fields = self::fieldlist($selected, $usermode); + $fields = self::fieldlist($usermode); $fields['thread'] = ['mention', 'ignored', 'iid']; @@ -518,13 +524,13 @@ class Item extends BaseObject * * @return array field list */ - private static function fieldlist($selected, $usermode) + private static function fieldlist($usermode) { $fields = []; $fields['item'] = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent', 'guid', 'contact-id', 'owner-id', 'author-id', 'type', 'wall', 'gravity', 'extid', - 'created', 'edited', 'commented', 'received', 'changed', 'psid', 'uri-hash', + 'created', 'edited', 'commented', 'received', 'changed', 'psid', 'resource-id', 'event-id', 'tag', 'attach', 'post-type', 'file', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'global', @@ -567,6 +573,8 @@ class Item extends BaseObject $fields['sign'] = ['signed_text', 'signature', 'signer']; + $fields['diaspora-interaction'] = ['interaction']; + return $fields; } @@ -653,12 +661,16 @@ class Item extends BaseObject $joins .= " LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id`"; } + if (strpos($sql_commands, "`diaspora-interaction`.") !== false) { + $joins .= " LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `item`.`uri-id`"; + } + if (strpos($sql_commands, "`item-activity`.") !== false) { - $joins .= " LEFT JOIN `item-activity` ON `item-activity`.`id` = `item`.`iaid`"; + $joins .= " LEFT JOIN `item-activity` ON `item-activity`.`uri-id` = `item`.`uri-id`"; } if (strpos($sql_commands, "`item-content`.") !== false) { - $joins .= " LEFT JOIN `item-content` ON `item-content`.`id` = `item`.`icid`"; + $joins .= " LEFT JOIN `item-content` ON `item-content`.`uri-id` = `item`.`uri-id`"; } if (strpos($sql_commands, "`item-delivery-data`.") !== false) { @@ -705,6 +717,10 @@ class Item extends BaseObject $selected[] = 'internal-user-ignored'; } + if (in_array('signed_text', $selected)) { + $selected[] = 'interaction'; + } + $selection = []; foreach ($fields as $table => $table_fields) { foreach ($table_fields as $field => $select) { @@ -750,19 +766,6 @@ class Item extends BaseObject return $query; } - /** - * @brief Generate a server unique item hash for linking between the item tables - * - * @param string $uri Item URI - * @param date $created Item creation date - * - * @return string the item hash - */ - private static function itemHash($uri, $created) - { - return round(strtotime($created) / 100) . hash('ripemd128', $uri); - } - /** * @brief Update existing item entries * @@ -788,7 +791,7 @@ class Item extends BaseObject // We cannot simply expand the condition to check for origin entries // The condition needn't to be a simple array but could be a complex condition. // And we have to execute this query before the update to ensure to fetch the same data. - $items = DBA::select('item', ['id', 'origin', 'uri', 'created', 'uri-hash', 'iaid', 'icid', 'tag', 'file'], $condition); + $items = DBA::select('item', ['id', 'origin', 'uri', 'uri-id', 'iaid', 'icid', 'tag', 'file'], $condition); $content_fields = []; foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { @@ -843,34 +846,11 @@ class Item extends BaseObject $rows = DBA::affectedRows(); while ($item = DBA::fetch($items)) { - - // This part here can safely be removed when the legacy fields in the item had been removed - if (empty($item['uri-hash']) && !empty($item['uri']) && !empty($item['created'])) { - - // Fetch the uri-hash from an existing item entry if there is one - $item_condition = ["`uri` = ? AND `uri-hash` != ''", $item['uri']]; - $existing = DBA::selectfirst('item', ['uri-hash'], $item_condition); - if (DBA::isResult($existing)) { - $item['uri-hash'] = $existing['uri-hash']; - } else { - $item['uri-hash'] = self::itemHash($item['uri'], $item['created']); - } - - DBA::update('item', ['uri-hash' => $item['uri-hash']], ['id' => $item['id']]); - DBA::update('item-activity', ['uri-hash' => $item['uri-hash']], ["`uri` = ? AND `uri-hash` = ''", $item['uri']]); - DBA::update('item-content', ['uri-plink-hash' => $item['uri-hash']], ["`uri` = ? AND `uri-plink-hash` = ''", $item['uri']]); - } - if (!empty($item['iaid']) || (!empty($content_fields['verb']) && (self::activityToIndex($content_fields['verb']) >= 0))) { - if (!empty($item['iaid'])) { - $update_condition = ['id' => $item['iaid']]; - } else { - $update_condition = ['uri-hash' => $item['uri-hash']]; - } - self::updateActivity($content_fields, $update_condition); + self::updateActivity($content_fields, ['uri-id' => $item['uri-id']]); if (empty($item['iaid'])) { - $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-hash' => $item['uri-hash']]); + $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_activity)) { $item_fields = ['iaid' => $item_activity['id'], 'icid' => null]; foreach (self::MIXED_CONTENT_FIELDLIST as $field) { @@ -894,15 +874,10 @@ class Item extends BaseObject } } } else { - if (!empty($item['icid'])) { - $update_condition = ['id' => $item['icid']]; - } else { - $update_condition = ['uri-plink-hash' => $item['uri-hash']]; - } - self::updateContent($content_fields, $update_condition); + self::updateContent($content_fields, ['uri-id' => $item['uri-id']]); if (empty($item['icid'])) { - $item_content = DBA::selectFirst('item-content', [], ['uri-plink-hash' => $item['uri-hash']]); + $item_content = DBA::selectFirst('item-content', [], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_content)) { $item_fields = ['icid' => $item_content['id']]; // Clear all fields in the item table that have a content in the item-content table @@ -999,7 +974,7 @@ class Item extends BaseObject * * @return boolean success */ - private static function deleteById($item_id, $priority = PRIORITY_HIGH) + public static function deleteById($item_id, $priority = PRIORITY_HIGH) { // locate item to be deleted $fields = ['id', 'uri', 'uid', 'parent', 'parent-uri', 'origin', @@ -1166,7 +1141,7 @@ class Item extends BaseObject if ($notify) { // We have to avoid duplicates. So we create the GUID in form of a hash of the plink or uri. // We add the hash of our own host because our host is the original creator of the post. - $prefix_host = get_app()->get_hostname(); + $prefix_host = get_app()->getHostName(); } else { $prefix_host = ''; @@ -1289,17 +1264,16 @@ class Item extends BaseObject */ $dsprsig = null; - if (x($item, 'dsprsig')) { + if (isset($item['dsprsig'])) { $encoded_signature = $item['dsprsig']; $dsprsig = json_decode(base64_decode($item['dsprsig'])); unset($item['dsprsig']); } - if (!empty($item['diaspora_signed_text'])) { + $diaspora_signed_text = ''; + if (isset($item['diaspora_signed_text'])) { $diaspora_signed_text = $item['diaspora_signed_text']; unset($item['diaspora_signed_text']); - } else { - $diaspora_signed_text = ''; } // Converting the plink @@ -1366,13 +1340,6 @@ class Item extends BaseObject } } - // Ensure to always have the same creation date. - $existing = self::selectfirst(['created', 'uri-hash'], ['uri' => $item['uri']]); - if (DBA::isResult($existing)) { - $item['created'] = $existing['created']; - $item['uri-hash'] = $existing['uri-hash']; - } - $item['wall'] = intval(defaults($item, 'wall', 0)); $item['extid'] = trim(defaults($item, 'extid', '')); $item['author-name'] = trim(defaults($item, 'author-name', '')); @@ -1415,9 +1382,6 @@ class Item extends BaseObject $item['inform'] = trim(defaults($item, 'inform', '')); $item['file'] = trim(defaults($item, 'file', '')); - // Unique identifier to be linked against item-activities and item-content - $item['uri-hash'] = defaults($item, 'uri-hash', self::itemHash($item['uri'], $item['created'])); - // When there is no content then we don't post it if ($item['body'].$item['title'] == '') { logger('No body, no title.'); @@ -1798,14 +1762,17 @@ class Item extends BaseObject logger("Repaired double encoded signature from handle ".$dsprsig->signer, LOGGER_DEBUG); } - DBA::insert('sign', ['iid' => $current_post, 'signed_text' => $dsprsig->signed_text, - 'signature' => $dsprsig->signature, 'signer' => $dsprsig->signer]); + if (!empty($dsprsig->signed_text) && empty($dsprsig->signature) && empty($dsprsig->signer)) { + DBA::insert('diaspora-interaction', ['uri-id' => $item['uri-id'], 'interaction' => $dsprsig->signed_text], true); + } else { + // The other fields are used by very old Friendica servers, so we currently store them differently + DBA::insert('sign', ['iid' => $current_post, 'signed_text' => $dsprsig->signed_text, + 'signature' => $dsprsig->signature, 'signer' => $dsprsig->signer]); + } } if (!empty($diaspora_signed_text)) { - // Formerly we stored the signed text, the signature and the author in different fields. - // We now store the raw data so that we are more flexible. - DBA::insert('sign', ['iid' => $current_post, 'signed_text' => $diaspora_signed_text]); + DBA::insert('diaspora-interaction', ['uri-id' => $item['uri-id'], 'interaction' => $diaspora_signed_text], true); } $deleted = self::tagDeliver($item['uid'], $current_post); @@ -1910,8 +1877,7 @@ class Item extends BaseObject return false; } - $fields = ['uri' => $item['uri'], 'activity' => $activity_index, - 'uri-hash' => $item['uri-hash'], 'uri-id' => $item['uri-id']]; + $fields = ['activity' => $activity_index, 'uri-hash' => (string)$item['uri-id'], 'uri-id' => $item['uri-id']]; // We just remove everything that is content foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { @@ -1925,7 +1891,7 @@ class Item extends BaseObject } // Do we already have this content? - $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-hash' => $item['uri-hash']]); + $item_activity = DBA::selectFirst('item-activity', ['id'], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_activity)) { $item['iaid'] = $item_activity['id']; logger('Fetched activity for URI ' . $item['uri'] . ' (' . $item['iaid'] . ')'); @@ -1951,8 +1917,7 @@ class Item extends BaseObject */ private static function insertContent(&$item) { - $fields = ['uri' => $item['uri'], 'uri-plink-hash' => $item['uri-hash'], - 'uri-id' => $item['uri-id']]; + $fields = ['uri-plink-hash' => (string)$item['uri-id'], 'uri-id' => $item['uri-id']]; foreach (array_merge(self::CONTENT_FIELDLIST, self::MIXED_CONTENT_FIELDLIST) as $field) { if (isset($item[$field])) { @@ -1968,7 +1933,7 @@ class Item extends BaseObject } // Do we already have this content? - $item_content = DBA::selectFirst('item-content', ['id'], ['uri-plink-hash' => $item['uri-hash']]); + $item_content = DBA::selectFirst('item-content', ['id'], ['uri-id' => $item['uri-id']]); if (DBA::isResult($item_content)) { $item['icid'] = $item_content['id']; logger('Fetched content for URI ' . $item['uri'] . ' (' . $item['icid'] . ')'); @@ -2361,7 +2326,7 @@ class Item extends BaseObject $guid = System::createUUID(); } - return self::getApp()->get_baseurl() . '/object/' . $guid; + return self::getApp()->getBaseURL() . '/objects/' . $guid; } /** @@ -2644,7 +2609,7 @@ class Item extends BaseObject } // Prevent to forward already forwarded posts - if ($datarray["app"] == $a->get_hostname()) { + if ($datarray["app"] == $a->getHostName()) { logger('Already forwarded (second test)', LOGGER_DEBUG); return false; } @@ -3043,7 +3008,7 @@ class Item extends BaseObject $uid = local_user(); } - if (!can_write_wall($uid)) { + if (!Security::canWriteToUserWall($uid)) { logger('like: unable to write on wall ' . $uid); return false; } @@ -3111,7 +3076,7 @@ class Item extends BaseObject return true; } - $objtype = $item['resource-id'] ? ACTIVITY_OBJ_IMAGE : ACTIVITY_OBJ_NOTE ; + $objtype = $item['resource-id'] ? ACTIVITY_OBJ_IMAGE : ACTIVITY_OBJ_NOTE; $new_item = [ 'guid' => System::createUUID(), @@ -3125,7 +3090,7 @@ class Item extends BaseObject 'parent' => $item['id'], 'parent-uri' => $item['uri'], 'thr-parent' => $item['uri'], - 'owner-id' => $item['owner-id'], + 'owner-id' => $author_id, 'author-id' => $author_id, 'body' => $activity, 'verb' => $activity, @@ -3229,4 +3194,41 @@ class Item extends BaseObject } } } + + public static function getPermissionsSQLByUserId($owner_id, $remote_verified = false, $groups = null) + { + $local_user = local_user(); + $remote_user = remote_user(); + + /* + * Construct permissions + * + * default permissions - anonymous user + */ + $sql = " AND NOT `item`.`private`"; + + // Profile owner - everything is visible + if ($local_user && ($local_user == $owner_id)) { + $sql = ''; + } elseif ($remote_user) { + /* + * Authenticated visitor. Unless pre-verified, + * check that the contact belongs to this $owner_id + * and load the groups the visitor belongs to. + * If pre-verified, the caller is expected to have already + * done this and passed the groups into this function. + */ + $set = PermissionSet::get($owner_id, $remote_user, $groups); + + if (!empty($set)) { + $sql_set = " OR (`item`.`private` IN (1,2) AND `item`.`wall` AND `item`.`psid` IN (" . implode(',', $set) . "))"; + } else { + $sql_set = ''; + } + + $sql = " AND (NOT `item`.`private`" . $sql_set . ")"; + } + + return $sql; + } }