Advertisement:

Author Topic: Имя файла на русском  (Read 21163 times)

Offline Sailorman

  • Semi-Newbie
  • *
  • Posts: 11
  • Gender: Male
    • Парусный спорт. Класс Мини. Гонки на парусных яхтах через атлантику.
Имя файла на русском
« on: December 24, 2006, 03:58:57 AM »
Подскажите пожалуйста как можно решить проблему с аттачами на русском языке.
Тыкаешь на скрепке в FireFox сохраняется правильно, а в IE кодировка имя файла слетает на всякие символы непонятные. Форум установлен в UTF-8.

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

Offline †MavN†

  • Local Moderator
  • Sophist Member
  • *
  • Posts: 1,203
  • Gender: Male
  • MavnGroup
    • MavnGroup
Re: Имя файла на русском
« Reply #1 on: December 24, 2006, 10:26:58 AM »
проверяйте настройки вашего программного обеспечения

Offline Sailorman

  • Semi-Newbie
  • *
  • Posts: 11
  • Gender: Male
    • Парусный спорт. Класс Мини. Гонки на парусных яхтах через атлантику.
Re: Имя файла на русском
« Reply #2 on: December 25, 2006, 08:20:44 AM »
емкий ответ!

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

Offline RXL

  • Semi-Newbie
  • *
  • Posts: 61
  • Gender: Male
    • Клуб программистов 'Весельчак У'
Re: Имя файла на русском
« Reply #3 on: December 29, 2006, 05:40:50 AM »
SMF отправляет тоже самое имя файла, которое было указано при заливке. Т.е. если при заливке была задана абракадабра, то при скачке будет тоже самое.
Винить можно только браузеры (особенно IE).

Offline fomenka

  • Newbie
  • *
  • Posts: 2
Re: Имя файла на русском
« Reply #4 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. Если я не прав, поправьте меня.

 

Offline Sailorman

  • Semi-Newbie
  • *
  • Posts: 11
  • Gender: Male
    • Парусный спорт. Класс Мини. Гонки на парусных яхтах через атлантику.
Re: Имя файла на русском
« Reply #5 on: March 14, 2007, 04:08:26 AM »
данное исправление не решает проблему :(
причем в опере файл с русскими буквами вообще предлагается к сохранению как html :(
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

Offline Sailorman

  • Semi-Newbie
  • *
  • Posts: 11
  • Gender: Male
    • Парусный спорт. Класс Мини. Гонки на парусных яхтах через атлантику.
Re: Имя файла на русском
« Reply #6 on: December 16, 2007, 10:44:14 AM »
мдя....
прошел год, как глюк был так он и остается.
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

Offline Sailorman

  • Semi-Newbie
  • *
  • Posts: 11
  • Gender: Male
    • Парусный спорт. Класс Мини. Гонки на парусных яхтах через атлантику.
Re: Имя файла на русском
« Reply #7 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);
извините что так криво описал - я не программер ;)

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

Offline RXL

  • Semi-Newbie
  • *
  • Posts: 61
  • Gender: Male
    • Клуб программистов 'Весельчак У'
Re: Имя файла на русском
« Reply #8 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. Надо прорабатывать этот вопрос. Вероятно нужно задать кодировку в заголовке.
« Last Edit: September 21, 2008, 10:35:07 AM by RXL »

Offline Sailorman

  • Semi-Newbie
  • *
  • Posts: 11
  • Gender: Male
    • Парусный спорт. Класс Мини. Гонки на парусных яхтах через атлантику.
Re: Имя файла на русском
« Reply #9 on: September 22, 2008, 04:04:56 AM »
дык, как сделать чтоб это проработали разработчики? этож касается не только кириллицы, а всех языков которые имеют национальные символы.
http://open650.ru [nofollow] - парусный спорт, минитрансат, класс Мини...

Offline RXL

  • Semi-Newbie
  • *
  • Posts: 61
  • Gender: Male
    • Клуб программистов 'Весельчак У'
Re: Имя файла на русском
« Reply #10 on: September 22, 2008, 05:49:34 AM »
Кабы знать... Я разработчиков не беспокою - у них и без меня советчиков море. Потому и написал сюда: кому надо - тот прочтет, а может и до разработчиков кто донесет.

Offline RXL

  • Semi-Newbie
  • *
  • Posts: 61
  • Gender: Male
    • Клуб программистов 'Весельчак У'
Re: Имя файла на русском
« Reply #11 on: September 22, 2008, 12:07:04 PM »
PHP, кстати, внутренне работает только с байтовыми (8-битными) кодировками, что означает непредсказуемый результат при работе с utf-8. Есть пара костылей - несколько функций из набора multibyte-поддержки, но этого очень мало. То, что происходит с basename() - это типичная бага. Думаю, что раньше PHP6 полноценной поддержки utf-8 ждать не стоит. Это значит, что придется выловить еще не один подобный баг.

Sailorman, не надо извратов - смотри в документации функцию iconv() - все придумано до нас.
« Last Edit: September 22, 2008, 12:09:42 PM by RXL »

Offline rtyug

  • Jr. Member
  • **
  • Posts: 127
Re: Имя файла на русском
« Reply #12 on: September 28, 2008, 06:32:24 AM »
кодировку нужно использовать utf8 скорее всего, ну там зависит от локали на сервере вся кодировка! вообще-то чем англиский не нарвится?

Offline RXL

  • Semi-Newbie
  • *
  • Posts: 61
  • Gender: Male
    • Клуб программистов 'Весельчак У'
Re: Имя файла на русском
« Reply #13 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.

Offline RXL

  • Semi-Newbie
  • *
  • Posts: 61
  • Gender: Male
    • Клуб программистов 'Весельчак У'
Re: Имя файла на русском
« Reply #14 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.