Добавление электронной подписи из файла / Модуль

файл
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ОписаниеПеременных

&НаКлиенте
Перем КлиентскиеПараметры Экспорт;

&НаКлиенте
Перем ОписаниеДанных, ФормаОбъекта, ТекущийСписокПредставлений;

&НаКлиенте
Перем ОтображениеДанныхОбновлено;

#КонецОбласти

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	УстановитьУсловноеОформление();
	
	АвтоЗаголовок = Ложь;
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
		Заголовок = НСтр("ru = 'Добавление электронных подписей из файлов на устройстве'");
		Элементы.ПодписиДобавить.Заголовок = НСтр("ru = 'Выбрать файлы с устройства...'");
	Иначе
		Заголовок = НСтр("ru = 'Добавление электронных подписей из файлов на компьютере'");
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Параметры.ЗаголовокДанных) Тогда
		Элементы.ПредставлениеДанных.Заголовок = Параметры.ЗаголовокДанных;
	Иначе
		Элементы.ПредставлениеДанных.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
	КонецЕсли;
	
	ПредставлениеДанных = Параметры.ПредставлениеДанных;
	Элементы.ПредставлениеДанных.Гиперссылка = Параметры.ПредставлениеДанныхОткрывается;
	
	Если Не ЗначениеЗаполнено(ПредставлениеДанных) Тогда
		Элементы.ПредставлениеДанных.Видимость = Ложь;
	КонецЕсли;
	
	Если Не Параметры.ПоказатьКомментарий Тогда
		Элементы.Подписи.Шапка = Ложь;
		Элементы.ПодписиКомментарий.Видимость = Ложь;
	КонецЕсли;
	
	МенеджерКриптографииНаСервереОписаниеОшибки = Новый Структура;
	
	Если ЭлектроннаяПодпись.ПроверятьЭлектронныеПодписиНаСервере()
	 Или ЭлектроннаяПодпись.СоздаватьЭлектронныеПодписиНаСервере() Тогда
		
		ПараметрыСоздания = ЭлектроннаяПодписьСлужебный.ПараметрыСозданияМенеджераКриптографии();
		ПараметрыСоздания.ОписаниеОшибки = Новый Структура;
		
		ЭлектроннаяПодписьСлужебный.МенеджерКриптографии("", ПараметрыСоздания);
		МенеджерКриптографииНаСервереОписаниеОшибки = ПараметрыСоздания.ОписаниеОшибки;
		
	КонецЕсли;
	
	ЭлектроннаяПодписьЛокализация.ПриСозданииНаСервере(ЭтотОбъект);
	
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	Если КлиентскиеПараметры = Неопределено Тогда
		Отказ = Истина;
	Иначе
		ОписаниеДанных             = КлиентскиеПараметры.ОписаниеДанных;
		ФормаОбъекта               = КлиентскиеПараметры.Форма;
		ТекущийСписокПредставлений = КлиентскиеПараметры.ТекущийСписокПредставлений;
		ПодключитьОбработчикОжидания("ПослеОткрытия", 0.1, Истина);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте
Процедура ПредставлениеДанныхНажатие(Элемент, СтандартнаяОбработка)
	
	ЭлектроннаяПодписьСлужебныйКлиент.ПредставлениеДанныхНажатие(ЭтотОбъект,
		Элемент, СтандартнаяОбработка, ТекущийСписокПредставлений);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыПодписи

&НаКлиенте
Процедура ПодписиПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)
	
	Отказ = Истина;
	
	Если ОтображениеДанныхОбновлено = Истина Тогда
		ВыбратьФайлы(Истина);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПодписиПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ВыбратьФайлы();
	
КонецПроцедуры

&НаКлиенте
Процедура ПодписиМашиночитаемаяДоверенностьНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ПодписиМашиночитаемаяДоверенностьНачалоВыбораПродолжение(Элемент, ДанныеВыбора);
	
КонецПроцедуры

&НаКлиенте
Асинх Процедура ПодписиМашиночитаемаяДоверенностьНачалоВыбораПродолжение(Элемент, ДанныеВыбора)
	
	ТекущиеДанные = Элементы.Подписи.ТекущиеДанные;
	
	СписокВыбора = Новый СписокЗначений;
	ЭлектроннаяПодписьКлиентЛокализация.ПриПолученииСпискаВыбораМашиночитаемыхДоверенностей(
		ЭтотОбъект, ТекущиеДанные, СписокВыбора);
	
	Если СписокВыбора.Количество() > 0 Тогда
		СписокВыбора.Добавить("ВыбратьИзСправочника", НСтр("ru = 'Выбрать из справочника...'"));
		Результат = Ждать ВыбратьИзСпискаАсинх(СписокВыбора, Элементы.ПодписиМашиночитаемаяДоверенность);
		Если Результат <> Неопределено Тогда
			Если Результат.Значение = "ВыбратьИзСправочника" Тогда
				МашиночитаемаяДоверенностьВыбратьИзСправочника();
				Возврат;
			КонецЕсли;
			
			ТекущиеДанные.МашиночитаемаяДоверенность = Результат.Представление;
			ТекущиеДанные.НомерДоверенности = Результат.Значение;
			ПодключитьОбработчикОжидания("ПодписиМашиночитаемаяДоверенностьПриИзменении", 0.1, Истина);
		КонецЕсли;
	Иначе
		МашиночитаемаяДоверенностьВыбратьИзСправочника();
	КонецЕсли;

