News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

Имя файла на русском

Started by Sailorman, December 24, 2006, 03:58:57 AM

Previous topic - Next topic

Sailorman

Подскажите пожалуйста как можно решить проблему с аттачами на русском языке.
Тыкаешь на скрепке в FireFox сохраняется правильно, а в IE кодировка имя файла слетает на всякие символы непонятные. Форум установлен в UTF-8.

P.S. Про русские имена файлов не надо, я каждого своего пользователя не собираюсь учить.
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

†MavN†

проверяйте настройки вашего программного обеспечения

Sailorman

http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

RXL

SMF отправляет тоже самое имя файла, которое было указано при заливке. Т.е. если при заливке была задана абракадабра, то при скачке будет тоже самое.
Винить можно только браузеры (особенно IE).

fomenka

Не пудрите человеку мозг. Он сам его себе запудрит!
Правильный ответ был на английском форуме. В файле 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. Если я не прав, поправьте меня.


Sailorman

данное исправление не решает проблему :(
причем в опере файл с русскими буквами вообще предлагается к сохранению как html :(
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

Sailorman

мдя....
прошел год, как глюк был так он и остается.
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

Sailorman

Прошло много время поставил 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);

извините что так криво описал - я не программер ;)

http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

RXL

#8
Глюк не вылечен. На своем форуме вылечил руками. Извиняюсь, что только словами - без четких инструкций...

1. Находим в Sources/Load.php блок, начинающийся со строки
Code (php) Select
          $func = array(
В конце блока добавляем:
Code (php) Select

                '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. Надо прорабатывать этот вопрос. Вероятно нужно задать кодировку в заголовке.

Sailorman

дык, как сделать чтоб это проработали разработчики? этож касается не только кириллицы, а всех языков которые имеют национальные символы.
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

RXL

Кабы знать... Я разработчиков не беспокою - у них и без меня советчиков море. Потому и написал сюда: кому надо - тот прочтет, а может и до разработчиков кто донесет.

RXL

#11
PHP, кстати, внутренне работает только с байтовыми (8-битными) кодировками, что означает непредсказуемый результат при работе с utf-8. Есть пара костылей - несколько функций из набора multibyte-поддержки, но этого очень мало. То, что происходит с basename() - это типичная бага. Думаю, что раньше PHP6 полноценной поддержки utf-8 ждать не стоит. Это значит, что придется выловить еще не один подобный баг.

Sailorman, не надо извратов - смотри в документации функцию iconv() - все придумано до нас.

rtyug

кодировку нужно использовать utf8 скорее всего, ну там зависит от локали на сервере вся кодировка! вообще-то чем англиский не нарвится?

RXL

Продолжение проблемы с не-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.

RXL

Код выше прошел тестирование и видоизменился.

Модуль 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.

Advertisement: