1474 | | function make_clickable( $ret ) { |
1475 | | // Long strings might contain expensive edge cases ... |
1476 | | if ( 10000 < strlen( $ret ) ) { |
1477 | | $r = ''; |
1478 | | // ... break it up |
1479 | | foreach ( _split_str_by_whitespace( $ret, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses |
1480 | | if ( 2101 < strlen( $chunk ) ) { |
1481 | | $r .= $chunk; // Too big, no whitespace: bail. |
1482 | | } else { |
1483 | | $r .= make_clickable( $chunk ); |
1484 | | } |
| 1474 | function make_clickable( $text ) { |
| 1475 | $r = ''; |
| 1476 | $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags |
| 1477 | foreach ( $textarr as $piece ) { |
| 1478 | if ( empty( $piece ) || ( $piece[0] == '<' && ! preg_match('|^<\s*[\w]{1,20}+://|', $piece) ) ) { |
| 1479 | $r .= $piece; |
| 1480 | continue; |
1489 | | $ret = " $ret "; // Pad with whitespace to simplify the regexes |
| 1483 | // Long strings might contain expensive edge cases ... |
| 1484 | if ( 10000 < strlen( $piece ) ) { |
| 1485 | // ... break it up |
| 1486 | foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses |
| 1487 | if ( 2101 < strlen( $chunk ) ) { |
| 1488 | $r .= $chunk; // Too big, no whitespace: bail. |
| 1489 | } else { |
| 1490 | $r .= make_clickable( $chunk ); |
| 1491 | } |
| 1492 | } |
| 1493 | } else { |
| 1494 | $ret = " $piece "; // Pad with whitespace to simplify the regexes |
1491 | | $url_clickable = '~ |
1492 | | ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation |
1493 | | ( # 2: URL |
1494 | | [\\w]{1,20}+:// # Scheme and hier-part prefix |
1495 | | (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long |
1496 | | [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character |
1497 | | (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character |
1498 | | [\'.,;:!?)] # Punctuation URL character |
1499 | | [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character |
1500 | | )* |
1501 | | ) |
1502 | | (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing) |
1503 | | ~xS'; // The regex is a non-anchored pattern and does not have a single fixed starting character. |
1504 | | // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. |
| 1496 | $url_clickable = '~ |
| 1497 | ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation |
| 1498 | ( # 2: URL |
| 1499 | [\\w]{1,20}+:// # Scheme and hier-part prefix |
| 1500 | (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long |
| 1501 | [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character |
| 1502 | (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character |
| 1503 | [\'.,;:!?)] # Punctuation URL character |
| 1504 | [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character |
| 1505 | )* |
| 1506 | ) |
| 1507 | (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing) |
| 1508 | ~xS'; // The regex is a non-anchored pattern and does not have a single fixed starting character. |
| 1509 | // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. |
1508 | | $ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret); |
1509 | | $ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret); |
| 1513 | $ret = preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret ); |
| 1514 | $ret = preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret ); |