当前位置: 首页 > 面试题库 >

用HTML链接替换文本中的URL

和魁
2023-03-14
问题内容

不过,这是一个设计:例如,我放置了一个链接,例如

http://example.com

textarea中 。我如何获取PHP以检测它是一个http://链接,然后将其打印为

print "<a href='http://www.example.com'>http://www.example.com</a>";

我记得以前做过这样的事情,但这并不是傻瓜式的证明,它会因为复杂的链接而中断。

修复它

print "<a href='http://example.com/test.php?val1=bla&val2=bla%20bla%20bla.bla'>";
print "http://example.com/test.php";
print "</a>";

这只是一个经过深思熟虑的.. stackoverflow也可能会使用它:D

有任何想法吗


问题答案:

让我们看一下需求。您有一些用户提供的纯文本,您希望使用超链接的URL显示这些纯文本。

  1. “ http://”协议前缀应该是可选的。
  2. 域和IP地址都应接受。
  3. 任何有效的顶级域都应该被接受,例如.aero和.xn–jxalpdlp。
  4. 端口号应被允许。
  5. 在普通句子上下文中必须允许使用URL。
  6. 您可能还希望允许“ https://” URL,也可能允许其他URL。
  7. 与以往一样,在HTML中显示用户提供的文本时,您要防止跨站点脚本(XSS)。另外,您还希望URL中的“&”号可以正确地转为&amp;。
  8. 您可能不需要对IPv6地址的支持。
  9. 编辑 :如评论中所述,绝对支持电子邮件地址。
  10. 编辑 :仅支持纯文本输入-输入中的HTML标记不应被保留。(Bitbucket版本支持HTML输入。)

编辑 :检出GitHub以获取最新版本,并支持电子邮件地址,身份验证的URL,引号和括号中的URL,HTML输入以及更新的TLD列表。

这是我的看法:

<?php
$text = <<<EOD
Here are some URLs:
stackoverflow.com/questions/1188129/pregreplace-to-detect-html-php
Here's the answer: http://www.google.com/search?rls=en&q=42&ie=utf-8&oe=utf-8&hl=en. What was the question?
A quick look at http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax is helpful.
There is no place like 127.0.0.1! Except maybe http://news.bbc.co.uk/1/hi/england/surrey/8168892.stm?
Ports: 192.168.0.1:8080, https://example.net:1234/.
Beware of Greeks bringing internationalized top-level domains: xn--hxajbheg2az3al.xn--jxalpdlp.
And remember.Nobody is perfect.

<script>alert('Remember kids: Say no to XSS-attacks! Always HTML escape untrusted input!');</script>
EOD;

$rexProtocol = '(https?://)?';
$rexDomain   = '((?:[-a-zA-Z0-9]{1,63}\.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}\.){3}[0-9]{1,3})';
$rexPort     = '(:[0-9]{1,5})?';
$rexPath     = '(/[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]*?)?';
$rexQuery    = '(\?[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?';
$rexFragment = '(#[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?';

// Solution 1:

function callback($match)
{
    // Prepend http:// if no protocol specified
    $completeUrl = $match[1] ? $match[0] : "http://{$match[0]}";

    return '<a href="' . $completeUrl . '">'
        . $match[2] . $match[3] . $match[4] . '</a>';
}

print "<pre>";
print preg_replace_callback("&\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\"]?(\s|$))&",
    'callback', htmlspecialchars($text));
print "</pre>";
  • 为了正确地转义<和&字符,在处理之前,我将整个文本通过htmlspecialchars抛出。这是不理想的,因为html转义会导致对URL边界的错误检测。
  • 正如“记住,没有人是完美的”所证明的。行(记住,由于缺少空格,没有人被视为URL),可能需要进一步检查有效的顶级域。

编辑
:以下代码解决了上述两个问题,但由于我要preg_replace_callback使用或多或少地重新实现,因此更加冗长preg_match

// Solution 2:

