From 3859b7ba106835e503ce89352e18b946f67e1960 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Feb 2021 10:20:51 -0500 Subject: [PATCH] Move /parse_url module to /parseurl - Update oexchange module to use BBCode::embedURL instead of a self-request - Remove mod/parse_url.php file - Restrict ParseUrl module to authenticated users --- mod/oexchange.php | 14 +- mod/parse_url.php | 182 ------------------- src/Module/ParseUrl.php | 129 +++++++++++++ static/routes.config.php | 1 + view/js/linkPreview.js | 2 +- view/templates/jot-header.tpl | 4 +- view/templates/msg-header.tpl | 4 +- view/templates/wallmsg-header.tpl | 4 +- view/theme/frio/js/jot.js | 2 +- view/theme/frio/js/textedit.js | 4 +- view/theme/frio/templates/jot-header.tpl | 2 +- view/theme/smoothly/templates/jot-header.tpl | 4 +- 12 files changed, 148 insertions(+), 204 deletions(-) delete mode 100644 mod/parse_url.php create mode 100644 src/Module/ParseUrl.php diff --git a/mod/oexchange.php b/mod/oexchange.php index f68fe6f2d2..e3ef01cc4d 100644 --- a/mod/oexchange.php +++ b/mod/oexchange.php @@ -47,16 +47,12 @@ function oexchange_content(App $a) { return; } - $url = ((!empty($_REQUEST['url'])) - ? urlencode(Strings::escapeTags(trim($_REQUEST['url']))) : ''); - $title = ((!empty($_REQUEST['title'])) - ? '&title=' . urlencode(Strings::escapeTags(trim($_REQUEST['title']))) : ''); - $description = ((!empty($_REQUEST['description'])) - ? '&description=' . urlencode(Strings::escapeTags(trim($_REQUEST['description']))) : ''); - $tags = ((!empty($_REQUEST['tags'])) - ? '&tags=' . urlencode(Strings::escapeTags(trim($_REQUEST['tags']))) : ''); + $url = !empty($_REQUEST['url']) ? trim($_REQUEST['url']) : ''; + $title = !empty($_REQUEST['title']) ? trim($_REQUEST['title']) : ''; + $description = !empty($_REQUEST['description']) ? trim($_REQUEST['description']) : ''; + $tags = !empty($_REQUEST['tags']) ? trim($_REQUEST['tags']) : ''; - $s = DI::httpRequest()->fetch(DI::baseUrl() . '/parse_url?url=' . $url . $title . $description . $tags); + $s = \Friendica\Content\Text\BBCode::embedURL($url, true, $title, $description, $tags); if (!strlen($s)) { return; diff --git a/mod/parse_url.php b/mod/parse_url.php deleted file mode 100644 index 83997958d9..0000000000 --- a/mod/parse_url.php +++ /dev/null @@ -1,182 +0,0 @@ -. - * - * This module does parse an url for embeddable content (audio, video, image files or link) - * information and does format this information to BBCode - * - * @see ParseUrl::getSiteinfo() for more information about scraping embeddable content - */ - -use Friendica\App; -use Friendica\Content\PageInfo; -use Friendica\Core\Hook; -use Friendica\Core\Logger; -use Friendica\Core\System; -use Friendica\DI; -use Friendica\Util\ParseUrl; -use Friendica\Util\Strings; - -function parse_url_content(App $a) -{ - $text = null; - $str_tags = ''; - $format = ''; - $ret= ['success' => false, 'contentType' => '']; - - $br = "\n"; - - if (!empty($_GET['binurl']) && Strings::isHex($_GET['binurl'])) { - $url = trim(hex2bin($_GET['binurl'])); - } elseif (!empty($_GET['url'])) { - $url = trim($_GET['url']); - // fallback in case no url is valid - } else { - Logger::info('No url given'); - exit(); - } - - if (!empty($_GET['title'])) { - $title = strip_tags(trim($_GET['title'])); - } - - if (!empty($_GET['description'])) { - $text = strip_tags(trim($_GET['description'])); - } - - if (!empty($_GET['tags'])) { - $arr_tags = ParseUrl::convertTagsToArray($_GET['tags']); - if (count($arr_tags)) { - $str_tags = $br . implode(' ', $arr_tags) . $br; - } - } - - if (isset($_GET['format']) && $_GET['format'] == 'json') { - $format = 'json'; - } - - // Add url scheme if it is missing - $arrurl = parse_url($url); - if (empty($arrurl['scheme'])) { - if (!empty($arrurl['host'])) { - $url = 'http:' . $url; - } else { - $url = 'http://' . $url; - } - } - - Logger::log($url); - - // Check if the URL is an image, video or audio file. If so format - // the URL with the corresponding BBCode media tag - // Fetch the header of the URL - $curlResponse = DI::httpRequest()->head($url); - - if ($curlResponse->isSuccess()) { - $hdrs = $curlResponse->getHeaderArray(); - - $type = null; - $content_type = ''; - $bbcode = ''; - if (array_key_exists('Content-Type', $hdrs)) { - $type = $hdrs['Content-Type']; - } - if ($type) { - if (stripos($type, 'image/') !== false) { - $content_type = 'image'; - $bbcode = $br . '[img]' . $url . '[/img]' . $br; - } - if (stripos($type, 'video/') !== false) { - $content_type = 'video'; - $bbcode = $br . '[video]' . $url . '[/video]' . $br; - } - if (stripos($type, 'audio/') !== false) { - $content_type = 'audio'; - $bbcode = $br . '[audio]' . $url . '[/audio]' . $br; - } - } - if (!empty($content_type)) { - if ($format == 'json') { - $ret['contentType'] = $content_type; - $ret['data'] = ['url' => $url]; - $ret['success'] = true; - System::jsonExit($ret); - } - - echo $bbcode; - exit(); - } - } - - - $template = '[bookmark=%s]%s[/bookmark]%s'; - - $arr = ['url' => $url, 'format' => $format, 'text' => null]; - - Hook::callAll('parse_link', $arr); - - if ($arr['text']) { - if ($format == 'json') { - System::jsonExit($arr['text']); - } else { - echo $arr['text']; - exit(); - } - } - - // If there is already some content information submitted we don't - // need to parse the url for content. - if (!empty($url) && !empty($title) && !empty($text)) { - $title = str_replace(["\r", "\n"], ['', ''], $title); - - $text = '[quote]' . trim($text) . '[/quote]' . $br; - - $result = sprintf($template, $url, ($title) ? $title : $url, $text) . $str_tags; - - Logger::log('(unparsed): returns: ' . $result); - - echo $result; - exit(); - } - - // Fetch the information directly from the webpage - $siteinfo = ParseUrl::getSiteinfo($url); - - unset($siteinfo['keywords']); - - // Bypass attachment if parse url for a comment - if (!empty($_GET['noAttachment'])) { - echo $br . '[url=' . $url . ']' . $siteinfo['title'] . '[/url]'; - exit(); - } - - if ($format == 'json') { - $ret['data'] = $siteinfo; - $ret['contentType'] = 'attachment'; - $ret['success'] = true; - - System::jsonExit($ret); - } - - // Format it as BBCode attachment - $info = "\n" . PageInfo::getFooterFromData($siteinfo); - - echo $info; - - exit(); -} diff --git a/src/Module/ParseUrl.php b/src/Module/ParseUrl.php new file mode 100644 index 0000000000..ed48ea1b26 --- /dev/null +++ b/src/Module/ParseUrl.php @@ -0,0 +1,129 @@ +. + * + */ + +namespace Friendica\Module; + +use Friendica\BaseModule; +use Friendica\Content\Text\BBCode; +use Friendica\Core\Hook; +use Friendica\Core\Session; +use Friendica\Core\System; +use Friendica\Network\HTTPException\BadRequestException; +use Friendica\Util; + +class ParseUrl extends BaseModule +{ + public static function rawContent(array $parameters = []) + { + if (!Session::isAuthenticated()) { + throw new \Friendica\Network\HTTPException\ForbiddenException(); + } + + $format = ''; + $title = ''; + $description = ''; + $ret = ['success' => false, 'contentType' => '']; + + if (!empty($_GET['binurl']) && Util\Strings::isHex($_GET['binurl'])) { + $url = trim(hex2bin($_GET['binurl'])); + } elseif (!empty($_GET['url'])) { + $url = trim($_GET['url']); + // fallback in case no url is valid + } else { + throw new BadRequestException('No url given'); + } + + if (!empty($_GET['title'])) { + $title = strip_tags(trim($_GET['title'])); + } + + if (!empty($_GET['description'])) { + $description = strip_tags(trim($_GET['description'])); + } + + if (!empty($_GET['tags'])) { + $arr_tags = Util\ParseUrl::convertTagsToArray($_GET['tags']); + if (count($arr_tags)) { + $str_tags = "\n" . implode(' ', $arr_tags) . "\n"; + } + } + + if (isset($_GET['format']) && $_GET['format'] == 'json') { + $format = 'json'; + } + + // Add url scheme if it is missing + $arrurl = parse_url($url); + if (empty($arrurl['scheme'])) { + if (!empty($arrurl['host'])) { + $url = 'http:' . $url; + } else { + $url = 'http://' . $url; + } + } + + $arr = ['url' => $url, 'format' => $format, 'text' => null]; + + Hook::callAll('parse_link', $arr); + + if ($arr['text']) { + if ($format == 'json') { + System::jsonExit($arr['text']); + } else { + echo $arr['text']; + exit(); + } + } + + if ($format == 'json') { + $siteinfo = Util\ParseUrl::getSiteinfoCached($url); + + if (in_array($siteinfo['type'], ['image', 'video', 'audio'])) { + switch ($siteinfo['type']) { + case 'video': + $content_type = 'video'; + break; + case 'audio': + $content_type = 'audio'; + break; + default: + $content_type = 'image'; + break; + } + + $ret['contentType'] = $content_type; + $ret['data'] = ['url' => $url]; + $ret['success'] = true; + } else { + unset($siteinfo['keywords']); + + $ret['data'] = $siteinfo; + $ret['contentType'] = 'attachment'; + $ret['success'] = true; + } + + System::jsonExit($ret); + } else { + echo BBCode::embedURL($url, empty($_GET['noAttachment']), $title, $description, $_GET['tags'] ?? ''); + exit(); + } + } +} diff --git a/static/routes.config.php b/static/routes.config.php index afb8ee12f8..031f6082b1 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -346,6 +346,7 @@ return [ '/openid' => [Module\Security\OpenID::class, [R::GET]], '/opensearch' => [Module\OpenSearch::class, [R::GET]], + '/parseurl' => [Module\ParseUrl::class, [R::GET]], '/permission/tooltip/{type}/{id:\d+}' => [Module\PermissionTooltip::class, [R::GET]], '/photo' => [ diff --git a/view/js/linkPreview.js b/view/js/linkPreview.js index 27102be11a..293020bc82 100644 --- a/view/js/linkPreview.js +++ b/view/js/linkPreview.js @@ -178,7 +178,7 @@ * @returns {void} */ var getContentData = function(binurl, callback) { - $.get('parse_url?binurl='+ binurl + '&format=json', function (answer) { + $.get('parseurl?binurl='+ binurl + '&format=json', function (answer) { obj = sanitizeInputData(answer); // Put the data into a cache diff --git a/view/templates/jot-header.tpl b/view/templates/jot-header.tpl index 8f9d59d985..db2e893e9b 100644 --- a/view/templates/jot-header.tpl +++ b/view/templates/jot-header.tpl @@ -103,7 +103,7 @@ function enableOnUser(){ if(reply && reply.length) { reply = bin2hex(reply); $('#profile-rotator').show(); - $.get('parse_url?binurl=' + reply, function(data) { + $.get('parseurl?binurl=' + reply, function(data) { addeditortext(data); $('#profile-rotator').hide(); }); @@ -160,7 +160,7 @@ function enableOnUser(){ if(reply && reply.length) { reply = bin2hex(reply); $('#profile-rotator').show(); - $.get('parse_url?binurl=' + reply, function(data) { + $.get('parseurl?binurl=' + reply, function(data) { if (!editor) $("#profile-jot-text").val(""); initEditor(function(){ addeditortext(data); diff --git a/view/templates/msg-header.tpl b/view/templates/msg-header.tpl index 1db1750dd2..1e1d51661b 100644 --- a/view/templates/msg-header.tpl +++ b/view/templates/msg-header.tpl @@ -23,7 +23,7 @@ reply = prompt("{{$linkurl}}"); if(reply && reply.length) { $('#profile-rotator').show(); - $.get('parse_url?url=' + reply, function(data) { + $.get('parseurl?url=' + reply, function(data) { addeditortext(data); $('#profile-rotator').hide(); }); @@ -42,7 +42,7 @@ event.preventDefault(); if(reply && reply.length) { $('#profile-rotator').show(); - $.get('parse_url?url=' + reply, function(data) { + $.get('parseurl?url=' + reply, function(data) { addeditortext(data); $('#profile-rotator').hide(); }); diff --git a/view/templates/wallmsg-header.tpl b/view/templates/wallmsg-header.tpl index c64e0f6454..5f6b0d40e1 100644 --- a/view/templates/wallmsg-header.tpl +++ b/view/templates/wallmsg-header.tpl @@ -7,7 +7,7 @@ reply = prompt("{{$linkurl}}"); if(reply && reply.length) { $('#profile-rotator').show(); - $.get('parse_url?url=' + reply, function(data) { + $.get('parseurl?url=' + reply, function(data) { addeditortext(data); $('#profile-rotator').hide(); }); @@ -26,7 +26,7 @@ event.preventDefault(); if(reply && reply.length) { $('#profile-rotator').show(); - $.get('parse_url?url=' + reply, function(data) { + $.get('parseurl?url=' + reply, function(data) { addeditortext(data); $('#profile-rotator').hide(); }); diff --git a/view/theme/frio/js/jot.js b/view/theme/frio/js/jot.js index 37ee9ec66e..d70f882bca 100644 --- a/view/theme/frio/js/jot.js +++ b/view/theme/frio/js/jot.js @@ -30,7 +30,7 @@ function jotGetLink() { // Fallback: insert the attachment bbcode directly into the textarea // if the attachment live preview isn't available } else { - $.get("parse_url?binurl=" + bin2hex(reply) + noAttachment, function (data) { + $.get("parseurl?binurl=" + bin2hex(reply) + noAttachment, function (data) { addeditortext(data); $("#profile-rotator").hide(); }); diff --git a/view/theme/frio/js/textedit.js b/view/theme/frio/js/textedit.js index 014f6504fd..e8e4a6eb44 100644 --- a/view/theme/frio/js/textedit.js +++ b/view/theme/frio/js/textedit.js @@ -40,7 +40,7 @@ function commentGetLink(id, prompttext) { reply = prompt(prompttext); if (reply && reply.length) { reply = bin2hex(reply); - $.get("parse_url?noAttachment=1&binurl=" + reply, function (data) { + $.get("parseurl?noAttachment=1&binurl=" + reply, function (data) { addCommentText(data, id); }); } @@ -64,7 +64,7 @@ function commentLinkDrop(event, id) { event.preventDefault(); if (reply && reply.length) { reply = bin2hex(reply); - $.get("parse_url?noAttachment=1&binurl=" + reply, function (data) { + $.get("parseurl?noAttachment=1&binurl=" + reply, function (data) { addCommentText(data, id); }); } diff --git a/view/theme/frio/templates/jot-header.tpl b/view/theme/frio/templates/jot-header.tpl index f9e10ca8cd..fdc49f54a5 100644 --- a/view/theme/frio/templates/jot-header.tpl +++ b/view/theme/frio/templates/jot-header.tpl @@ -223,7 +223,7 @@ if (currentText.includes("[attachment") && currentText.includes("[/attachment]")) { noAttachment = '&noAttachment=1'; } - $.get('parse_url?binurl=' + reply + noAttachment, function(data) { + $.get('parseurl?binurl=' + reply + noAttachment, function(data) { if (!editor) $("#profile-jot-text").val(""); initEditor(function(){ addeditortext(data); diff --git a/view/theme/smoothly/templates/jot-header.tpl b/view/theme/smoothly/templates/jot-header.tpl index 71e54246b3..3f0040ddf3 100644 --- a/view/theme/smoothly/templates/jot-header.tpl +++ b/view/theme/smoothly/templates/jot-header.tpl @@ -129,7 +129,7 @@ function enableOnUser(){ if(reply && reply.length) { reply = bin2hex(reply); $('#profile-rotator').show(); - $.get('parse_url?binurl=' + reply, function(data) { + $.get('parseurl?binurl=' + reply, function(data) { addeditortext(data); $('#profile-rotator').hide(); }); @@ -190,7 +190,7 @@ function enableOnUser(){ if(reply && reply.length) { reply = bin2hex(reply); $('#profile-rotator').show(); - $.get('parse_url?binurl=' + reply, function(data) { + $.get('parseurl?binurl=' + reply, function(data) { if (!editor) $("#profile-jot-text").val(""); initEditor(function(){ addeditortext(data);