КонецПроцедуры

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура ПодобратьДоверенности(Команда)
	
	Если ОписаниеДанных.Свойство("Объект") И ТипЗнч(ОписаниеДанных.Объект) <> Тип("ОписаниеОповещения") Тогда
		ЗаполнитьМашиночитаемыеДоверенности(ОписаниеДанных.Объект);
	Иначе
		ЗаполнитьМашиночитаемыеДоверенности();
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ОК(Команда)
	
	Если Подписи.Количество() = 0 Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Не выбрано ни одного файла подписи'"));
		Возврат;
	КонецЕсли;
	
	ЗагрузитьМашиночитаемыеДоверенности();
		
	Если Не ОписаниеДанных.Свойство("Объект") Тогда
		ОписаниеДанных.Вставить("Подписи", ДобавляемыеПодписи());
		Закрыть(Истина);
		Возврат;
	КонецЕсли;
	
	Если ТипЗнч(ОписаниеДанных.Объект) <> Тип("ОписаниеОповещения") Тогда
		ВерсияОбъекта = Неопределено;
		ОписаниеДанных.Свойство("ВерсияОбъекта", ВерсияОбъекта);
		Попытка
			МассивПодписей = ДобавитьПодпись(ОписаниеДанных.Объект, ВерсияОбъекта);
		Исключение
			ИнформацияОбОшибке = ИнформацияОбОшибке();
			ОКЗавершение(Новый Структура("ОписаниеОшибки", ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке)));
			Возврат;
		КонецПопытки;
		ОписаниеДанных.Вставить("Подписи", МассивПодписей);
		ОповеститьОбИзменении(ОписаниеДанных.Объект);
	Иначе
		ОписаниеДанных.Вставить("Подписи", ДобавляемыеПодписи());
		
		ПараметрыВыполнения = Новый Структура;
		ПараметрыВыполнения.Вставить("ОписаниеДанных", ОписаниеДанных);
		ПараметрыВыполнения.Вставить("Оповещение", Новый ОписаниеОповещения("ОКЗавершение", ЭтотОбъект));
		
		Попытка
			ВыполнитьОбработкуОповещения(ОписаниеДанных.Объект, ПараметрыВыполнения);
			Возврат;
		Исключение
			ИнформацияОбОшибке = ИнформацияОбОшибке();
			ОКЗавершение(Новый Структура("ОписаниеОшибки", ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке)));
			Возврат;
		КонецПопытки;
	КонецЕсли;
	
	ОКЗавершение(Новый Структура);
	
КонецПроцедуры

// Продолжение процедуры ОК.
&НаКлиенте
Процедура ОКЗавершение(Результат, Контекст = Неопределено) Экспорт
	
	Если Результат.Свойство("ОписаниеОшибки") Тогда
		ОписаниеДанных.Удалить("Подписи");
		
		Ошибка = Новый Структура("ОписаниеОшибки",
			НСтр("ru = 'Не удалось записать подпись по причине:'") + Символы.ПС + Результат.ОписаниеОшибки);
			
		ЭлектроннаяПодписьСлужебныйКлиент.ПоказатьОшибкуОбращенияКПрограмме(
			НСтр("ru = 'Не удалось добавить электронную подпись из файла'"), "", Ошибка, Новый Структура);
		Возврат;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ПредставлениеДанных) Тогда
		ЭлектроннаяПодписьКлиент.ИнформироватьОПодписанииОбъекта(
			ЭлектроннаяПодписьСлужебныйКлиент.ПолноеПредставлениеДанных(ЭтотОбъект),, Истина);
	КонецЕсли;
	
	Закрыть(Истина);
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаКлиенте
Процедура ПослеОткрытия()
	
	ОтображениеДанныхОбновлено = Истина;
	ВыбратьФайлы(Истина);
	
КонецПроцедуры

&НаСервере
Процедура УстановитьУсловноеОформление()
	
	УсловноеОформление.Элементы.Очистить();
	
	Элемент = УсловноеОформление.Элементы.Добавить();
	
	ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
	ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.ПодписиПутьКФайлу.Имя);
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Подписи.ПутьКФайлу");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	Элемент.Оформление.УстановитьЗначениеПараметра("ОтметкаНезаполненного", Истина);
	
КонецПроцедуры

