diff -urN program.orig/lib/Roundcube/rcube_vcard.php program/lib/Roundcube/rcube_vcard.php --- program.orig/lib/Roundcube/rcube_vcard.php 2013-10-21 22:39:20.000000000 +0300 +++ program/lib/Roundcube/rcube_vcard.php 2013-11-16 02:13:05.000000000 +0200 @@ -871,6 +871,49 @@ */ private static function detect_encoding($string) { + if (substr($string, 0, 4) == "\0\0\xFE\xFF") return 'UTF-32BE'; // Big Endian + if (substr($string, 0, 4) == "\xFF\xFE\0\0") return 'UTF-32LE'; // Little Endian + if (substr($string, 0, 2) == "\xFE\xFF") return 'UTF-16BE'; // Big Endian + if (substr($string, 0, 2) == "\xFF\xFE") return 'UTF-16LE'; // Little Endian + if (substr($string, 0, 3) == "\xEF\xBB\xBF") return 'UTF-8'; + + // heuristics + if ($string[0] == "\0" && $string[1] == "\0" && $string[2] == "\0" && $string[3] != "\0") return 'UTF-32BE'; + if ($string[0] != "\0" && $string[1] == "\0" && $string[2] == "\0" && $string[3] == "\0") return 'UTF-32LE'; + if ($string[0] == "\0" && $string[1] != "\0" && $string[2] == "\0" && $string[3] != "\0") return 'UTF-16BE'; + if ($string[0] != "\0" && $string[1] == "\0" && $string[2] != "\0" && $string[3] == "\0") return 'UTF-16LE'; + + $rcube = rcube::get_instance(); + $language = $rcube->get_user_language(); + + // + // mb_detect_encoding can not correctly identify russian charsets + // + // Use this charset as fallback for vcard decoding + // $rcmail_config['default_vcard_charset'] = 'WINDOWS-1251'; + // + + if (($language == 'ru_RU') and (function_exists('iconv'))) { + $fallback = strtoupper(rcube::get_instance()->config->get('default_vcard_charset', 'WINDOWS-1251')); + $encodings = array('UTF-8', 'WINDOWS-1251', 'KOI8-R'); + if (!in_array($fallback, $encodings)) $encodings[] = $fallback; + + $res = array(); + foreach ($encodings as $encoding) { + $sample = iconv($encoding, $encoding, $string); + if (md5($sample) == md5($string)) { + $sample = iconv($encoding, 'UTF-8', $string); + $sample = iconv('UTF-8', $encoding, $sample); + if (md5($sample) == md5($string)) $res[] = $encoding; + } + } + + if (count($res) == 1) { + return($res[0]); + } elseif (count($res) > 1) { + if (in_array($fallback, $res)) return($fallback); + } + } $fallback = rcube::get_instance()->config->get('default_charset', 'ISO-8859-1'); // fallback to Latin-1 return rcube_charset::detect($string, $fallback);