<span class="quoteBoxTitle">
{if $quoteAuthor}
{if $quoteLink}
- <a {anchorAttributes url=$quoteLink}>{lang}wcf.bbcode.quote.title{/lang}</a>
+ <a {anchorAttributes url=$quoteLink isUgc=true}>{lang}wcf.bbcode.quote.title{/lang}</a>
{else}
{lang}wcf.bbcode.quote.title{/lang}
{/if}
<ul class="buttonList iconList">
{content}
{if $user->homepage && $user->homepage != 'http://'}
- <li><a class="jsTooltip" title="{lang}wcf.user.option.homepage{/lang}" {anchorAttributes url=$user->homepage appendClassname=false}><span class="icon icon16 fa-home"></span> <span class="invisible">{lang}wcf.user.option.homepage{/lang}</span></a></li>
+ <li><a class="jsTooltip" title="{lang}wcf.user.option.homepage{/lang}" {anchorAttributes url=$user->homepage appendClassname=false isUgc=true}><span class="icon icon16 fa-home"></span> <span class="invisible">{lang}wcf.user.option.homepage{/lang}</span></a></li>
{/if}
{if $user->userID != $__wcf->user->userID}
else {
$htmlOutputProcessor = new HtmlOutputProcessor();
$htmlOutputProcessor->setOutputType('text/plain');
+ $htmlOutputProcessor->enableUgc(false);
$htmlOutputProcessor->process($this->content, 'com.woltlab.wcf.article.content', $this->articleContentID, false, $this->languageID);
return nl2br(StringUtil::encodeHTML(StringUtil::truncate($htmlOutputProcessor->getHtml(), 500)), false);
*/
public function getFormattedContent() {
$processor = new HtmlOutputProcessor();
+ $processor->enableUgc(false);
$processor->process($this->content, 'com.woltlab.wcf.article.content', $this->articleContentID, false, $this->languageID);
return $processor->getHtml();
*/
public function getAmpFormattedContent() {
$processor = new AmpHtmlOutputProcessor();
+ $processor->enableUgc(false);
$processor->process($this->content, 'com.woltlab.wcf.article.content', $this->articleContentID);
return $processor->getHtml();
case 'text/plain':
$processor = new HtmlOutputProcessor();
$processor->setOutputType('text/plain');
+ $processor->enableUgc(false);
$processor->process($this->content, 'com.woltlab.wcf.article.content', $this->articleContentID);
return $processor->getHtml();
// parse and return message
$processor = new HtmlOutputProcessor();
$processor->setOutputType('text/simplified-html');
+ $processor->enableUgc(false);
$processor->process($this->content, 'com.woltlab.wcf.article.content', $this->articleContentID);
return $processor->getHtml();
*/
public function getFormattedContent() {
$processor = new HtmlOutputProcessor();
+ $processor->enableUgc(false);
$processor->process($this->content, 'com.woltlab.wcf.box.content', $this->boxContentID);
return $processor->getHtml();
/** @noinspection PhpMissingBreakStatementInspection */
case 'URL':
- if (!$forcePlaintext) return StringUtil::getAnchorTag($this->optionValue);
+ if (!$forcePlaintext) return StringUtil::getAnchorTag($this->optionValue, '', true, true);
// fallthrough
default:
MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.page.content', [$this->pageContentID]);
$processor = new HtmlOutputProcessor();
+ $processor->enableUgc(false);
$processor->process($this->content, 'com.woltlab.wcf.page.content', $this->pageContentID);
return $processor->getHtml();
foreach (BBCodeMediaProvider::getCache() as $provider) {
if ($provider->matches($content)) {
if ($parser instanceof HtmlBBCodeParser && $parser->getIsGoogleAmp()) {
- return StringUtil::getAnchorTag($content);
+ return StringUtil::getAnchorTag($content, '', true, true);
}
else {
return $provider->getOutput($content);
else if ($parser->getOutputType() == 'text/simplified-html' && !$parser->getRemoveLinks()) {
foreach (BBCodeMediaProvider::getCache() as $provider) {
if ($provider->matches($content)) {
- return StringUtil::getAnchorTag($content);
+ return StringUtil::getAnchorTag($content, '', true, true);
}
}
}
$url = 'http://'.$url;
}
- $text = str_replace($hash, StringUtil::getAnchorTag($url), $text);
+ $text = str_replace($hash, StringUtil::getAnchorTag($url, '', true, true), $text);
}
foreach ($this->cachedEmails as $hash => $email) {
*/
protected $outputType = 'text/html';
+ /**
+ * enables rel=ugc for external links
+ * @var bool
+ */
+ protected $ugc = true;
+
/**
* Processes the input html string.
*
return $this->htmlOutputNodeProcessor;
}
+
+ /**
+ * Enables rel=ugc for external links.
+ *
+ * @param bool $enable
+ */
+ public function enableUgc($enable = true) {
+ $this->ugc = $enable;
+ }
+
+ /**
+ * Returns true, if content is user-generated.
+ *
+ * @return bool
+ */
+ public function isUgc() {
+ return $this->ugc;
+ }
}
$element->setAttribute('href', preg_replace('~^https?://~', RouteHandler::getProtocol(), $href));
}
else {
- self::markLinkAsExternal($element);
+ /** @var HtmlOutputNodeProcessor $htmlNodeProcessor */
+ self::markLinkAsExternal($element, $htmlNodeProcessor->getHtmlProcessor()->isUgc());
}
$value = StringUtil::trim($element->textContent);
* Marks an element as external.
*
* @param \DOMElement $element
+ * @param bool $isUgc
*/
- public static function markLinkAsExternal(\DOMElement $element) {
+ public static function markLinkAsExternal(\DOMElement $element, $isUgc = false) {
$element->setAttribute('class', 'externalURL');
$rel = 'nofollow';
$element->setAttribute('target', '_blank');
}
+ if ($isUgc) {
+ $rel .= ' ugc';
+ }
+
$element->setAttribute('rel', $rel);
// If the link contains only a single image that is floated to the right,
if (IMAGE_PROXY_INSECURE_ONLY && $urlComponents['scheme'] === 'https') {
// proxy is enabled for insecure connections only
if (!IMAGE_ALLOW_EXTERNAL_SOURCE && !$this->isAllowedOrigin($src)) {
- $this->replaceExternalSource($element, $src);
+ /** @var HtmlOutputNodeProcessor $htmlNodeProcessor */
+ $this->replaceExternalSource($element, $src, $htmlNodeProcessor->getHtmlProcessor()->isUgc());
}
continue;
}
}
else if (!IMAGE_ALLOW_EXTERNAL_SOURCE && !$this->isAllowedOrigin($src)) {
- $this->replaceExternalSource($element, $src);
+ /** @var HtmlOutputNodeProcessor $htmlNodeProcessor */
+ $this->replaceExternalSource($element, $src, $htmlNodeProcessor->getHtmlProcessor()->isUgc());
}
else if (MESSAGE_FORCE_SECURE_IMAGES && Url::parse($src)['scheme'] === 'http') {
// rewrite protocol to `https`
*
* @param \DOMElement $element
* @param string $src
+ * @param bool $isUgc
*/
- protected function replaceExternalSource(\DOMElement $element, $src) {
+ protected function replaceExternalSource(\DOMElement $element, $src, $isUgc = false) {
$element->parentNode->insertBefore($element->ownerDocument->createTextNode('['.WCF::getLanguage()->get('wcf.bbcode.image.blocked').': '), $element);
if (!DOMUtil::hasParent($element, 'a')) {
$link = $element->ownerDocument->createElement('a');
$link->setAttribute('href', $src);
$link->textContent = $src;
- HtmlOutputNodeA::markLinkAsExternal($link);
+ HtmlOutputNodeA::markLinkAsExternal($link, $isUgc);
}
else {
$link = $element->ownerDocument->createTextNode($src);
public function getOutput(User $user, UserOption $option, $value) {
if (empty($value)) return '';
- return StringUtil::getAnchorTag('https://www.facebook.com/'.$value, $value);
+ return StringUtil::getAnchorTag('https://www.facebook.com/'.$value, $value, true, true);
}
}
public function getOutput(User $user, UserOption $option, $value) {
if (empty($value)) return '';
- return StringUtil::getAnchorTag('https://twitter.com/'.$value, $value);
+ return StringUtil::getAnchorTag('https://twitter.com/'.$value, $value, true, true);
}
}
$value = self::getURL($value);
- return StringUtil::getAnchorTag($value, $value);
+ return StringUtil::getAnchorTag($value, $value, true, true);
}
/**
* Optional parameter:
* `appendHref` (bool, default true)
* `appendClassname` (bool, default true)
+ * `isUgc` (bool, default false)
*
* Usage:
* {anchorAttributes url=$url}
$url = $tagArgs['url'];
$appendClassname = $tagArgs['appendClassname'] ?? true;
$appendHref = $tagArgs['appendHref'] ?? true;
+ $isUgc = $tagArgs['isUgc'] ?? false;
$external = true;
if (ApplicationHandler::getInstance()->isInternalURL($url)) {
$rel .= ' noopener noreferrer';
$attributes .= 'target="_blank"';
}
+ if ($isUgc) {
+ $rel .= ' ugc';
+ }
$attributes .= ' rel="' . $rel . '"';
}
* @param string $url
* @param string $title
* @param boolean $encodeTitle
+ * @param boolean $isUgc true to add rel=ugc to the anchor tag
* @return string anchor tag
*/
- public static function getAnchorTag($url, $title = '', $encodeTitle = true) {
+ public static function getAnchorTag($url, $title = '', $encodeTitle = true, $isUgc = false) {
$url = self::trim($url);
// cut visible url
if (!$encodeTitle) $title = self::encodeHTML($title);
}
- return '<a '. self::getAnchorTagAttributes($url) .'>' . ($encodeTitle ? self::encodeHTML($title) : $title) . '</a>';
+ return '<a '. self::getAnchorTagAttributes($url, $isUgc) .'>' . ($encodeTitle ? self::encodeHTML($title) : $title) . '</a>';
}
/**
* Generates the attributes for an anchor tag from given URL.
*
* @param string $url
+ * @param boolean $isUgc true to add rel=ugc to the attributes
* @return string attributes
* @since 5.3
*/
- public static function getAnchorTagAttributes($url) {
+ public static function getAnchorTagAttributes($url, $isUgc = false) {
$external = true;
if (ApplicationHandler::getInstance()->isInternalURL($url)) {
$external = false;
$rel .= ' noopener noreferrer';
$attributes .= 'target="_blank"';
}
+ if ($isUgc) {
+ $rel .= ' ugc';
+ }
$attributes .= ' rel="' . $rel . '"';
}