&НаКлиенте
Асинх Процедура ВыбратьФайлы(МножественныйВыбор = Ложь, ПовторныйВызов = Ложь)
	
	Если Не ПовторныйВызов Тогда
		ОповещениеПриОтсутствииКомпонентРаботыСЭП = Новый ОписаниеОповещения("ВыбратьФайлыПовторноПослеУстановкиКомпонент", ЭтотОбъект, МножественныйВыбор);
		ВыполняетсяУстановкаДополнительныхКомпонент = Ждать ЭлектроннаяПодписьСлужебныйКлиент.ВыполнитьУстановкуДополнительныхКомпонентПослеПроверкиРасширенияРаботыС1СПредприятием(
			ОповещениеПриОтсутствииКомпонентРаботыСЭП);
		Если ВыполняетсяУстановкаДополнительныхКомпонент Тогда
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	ОшибкиПриЗагрузкеДоверенностей = "";
	Доверенности.Очистить();
	
	Контекст = Новый Структура;
	Контекст.Вставить("ДобавитьНовыеСтроки", МножественныйВыбор);
	
	Оповещение = Новый ОписаниеОповещения("ВыбратьФайлыПослеПомещенияФайлов", ЭтотОбъект, Контекст);
	
	ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
	ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;
	
	Если МножественныйВыбор Тогда
		ПараметрыЗагрузки.Диалог.Заголовок = НСтр("ru = 'Выберите файлы электронной подписи'");
	Иначе
		ПараметрыЗагрузки.Диалог.Заголовок = НСтр("ru = 'Выберите файл электронной подписи'");
	КонецЕсли;
	ПараметрыЗагрузки.Диалог.МножественныйВыбор = МножественныйВыбор;
	
	ФильтрДляВыбораПодписей = НСтр("ru = 'Файлы подписи (*.p7s, *.sig%1)|*.p7s;*.sig%2'");
	ЭлектроннаяПодписьКлиентЛокализация.ПриПолученииФильтраДляВыбораПодписей(ФильтрДляВыбораПодписей);
		
	РасширениеДляФайловПодписи = ЭлектроннаяПодписьКлиент.ПерсональныеНастройки().РасширениеДляФайловПодписи;
	Если СтрНайти(ФильтрДляВыбораПодписей, РасширениеДляФайловПодписи) = 0 Тогда
		ФильтрДляВыбораПодписей= СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ФильтрДляВыбораПодписей,
			", *." + РасширениеДляФайловПодписи, ";*." + РасширениеДляФайловПодписи);
	Иначе		
		ФильтрДляВыбораПодписей= СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ФильтрДляВыбораПодписей, "", "");
	КонецЕсли;
	
	ПараметрыЗагрузки.Диалог.Фильтр = ФильтрДляВыбораПодписей;
	ПараметрыЗагрузки.Диалог.Фильтр = ПараметрыЗагрузки.Диалог.Фильтр + "|" + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Все файлы (%1)|%1'"), ПолучитьМаскуВсеФайлы());
	
	Если Не МножественныйВыбор Тогда
		ПараметрыЗагрузки.Диалог.ПолноеИмяФайла = Элементы.Подписи.ТекущиеДанные.ПутьКФайлу;
	КонецЕсли;
	
	ФайловаяСистемаКлиент.ЗагрузитьФайлы(Оповещение, ПараметрыЗагрузки);
	
КонецПроцедуры

