diff --git a/include/class.format.php b/include/class.format.php
index 7fc8e7834a96e3ab62a83fab41f8d753822bec3e..37abcf2388f293ddd98f928f9bf1a053606f497b 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -276,10 +276,6 @@ class Format {
     function display($text, $inline_images=true) {
         global $cfg;
 
-        //make urls clickable.
-        if($cfg && $cfg->clickableURLS() && $text)
-            $text=Format::clickableurls($text);
-
         //Wrap long words...
         #$text=preg_replace_callback('/\w{75,}/',
         #    create_function(
@@ -297,6 +293,10 @@ class Format {
             },
             $text);
 
+        //make urls clickable.
+        if($cfg && $cfg->clickableURLS() && $text)
+            $text = Format::clickableurls($text);
+
         if ($inline_images)
             return self::viewableImages($text);
 
@@ -316,23 +316,69 @@ class Format {
         global $ost;
 
         $token = $ost->getLinkToken();
-        //Not perfect but it works - please help improve it.
-        $text=preg_replace_callback('/(?<!"|>)(((f|ht)tp(s?):\/\/)[-a-zA-Z0-9@:%_\+.~#?&;\/\/=]+)/',
-                create_function('$matches',
-                    sprintf('return "<a href=\"l.php?url=".urlencode($matches[1])."&auth=%s\" target=\"_blank\">".$matches[1]."</a>";',
-                        $token)),
-                $text);
-
-        $text=preg_replace_callback("/(^|[ \\n\\r\\t])(www\.([a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+)(\/[^\/ \\n\\r]*)*)/",
-                create_function('$matches',
-                    sprintf('return "<a href=\"l.php?url=".urlencode("http://".$matches[2])."&auth=%s\" target=\"_blank\">".$matches[2]."</a>";',
-                        $token)),
-                $text);
-
-        $text=preg_replace("/(^|[ \\n\\r\\t])([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4})/",
-            '\\1<a href="mailto:\\2" target="_blank">\\2</a>', $text);
 
-        return $text;
+        // Find all text between tags
+        $text = preg_replace_callback(':^[^<]+|>[^<]+:',
+            function($match) use ($token) {
+                // Scan for things that look like URLs
+                $links = preg_replace_callback(
+                    '`(?<!>)(((f|ht)tp(s?)://|(?<!//)www\.)([a-zA-Z0-9_-]+(\.|/|$))+\S*)`',
+                    function ($match) use ($token) {
+                        if (in_array(substr($match[1], -1),
+                                array(',','.','?','!',':',';'))) {
+                            $match[7] = substr($match[1], -1);
+                            $match[1] = substr($match[1], 0, strlen($match[1])-1);
+                        }
+                        return '<a href="l.php?url='.urlencode($match[1])
+                            .sprintf('&auth=%s" target="_blank">', $token)
+                            .$match[1].'</a>'.$match[7];
+                    },
+                    $match[0]);
+                // Now change email addresses to links with mailto: scheme
+                return preg_replace(
+                    '/(\b[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4})/',
+                    '<a href="mailto:\\1" target="_blank">\\1</a>', $links);
+            },
+            $text);
+
+        // Now change @href and @src attributes to come back through our
+        // system as well
+        $config = array(
+            'hook_tag' => function($e, $a=0) use ($token) {
+                static $eE = array('area'=>1, 'br'=>1, 'col'=>1, 'embed'=>1,
+                    'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'param'=>1);
+                if ($e == 'a' && $a) {
+                    if (isset($a['href'])
+                            && strpos($a['href'], 'l.php?') === false)
+                        $a['href'] = 'l.php?url='.urlencode($a['href'])
+                            .'&amp;auth='.$token;
+                    // ALL link targets open in a new tab
+                    $a['target'] = '_blank';
+                }
+                // Images which are external are rewritten to <div
+                // data-src='url...'/>
+                elseif ($e == 'div' && $a && isset($a['data-src']))
+                    $a['data-src'] = 'l.php?url='.urlencode($a['data-src'])
+                        .'&amp;auth='.$token;
+                // URLs for videos need to route too
+                elseif ($e == 'iframe' && $a && isset($a['src']))
+                    $a['src'] = 'l.php?url='.urlencode($a['src'])
+                        .'&amp;auth='.$token;
+                $at = '';
+                if (is_array($a)) {
+                    foreach ($a as $k=>$v)
+                        $at .= " $k=\"$v\"";
+                    return "<{$e}{$at}".(isset($eE[$e])?" /":"").">";
+                }
+                else {
+                    return "</{$e}>";
+                }
+            },
+            'schemes' => 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https; src: cid, http, https, data',
+            'elements' => '*+iframe',
+            'spec' => 'div=data-src,width,height',
+        );
+        return Format::html($text, $config);
     }
 
     function stripEmptyLines($string) {
diff --git a/l.php b/l.php
index cd963af74d7c2260b2de610ab904dad52b53199b..150048429a832048acc3f532bf41812387c6f271 100644
--- a/l.php
+++ b/l.php
@@ -15,14 +15,14 @@
 **********************************************************************/
 require 'secure.inc.php';
 //Basic url validation + token check.
-if (!($url=trim($_GET['url'])) || !Validator::is_url($url) || !$ost->validateLinkToken($_GET['auth']))
-    exit('Invalid url');
+
+# PHP < 5.4.7 will not handle a URL like //host.tld/path correctly
+if (!($url=trim($_GET['url'])))
+    Http::response(422, 'Invalid URL');
+
+$check = (strpos($url, '//') === 0) ? 'http:' . $url : $url;
+if (!Validator::is_url($check) || !$ost->validateLinkToken($_GET['auth']))
+    Http::response(403, 'URL link not authorized');
+else
+    Http::redirect($url);
 ?>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-    <meta http-equiv="refresh" content="0;URL=<?php echo $url; ?>"/>
-</head>
-<body/>
-</html>
diff --git a/scp/l.php b/scp/l.php
index 99f27fd57ac251f111350124ff4023269dc85b29..8e0dd28b7bb5e264d0ad0fc4e2642508eac38eb9 100644
--- a/scp/l.php
+++ b/scp/l.php
@@ -15,14 +15,14 @@
 **********************************************************************/
 require_once 'staff.inc.php';
 //Basic url validation + token check.
-if (!($url=trim($_GET['url'])) || !Validator::is_url($url) || !$ost->validateLinkToken($_GET['auth']))
-    exit('Invalid url');
+
+# PHP < 5.4.7 will not handle a URL like //host.tld/path correctly
+if (!($url=trim($_GET['url'])))
+    Http::response(422, 'Invalid URL');
+
+$check = (strpos($url, '//') === 0) ? 'http:' . $url : $url;
+if (!Validator::is_url($check) || !$ost->validateLinkToken($_GET['auth']))
+    Http::response(403, 'URL link not authorized');
+else
+    Http::redirect($url);
 ?>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-    <meta http-equiv="refresh" content="0; URL=<?php echo $url; ?>"/>
-</head>
-<body/>
-</html>