Skip to content

Commit

Permalink
Fix long URL formatting causing bugnote/text to be blank
Browse files Browse the repository at this point in the history
When MantisCoreFormatting plugin processes text (e.g. bugnote)
containing a long URL, a PREG_BACKTRACK_LIMIT_ERROR may occur in
string_insert_hrefs() when replacing email address links with
preg_replace_callback(). When pcre.backtrack_limit = 100000, the longest
URL that can be processed successfully is 152 chars. A bigger URL
triggers the PCRE error and the function returns NULL.

This was introduced by commit 21a3469.

We now use preg_split() instead of preg_replace_callback(), which is
more efficient and avoids the backtrace error issue

The url replacement string was also moved to a variable to make code
more readable.

Fixes #14447
  • Loading branch information
dregad committed Aug 3, 2012
1 parent adc66fe commit 38ef324
Showing 1 changed file with 24 additions and 28 deletions.
52 changes: 24 additions & 28 deletions core/string_api.php
Expand Up @@ -446,7 +446,7 @@ function string_process_bugnote_link( $p_string, $p_include_anchor = true, $p_de
*/
function string_insert_hrefs( $p_string ) {
static $s_url_regex = null;
static $s_email_regex = null;
static $s_anchor_regex = '/(<a[^>]*>.*?<\/a>)/is';

if( !config_get( 'html_make_links' ) ) {
return $p_string;
Expand All @@ -458,54 +458,50 @@ function string_insert_hrefs( $p_string ) {
ini_set( 'magic_quotes_sybase', false );
}

# Find any URL in a string and replace it by a clickable link
$t_url_protocol = '([[:alpha:]][-+.[:alnum:]]*):\/\/';
# Initialize URL regex static variable
if ( is_null( $s_url_regex ) ) {
$t_url_protocol = '(?:[[:alpha:]][-+.[:alnum:]]*):\/\/';

# %2A notation in url's
$t_url_hex = '%[[:digit:]A-Fa-f]{2}';

# valid set of characters that may occur in url scheme. Note: - should be first (A-F != -AF).
$t_url_valid_chars = '-_.,!~*\';\/?%^\\\\:@&={\|}+$#[:alnum:]\pL';

$t_url_chars = "(?:${t_url_hex}|[${t_url_valid_chars}\(\)\[\]])";
$t_url_chars2 = "(?:${t_url_hex}|[${t_url_valid_chars}])";
$t_url_valid_chars = '-_.,!~*\';\/?%^\\\\:@&={\|}+$#[:alnum:]\pL';
$t_url_chars = "(?:${t_url_hex}|[${t_url_valid_chars}\(\)\[\]])";
$t_url_chars2 = "(?:${t_url_hex}|[${t_url_valid_chars}])";
$t_url_chars_in_brackets = "(?:${t_url_hex}|[${t_url_valid_chars}\(\)])";
$t_url_chars_in_parens = "(?:${t_url_hex}|[${t_url_valid_chars}\[\]])";
$t_url_chars_in_parens = "(?:${t_url_hex}|[${t_url_valid_chars}\[\]])";

$t_url_part1 = "${t_url_chars}";
$t_url_part2 = "(?:\(${t_url_chars_in_parens}*\)|\[${t_url_chars_in_brackets}*\]|${t_url_chars2})";

$s_url_regex = "/(${t_url_protocol}(${t_url_part1}*?${t_url_part2}+))/sue";
}

# Find any URL in a string and replace it by a clickable link
$p_string = preg_replace( $s_url_regex, "'<a href=\"'.rtrim('\\1','.').'\">\\1</a> [<a href=\"'.rtrim('\\1','.').'\" target=\"_blank\">^</a>]'", $p_string );
if( $t_change_quotes ) {
ini_set( 'magic_quotes_sybase', true );
}

# Find any email addresses in the string and replace them with a clickable
# mailto: link, making sure that URLs such as http://user@example.com/ or
# http://user:password@example.com/ are not processed as an email
if( is_null( $s_email_regex ) ) {
$s_email_regex = email_regex_simple();
$s_email_regex =
substr( $s_email_regex, 0, 1 ) .
'(' . $t_url_protocol . '.*?)?' .
substr( $s_email_regex, 1 );
# mailto: link, making sure that we skip processing of any existing anchor
# tags, to avoid parts of URLs such as https://user@example.com/ or
# http://user:password@example.com/ to be not treated as an email.
$t_pieces = preg_split( $s_anchor_regex, $p_string, null, PREG_SPLIT_DELIM_CAPTURE );
$p_string = '';
foreach( $t_pieces as $piece ) {
if( preg_match( $s_anchor_regex, $piece ) ) {
$p_string .= $piece;
} else {
$p_string .= preg_replace(
email_regex_simple(),
'<a href="mailto:\0">\0</a>',
$piece
);
}
}

$p_string = preg_replace_callback(
$s_email_regex,
create_function(
'$p_match',
'if( 0 === preg_match( "/' . $t_url_protocol . '/", $p_match[0] ) ) {
return \'<a href="mailto:\' . $p_match[0] . \'">\' . $p_match[0] . \'</a>\';
} else {
return $p_match[0];
}'
),
$p_string );

return $p_string;
}

Expand Down

0 comments on commit 38ef324

Please sign in to comment.