// Повторный вызов процедуры ВыбратьФайлы после установки компонент.
&НаКлиенте
Процедура ВыбратьФайлыПовторноПослеУстановкиКомпонент(Результат, МножественныйВыбор) Экспорт
	
	Если Результат = Истина Тогда
		ВыбратьФайлы(МножественныйВыбор, Истина)
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлыПослеПомещенияФайлов(ПомещенныеФайлы, Контекст) Экспорт
	
	Если ПомещенныеФайлы = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ТипЗнч(ПомещенныеФайлы) = Тип("Файл") Тогда
		ПомещенныеФайлы = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ПомещенныеФайлы);
	КонецЕсли;
		
	Результат = ДобавитьСтрокиНаСервере(ПомещенныеФайлы, Контекст.ДобавитьНовыеСтроки);
	
	Контекст.Вставить("ПомещенныеФайлы", ПомещенныеФайлы);
	Контекст.Вставить("ДанныеДляПроверкиПодписи", Неопределено);
	Контекст.Вставить("РезультатДобавленияПодписей", Результат);
	Контекст.Вставить("ДругиеФайлы", Результат);
	Контекст.Вставить("Ошибки", Новый Структура("ОшибкиНаКлиенте, ОшибкиНаСервере", Новый Соответствие, Новый Соответствие));
	Контекст.Вставить("Индекс", -1);
	ВыбратьФайлыЦиклНачало(Контекст);
	
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьФайлыЦиклНачало(Контекст)
	
	Если Контекст.ПомещенныеФайлы.Количество() <= Контекст.Индекс + 1 Тогда
		ВыбратьФайлыПослеЦикла(Контекст);
		Возврат;
	КонецЕсли;
	
	Контекст.Индекс = Контекст.Индекс + 1;
	
	ПомещенныйФайл = Контекст.ПомещенныеФайлы[Контекст.Индекс];
	
	СоставИмени = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ПомещенныйФайл.Имя);

	РезультатДобавленияПодписи = Контекст.РезультатДобавленияПодписей.Получить(ПомещенныйФайл.Имя);
	
	Если РезультатДобавленияПодписи = Неопределено Тогда
		ВыбратьФайлыЦиклНачало(Контекст);
		Возврат;
	КонецЕсли;
	
	Контекст.Вставить("РезультатДобавленияПодписи", РезультатДобавленияПодписи);
	
	Если РезультатДобавленияПодписи.Успех Тогда
		ВыбратьФайлПослеДобавленияСтроки(Контекст);
		Возврат;
	КонецЕсли;
	
	ПараметрыСоздания = ЭлектроннаяПодписьСлужебныйКлиент.ПараметрыСозданияМенеджераКриптографии();
	ПараметрыСоздания.АлгоритмПодписи = ЭлектроннаяПодписьСлужебныйКлиентСервер.АлгоритмСформированнойПодписи(
			Контекст.РезультатДобавленияПодписи.ДанныеПодписи);
	ПараметрыСоздания.ПоказатьОшибку = Неопределено;

	ЭлектроннаяПодписьСлужебныйКлиент.СоздатьМенеджерКриптографии(
			Новый ОписаниеОповещения("ВыбратьФайлПослеСозданияМенеджераКриптографии", ЭтотОбъект, Контекст), "",
		ПараметрыСоздания);
	
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьФайлыПослеЦикла(Контекст)
	
	ЗаполнитьМашиночитаемыеДоверенности();
	
	Если Контекст.Ошибки.ОшибкиНаКлиенте.Количество() = 0
		И Контекст.Ошибки.ОшибкиНаСервере.Количество() = 0
		И ОшибкиПриЗагрузкеДоверенностей = "" Тогда
		Возврат;
	КонецЕсли;
	
	ОшибкаНаКлиенте = ЭлектроннаяПодписьСлужебныйКлиентСервер.НовоеОписаниеОшибок();
	ОшибкаНаКлиенте.ЗаголовокОшибки = НСтр("ru = 'Не удалось добавить файлы'");
	
	Для Каждого КлючИЗначение Из Контекст.Ошибки.ОшибкиНаКлиенте Цикл
		
		СвойстваОшибки = ЭлектроннаяПодписьСлужебныйКлиентСервер.НовыеСвойстваОшибки();
		Если ЗначениеЗаполнено(КлючИЗначение.Значение.ДополнительныеПараметры) Тогда
			ЗаполнитьЗначенияСвойств(СвойстваОшибки, КлючИЗначение.Значение.ДополнительныеПараметры);
		КонецЕсли;
		
		СвойстваОшибки.Описание = СтрШаблон("%1:
			|%2", КлючИЗначение.Ключ, СтрСоединить(КлючИЗначение.Значение.Файлы, Символы.ПС));
		ОшибкаНаКлиенте.Ошибки.Добавить(СвойстваОшибки);
		
	КонецЦикла;
	
	ОшибкаНаСервере = ЭлектроннаяПодписьСлужебныйКлиентСервер.НовоеОписаниеОшибок();
	ОшибкаНаСервере.ЗаголовокОшибки = НСтр("ru = 'Не удалось добавить файлы'");
	
	Если ОшибкиПриЗагрузкеДоверенностей <> "" Тогда
		
		СвойстваОшибки = ЭлектроннаяПодписьСлужебныйКлиентСервер.НовыеСвойстваОшибки();
		СвойстваОшибки.Описание = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Не удалось загрузить доверенности:
			|%1'"), ОшибкиПриЗагрузкеДоверенностей);
		ОшибкаНаСервере.Ошибки.Добавить(СвойстваОшибки);
	КонецЕсли;
	
	Для Каждого КлючИЗначение Из Контекст.Ошибки.ОшибкиНаСервере Цикл
		
		СвойстваОшибки = ЭлектроннаяПодписьСлужебныйКлиентСервер.НовыеСвойстваОшибки();
		Если ЗначениеЗаполнено(КлючИЗначение.Значение.ДополнительныеПараметры) Тогда
			ЗаполнитьЗначенияСвойств(СвойстваОшибки, КлючИЗначение.Значение.ДополнительныеПараметры);
		КонецЕсли;
		
		СвойстваОшибки.Описание = СтрШаблон("%1:
			|%2", КлючИЗначение.Ключ, СтрСоединить(КлючИЗначение.Значение.Файлы, Символы.ПС));
		ОшибкаНаСервере.Ошибки.Добавить(СвойстваОшибки);
		
	КонецЦикла;
	
	ПоказатьОшибку(ОшибкаНаКлиенте, ОшибкаНаСервере);
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеСозданияМенеджераКриптографии(МенеджерКриптографии, Контекст) Экспорт
	
	Если ТипЗнч(МенеджерКриптографии) <> Тип("МенеджерКриптографии") Тогда
		ЭлектроннаяПодписьСлужебныйКлиент.ПрочитатьСвойстваПодписи(Новый ОписаниеОповещения(
			"ВыбратьФайлПослеЧтенияСвойствПодписи", ЭтотОбъект, Контекст),
			Контекст.РезультатДобавленияПодписи.ДанныеПодписи, Истина, Ложь);
		Возврат;
	КонецЕсли;
	
	Контекст.Вставить("МенеджерКриптографии", МенеджерКриптографии);
	
	МенеджерКриптографии.НачатьПолучениеКонтейнераПодписейКриптографии(Новый ОписаниеОповещения(
		"ВыбратьФайлПослеПолученияКонтейнераПодписи", ЭтотОбъект, Контекст,
		"ВыбратьФайлПослеОшибкиПолученияКонтейнераПодписи", ЭтотОбъект), Контекст.РезультатДобавленияПодписи.ДанныеПодписи);
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеЧтенияСвойствПодписи(Результат, Контекст) Экспорт
	
	Если Результат.Успех = Ложь Тогда
		ДобавитьОшибку(Новый Структура("ОписаниеОшибки", Результат.ТекстОшибки), Контекст);
		Возврат;
	КонецЕсли;
	
	Контекст.Вставить("МенеджерКриптографии", Неопределено);
	Контекст.Вставить("ПараметрыПодписи", Результат);
	
	Если Результат.Сертификат <> Неопределено Тогда
		
		СвойстваСертификата = Новый Структура;
		СвойстваСертификата.Вставить("ДвоичныеДанные", Результат.Сертификат);
		СвойстваСертификата.Вставить("Отпечаток", Результат.Отпечаток);
		СвойстваСертификата.Вставить("КомуВыдан", Результат.КомуВыданСертификат);
		
		СвойстваПодписи = ЭлектроннаяПодписьСлужебныйКлиентСервер.СвойстваПодписи(Контекст.РезультатДобавленияПодписи.ДанныеПодписи,
			СвойстваСертификата, "", ПользователиКлиент.АвторизованныйПользователь(), Контекст.РезультатДобавленияПодписи.ИмяФайла,
			Контекст.ПараметрыПодписи, Истина);

		ДобавитьСтроку(ЭтотОбъект, Контекст.ДобавитьНовыеСтроки, СвойстваПодписи, Контекст.РезультатДобавленияПодписи.ИмяФайла,
			Контекст.РезультатДобавленияПодписи.АдресСвойствПодписи);

		ВыбратьФайлПослеДобавленияСтроки(Контекст);
	Иначе
		ОшибкаНаКлиенте = Новый Структура("ОписаниеОшибки", НСтр("ru = 'В файле подписи нет ни одного сертификата.'"));

		ДобавитьОшибку(ОшибкаНаКлиенте, Контекст);
		
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеОшибкиПолученияКонтейнераПодписи(ИнформацияОбОшибке, СтандартнаяОбработка, Контекст) Экспорт
	
	СтандартнаяОбработка = Ложь;
	
	ОшибкаНаКлиенте = Новый Структура("ОписаниеОшибки", СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Не удалось получить контейнер подписи из файла подписи по причине:
		           |%1'"),
		ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке)));
	
	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("ПоказатьИнструкцию", Истина);
	ДополнительныеПараметры.Вставить("Подпись", Контекст.РезультатДобавленияПодписи.ДанныеПодписи);
	
	ДобавитьОшибку(ОшибкаНаКлиенте, Контекст, ДополнительныеПараметры);
		
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Асинх Процедура ВыбратьФайлПослеПолученияКонтейнераПодписи(КонтейнерПодписи, Контекст) Экспорт
	
	ДатаСеанса = ОбщегоНазначенияКлиент.ДатаСеанса();
	РазницаСУниверсальнымВременем = ДатаСеанса - ОбщегоНазначенияКлиент.ДатаУниверсальная();
	ПараметрыПодписи = Ждать ЭлектроннаяПодписьСлужебныйКлиент.ПараметрыПодписиКриптографии(
		КонтейнерПодписи, РазницаСУниверсальнымВременем, ДатаСеанса);
			
	Контекст.Вставить("ПараметрыПодписи", ПараметрыПодписи);
	ДатаПодписи = ПараметрыПодписи.НеподтвержденнаяДатаПодписи;
	Если ЗначениеЗаполнено(ДатаПодписи) Тогда
		Контекст.РезультатДобавленияПодписи.ДатаПодписи = ДатаПодписи;
	КонецЕсли;
	
	Сертификаты = Новый Массив;
	Если ПараметрыПодписи.ОписаниеСертификата <> Неопределено Тогда
		Сертификаты.Добавить(КонтейнерПодписи.Подписи[0].СертификатПодписи);
	КонецЕсли;

	ВыбратьФайлПослеПолученияСертификатовИзПодписи(Сертификаты, Контекст);
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеПолученияСертификатовИзПодписи(Сертификаты, Контекст)
	
	Если Сертификаты.Количество() = 0 Тогда
		ОшибкаНаКлиенте = Новый Структура("ОписаниеОшибки",
			НСтр("ru = 'В файле подписи нет ни одного сертификата.'"));
		
		ДобавитьОшибку(ОшибкаНаКлиенте, Контекст);
		Возврат;
	КонецЕсли;
	
	Попытка
		Если Сертификаты.Количество() = 1 Тогда
			Сертификат = Сертификаты[0];
		ИначеЕсли Сертификаты.Количество() > 1 Тогда
			Сертификат = ЭлектроннаяПодписьСлужебныйКлиентСервер.СертификатыПоПорядкуДоКорневого(Сертификаты)[0];
		КонецЕсли;
	Исключение
		ОшибкаНаКлиенте = Новый Структура("ОписаниеОшибки",
			ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
		ДобавитьОшибку(ОшибкаНаКлиенте, Контекст);
		Возврат;
	КонецПопытки;
	
	Контекст.Вставить("Сертификат", Сертификат);
	
	ТекущийСертификат = Контекст.Сертификат; // СертификатКриптографии
	ТекущийСертификат.НачатьВыгрузку(Новый ОписаниеОповещения(
		"ВыбратьФайлПослеВыгрузкиСертификата", ЭтотОбъект, Контекст));
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Асинх Процедура ВыбратьФайлПослеВыгрузкиСертификата(ДанныеСертификата, Контекст) Экспорт
	
	СвойстваСертификата = Ждать ЭлектроннаяПодписьСлужебныйКлиент.СвойстваСертификата(Контекст.Сертификат);
	СвойстваСертификата.Вставить("ДвоичныеДанные", ДанныеСертификата);
	
	СвойстваПодписи = ЭлектроннаяПодписьСлужебныйКлиентСервер.СвойстваПодписи(Контекст.РезультатДобавленияПодписи.ДанныеПодписи,
		СвойстваСертификата, "", ПользователиКлиент.АвторизованныйПользователь(), 
		Контекст.РезультатДобавленияПодписи.ИмяФайла, Контекст.ПараметрыПодписи, Истина);
	
	ДобавитьСтроку(ЭтотОбъект, Контекст.ДобавитьНовыеСтроки, СвойстваПодписи,
		Контекст.РезультатДобавленияПодписи.ИмяФайла, Контекст.РезультатДобавленияПодписи.АдресСвойствПодписи);
	
	ВыбратьФайлПослеДобавленияСтроки(Контекст);
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеДобавленияСтроки(Контекст)
	
	Если Не ОписаниеДанных.Свойство("Данные") Или Контекст.ДанныеДляПроверкиПодписи = Ложь Тогда
		ВыбратьФайлыЦиклНачало(Контекст);
		Возврат; // Если данные не указаны, подпись проверить невозможно.
	КонецЕсли;
	
	Если Контекст.ДанныеДляПроверкиПодписи = Неопределено Тогда
		ЭлектроннаяПодписьСлужебныйКлиент.ПолучитьДанныеИзОписанияДанных(Новый ОписаниеОповещения(
			"ВыбратьФайлПослеПолученияДанных", ЭтотОбъект, Контекст),
		ЭтотОбъект, ОписаниеДанных, ОписаниеДанных.Данные, Истина);
	Иначе
		ВыбратьФайлПослеПолученияДанных(Контекст.ДанныеДляПроверкиПодписи, Контекст);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеПолученияДанных(Результат, Контекст) Экспорт
	
	Если ТипЗнч(Результат) = Тип("Структура") Тогда
		Контекст.ДанныеДляПроверкиПодписи = Ложь;
		ВыбратьФайлыЦиклНачало(Контекст);
		Возврат; // Не удалось получить данные, подпись проверить невозможно.
	КонецЕсли;
	
	Если Контекст.ДанныеДляПроверкиПодписи = Неопределено Тогда
		Контекст.ДанныеДляПроверкиПодписи = Результат;
	КонецЕсли;
	
	ПараметрыДляПроверки = ЭлектроннаяПодписьКлиент.ПараметрыПроверкиПодписи();
	ПараметрыДляПроверки.ПоказатьОшибкуСозданияМенеджераКриптографии = Ложь;
	ПараметрыДляПроверки.РезультатВВидеСтруктуры = Истина;
	ЭлектроннаяПодписьСлужебныйКлиент.ПроверитьПодпись(Новый ОписаниеОповещения(
			"ВыбратьФайлПослеПроверкиПодписи", ЭтотОбъект, Контекст),
		Контекст.ДанныеДляПроверкиПодписи, Контекст.РезультатДобавленияПодписи.ДанныеПодписи, ,
		Контекст.РезультатДобавленияПодписи.ДатаПодписи, ПараметрыДляПроверки);
	
КонецПроцедуры

// Продолжение процедуры ВыбратьФайл.
&НаКлиенте
Процедура ВыбратьФайлПослеПроверкиПодписи(РезультатПроверки, Контекст) Экспорт
	
	Если РезультатПроверки.Результат = Неопределено Тогда
		ВыбратьФайлыЦиклНачало(Контекст);
		Возврат; // Не удалось проверить подпись.
	КонецЕсли;
	
	ОбновитьРезультатПроверкиПодписи(Контекст.РезультатДобавленияПодписи.АдресСвойствПодписи, РезультатПроверки);
	ВыбратьФайлыЦиклНачало(Контекст);
	
КонецПроцедуры

&НаСервере
Процедура ОбновитьРезультатПроверкиПодписи(АдресСвойствПодписи, РезультатПроверки)
	
	ТекущаяДатаСеанса = ТекущаяДатаСеанса(); 
	
	СвойстваПодписи = ПолучитьИзВременногоХранилища(АдресСвойствПодписи);
	
	НовыеСвойстваПодписи = ЭлектроннаяПодписьКлиентСервер.НовыеСвойстваПодписи();
	ЗаполнитьЗначенияСвойств(НовыеСвойстваПодписи, СвойстваПодписи);
	ЗаполнитьЗначенияСвойств(НовыеСвойстваПодписи, РезультатПроверки);
	НовыеСвойстваПодписи.ДатаПроверкиПодписи = ТекущаяДатаСеанса;
	
	ПоместитьВоВременноеХранилище(НовыеСвойстваПодписи, АдресСвойствПодписи);
	
КонецПроцедуры

&НаСервере
Функция ДобавитьСтрокиНаСервере(ПомещенныеФайлы, ДобавитьНовыеСтроки)
	
	Соответствие = Новый Соответствие;
	ДругиеФайлы = Новый Соответствие;
	
	ЭлектроннаяПодписьЛокализация.ПриДобавленииСтрокНаСервере(
		ЭтотОбъект, ПомещенныеФайлы, ДругиеФайлы, ОшибкиПриЗагрузкеДоверенностей, УникальныйИдентификатор);
	
	Для Каждого ПомещенныйФайл Из ПомещенныеФайлы Цикл
		
		СоставИмени = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ПомещенныйФайл.Имя);
		
		Если ДругиеФайлы.Получить(СоставИмени.Имя) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;

		РезультатДобавленияСтроки = Новый Структура;

		РезультатДобавленияСтроки.Вставить("Успех", Ложь);
		РезультатДобавленияСтроки.Вставить("Адрес", ПомещенныйФайл.Хранение);
		РезультатДобавленияСтроки.Вставить("ИмяФайла", СоставИмени.Имя);
		РезультатДобавленияСтроки.Вставить("ОшибкаНаСервере", Новый Структура);
		РезультатДобавленияСтроки.Вставить("ДанныеПодписи", Неопределено);
		РезультатДобавленияСтроки.Вставить("ДатаПодписи", Неопределено);
		РезультатДобавленияСтроки.Вставить("АдресСвойствПодписи", Неопределено);
		
		РезультатДобавленияСтроки = ДобавитьСтрокуНаСервере(РезультатДобавленияСтроки, ДобавитьНовыеСтроки);
		Соответствие.Вставить(ПомещенныйФайл.Имя, РезультатДобавленияСтроки);
		
	КонецЦикла;
	
	Возврат Соответствие;
	
