Server-side Text Linkification with PHP Digg this entry Add this entry to del.icio.us bookmarks Add this entry to Slashdot bookmarks

I began writing the Linkification extension for Firefox after browsing several message boards and comment areas, and becoming frustrated at the number of plain text links. I just wanted to click the text like any other link, rather than having to highlight, copy, and paste the text into the address bar. I don't know how many people are immediately put off by text links, but I do know that I'm personally more likely to visit a site if all I have to do is click once.

While coding my comment system, I knew I didn't want to deal with the potential security risk of allowing users to post certain HTML tags, most notably <a>. I also knew that not everyone would be using Firefox, and even fewer visitors would have Linkification installed. Instead of relying on client-side javascript, I ported the javascript logic from Linkification to a server-side PHP function.

The PHP LinkifyText() function

<?php
function LinkifyText($sText, $aAttributes = array('title' => 'Linkified Text', 'rel' => 'nofollow'), $aProtocols = array('http:\/\/', 'https:\/\/', 'ftp:\/\/', 'news:\/\/', 'nntp:\/\/', 'telnet:\/\/', 'irc:\/\/', 'mms:\/\/', 'ed2k:\/\/', 'xmpp:', 'mailto:'), $aSubdomains = array('www'=>'http://', 'ftp'=>'ftp://', 'irc'=>'irc://', 'jabber'=>'xmpp:'))
{
	$sRELinks = '/(?:(' . implode('|', $aProtocols) . ')[^\^\[\]{}|\\"\'<>`\s]*[^!@\^()\[\]{}|\\:;"\',.?<>`\s])|(?:(?:(?:(?:[^@:<>(){}`\'"\/\[\]\s]+:)?[^@:<>(){}`\'"\/\[\]\s]+@)?(' . implode('|', array_keys($aSubdomains)) . ')\.(?:[^`~!@#$%^&*()_=+\[{\]}\\|;:\'",<.>\/?\s]+\.)+[a-z]{2,6}(?:[\/#?](?:[^\^\[\]{}|\\"\'<>`\s]*[^!@\^()\[\]{}|\\:;"\',.?<>`\s])?)?)|(?:(?:[^@:<>(){}`\'"\/\[\]\s]+@)?((?:(?:(?:(?:[0-1]?[0-9]?[0-9])|(?:2[0-4][0-9])|(?:25[0-5]))(?:\.(?:(?:[0-1]?[0-9]?[0-9])|(?:2[0-4][0-9])|(?:25[0-5]))){3})|(?:[A-Fa-f0-9:]{16,39}))|(?:(?:[^`~!@#$%^&*()_=+\[{\]}\\|;:\'",<.>\/?\s]+\.)+[a-z]{2,6}))\/(?:[^\^\[\]{}|\\"\'<>`\s]*[^!@\^()\[\]{}|\\:;"\',.?<>`\s](?:[#?](?:[^\^\[\]{}|\\"\'<>`\s]*[^!@\^()\[\]{}|\\:;"\',.?<>`\s])?)?)?)|(?:[^@:<>(){}`\'"\/\[\]\s]+:[^@:<>(){}`\'"\/\[\]\s]+@((?:(?:(?:(?:[0-1]?[0-9]?[0-9])|(?:2[0-4][0-9])|(?:25[0-5]))(?:\.(?:(?:[0-1]?[0-9]?[0-9])|(?:2[0-4][0-9])|(?:25[0-5]))){3})|(?:[A-Fa-f0-9:]{16,39}))|(?:(?:[^`~!@#$%^&*()_=+\[{\]}\\|;:\'",<.>\/?\s]+\.)+[a-z]{2,6}))(?:\/(?:(?:[^\^\[\]{}|\\"\'<>`\s]*[^!@\^()\[\]{}|\\:;"\',.?<>`\s])?)?)?(?:[#?](?:[^\^\[\]{}|\\"\'<>`\s]*[^!@\^()\[\]{}|\\:;"\',.?<>`\s])?)?))|([^@:<>(){}`\'"\/\[\]\s]+@(?:(?:(?:[^`~!@#$%^&*()_=+\[{\]}\\|;:\'",<.>\/?\s]+\.)+[a-z]{2,6})|(?:(?:(?:(?:(?:[0-1]?[0-9]?[0-9])|(?:2[0-4][0-9])|(?:25[0-5]))(?:\.(?:(?:[0-1]?[0-9]?[0-9])|(?:2[0-4][0-9])|(?:25[0-5]))){3})|(?:[A-Fa-f0-9:]{16,39}))))(?:[^\^*\[\]{}|\\"<>\/`\s]+[^!@\^()\[\]{}|\\:;"\',.?<>`\s])?)/i';

	$sAttributes = '';
	while (list($sKey, $sValue) = each($aAttributes))
	{
		$sAttributes .= ' ' . $sKey . '="' . $sValue . '"';
	}

	$sNewText = '';
	while (preg_match($sRELinks, $sText, $aMatches))
	{
		$nMatchType = sizeof($aMatches) - 1;
		$sMatchText = $aMatches[$nMatchType];

		$sNewText .= substr($sText, 0, strpos($sText, $aMatches[0]));
		$sText = substr($sText, strpos($sText, $aMatches[0]) + strlen($aMatches[0]));

		if ($nMatchType == 1)
		{
			$sNewText .= '<a href="' . $aMatches[0] . '"' . $sAttributes . '>' . $aMatches[0] . '</a>';
		}
		elseif ($nMatchType == 2)
		{
			$sNewText .= '<a href="' . $aSubdomains[$sMatchText] . $aMatches[0] . '"' . $sAttributes . '>' . $aMatches[0] . '</a>';
		}
		elseif (($nMatchType == 3) || ($nMatchType == 4))
		{
			$sNewText .= '<a href="http://' . $aMatches[0] . '"' . $sAttributes . '>' . $aMatches[0] . '</a>';
		}
		else
		{
			$sNewText .= '<a href="mailto:' . $aMatches[0] . '"' . $sAttributes . '>' . $aMatches[0] . '</a>';
		}
	}

	return $sNewText . $sText;
}
?>

LinkifyText() Examples

<?php
	print LinkifyText('This is a test link: http://example.com');
	print LinkifyText('This is a test link: www.example.com');
	print LinkifyText('This is a test link: ftp.example.com');
	print LinkifyText('This is a test link: example.com/test/');
	print LinkifyText('This is a test link: email@example.com');
?>

Download LinkifyText()


2 CommentsRSS

1 Mek wrote: [5:17pm on July 17 2007]

Hey, I really love this function, it has helped me a lot!

I like your Linkification addon for Firefox too, I recommend it to all my Firefox friends (users).

Thank you again, because this is what I was looking for :)

2 Steve Graham wrote: [10:39am on October 26 2007]

Thanks for the script. I'm working on my company intranet and will use the code there. I appreciated the time and effort you've put into the coding of linkification (and this php script).


Steve

Comments are disabled for this entry.