Simple Machines Community Forum

SMF Support => Language Specific Support => Русский (Russian) => Topic started by: Sailorman on December 24, 2006, 03:58:57 AM

Title: Имя файла на русском
Post by: Sailorman on December 24, 2006, 03:58:57 AM
Подскажите пожалуйста как можно решить проблему с аттачами на русском языке.
Тыкаешь на скрепке в FireFox сохраняется правильно, а в IE кодировка имя файла слетает на всякие символы непонятные. Форум установлен в UTF-8.

P.S. Про русские имена файлов не надо, я каждого своего пользователя не собираюсь учить.
Title: Re: Имя файла на русском
Post by: †MavN† on December 24, 2006, 10:26:58 AM
проверяйте настройки вашего программного обеспечения
Title: Re: Имя файла на русском
Post by: Sailorman on December 25, 2006, 08:20:44 AM
емкий ответ!

например?
Title: Re: Имя файла на русском
Post by: RXL on December 29, 2006, 05:40:50 AM
SMF отправляет тоже самое имя файла, которое было указано при заливке. Т.е. если при заливке была задана абракадабра, то при скачке будет тоже самое.
Винить можно только браузеры (особенно IE).
Title: Re: Имя файла на русском
Post by: fomenka on February 07, 2007, 06:53:30 PM
Не пудрите человеку мозг. Он сам его себе запудрит!
Правильный ответ был на английском форуме. В файле Subs-Post.php надо исправить
Code: [Select]
//$attachmentOptions['destination'] = $modSettings['attachmentUploadDir'] . '/' . getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], true);
$attachmentOptions['destination'] = $modSettings['attachmentUploadDir'] . '/' . getAttachmentFilename($attachmentOptions['name'], $attachmentOptions['id'], true);

Русские имена убивает функция basename. Если я не прав, поправьте меня.

 
Title: Re: Имя файла на русском
Post by: Sailorman on March 14, 2007, 04:08:26 AM
данное исправление не решает проблему :(
причем в опере файл с русскими буквами вообще предлагается к сохранению как html :(
Title: Re: Имя файла на русском
Post by: Sailorman on December 16, 2007, 10:44:14 AM
мдя....
прошел год, как глюк был так он и остается.
Title: Re: Имя файла на русском
Post by: Sailorman on September 17, 2008, 05:51:46 AM
Прошло много время поставил 2.0 а глюки теже.

Разобрался почему:

Некоторые функции PHP не корректно работает с 2-х байтовой кодировкой UTF8
и имя файла уродуется как попало!

в файле subs.php

добавил вот такую функцию:
Code: [Select]
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 вот это:
Code: [Select]
$filename = Utf8ToWin($filename);
извините что так криво описал - я не программер ;)

Title: Re: Имя файла на русском
Post by: RXL on September 21, 2008, 10:21:00 AM
Глюк не вылечен. На своем форуме вылечил руками. Извиняюсь, что только словами - без четких инструкций...

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. Надо прорабатывать этот вопрос. Вероятно нужно задать кодировку в заголовке.
Title: Re: Имя файла на русском
Post by: Sailorman on September 22, 2008, 04:04:56 AM
дык, как сделать чтоб это проработали разработчики? этож касается не только кириллицы, а всех языков которые имеют национальные символы.
Title: Re: Имя файла на русском
Post by: RXL on September 22, 2008, 05:49:34 AM
Кабы знать... Я разработчиков не беспокою - у них и без меня советчиков море. Потому и написал сюда: кому надо - тот прочтет, а может и до разработчиков кто донесет.
Title: Re: Имя файла на русском
Post by: RXL on September 22, 2008, 12:07:04 PM
PHP, кстати, внутренне работает только с байтовыми (8-битными) кодировками, что означает непредсказуемый результат при работе с utf-8. Есть пара костылей - несколько функций из набора multibyte-поддержки, но этого очень мало. То, что происходит с basename() - это типичная бага. Думаю, что раньше PHP6 полноценной поддержки utf-8 ждать не стоит. Это значит, что придется выловить еще не один подобный баг.

Sailorman, не надо извратов - смотри в документации функцию iconv() - все придумано до нас.
Title: Re: Имя файла на русском
Post by: rtyug on September 28, 2008, 06:32:24 AM
кодировку нужно использовать utf8 скорее всего, ну там зависит от локали на сервере вся кодировка! вообще-то чем англиский не нарвится?
Title: Re: Имя файла на русском
Post by: RXL on December 15, 2009, 12:44:24 PM
Продолжение проблемы с не-ASCII символами в именах файлов.
После обновления до 1.1.11 имена скачиваемых атачей в IE получаются кракозябрами (UTF-8 текст, интерпретированный как windows-1251).
Лечение простое: в модуле Source/Display.php, в функции Download() ищем строку:
Code: [Select]
        header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename="' . $real_filename . '"');
и заменяем ее на:
Code: [Select]
        header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename=' . str_replace('+', '%20', urlencode($real_filename)));

Протестировано с IE 6/7/8 и FF 3.5.
Title: Re: Имя файла на русском
Post by: RXL on December 17, 2009, 09:40:36 AM
Код выше прошел тестирование и видоизменился.

Модуль Source/Load.php, функция loadTheme().
Было:
Code: [Select]
        // 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'];
Стало:
Code: [Select]
        // 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().
Было:
Code: [Select]
        header('Content-Disposition: ' . (isset($_REQUEST['image']) ? 'inline' : 'attachment') . '; filename="' . $real_filename . '"');
Стало:
Code: [Select]
        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.