КонецФункции

&НаСервере
Функция ДобавитьСтрокуНаСервере(Знач РезультатДобавленияСтроки, ДобавитьНовуюСтроку)
	
	Попытка
		РезультатДобавленияСтроки.ДанныеПодписи = ЭлектроннаяПодпись.ПодписьВКодировкеDER(РезультатДобавленияСтроки.Адрес);
	Исключение
		ИнформацияОбОшибке = ИнформацияОбОшибке();
		РезультатДобавленияСтроки.ОшибкаНаСервере.Вставить("ОписаниеОшибки", ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке));
		Возврат РезультатДобавленияСтроки;
	КонецПопытки;
	
	РезультатДобавленияСтроки.ДатаПодписи = ЭлектроннаяПодпись.ДатаПодписания(РезультатДобавленияСтроки.ДанныеПодписи);
	
	Если Не ЭлектроннаяПодпись.ПроверятьЭлектронныеПодписиНаСервере()
		И Не ЭлектроннаяПодпись.СоздаватьЭлектронныеПодписиНаСервере() Тогда
		
		Возврат РезультатДобавленияСтроки;
	КонецЕсли;
	
	ПараметрыСоздания = ЭлектроннаяПодписьСлужебный.ПараметрыСозданияМенеджераКриптографии();
	ПараметрыСоздания.ОписаниеОшибки = РезультатДобавленияСтроки.ОшибкаНаСервере;
	ПараметрыСоздания.АлгоритмПодписи = ЭлектроннаяПодписьСлужебныйКлиентСервер.АлгоритмСформированнойПодписи(
		РезультатДобавленияСтроки.ДанныеПодписи);
	
	МенеджерКриптографии = ЭлектроннаяПодписьСлужебный.МенеджерКриптографии("", ПараметрыСоздания);
	
	РезультатДобавленияСтроки.ОшибкаНаСервере = ПараметрыСоздания.ОписаниеОшибки;
	Если МенеджерКриптографии = Неопределено Тогда
		Возврат РезультатДобавленияСтроки;
	КонецЕсли;
	
	Попытка
		КонтейнерПодписи = МенеджерКриптографии.ПолучитьКонтейнерПодписейКриптографии(РезультатДобавленияСтроки.ДанныеПодписи);
	Исключение
		ИнформацияОбОшибке = ИнформацияОбОшибке();
		РезультатДобавленияСтроки.ОшибкаНаСервере.Вставить("ОписаниеОшибки", СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Не удалось получить контейнер подписи из файла подписи по причине:
			|%1'"),
			ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке)));
		Возврат РезультатДобавленияСтроки;
	КонецПопытки;
	
	ПараметрыПодписи = ЭлектроннаяПодписьСлужебный.ПараметрыПодписиКриптографии(КонтейнерПодписи,
		ЭлектроннаяПодписьСлужебный.РазницаСУниверсальнымВременем(), ТекущаяДатаСеанса());
	
	Если ЗначениеЗаполнено(ПараметрыПодписи.НеподтвержденнаяДатаПодписи) Тогда
		РезультатДобавленияСтроки.ДатаПодписи = ПараметрыПодписи.НеподтвержденнаяДатаПодписи;
	КонецЕсли;
	
	СвойстваСертификата = ПараметрыПодписи.ОписаниеСертификата;
	Сертификат = КонтейнерПодписи.Подписи[0].СертификатПодписи;
	
	СвойстваСертификата.Вставить("ДвоичныеДанные", Сертификат.Выгрузить());
	
	СвойстваПодписи = ЭлектроннаяПодписьСлужебныйКлиентСервер.СвойстваПодписи(РезультатДобавленияСтроки.ДанныеПодписи,
		СвойстваСертификата, "", Пользователи.АвторизованныйПользователь(), РезультатДобавленияСтроки.ИмяФайла, ПараметрыПодписи, Истина);
	
	ДобавитьСтроку(ЭтотОбъект, ДобавитьНовуюСтроку, СвойстваПодписи, РезультатДобавленияСтроки.ИмяФайла,
		РезультатДобавленияСтроки.АдресСвойствПодписи);
	РезультатДобавленияСтроки.Успех = Истина;
	
	Возврат РезультатДобавленияСтроки;
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Процедура ДобавитьСтроку(Форма, ДобавитьНовуюСтроку, СвойстваПодписи, ИмяФайла, АдресСвойствПодписи)
	
	НовыеСвойстваПодписи = ЭлектроннаяПодписьКлиентСервер.НовыеСвойстваПодписи();
	ЗаполнитьЗначенияСвойств(НовыеСвойстваПодписи, СвойстваПодписи);
	
	АдресСвойствПодписи = ПоместитьВоВременноеХранилище(НовыеСвойстваПодписи, Форма.УникальныйИдентификатор);
	
	Если ДобавитьНовуюСтроку Тогда
		ТекущиеДанные = Форма.Подписи.Добавить();
	Иначе
		ТекущиеДанные = Форма.Подписи.НайтиПоИдентификатору(Форма.Элементы.Подписи.ТекущаяСтрока);
	КонецЕсли;
	
	ТекущиеДанные.ПутьКФайлу = ИмяФайла;
	ТекущиеДанные.АдресСвойствПодписи = АдресСвойствПодписи;
	
