Simple Machines Community Forum
SMF Support => Language Specific Support => Русский (Russian) => Topic started by: Sailorman on December 24, 2006, 03:58:57 AM
-
Подскажите пожалуйста как можно решить проблему с аттачами на русском языке.
Тыкаешь на скрепке в FireFox сохраняется правильно, а в IE кодировка имя файла слетает на всякие символы непонятные. Форум установлен в UTF-8.
P.S. Про русские имена файлов не надо, я каждого своего пользователя не собираюсь учить.
-
проверяйте настройки вашего программного обеспечения
-
емкий ответ!
например?
-
SMF отправляет тоже самое имя файла, которое было указано при заливке. Т.е. если при заливке была задана абракадабра, то при скачке будет тоже самое.
Винить можно только браузеры (особенно IE).
-
Не пудрите человеку мозг. Он сам его себе запудрит!
Правильный ответ был на английском форуме. В файле Subs-Post.php надо исправить
//$attachmentOptions['destination'] = $modSettings['attachmentUploadDir'] . '/' . getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], true);
$attachmentOptions['destination'] = $modSettings['attachmentUploadDir'] . '/' . getAttachmentFilename($attachmentOptions['name'], $attachmentOptions['id'], true);
Русские имена убивает функция basename. Если я не прав, поправьте меня.
-
данное исправление не решает проблему :(
причем в опере файл с русскими буквами вообще предлагается к сохранению как html :(
-
мдя....
прошел год, как глюк был так он и остается.
-
Прошло много время поставил 2.0 а глюки теже.
Разобрался почему:
Некоторые функции PHP не корректно работает с 2-х байтовой кодировкой UTF8
и имя файла уродуется как попало!
в файле subs.php
добавил вот такую функцию:
function Utf8ToWin($fcontents) {
$out = $c1 = '';
$byte2 = false;
for ($c = 0;$c < strlen($fcontents);$c++) {
$i = ord($fcontents[$c]);
if ($i <= 127) {
$out .= $fcontents[$c];
}
if ($byte2) {
$new_c2 = ($c1 & 3) * 64 + ($i & 63);
$new_c1 = ($c1 >> 2) & 5;
$new_i = $new_c1 * 256 + $new_c2;
if ($new_i == 1025) {
$out_i = 168;
} else {
if ($new_i == 1105) {
$out_i = 184;
} else {
$out_i = $new_i - 848;
}
}
// UKRAINIAN fix
switch ($out_i){
case 262: $out_i=179;break;// і
case 182: $out_i=178;break;// І
case 260: $out_i=186;break;// є
case 180: $out_i=170;break;// Є
case 263: $out_i=191;break;// ї
case 183: $out_i=175;break;// Ї
case 321: $out_i=180;break;// ґ
case 320: $out_i=165;break;// Ґ
}
$out .= chr($out_i);
$byte2 = false;
}
if ( ( $i >> 5) == 6) {
$c1 = $i;
$byte2 = true;
}
}
return $out;
}
и потом добавил в функцию
function getAttachmentFilename($filename, $attachment_id, $dir = null, $new = false)
после global вот это:
$filename = Utf8ToWin($filename);
извините что так криво описал - я не программер ;)
-
Глюк не вылечен. На своем форуме вылечил руками. Извиняюсь, что только словами - без четких инструкций...
1. Находим в Sources/Load.php блок, начинающийся со строки
$func = array(
В конце блока добавляем:
'basename' => $utf8 ?
create_function('$filepath, $suffix = false', '
$tmp = end(explode("/", $filepath));
return $suffix === false ? $tmp : preg_replace("/$suffix\\$/", "", $tmp);') :
create_function('$filepath, $suffix = false', 'return basename($filepath, $suffix);'),
Это основа.
2. В следующих файлах ищем использование ф-ии basename и заменяем его на $func['basename']. Внимание! В каждой ф-ии, где происходит такая замена, в начало надо добавить global $func;. Альтернатива - заменять на $GLOBALS['func']['basename'] - тогда объявленеи global в начале ф-ии не потребуется.
Список файлов в директории Sources:
Admin.php
Load.php
ManageSmileys.php
PackageGet.php
Packages.php
Post.php
QueryString.php
Subs-Package.php
Subs-Post.php
Themes.php
Побочный эффект: IE читает, что имена файлов по дефолту - в кодировке 1251. Надо прорабатывать этот вопрос. Вероятно нужно задать кодировку в заголовке.
-
дык, как сделать чтоб это проработали разработчики? этож касается не только кириллицы, а всех языков которые имеют национальные символы.
-
Кабы знать... Я разработчиков не беспокою - у них и без меня советчиков море. Потому и написал сюда: кому надо - тот прочтет, а может и до разработчиков кто донесет.
-
PHP, кстати, внутренне работает только с байтовыми (8-битными) кодировками, что означает непредсказуемый результат при работе с utf-8. Есть пара костылей - несколько функций из набора multibyte-поддержки, но этого очень мало. То, что происходит с basename() - это типичная бага. Думаю, что раньше PHP6 полноценной поддержки utf-8 ждать не стоит. Это значит, что придется выловить еще не один подобный баг.
Sailorman, не надо извратов - смотри в документации функцию iconv() - все придумано до нас.
-
кодировку нужно использовать utf8 скорее всего, ну там зависит от локали на сервере вся кодировка! вообще-то чем англиский не нарвится?
-
Продолжение проблемы с не-ASCII символами в именах файлов.
После обновления до 1.1.11 имена скачиваемых атачей в IE получаются кракозябрами (UTF-8 текст, интерпретированный как windows-1251).
Лечение простое: в модуле Source/Display.php, в функции Download() ищем строку:
header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename="' . $real_filename . '"');
и заменяем ее на:
header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename=' . str_replace('+', '%20', urlencode($real_filename)));
Протестировано с IE 6/7/8 и FF 3.5.
-
Код выше прошел тестирование и видоизменился.
Модуль Source/Load.php, функция loadTheme().
Было:
// Internet Explorer 5 and 6 are often "emulated".
$context['browser']['is_ie7'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie6'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie5.5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.5') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.0') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie'] = $context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie6'] || $context['browser']['is_ie7'];
Стало:
// Internet Explorer 5 and 6 are often "emulated".
$context['browser']['is_ie8'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 8') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie7'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie6'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie5.5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.5') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.0') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie'] = $context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie6'] || $context['browser']['is_ie7'] || $context['browser']['is_ie8'];
Модуль Source/Display.php, функция download().
Было:
header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename="' . $real_filename . '"');
Стало:
if ($context['browser']['is_ie'])
header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename=' . str_replace('+', '%20', urlencode($real_filename)));
else
header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename="' . $real_filename . '"');
Проверено на нескольких системах с разной локализацией с браузерами: IE[678], FF 3.0 и 3.5, Opera 9, Chrome 4.