'wall', 'private', 'starred', 'origin', 'parent-origin', 'title', 'body', 'language',
'content-warning', 'location', 'coord', 'app', 'rendered-hash', 'rendered-html', 'object',
'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', 'mention', 'global',
- 'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network',
- 'owner-id', 'owner-link', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type',
+ 'author-id', 'author-link', 'author-name', 'author-avatar', 'author-network', 'author-updated', 'author-gsid', 'author-addr', 'author-uri-id',
+ 'owner-id', 'owner-link', 'owner-name', 'owner-avatar', 'owner-network', 'owner-contact-type', 'owner-updated',
'causer-id', 'causer-link', 'causer-name', 'causer-avatar', 'causer-contact-type', 'causer-network',
'contact-id', 'contact-uid', 'contact-link', 'contact-name', 'contact-avatar',
'writable', 'self', 'cid', 'alias',
$item["contact-id"] = self::contactId($item);
if (!empty($item['direction']) && in_array($item['direction'], [Conversation::PUSH, Conversation::RELAY]) &&
- self::isTooOld($item)) {
+ empty($item['origin']) &&self::isTooOld($item)) {
Logger::info('Item is too old', ['item' => $item]);
return 0;
}
unset($item['causer-id']);
}
+ if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN])) {
+ $content_warning = BBCode::getAbstract($item['body'], Protocol::ACTIVITYPUB);
+ if (!empty($content_warning) && empty($item['content-warning'])) {
+ $item['content-warning'] = $content_warning;
+ }
+ }
+
Post::insert($item['uri-id'], $item);
if ($item['gravity'] == GRAVITY_PARENT) {
Worker::add(['priority' => $priority, 'dont_fork' => true], 'Notifier', $notify_type, (int)$posted_item['uri-id'], (int)$posted_item['uid']);
}
+ // Fill the cache with the rendered content.
+ if (in_array($posted_item['gravity'], [GRAVITY_PARENT, GRAVITY_COMMENT]) && ($posted_item['uid'] == 0)) {
+ self::updateDisplayCache($posted_item['uri-id']);
+ }
+
return $post_user_id;
}
+ /**
+ * Update the display cache
+ *
+ * @param integer $uri_id
+ * @return void
+ */
+ public static function updateDisplayCache(int $uri_id)
+ {
+ $item = Post::selectFirst(self::DISPLAY_FIELDLIST, ['uri-id' => $uri_id]);
+ self::prepareBody($item, false, false, true);
+ }
+
/**
* Change the owner of a parent item if it had been shared by a forum
*
$self_contact = Contact::selectFirst(['id'], ['uid' => $item['uid'], 'self' => true]);
$self = !empty($self_contact) ? $self_contact['id'] : 0;
-
+
$cid = Contact::getIdForURL($author['url'], $item['uid']);
if (empty($cid) || (!Contact::isSharing($cid, $item['uid']) && ($cid != $self))) {
Logger::info('The resharer is not a following contact: quit', ['resharer' => $author['url'], 'uid' => $item['uid'], 'cid' => $cid]);
// which point it will be automatically available through `getAvailableLanguages()` and this should be removed.
$availableLanguages['fa'] = 'fa';
- $ld = new Language($availableLanguages);
+ $ld = new Language(array_keys($availableLanguages));
$languages = $ld->detect($naked_body)->limit(0, 3)->close();
if (is_array($languages)) {
return json_encode($languages);
}
/**
- * Creates an unique guid out of a given uri
+ * Creates an unique guid out of a given uri.
+ * This function is used for messages outside the fediverse (Connector posts, feeds, Mails, ...)
+ * Posts that are created on this system are using System::createUUID.
+ * Received ActivityPub posts are using Processor::getGUIDByURL.
*
* @param string $uri uri of an item entry
* @param string $host hostname for the GUID prefix
// We have to avoid that different routines could accidentally create the same value
$parsed = parse_url($uri);
- // We use a hash of the hostname as prefix for the guid
- $guid_prefix = hash("crc32", $host);
-
// Remove the scheme to make sure that "https" and "http" doesn't make a difference
unset($parsed["scheme"]);
// Glue it together to be able to make a hash from it
$host_id = implode("/", $parsed);
- // We could use any hash algorithm since it isn't a security issue
- $host_hash = hash("ripemd128", $host_id);
-
- return $guid_prefix.$host_hash;
+ // Use a mixture of several hashes to provide some GUID like experience
+ return hash("crc32", $host) . '-'. hash('joaat', $host_id) . '-'. hash('fnv164', $host_id);
}
/**
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo Remove reference, simply return "rendered-html" and "rendered-hash"
*/
- public static function putInCache(&$item)
+ private static function putInCache(&$item)
{
// Save original body to prevent addons to modify it
$body = $item['body'];
|| $rendered_hash != hash('md5', BBCode::VERSION . '::' . $body)
|| DI::config()->get('system', 'ignore_cache')
) {
- self::addRedirToImageTags($item);
-
$item['rendered-html'] = BBCode::convertForUriId($item['uri-id'], $item['body']);
$item['rendered-hash'] = hash('md5', BBCode::VERSION . '::' . $body);
$item['body'] = $body;
}
- /**
- * Find any non-embedded images in private items and add redir links to them
- *
- * @param array &$item The field array of an item row
- */
- private static function addRedirToImageTags(array &$item)
- {
- $app = DI::app();
-
- $matches = [];
- $cnt = preg_match_all('|\[img\](http[^\[]*?/photo/[a-fA-F0-9]+?(-[0-9]\.[\w]+?)?)\[\/img\]|', $item['body'], $matches, PREG_SET_ORDER);
- if ($cnt) {
- foreach ($matches as $mtch) {
- if (strpos($mtch[1], '/redir') !== false) {
- continue;
- }
-
- if ((local_user() == $item['uid']) && ($item['private'] == self::PRIVATE) && ($item['contact-id'] != $app->getContactId()) && ($item['network'] == Protocol::DFRN)) {
- $img_url = 'redir/' . $item['contact-id'] . '?url=' . urlencode($mtch[1]);
- $item['body'] = str_replace($mtch[0], '[img]' . $img_url . '[/img]', $item['body']);
- }
- }
- }
- }
-
/**
* Given an item array, convert the body element from bbcode to html and add smilie icons.
* If attach is true, also add icons for item attachments.
* @param array $item
* @param boolean $attach
* @param boolean $is_preview
+ * @param boolean $only_cache
* @return string item body html
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
* @hook prepare_body ('item'=>item array, 'html'=>body string, 'is_preview'=>boolean, 'filter_reasons'=>string array) after first bbcode to html
* @hook prepare_body_final ('item'=>item array, 'html'=>body string) after attach icons and blockquote special case handling (spoiler, author)
*/
- public static function prepareBody(array &$item, $attach = false, $is_preview = false)
+ public static function prepareBody(array &$item, $attach = false, $is_preview = false, $only_cache = false)
{
$a = DI::app();
Hook::callAll('prepare_body_init', $item);
$item['body'] = $body;
$s = $item["rendered-html"];
+ if ($only_cache) {
+ return;
+ }
+
// Compile eventual content filter reasons
$filter_reasons = [];
if (!$is_preview && public_contact() != $item['author-id']) {
*/
public static function getPlink($item)
{
+ if (!empty($item['plink']) && Network::isValidHttpUrl($item['plink'])) {
+ $plink = $item['plink'];
+ } elseif (!empty($item['uri']) && Network::isValidHttpUrl($item['uri']) && !Network::isLocalLink($item['uri'])) {
+ $plink = $item['uri'];
+ }
+
if (local_user()) {
$ret = [
'href' => "display/" . $item['guid'],
'orig_title' => DI::l10n()->t('View on separate page'),
];
- if (!empty($item['plink'])) {
- $ret['href'] = DI::baseUrl()->remove($item['plink']);
+ if (!empty($plink) && ($item['private'] == self::PRIVATE)) {
+ $author = ['uid' => 0, 'id' => $item['author-id'],
+ 'network' => $item['author-network'], 'url' => $item['author-link']];
+ $plink = Contact::magicLinkByContact($author, $plink);
+ }
+
+ if (!empty($plink)) {
+ $ret['href'] = DI::baseUrl()->remove($plink);
$ret['title'] = DI::l10n()->t('Link to source');
}
- } elseif (!empty($item['plink']) && ($item['private'] != self::PRIVATE)) {
+ } elseif (!empty($plink) && ($item['private'] != self::PRIVATE)) {
$ret = [
- 'href' => $item['plink'],
- 'orig' => $item['plink'],
+ 'href' => $plink,
+ 'orig' => $plink,
'title' => DI::l10n()->t('Link to source'),
'orig_title' => DI::l10n()->t('Link to source'),
];