$validTlds = array_fill_keys(explode(" ", ".aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cu .cv .cx .cy .cz .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .yu .za .zm .zw .xn--0zwm56d .xn--11b5bs3a9aj6g .xn--80akhbyknj4f .xn--9t4b11yi5a .xn--deba0ad .xn--g6w251d .xn--hgbk6aj7f53bba .xn--hlcj6aya9esc7a .xn--jxalpdlp .xn--kgbechtv .xn--zckzah .arpa"), true);

$position = 0;
while (preg_match("{\\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:\"]?(\s|$))}", $text, &$match, PREG_OFFSET_CAPTURE, $position))
{
    list($url, $urlPosition) = $match[0];

    // Print the text leading up to the URL.
    print(htmlspecialchars(substr($text, $position, $urlPosition - $position)));

    $domain = $match[2][0];
    $port   = $match[3][0];
    $path   = $match[4][0];

    // Check if the TLD is valid - or that $domain is an IP address.
    $tld = strtolower(strrchr($domain, '.'));
    if (preg_match('{\.[0-9]{1,3}}', $tld) || isset($validTlds[$tld]))
    {
        // Prepend http:// if no protocol specified
        $completeUrl = $match[1][0] ? $url : "http://$url";

        // Print the hyperlink.
        printf('<a href="%s">%s</a>', htmlspecialchars($completeUrl), htmlspecialchars("$domain$port$path"));
    }
    else
    {
        // Not a valid URL.
        print(htmlspecialchars($url));
    }

    // Continue text parsing from after the URL.
    $position = $urlPosition + strlen($url);
}

// Print the remainder of the text.
print(htmlspecialchars(substr($text, $position)));


 类似资料:
  • 问题内容: 我正在尝试通过将包含某些URL的String替换为与浏览器兼容的链接URL来做一些事情。 我最初的String看起来像这样: 我想要得到的是一个看起来像这样的字符串: 我可以使用以下代码行捕获URL: 也许regexp表达式需要一些更正,但是它工作正常,需要进一步测试。 因此,问题是如何保持正则表达式捕获表达式并仅添加创建链接所需的内容:catched string 预先感谢您的关注和

  • 我有一条短信。在这篇文章中是一张图片。我想把每个单词柏林都换成一个链接。现在我有问题,这站在图片的旧部分也是柏林,这也被取代。 有没有可能照片中的柏林没有被取代?注意,代码只是一个示例。我通常从wordpress获取内容。但这与此无关。我想。

  • 问题内容: 在我的数据库中,contenfields具有许多内部链接。我必须将链接结构从www.mydomain.de/page.html更改为www.mydomain.de/page/,但是replace语句应尊重该域: 这是预期将被替换的内容: 所有其他链接都应保持不变,此处提供一些示例,但也可以是网络上的任何链接: 一个内容字段中可以有不同的链接: 这是在做替换: 我的想法(但不知道如何为它

  • 它是在Android上的,在加载到WebView之前需要修复html。 这可以在JAVA内部完成还是必须在WebView的JavaScript内部完成?

  • 问题内容: 我有一个简单的评论系统,人们可以在纯文本字段内提交超链接。当我将这些记录从数据库显示回到网页中时,可以使用PHP中的哪些RegExp将这些链接转换为HTML型锚链接? 我不希望算法通过任何其他类型的链接(仅http和https)来执行此操作。 问题答案: 这是另一种解决方案,它将捕获所有http / https / www并转换为可单击的链接。 或者,仅捕获http / https,然

  • 我想改变HTML元素的文本内容,使其具有一定的背景色。HTML的格式如下 我有像下面这样需要匹配的关键字: 我有字符串形式的html 我想匹配元素文本内容,并在匹配HTML字符串时用关键字替换它们。我会改变他们的跨度有给定的背景颜色和匹配关键字的文本。 生成的HTML如下所示。 如何用java实现它。我正在使用jsoup库。 这个代码对我有用。这是最佳方法吗?。或者有没有更好的替代html字符串的