КонецПроцедуры

&НаСервере
Функция ДобавляемыеПодписи()
	
	Результат = Новый Массив;
	Для каждого Подпись Из Подписи Цикл
		СвойстваПодписи = ПолучитьИзВременногоХранилища(Подпись.АдресСвойствПодписи);
		СвойстваПодписи.Вставить("Комментарий", Подпись.Комментарий);
		Результат.Добавить(ПоместитьВоВременноеХранилище(СвойстваПодписи, УникальныйИдентификатор));
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

&НаСервере
Функция ДобавитьПодпись(СсылкаНаОбъект, ВерсияОбъекта)
	
	Результат = ДобавляемыеПодписи();
	ЭлектроннаяПодпись.ДобавитьПодпись(СсылкаНаОбъект, Результат, УникальныйИдентификатор, ВерсияОбъекта);
	Возврат Результат;
	
КонецФункции

&НаКлиенте
Процедура ДобавитьОшибку(ОшибкаНаКлиенте, Контекст, ДополнительныеПараметры = Неопределено)
	
	Если ЗначениеЗаполнено(ОшибкаНаКлиенте.ОписаниеОшибки) Тогда
		Найдено = Контекст.Ошибки.ОшибкиНаКлиенте.Получить(ОшибкаНаКлиенте.ОписаниеОшибки);
		Если Найдено = Неопределено Тогда
			Найдено = Новый Структура("Файлы, ДополнительныеПараметры", Новый Массив);
		КонецЕсли;

		Найдено.Файлы.Добавить(Контекст.РезультатДобавленияПодписи.ИмяФайла);
		Найдено.ДополнительныеПараметры = ДополнительныеПараметры;
		Контекст.Ошибки.ОшибкиНаКлиенте.Вставить(ОшибкаНаКлиенте.ОписаниеОшибки, Найдено);
	КонецЕсли;

	Если ЗначениеЗаполнено(Контекст.РезультатДобавленияПодписи.ОшибкаНаСервере) Тогда
		ОшибкаНаСервере = Контекст.РезультатДобавленияПодписи.ОшибкаНаСервере;
		Если ОшибкаНаСервере.ОписаниеОшибки <> ОшибкаНаКлиенте.ОписаниеОшибки Тогда
			Найдено = Контекст.Ошибки.ОшибкиНаСервере.Получить(ОшибкаНаСервере.ОписаниеОшибки);
			Если Найдено = Неопределено Тогда
				Найдено = Новый Структура("Файлы, ДополнительныеПараметры", Новый Массив);
			КонецЕсли;

			Найдено.Файлы.Добавить(Контекст.РезультатДобавленияПодписи.ИмяФайла);
			Найдено.ДополнительныеПараметры = ДополнительныеПараметры;
			Контекст.Ошибки.ОшибкиНаСервере.Вставить(ОшибкаНаСервере.ОписаниеОшибки, Найдено);
		КонецЕсли;
	КонецЕсли;

	ВыбратьФайлыЦиклНачало(Контекст);
	
