My fix? Oh well. In that bug report I suggested sorting the smiley cache by key length. Which works fine, and is the minimal change that retains current smiley parser semantics, but I've actually done something different.
PHP has this nice mass string replacement function
strtr() that works exactly this way (longest first).
So instead of this:
foreach ($this->smilies_cache as $find => $replace)
{
$orig_message = $message;
$find = $this->parse_html($find);
$find = preg_quote($find, "#");
$replace = strip_tags($replace, "<img>");
// Fix issues for smileys starting with a ";"
$orig_find = $find;
if (substr($find, 0, 1) == ";")
{
$find = "(?<!>|<|&)" . $find;
}
$message = @preg_replace("#(?<=[^\"])" . $find . "(?=.\W|\"|\W.|\W$)#si", $replace, $message, $remaining, $replacements);
if ($message == null)
{
$message = preg_replace("#(?<=[^&;\"])" . $orig_find . "(?=.\W|\"|\W.|\W$)#si", $replace, $orig_message, $remaining);
}
$remaining -= $replacements;
if ($remaining <= 0)
{
break; // Reached the limit
}
}
I have this:
$message = strtr($message, $this->smilies_cache);
The upside is you don't have to sort and it makes smiley parsing faster by an order of magnitude.
The downside is you can't have custom rules like (?<=[^\"])".$find."(?=.\W|\"|\W.|\W$), smiley limit to 500, and whatever else that foreach loop is doing. Which is fine by me since I don't need it.
The // Fix issues for smileys starting with a ";" also isn't there. Normally, the only smiley that is affected by that is

or ;-) and you can protect that in strtr() by adding "&"=>"&", ">"=>">", "<"=>"<", to the smiley cache array. Since "<" with 4 chars is longer than ";-)" with three chars, it will replace "<" (with itself) first and

or ;-) is protected if there is a &) anywhere.