From 2233fa0e46d80fd040328eb391316426f0d5621c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 6 Jun 2020 14:32:51 -0400 Subject: [PATCH 1/7] Fix issue with Probe returning local baseurl for probed Twitter accounts --- src/Network/Probe.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 9655590dc9..241988dd53 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -441,7 +441,7 @@ class Probe } } - if (!empty(self::$baseurl)) { + if (empty($data['baseurl']) && !empty(self::$baseurl)) { $data['baseurl'] = self::$baseurl; } @@ -1730,6 +1730,8 @@ class Probe */ private static function twitter($uri) { + self::$baseurl = ''; + if (preg_match('=(.*)@twitter.com=i', $uri, $matches)) { $nick = $matches[1]; } elseif (preg_match('=https?://twitter.com/(.*)=i', $uri, $matches)) { From be41095936ad54fada7fd2f1e7a8e95866c1a9c2 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 6 Jun 2020 14:36:04 -0400 Subject: [PATCH 2/7] Add probe data return if Contact::getDetailsByURL didn't yield a result in Contact::getDetailsByAddr --- src/Model/Contact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 02f9e829f2..470bff1077 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1168,7 +1168,7 @@ class Contact if (!DBA::isResult($r)) { $data = Probe::uri($addr); - $profile = self::getDetailsByURL($data['url'], $uid); + $profile = self::getDetailsByURL($data['url'], $uid, $data); } else { $profile = $r[0]; } From e7f50a05d1286640460c3d611ce8bfa754794959 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 10 Jun 2020 10:13:32 -0400 Subject: [PATCH 3/7] Move handle_tag() to Content\Item::replaceTag --- mod/item.php | 123 +------------------------------------------ src/Content/Item.php | 122 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 121 deletions(-) diff --git a/mod/item.php b/mod/item.php index 31336c4348..18efd67bab 100644 --- a/mod/item.php +++ b/mod/item.php @@ -29,6 +29,7 @@ */ use Friendica\App; +use Friendica\Content\Item as ItemHelper; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; @@ -395,7 +396,7 @@ function item_post(App $a) { } } - $success = handle_tag($body, $inform, local_user() ? local_user() : $profile_uid, $tag, $network); + $success = ItemHelper::replaceTag($body, $inform, local_user() ? local_user() : $profile_uid, $tag, $network); if ($success['replaced']) { $tagged[] = $tag; } @@ -868,123 +869,3 @@ function item_content(App $a) return $o; } - -/** - * This function removes the tag $tag from the text $body and replaces it with - * the appropriate link. - * - * @param App $a - * @param string $body the text to replace the tag in - * @param string $inform a comma-seperated string containing everybody to inform - * @param integer $profile_uid - * @param string $tag the tag to replace - * @param string $network The network of the post - * - * @return array|bool ['replaced' => $replaced, 'contact' => $contact]; - * @throws ImagickException - * @throws HTTPException\InternalServerErrorException - */ -function handle_tag(&$body, &$inform, $profile_uid, $tag, $network = "") -{ - $replaced = false; - - //is it a person tag? - if (Tag::isType($tag, Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION)) { - $tag_type = substr($tag, 0, 1); - //is it already replaced? - if (strpos($tag, '[url=')) { - // Checking for the alias that is used for OStatus - $pattern = "/[@!]\[url\=(.*?)\](.*?)\[\/url\]/ism"; - if (preg_match($pattern, $tag, $matches)) { - $data = Contact::getDetailsByURL($matches[1]); - - if ($data["alias"] != "") { - $newtag = '@[url=' . $data["alias"] . ']' . $data["nick"] . '[/url]'; - } - } - - return $replaced; - } - - //get the person's name - $name = substr($tag, 1); - - // Sometimes the tag detection doesn't seem to work right - // This is some workaround - $nameparts = explode(" ", $name); - $name = $nameparts[0]; - - // Try to detect the contact in various ways - if (strpos($name, 'http://')) { - // At first we have to ensure that the contact exists - Contact::getIdForURL($name); - - // Now we should have something - $contact = Contact::getDetailsByURL($name); - } elseif (strpos($name, '@')) { - // This function automatically probes when no entry was found - $contact = Contact::getDetailsByAddr($name); - } else { - $contact = false; - $fields = ['id', 'url', 'nick', 'name', 'alias', 'network', 'forum', 'prv']; - - if (strrpos($name, '+')) { - // Is it in format @nick+number? - $tagcid = intval(substr($name, strrpos($name, '+') + 1)); - $contact = DBA::selectFirst('contact', $fields, ['id' => $tagcid, 'uid' => $profile_uid]); - } - - // select someone by nick or attag in the current network - if (!DBA::isResult($contact) && ($network != "")) { - $condition = ["(`nick` = ? OR `attag` = ?) AND `network` = ? AND `uid` = ?", - $name, $name, $network, $profile_uid]; - $contact = DBA::selectFirst('contact', $fields, $condition); - } - - //select someone by name in the current network - if (!DBA::isResult($contact) && ($network != "")) { - $condition = ['name' => $name, 'network' => $network, 'uid' => $profile_uid]; - $contact = DBA::selectFirst('contact', $fields, $condition); - } - - // select someone by nick or attag in any network - if (!DBA::isResult($contact)) { - $condition = ["(`nick` = ? OR `attag` = ?) AND `uid` = ?", $name, $name, $profile_uid]; - $contact = DBA::selectFirst('contact', $fields, $condition); - } - - // select someone by name in any network - if (!DBA::isResult($contact)) { - $condition = ['name' => $name, 'uid' => $profile_uid]; - $contact = DBA::selectFirst('contact', $fields, $condition); - } - } - - // Check if $contact has been successfully loaded - if (DBA::isResult($contact)) { - if (strlen($inform) && (isset($contact["notify"]) || isset($contact["id"]))) { - $inform .= ','; - } - - if (isset($contact["id"])) { - $inform .= 'cid:' . $contact["id"]; - } elseif (isset($contact["notify"])) { - $inform .= $contact["notify"]; - } - - $profile = $contact["url"]; - $newname = ($contact["name"] ?? '') ?: $contact["nick"]; - } - - //if there is an url for this persons profile - if (isset($profile) && ($newname != "")) { - $replaced = true; - // create profile link - $profile = str_replace(',', '%2c', $profile); - $newtag = $tag_type.'[url=' . $profile . ']' . $newname . '[/url]'; - $body = str_replace($tag_type . $name, $newtag, $body); - } - } - - return ['replaced' => $replaced, 'contact' => $contact]; -} diff --git a/src/Content/Item.php b/src/Content/Item.php index 51a14435ef..40deb976c7 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -21,7 +21,10 @@ namespace Friendica\Content; +use Friendica\Database\DBA; +use Friendica\Model\Contact; use Friendica\Model\FileTag; +use Friendica\Model\Tag; /** * A content helper class for displaying items @@ -100,4 +103,123 @@ class Item return [$categories, $folders]; } + + /** + * This function removes the tag $tag from the text $body and replaces it with + * the appropriate link. + * + * @param string $body the text to replace the tag in + * @param string $inform a comma-seperated string containing everybody to inform + * @param integer $profile_uid the user id to replace the tag for (0 = anyone) + * @param string $tag the tag to replace + * @param string $network The network of the post + * + * @return array|bool ['replaced' => $replaced, 'contact' => $contact]; + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function replaceTag(&$body, &$inform, $profile_uid, $tag, $network = '') + { + $replaced = false; + + //is it a person tag? + if (Tag::isType($tag, Tag::MENTION, Tag::IMPLICIT_MENTION, Tag::EXCLUSIVE_MENTION)) { + $tag_type = substr($tag, 0, 1); + //is it already replaced? + if (strpos($tag, '[url=')) { + // Checking for the alias that is used for OStatus + $pattern = '/[@!]\[url\=(.*?)\](.*?)\[\/url\]/ism'; + if (preg_match($pattern, $tag, $matches)) { + $data = Contact::getDetailsByURL($matches[1]); + + if ($data['alias'] != '') { + $newtag = '@[url=' . $data['alias'] . ']' . $data['nick'] . '[/url]'; + } + } + + return $replaced; + } + + //get the person's name + $name = substr($tag, 1); + + // Sometimes the tag detection doesn't seem to work right + // This is some workaround + $nameparts = explode(' ', $name); + $name = $nameparts[0]; + + // Try to detect the contact in various ways + if (strpos($name, 'http://')) { + // At first we have to ensure that the contact exists + Contact::getIdForURL($name); + + // Now we should have something + $contact = Contact::getDetailsByURL($name, $profile_uid); + } elseif (strpos($name, '@')) { + // This function automatically probes when no entry was found + $contact = Contact::getDetailsByAddr($name, $profile_uid); + } else { + $contact = false; + $fields = ['id', 'url', 'nick', 'name', 'alias', 'network', 'forum', 'prv']; + + if (strrpos($name, '+')) { + // Is it in format @nick+number? + $tagcid = intval(substr($name, strrpos($name, '+') + 1)); + $contact = DBA::selectFirst('contact', $fields, ['id' => $tagcid, 'uid' => $profile_uid]); + } + + // select someone by nick or attag in the current network + if (!DBA::isResult($contact) && ($network != '')) { + $condition = ["(`nick` = ? OR `attag` = ?) AND `network` = ? AND `uid` = ?", + $name, $name, $network, $profile_uid]; + $contact = DBA::selectFirst('contact', $fields, $condition); + } + + //select someone by name in the current network + if (!DBA::isResult($contact) && ($network != '')) { + $condition = ['name' => $name, 'network' => $network, 'uid' => $profile_uid]; + $contact = DBA::selectFirst('contact', $fields, $condition); + } + + // select someone by nick or attag in any network + if (!DBA::isResult($contact)) { + $condition = ["(`nick` = ? OR `attag` = ?) AND `uid` = ?", $name, $name, $profile_uid]; + $contact = DBA::selectFirst('contact', $fields, $condition); + } + + // select someone by name in any network + if (!DBA::isResult($contact)) { + $condition = ['name' => $name, 'uid' => $profile_uid]; + $contact = DBA::selectFirst('contact', $fields, $condition); + } + } + + // Check if $contact has been successfully loaded + if (DBA::isResult($contact)) { + if (strlen($inform) && (isset($contact['notify']) || isset($contact['id']))) { + $inform .= ','; + } + + if (isset($contact['id'])) { + $inform .= 'cid:' . $contact['id']; + } elseif (isset($contact['notify'])) { + $inform .= $contact['notify']; + } + + $profile = $contact['url']; + $newname = ($contact['name'] ?? '') ?: $contact['nick']; + } + + //if there is an url for this persons profile + if (isset($profile) && ($newname != '')) { + $replaced = true; + // create profile link + $profile = str_replace(',', '%2c', $profile); + $newtag = $tag_type.'[url=' . $profile . ']' . $newname . '[/url]'; + $body = str_replace($tag_type . $name, $newtag, $body); + } + } + + return ['replaced' => $replaced, 'contact' => $contact]; + } } From a5f0225d60777c810bb84d96997f0f7614c067a0 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 6 Jun 2020 14:36:48 -0400 Subject: [PATCH 4/7] Add mention support to shared content --- src/Content/Text/BBCode.php | 66 +++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 0f3c4ad529..ae1af435c6 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -24,6 +24,8 @@ namespace Friendica\Content\Text; use DOMDocument; use DOMXPath; use Exception; +use Friendica\Content\ContactSelector; +use Friendica\Content\Item; use Friendica\Content\OEmbed; use Friendica\Content\Smilies; use Friendica\Core\Hook; @@ -35,6 +37,7 @@ use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Event; use Friendica\Model\Photo; +use Friendica\Model\Tag; use Friendica\Network\Probe; use Friendica\Object\Image; use Friendica\Protocol\Activity; @@ -1073,14 +1076,21 @@ class BBCode default: $text = ($is_quote_share? "\n" : ''); + $authorId = Contact::getIdForURL($attributes['profile'], 0); + + $contact = Contact::getById($authorId, ['network']); + $tpl = Renderer::getMarkupTemplate('shared_content.tpl'); $text .= Renderer::replaceMacros($tpl, [ - '$profile' => $attributes['profile'], - '$avatar' => $attributes['avatar'], - '$author' => $attributes['author'], - '$link' => $attributes['link'], - '$posted' => $attributes['posted'], - '$content' => trim($content) + '$profile' => $attributes['profile'], + '$avatar' => $attributes['avatar'], + '$author' => $attributes['author'], + '$link' => $attributes['link'], + '$link_title' => DI::l10n()->t('link to source'), + '$posted' => $attributes['posted'], + '$network_name' => ContactSelector::networkToName($contact['network'], $attributes['profile']), + '$network_icon' => ContactSelector::networkToIcon($contact['network'], $attributes['profile']), + '$content' => self::setMentions(trim($content), 0, $contact['network']), ]); break; } @@ -2165,4 +2175,48 @@ class BBCode return Strings::performWithEscapedBlocks($text, '#\[(?:' . implode('|', $tagList) . ').*?\[/(?:' . implode('|', $tagList) . ')]#ism', $callback); } + + /** + * Replaces mentions in the provided message body for the provided user and network if any + * + * @param $body + * @param $profile_uid + * @param $network + * @return string + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function setMentions($body, $profile_uid = 0, $network = '') + { + $tags = BBCode::getTags($body); + + $tagged = []; + $inform = ''; + + foreach ($tags as $tag) { + $tag_type = substr($tag, 0, 1); + + if ($tag_type == Tag::TAG_CHARACTER[Tag::HASHTAG]) { + continue; + } + + /* + * If we already tagged 'Robert Johnson', don't try and tag 'Robert'. + * Robert Johnson should be first in the $tags array + */ + foreach ($tagged as $nextTag) { + if (stristr($nextTag, $tag . ' ')) { + continue 2; + } + } + + $success = Item::replaceTag($body, $inform, $profile_uid, $tag, $network); + + if ($success['replaced']) { + $tagged[] = $tag; + } + } + + return $body; + } } From 1de5f2eebb4b9b4b8dbb6d321dab39c52798f4d7 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 6 Jun 2020 14:37:07 -0400 Subject: [PATCH 5/7] [frio] Improve shared content display --- view/global.css | 5 ---- view/theme/frio/css/style.css | 23 +++++++++++-------- view/theme/frio/templates/search_item.tpl | 5 ---- view/theme/frio/templates/shared_content.tpl | 24 ++++++++++++++++++++ 4 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 view/theme/frio/templates/shared_content.tpl diff --git a/view/global.css b/view/global.css index cd0253ac66..874b1d6e98 100644 --- a/view/global.css +++ b/view/global.css @@ -180,11 +180,6 @@ span.connector { margin-right: 9px; } -.shared_header span { - display: table-cell; - float: none; -} - blockquote.shared_content { margin-left: 32px; color: #000; diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 014b3daaa3..e9b42ff409 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1747,19 +1747,24 @@ aside .panel-body { } /* wall-item content elements */ -.shared-wrapper, +.shared-wrapper { + position: relative; + margin-top: 10px; + margin-bottom: 0; +} .vevent { padding: 10px; box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .1) inset, 0 1px 1px rgba(0, 0, 0, .05); } @media screen and (max-width: 767px) { - .shared-wrapper, .vevent { - margin-left: 0px; - margin-right: 0px; + margin-left: 0px; + margin-right: 0px; } + .shared-wrapper { + margin: 5px -10px 0; + } } -.shared-wrapper:hover, .vevent:hover { box-shadow: 0 0 0 1.5px rgba(0, 0, 0, .15) inset, 0 1px 1px rgba(0, 0, 0, .05); } @@ -1915,7 +1920,7 @@ code > .hl-main { /* * Comments */ -.well { +wall-item-comment-wrapper.well { border: none; box-shadow: none; /*background-color: #ededed;*/ @@ -1923,14 +1928,14 @@ code > .hl-main { background-image: none; margin-bottom: 1px; } -.well-small { +wall-item-comment-wrapper.well-small { padding: 10px; border-radius: 3px; } -.well hr { +wall-item-comment-wrapper.well hr { border-top: 1px solid #d9d9d9; } -.wall-entry .well { +.wall-entry wall-item-comment-wrapper.well { margin-bottom: 0; } .comment-container { diff --git a/view/theme/frio/templates/search_item.tpl b/view/theme/frio/templates/search_item.tpl index ce5497dda5..a5b6d52d6d 100644 --- a/view/theme/frio/templates/search_item.tpl +++ b/view/theme/frio/templates/search_item.tpl @@ -92,11 +92,6 @@ {{* item content *}}
- {{* insert some space if it's an top-level post *}} - {{if $item.thread_level==1}} -
 
- {{/if}} - {{if $item.title}}

{{$item.title}}


{{/if}} diff --git a/view/theme/frio/templates/shared_content.tpl b/view/theme/frio/templates/shared_content.tpl new file mode 100644 index 0000000000..a4f47e6184 --- /dev/null +++ b/view/theme/frio/templates/shared_content.tpl @@ -0,0 +1,24 @@ +
+
+ {{if $avatar}} + + + + {{/if}} + +
+ {{if $network_icon}} + + {{else}} + {{$network_name}} + {{/if}} + {{if $link}} + + + + {{/if}} +
+
{{$posted}}
+
+
{{$content nofilter}}
+
From eaa7740da606872f57765f1744b32c6e1f1d28a9 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 6 Jun 2020 17:31:23 -0400 Subject: [PATCH 6/7] Remove superfluous code - Remove explicit default parameter value in BBCode::convertShareCallback - Remove Probe::$baseurl reset since the twitter probe sets the `baseurl` property - Remove baseurl guessing in Probe::detect --- src/Content/Text/BBCode.php | 2 +- src/Network/Probe.php | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index ae1af435c6..70c7eb92a9 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -1076,7 +1076,7 @@ class BBCode default: $text = ($is_quote_share? "\n" : ''); - $authorId = Contact::getIdForURL($attributes['profile'], 0); + $authorId = Contact::getIdForURL($attributes['profile']); $contact = Contact::getById($authorId, ['network']); diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 241988dd53..19fc135d7b 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -781,13 +781,6 @@ class Probe Logger::log($uri." is ".$result["network"], Logger::DEBUG); - if (empty($result["baseurl"]) && ($result["network"] != Protocol::PHANTOM)) { - $pos = strpos($result["url"], $host); - if ($pos) { - $result["baseurl"] = substr($result["url"], 0, $pos).$host; - } - } - return $result; } @@ -1730,8 +1723,6 @@ class Probe */ private static function twitter($uri) { - self::$baseurl = ''; - if (preg_match('=(.*)@twitter.com=i', $uri, $matches)) { $nick = $matches[1]; } elseif (preg_match('=https?://twitter.com/(.*)=i', $uri, $matches)) { From 9b2d758c1acae28c2a013fd3493c9a32d7f4fdec Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 10 Jun 2020 09:55:52 -0400 Subject: [PATCH 7/7] Add no-parsing block escaping in BBCode::setMentions --- src/Content/Text/BBCode.php | 44 ++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 70c7eb92a9..d7fda23aeb 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -2188,34 +2188,38 @@ class BBCode */ public static function setMentions($body, $profile_uid = 0, $network = '') { - $tags = BBCode::getTags($body); + BBCode::performWithEscapedTags($body, ['noparse', 'pre', 'code'], function ($body) use ($profile_uid, $network) { + $tags = BBCode::getTags($body); - $tagged = []; - $inform = ''; + $tagged = []; + $inform = ''; - foreach ($tags as $tag) { - $tag_type = substr($tag, 0, 1); + foreach ($tags as $tag) { + $tag_type = substr($tag, 0, 1); - if ($tag_type == Tag::TAG_CHARACTER[Tag::HASHTAG]) { - continue; - } - - /* - * If we already tagged 'Robert Johnson', don't try and tag 'Robert'. - * Robert Johnson should be first in the $tags array - */ - foreach ($tagged as $nextTag) { - if (stristr($nextTag, $tag . ' ')) { - continue 2; + if ($tag_type == Tag::TAG_CHARACTER[Tag::HASHTAG]) { + continue; + } + + /* + * If we already tagged 'Robert Johnson', don't try and tag 'Robert'. + * Robert Johnson should be first in the $tags array + */ + foreach ($tagged as $nextTag) { + if (stristr($nextTag, $tag . ' ')) { + continue 2; + } } - } $success = Item::replaceTag($body, $inform, $profile_uid, $tag, $network); - if ($success['replaced']) { - $tagged[] = $tag; + if ($success['replaced']) { + $tagged[] = $tag; + } } - } + + return $body; + }); return $body; }