diff --git a/src/OneScript.StandardLibrary/FileContext.cs b/src/OneScript.StandardLibrary/FileContext.cs index 739a5da8a..9ba9f0abd 100644 --- a/src/OneScript.StandardLibrary/FileContext.cs +++ b/src/OneScript.StandardLibrary/FileContext.cs @@ -24,6 +24,10 @@ public class FileContext : AutoContext public FileContext(string name) { + // Strip null characters that can be added by Windows WebDAV client + // to maintain compatibility with 1.x behavior + name = PathHelper.StripNullCharacters(name); + if (String.IsNullOrWhiteSpace(name)) { _name = ""; diff --git a/src/OneScript.StandardLibrary/FileOperations.cs b/src/OneScript.StandardLibrary/FileOperations.cs index a3ddb95c5..7d6188851 100644 --- a/src/OneScript.StandardLibrary/FileOperations.cs +++ b/src/OneScript.StandardLibrary/FileOperations.cs @@ -138,6 +138,11 @@ public string GetTempFilename(string ext = null) [ContextMethod("НайтиФайлы", "FindFiles")] public ArrayImpl FindFiles(string dir, string mask = null, bool recursive = false) { + // Strip null characters that can be added by Windows WebDAV client + // to maintain compatibility with 1.x behavior + dir = PathHelper.StripNullCharacters(dir); + mask = PathHelper.StripNullCharacters(mask); + if (mask == null) { // fix 225, 227, 228 diff --git a/src/OneScript.StandardLibrary/PathHelper.cs b/src/OneScript.StandardLibrary/PathHelper.cs new file mode 100644 index 000000000..a7fd9d3c2 --- /dev/null +++ b/src/OneScript.StandardLibrary/PathHelper.cs @@ -0,0 +1,30 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +namespace OneScript.StandardLibrary +{ + /// + /// Utility methods for working with file paths + /// + internal static class PathHelper + { + /// + /// Strips null characters from a path string. + /// This is needed because Windows WebDAV client can add null characters to paths, + /// which causes ArgumentException in System.IO methods. + /// + /// Path that may contain null characters + /// Path with null characters removed, or null if input was null + public static string StripNullCharacters(string path) + { + if (path == null) + return null; + + return path.Replace("\0", ""); + } + } +} diff --git a/tests/null-character-handling.os b/tests/null-character-handling.os new file mode 100644 index 000000000..631f7cc7c --- /dev/null +++ b/tests/null-character-handling.os @@ -0,0 +1,110 @@ +Перем юТест; + +Функция Версия() Экспорт + Возврат "0.1"; +КонецФункции + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_СоздатьФайлСНулевымСимволом"); + ВсеТесты.Добавить("ТестДолжен_ВыполнитьНайтиФайлыСНулевымСимволом"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьСвойстваФайлаСНулевымСимволом"); + + Возврат ВсеТесты; +КонецФункции + +Процедура ТестДолжен_СоздатьФайлСНулевымСимволом() Экспорт + + ВремФайл = ПолучитьИмяВременногоФайла("txt"); + ЗаписьТекста = Новый ЗаписьТекста(ВремФайл); + ЗаписьТекста.ЗаписатьСтроку("тестовое содержимое"); + ЗаписьТекста.Закрыть(); + + Попытка + // Добавляем нулевой символ в путь, как это делает Windows WebDAV клиент + ПутьСНулевымСимволом = ВремФайл + Символ(0); + Файл = Новый Файл(ПутьСНулевымСимволом); + + // Проверяем, что файл доступен и не выбрасывает исключение + юТест.ПроверитьИстину(Файл.Существует(), "Файл должен существовать"); + юТест.ПроверитьРавенство("txt", Прав(Файл.Расширение, 3), "Расширение должно быть txt"); + + Исключение + УдалитьФайлы(ВремФайл); + ВызватьИсключение; + КонецПопытки; + + УдалитьФайлы(ВремФайл); + +КонецПроцедуры + +Процедура ТестДолжен_ВыполнитьНайтиФайлыСНулевымСимволом() Экспорт + + ВремКаталог = КаталогВременныхФайлов(); + ИмяТестовогоФайла = "test_null_char_" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + ".txt"; + ВремФайл = ОбъединитьПути(ВремКаталог, ИмяТестовогоФайла); + + ЗаписьТекста = Новый ЗаписьТекста(ВремФайл); + ЗаписьТекста.ЗаписатьСтроку("тестовое содержимое"); + ЗаписьТекста.Закрыть(); + + Попытка + // Добавляем нулевой символ в путь к каталогу + ПутьКаталогаСНулевымСимволом = ВремКаталог + Символ(0); + + // Проверяем, что НайтиФайлы не выбрасывает исключение + НайденныеФайлы = НайтиФайлы(ПутьКаталогаСНулевымСимволом, ИмяТестовогоФайла); + + // Проверяем, что файл был найден + юТест.ПроверитьРавенство(1, НайденныеФайлы.Количество(), "Должен быть найден один файл"); + юТест.ПроверитьРавенство(ИмяТестовогоФайла, НайденныеФайлы[0].Имя, "Имя файла должно совпадать"); + + Исключение + УдалитьФайлы(ВремФайл); + ВызватьИсключение; + КонецПопытки; + + УдалитьФайлы(ВремФайл); + +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьСвойстваФайлаСНулевымСимволом() Экспорт + + ВремФайл = ПолучитьИмяВременногоФайла("txt"); + ЗаписьТекста = Новый ЗаписьТекста(ВремФайл); + ЗаписьТекста.ЗаписатьСтроку("тестовое содержимое"); + ЗаписьТекста.Закрыть(); + + Попытка + // Добавляем нулевой символ в конец пути + ПутьСНулевымСимволом = ВремФайл + Символ(0); + Файл = Новый Файл(ПутьСНулевымСимволом); + + // Проверяем, что все свойства доступны без исключений + ПолноеИмя = Файл.ПолноеИмя; + юТест.ПроверитьНеравенство("", ПолноеИмя, "ПолноеИмя не должно быть пустым"); + + Имя = Файл.Имя; + юТест.ПроверитьНеравенство("", Имя, "Имя не должно быть пустым"); + + Путь = Файл.Путь; + юТест.ПроверитьНеравенство("", Путь, "Путь не должен быть пустым"); + + Расширение = Файл.Расширение; + юТест.ПроверитьРавенство(".txt", Расширение, "Расширение должно быть .txt"); + + Размер = Файл.Размер(); + юТест.ПроверитьБольше(Размер, 0, "Размер должен быть больше 0"); + + Исключение + УдалитьФайлы(ВремФайл); + ВызватьИсключение; + КонецПопытки; + + УдалитьФайлы(ВремФайл); + +КонецПроцедуры