КонецПроцедуры

&НаКлиенте
Процедура ПоказатьОшибку(ОшибкаНаКлиенте, ОшибкаНаСервере, ДополнительныеПараметры = Неопределено)
	
	ЭлектроннаяПодписьСлужебныйКлиент.ПоказатьОшибкуОбращенияКПрограмме(
		НСтр("ru = 'Не удалось получить подпись из файла'"),
		"", ОшибкаНаКлиенте, ОшибкаНаСервере, ДополнительныеПараметры);
	
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьМашиночитаемыеДоверенности()
	
	ЭлектроннаяПодписьЛокализация.ПриЗагрузкеМашиночитаемыхДоверенностей(ЭтотОбъект);
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьМашиночитаемыеДоверенности(ПодписанныйОбъект = Неопределено)
	
	ЭлектроннаяПодписьЛокализация.ПриЗаполненииМашиночитаемыхДоверенностей(ЭтотОбъект);
	
КонецПроцедуры

&НаКлиенте
Процедура МашиночитаемаяДоверенностьВыбратьИзСправочника()
	
	ТекущиеДанные = Элементы.Подписи.ТекущиеДанные;
	ОбработчикЗавершения = Новый ОписаниеОповещения("МашиночитаемаяДоверенностьОкончаниеВыбора", ЭтотОбъект);
	ЭлектроннаяПодписьКлиентЛокализация.ПриВыбореМашиночитаемойДоверенности(ОбработчикЗавершения, ТекущиеДанные);
	
