При разработке интерфейсов выбора файлов в системе 1С:Предприятие часто возникает задача ограничить пользователя в выборе определенных типов файлов. Стандартный объект ДиалогВыбораФайла отлично справляется с созданием "белого списка" (разрешенных расширений), однако разработчики часто сталкиваются с вопросом: можно ли инвертировать эту логику? Например, разрешить выбирать всё, кроме файлов .exe или .bat.
В этой статье мы разберем, почему стандартный фильтр не поддерживает исключающую логику, и как правильно реализовать проверку "черного списка" расширений программными методами, учитывая кроссплатформенность и требования безопасности.
Прежде всего, проанализируем возможности свойства Фильтр объекта ДиалогВыбораФайла. Стандартная конструкция позволяет задать описание и маску, например: "Текстовые файлы (*.txt)|*.txt". К сожалению, синтаксис типа "Все кроме (*.exe)|!*.exe" или использование операторов НЕ внутри строки фильтра не предусмотрены платформой.
Разберем причину этого ограничения. Механизм ДиалогВыбораФайла в 1С является оболочкой над системными API операционной системы (Common Item Dialog в Windows или соответствующие библиотеки в Linux) и API браузеров (для веб-клиента). Ни одна из этих базовых технологий на текущий момент не поддерживает фильтрацию "от противного". Атрибуты фильтрации работают исключительно по принципу включения (белого списка). Следовательно, попытка реализовать это через одно лишь свойство Фильтр не увенчается успехом.
Единственным надежным способом реализовать "черный список" расширений является постобработка результата выбора. Рассмотрим алгоритм: мы позволяем пользователю выбрать любой файл (используя фильтр "Все файлы (*.*)|*.*"), а затем программно анализируем его расширение. Если расширение находится в списке запрещенных, мы выводим предупреждение и отменяем дальнейшие действия.
Посмотрим на пример реализации в асинхронном режиме, который является обязательным для современных версий платформы (начиная с 8.3.15):
&НаКлиенте
Процедура ВыбратьФайл(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл для загрузки";
Диалог.Фильтр = "Все файлы (*.*)|*.*";
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы = Неопределено Тогда
Возврат;
КонецЕсли;
ПутьКФайлу = ВыбранныеФайлы[0];
ФайлНаДиске = Новый Файл(ПутьКФайлу);
// Определим список запрещенных расширений в нижнем регистре
ЗапрещенныеРасширения = Новый Массив;
ЗапрещенныеРасширения.Добавить(".exe");
ЗапрещенныеРасширения.Добавить(".bat");
ЗапрещенныеРасширения.Добавить(".msi");
// Получаем расширение и приводим к нижнему регистру для корректного сравнения
ТекущееРасширение = НРег(ФайлНаДиске.Расширение);
Если ЗапрещенныеРасширения.Найти(ТекущееРасширение) <> Неопределено Тогда
ПоказатьПредупреждение(, "Выбор файлов данного типа (" + ТекущееРасширение + ") запрещен в целях безопасности!");
Возврат;
КонецЕсли;
// Если проверка пройдена, продолжаем работу
ПрочитатьФайл(ПутьКФайлу);
КонецПроцедуры
При реализации программной проверки крайне важно учитывать особенности файловых систем. Проанализируем ситуацию: в Windows файлы DOCUMENT.PDF и document.pdf воспринимаются одинаково. Однако в Linux-системах расширение может быть чувствительно к регистру. Чтобы ваш код работал корректно везде, всегда используйте функцию НРег() при сравнении расширений, как показано в примере выше.
Также стоит обратить внимание на свойство Расширение объекта Файл. Мы рекомендуем использовать именно его, а не пытаться самостоятельно парсить строку пути поиском последней точки. Объект Файл корректно обрабатывает специфические случаи, такие как отсутствие расширения или скрытые файлы, имя которых начинается с точки (например, .htaccess).
Выясним причину, по которой полагаться только на визуальный фильтр в окне диалога нельзя, даже если вы используете "белый список". Существует критическая особенность поведения системных диалогов: пользователь может вручную вставить полный путь к файлу в поле "Имя файла" или переключить тип фильтра на *.* самостоятельно. В этом случае операционная система позволит выбрать файл, даже если он не соответствует заданному вами фильтру. Таким образом, **проверка в коде 1С после закрытия диалога является обязательным элементом защиты**, а не просто дополнением.
Если ваша задача связана с обеспечением безопасности (например, предотвращение загрузки вредоносного ПО), простой проверки расширения недостаточно. Злоумышленник может переименовать файл virus.exe в image.jpg. Для серьезных систем рекомендуется после выбора файла выполнять следующие шаги:
Если стандартный диалог ОС категорически не подходит из-за невозможности скрыть запрещенные файлы "на лету", мы можем рассмотреть вариант создания собственной формы выбора. Разберем, как это реализовать:
ГДЕ Расширение НЕ В (&СписокЗапрещенных).Этот способ более трудоемок, так как вам придется самостоятельно реализовывать навигацию по папкам, обработку прав доступа и внешний вид проводника, но он дает полный контроль над тем, какие файлы видит пользователь.
Подводя итог, можно сказать, что хотя ДиалогВыбораФайла не имеет встроенного свойства для исключения расширений, комбинация широкого фильтра *.* и последующей программной проверки через объект Файл является стандартом разработки в 1С, обеспечивающим необходимый функционал и безопасность.