// This code is licensed under the MIT license // //################################################################### // // These are global options. You can set them before calling the autolinking // functions to change the output. // $GLOBALS['autolink_options'] = [ // Should http:// be visibly stripped from the front // of URLs? 'strip_protocols' => false, ]; //################################################################### function autolink($text, $limit = 30, $tagfill = '', $auto_title = true) { $text = autolink_do($text, '![a-z][a-z-]+://!i', $limit, $tagfill, $auto_title); $text = autolink_do($text, '!(mailto|skype):!i', $limit, $tagfill, $auto_title); $text = autolink_do($text, '!www\\.!i', $limit, $tagfill, $auto_title, 'http://'); return $text; } //################################################################### function autolink_do($text, $sub, $limit, $tagfill, $auto_title, $force_prefix = null) { $text_l = strtolower($text); $cursor = 0; $loop = 1; $buffer = ''; while (($cursor < strlen($text)) && $loop) { $ok = 1; $matched = preg_match($sub, $text_l, $m, PREG_OFFSET_CAPTURE, $cursor); if (! $matched) { $loop = 0; $ok = 0; } else { $pos = $m[0][1]; $sub_len = strlen($m[0][0]); $pre_hit = substr($text, $cursor, $pos - $cursor); $hit = substr($text, $pos, $sub_len); $pre = substr($text, 0, $pos); $post = substr($text, $pos + $sub_len); $fail_text = $pre_hit.$hit; $fail_len = strlen($fail_text); // // substring found - first check to see if we're inside a link tag already... // $bits = preg_split('!!i', $pre); $last_bit = array_pop($bits); if (preg_match("!\n"; $ok = 0; $cursor += $fail_len; $buffer .= $fail_text; } } // // looks like a nice spot to autolink from - check the pre // to see if there was whitespace before this match // if ($ok) { if ($pre) { if (! preg_match('![\s\(\[\{>]$!s', $pre)) { //echo "fail 2 at $cursor ($pre)
\n"; $ok = 0; $cursor += $fail_len; $buffer .= $fail_text; } } } // // we want to autolink here - find the extent of the url // if ($ok) { if (preg_match('/^([a-z0-9\-\.\/\-_%~!?=,:;&+*#@\(\)\$]+)/i', $post, $matches)) { $url = $hit.$matches[1]; $cursor += strlen($url) + strlen($pre_hit); $buffer .= $pre_hit; $url = html_entity_decode($url); // // remove trailing punctuation from url // while (preg_match('|[.,!;:?]$|', $url)) { $url = substr($url, 0, strlen($url) - 1); $cursor--; } foreach (['()', '[]', '{}'] as $pair) { $o = substr($pair, 0, 1); $c = substr($pair, 1, 1); if (preg_match("!^(\\$c|^)[^\\$o]+\\$c$!", $url)) { $url = substr($url, 0, strlen($url) - 1); $cursor--; } } // // nice-i-fy url here // $link_url = $url; $display_url = $url; if ($force_prefix) { $link_url = $force_prefix.$link_url; } if ($GLOBALS['autolink_options']['strip_protocols']) { if (preg_match('!^(http|https)://!i', $display_url, $m)) { $display_url = substr($display_url, strlen($m[1]) + 3); } } $display_url = autolink_label($display_url, $limit); // // add the url // $currentTagfill = $tagfill; if ($display_url != $link_url && ! preg_match('@title=@msi', $currentTagfill) && $auto_title) { $display_quoted = preg_quote($display_url, '!'); if (! preg_match("!^(http|https)://{$display_quoted}$!i", $link_url)) { $currentTagfill .= ' title="'.$link_url.'"'; } } $link_url_enc = htmlspecialchars($link_url); $display_url_enc = htmlspecialchars($display_url); $buffer .= "{$display_url_enc}"; } else { //echo "fail 3 at $cursor
\n"; $ok = 0; $cursor += $fail_len; $buffer .= $fail_text; } } } // // add everything from the cursor to the end onto the buffer. // $buffer .= substr($text, $cursor); return $buffer; } //################################################################### function autolink_label($text, $limit) { if (! $limit) { return $text; } if (strlen($text) > $limit) { return substr($text, 0, $limit - 3).'...'; } return $text; } //################################################################### function autolink_email($text, $tagfill = '') { $atom = '[^()<>@,;:\\\\".\\[\\]\\x00-\\x20\\x7f]+'; // from RFC822 //die($atom); $text_l = strtolower($text); $cursor = 0; $loop = 1; $buffer = ''; while (($cursor < strlen($text)) && $loop) { // // find an '@' symbol // $ok = 1; $pos = strpos($text_l, '@', $cursor); if ($pos === false) { $loop = 0; $ok = 0; } else { $pre = substr($text, $cursor, $pos - $cursor); $hit = substr($text, $pos, 1); $post = substr($text, $pos + 1); $fail_text = $pre.$hit; $fail_len = strlen($fail_text); //die("$pre::$hit::$post::$fail_text"); // // substring found - first check to see if we're inside a link tag already... // $bits = preg_split('!!i', $pre); $last_bit = array_pop($bits); if (preg_match("!\n"; $ok = 0; $cursor += $fail_len; $buffer .= $fail_text; } } // // check backwards // if ($ok) { if (preg_match("!($atom(\.$atom)*)\$!", $pre, $matches)) { // move matched part of address into $hit $len = strlen($matches[1]); $plen = strlen($pre); $hit = substr($pre, $plen - $len).$hit; $pre = substr($pre, 0, $plen - $len); } else { //echo "fail 2 at $cursor ($pre)
\n"; $ok = 0; $cursor += $fail_len; $buffer .= $fail_text; } } // // check forwards // if ($ok) { if (preg_match("!^($atom(\.$atom)*)!", $post, $matches)) { // move matched part of address into $hit $len = strlen($matches[1]); $hit .= substr($post, 0, $len); $post = substr($post, $len); } else { //echo "fail 3 at $cursor ($post)
\n"; $ok = 0; $cursor += $fail_len; $buffer .= $fail_text; } } // // commit // if ($ok) { $cursor += strlen($pre) + strlen($hit); $buffer .= $pre; $buffer .= "$hit"; } } // // add everything from the cursor to the end onto the buffer. // $buffer .= substr($text, $cursor); return $buffer; } //###################################################################;