КонецПроцедуры

&НаКлиенте
Процедура МашиночитаемаяДоверенностьОкончаниеВыбора(Результат, ДополнительныеПараметры) Экспорт
	
	Если Результат = Неопределено Тогда
		Возврат;
	КонецЕсли;
	ТекущиеДанные = Элементы.Подписи.ТекущиеДанные;
	ТекущиеДанные.МашиночитаемаяДоверенность = Результат;
	ПодписиМашиночитаемаяДоверенностьПриИзменении();
	
КонецПроцедуры

&НаКлиенте
Процедура ПодписиМашиночитаемаяДоверенностьПриИзменении()
	
	Если ОписаниеДанных.Свойство("Объект") И ТипЗнч(ОписаниеДанных.Объект) <> Тип("ОписаниеОповещения") Тогда
		ЗаполнитьМашиночитаемуюДоверенностьВСтроке(Элементы.Подписи.ТекущаяСтрока, ОписаниеДанных.Объект);
	Иначе
		ЗаполнитьМашиночитаемуюДоверенностьВСтроке(Элементы.Подписи.ТекущаяСтрока);
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьМашиночитаемуюДоверенностьВСтроке(ИдентификаторСтроки, ПодписанныйОбъект = Неопределено)
	
	ЭлектроннаяПодписьЛокализация.ПриЗаполненииМашиночитаемойДоверенностиВСтроке(ЭтотОбъект, ИдентификаторСтроки, ПодписанныйОбъект);
		
КонецПроцедуры

&НаКлиенте
Процедура ПодписиМашиночитаемаяДоверенностьАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;
КонецПроцедуры

#КонецОбласти

Связанные материалы