понедельник, 29 октября 2012 г.

Клиент Notal System - перехват событий в офисных программах

Постановка проблемы
Большинство документов СЭД (системы электронного документооборота) редактируются в офисных программах - нас интересуют ставшие стандартом де-факто Ms Office и Open Office. В них требуется научиться делать следующие вещи:
  • Перехватывать закрытие документа
  • Перехватывать печать документа
  • Отличать документ, полученный из Notal System, от просто документа на локальном компе
  • Различать взятые из Notal System документы по типу - взятые на просмотр и взятые на редактирование
  • Различать, из какой именно базы Notal System взят документ - пользователь может с одного компа работать с несколькими базами
Если мы можем перехватить печать документа и можем понять, что он получен из Notal System, то дальше можем после печати сохранить новую версию в СЭД или более интересные штуки типа логирования печати и т.п.

Требования к опознанию документов как взятых из СЭД Notal System
Считаем, что вмешиваться во внутреннюю структуру документа мы не можем - для офисных документов это в принципе возможно, но хотелось бы иметь механизм, который бы не зависел от типа файла и мог бы быть распространен на другие типы файлов (к примеру, на инженерную графику - t-flex и т.п. имеют встроенные языки программирования, так что в будущем и на них можно портировать те же механизмы.
То есть у нас имеется не так много способов различать файлы:
  • Складывать взятые из СЭД файлы в определенную папку (или структуру папок)
  • Записывать имя файла в БД на локальном компе и потом сверяться с этими записями
  • Всю нужную информацию кодировать в имени файла
Поскольку СЭД Notal System работает в веб-интерфейсе, то не всё подконтрольно: разные браузеры складывают документы в разные папки, причем не всегда это можно настраивать. Кроме того, использовать локальную БД нежелательно, поскольку это переусложнит клиентскую часть и может потеряться гибкость веб-технологий.
Опознавать документ будем по имени файла, причем это опознание должно быть устойчиво к некоторым модификациям имени файла которые делают браузеры: к примеру, при повторном скачивании файла браузеры по-разному модифицируют его имя - Opera добавляет в конце " (1)", " (2)" и т.д., Mozilla Firefox добавляет "-1", "-2" и т.д.

Структура имени файла документа из Notal System
Различать разные базы Notal System будем по ключевому числу NN - целое трехзначное число, желательно простое или произведение двух двузначных простых чисел. Зададим его и тогда формат взятого из Notal System документа будет таким (жирным выделены константные части:
iiii_vvvE=AAAAAAABBB=
где iiii - id документа в Notal System (переменое число знаков, цифры, не может начинаться с 0),
vvv - номер версии документа (переменое число знаков, цифры, не может начинаться с 0),
E - указатель на то, что документ взят на редактирование; для взятых на просмотр ставим знак V,
AAAAAAA - случайное число 7 цифр с ведущими нулями, если требуется. Должно быть больше 1000.
BBB - проверочный код, 3 цифры с ведущими нулями, если требуется; вычисляется по формуле BBB = AAAAAAA mod NN, т.е. остаток от деления AAAAAAA на ключевое число NN.
Знаки "_" и "=" задают структуру имени файла. Всё, что идет после второго знака "=", при аналие отбрасывается.
Структура имени файла позволяет узнать id документа и узнать, взят ли документ на редактирование или только на просмотр. Номер версии документа для работы программы не важен, но полезен для пользователя. Случайное число в имени файла гарантирует, что дважды взяв документ из СЭД мы получим разные имена файлов. Проверка соотношения чисел AAAAAAA и BBB позволяет с большой долей надежности установить базу Notal System, из которой взят документ.

Расчет вероятности ложного опознания базы-источника документа
Считаем, что сама специфическая структура имени файла однозначно указывает на то, что файл взят из СЭД Notal System. Пусть на локальном компьютере пользователя зарегистрированы две базы с ключевыми числами NN1 и NN2. Тогда вероятность того, что одновременно выполняются два соотношения
  • BBB = AAAAAAA mod NN1
  • BBB = AAAAAAA mod NN2
равна 1/НОК(NN1, NN2), где НОК - наименьшее общее кратное. Поскольку мы выбираем NN1 и NN2 простыми, то формула упрощается до 1/(NN1*NN2). Поскольку оба числа трехзначные, то полученная вероятность гарантированно меньше 10-4 и почти всегда меньше 10-5, что позволяет нам не заботиться о ложных срабатываниях (по крайней мере в первой версии клиентской части Notal System).

Необходимые доработки серверной части Notal System
  • Добавить в раздел общей информации системы ключевое число
  • Создать механизм задания ключевого числа - вручную или случайно из списка подходящих простых чисел (контроль того, что все эти числа для установленных на нашем сервере баз различны, осуществляем пока вручную)
  • Написать функцию API, которая запрашивает у базы ее ключевое число (понадобится для конфигурирования ini-файла клиента)


Информация в ini-файле на машине клиента
В файле notalconfig.ini, расположенном в папке C:\NotalSystem\conf\, раздел каждой базы (имя раздела [base*], где "*" означает любой текст без пробелов) должен содержать следующие строки:
URL = http://test.notalsystem.ru/ - веб-адрес базы Notal System
KeyNumber = 449 - ключевое число
Name = "Тест" - название базы: произвольный краткий текст, нужен для показа в диалоговых окнах и т.п.
Сейчас считаем, что пользователь руками редактирует ini-файл, позже можно сделать конфигуратор клиента.

Что должна делать клиентская программа в офисном пакете
Для каждого офисного пакета (и в будущем - для программ инженерной графики) настраиваем отдельно, но одинаковый функционал:
  • Перехватываем закрытие документа и определяем базу
    • Если он взят на редактирование и изменен, то предлагаем отправить новую версию документа в СЭД
  • Перехватываем печать документа и определяем базу
    • Если он взят на редактирование и изменен, то печатаем и после этого отправляем новую версию документа в СЭД. Вариант: спрашиваем пользователя, делать ли это, если нет, то не отправляем новую версию, но и не печатаем.
    • Если он взят на просмотр и изменен, то не печатаем. Вариант: предупреждаем об этом пользователя, проверяем, что он имеет право редактировать этот документ, предлагаем ему сохранить отредактированную версию в СЭД (тут используется механизм, который мы используем для добавления новых версий документов из 1С, т.е. не беря предварительно документ на редактрирование.
    • Если документ не был изменен, то печатаем без каких-либо иных действий.
Позже к этому функционалу можем добавить логирование печати (потребуются соответствующие функции API).

Особенности реализации перехвата событий в Ms Office
Нас интересуют только Ms Word и Ms Excel. В этих программах перехват событий организован по-разному.
В Excel подключенная надстройка загружается как рабочая книга, так что в контейнере ThisWorkbook размещаем предопределенную функцию Workbook_Open(), а в ней включаем перехват событий через специальный класс.
В Word в шаблоне, расположенном в папке Word\STARTUP, создаем модуль AutoExec с процедурой MAIN(), которая запускается при загрузке Word. Перехват событий в ней организуется аналогично Excel.

Особенности реализации перехвата событий в Open Office
В Open Office для всех типов файлов работает единый механизм, организация перехвата событий там требует отдельного описания.

Комментариев нет:

Отправить комментарий