Revised Object Inspector для Delphi 2010-XE3 от Uwe Schuster. Обзор.

Этот пост является укороченным переводом описания первой версии Продвинутого Инспектора Объектов из блога Uwe. Не так давно, коллега рассказал про расширение для Delphi замещающий стандартный

Читать на сайте автора.

Revised Object Inspector для Delphi 2010-XE3 от Uwe Schuster. Обзор.

Этот пост является укороченным переводом описания первой версии Продвинутого Инспектора Объектов из блога Uwe.
Не так давно, коллега рассказал про расширение для Delphi замещающий стандартный инспектор объектов альтернативным, с поддержкой фильтра и функции любимых свойств. Пользуюсь этим расширением уже месяц в Delphi XE. Работает стабильно.
На данный момент Revised Object Inspector поддерживает Delphi 2010, Delphi XE, XE2 и XE3. На 21 сентября 2012 года последней версией является Beta 6.
Автор эксперта: Uwe Schuster. Uwe также является активным разработчиком Version Insight Plus, Modal Search Dialog expert, Platforms Expert, IDE Compiler Utils, а также Jedi Version Control System.
См. также: Страница загрузок в блоге Uwe. Все публикации об экспертах в блоге Uwe. …

[[ This is a content summary only. Visit my website for full links, other content, and more! ]]

Читать на сайте автора.

Delphi XE3 Professional и Client/Server

Перед выходом линейки XE3 продуктов Embarcadero (Delphi, C++Builder, RAD Studio), «в интернетах» произошел ужас — произошла утечка (намеренная ли нет, неизвестно) сведений, что новая лицензия для Professional не будет разрешать написание клиент-серверных приложений.

Разумеется, под «не будет разрешать» имеется в виду формальный запрет в лицензионном соглашении, потому что контролировать на уровне кода это никто не собирался, и сделать это достаточно проблематично.

Так вот, в блогах шли одинаковые сообщения о грядущем апокалипсисе, одно за другим. Ленты delphifeeds (что com, что ru) содержали по нескольку таких сообщений подряд. На форумах развернулись баталии с обвинением Embarcadero в чудовищной жадности.

Если честно, у меня как у продавца, специфическое отношение к этому вопросу. С одной стороны, подобные изменения лицензии не радуют. С другой стороны, много людей, которые обвиняли Эмбаркадеро в данном грехе, скорее всего вообще никакую версию не покупали. Ну или покупали, но старую, и обновляться не собирались.

К счастью, в момент выхода релиза XE3 было объявлено, что лицензионное соглашение в данном плане осталось как и прежним, и даже вывесили экземпляр на всеобщее обозрение. И все успокоились.

Однако, присмотревшись к лицензии, я обнаружил, что все-таки в Professional писать клиент-серверные программы запрещено. Правда, только в отношении dbExpress:

ADDITIONAL LICENSE TERMS APPLICABLE TO RAD STUDIO, DELPHI AND C++BUILDER, PROFESSIONAL AND PROFESSIONAL ACADEMIC EDITIONS 
In the event Licensee has obtained a RAD Studio, Delphi or C++Builder Professional, or Professional Academic product license then the following terms apply. 
Subject to the terms and conditions of this Agreement, Licensor grants to Licensee as the licensed user of the Product the limited right to use that portion of the Product identified as «dbExpress», in executable form only, to access a local database installed on the same machine as the Work.  Licensee may not use that portion of the Product identified as «dbExpress» in association with a database located on a different machine other than the machine on which the Works are installed.

Предчувствуя недоброе, я открыл license.rtf от Delphi 2007. Нет такого пункта. Открыл от Delphi 2010 — ЕСТЬ, причем слово в слово.
Delphi 2009 у меня нет, возможно этот пункт появился там — не знаю. Но оказывается, он кочует по лицензионным соглашениям уже несколько лет, как минимум 2.5-3 года.
При этом я знаю несколько компаний, которые покупали Professional 2010/XE/XE2 и используют dbExpress именно для клиент-серверных приложений…

Читать на сайте автора.

Хранение массива в BLOB-поле — версия 2

    Комментарий Алексея Тимохина к моей заметке «Хранение массива в BLOB-поле» навел меня на мысль, что приведенный мной код можно значительно упростить, если выбросить из него использование TMemoryStream для временного хранения информации.
    Что бы загрузить массив в параметр query типа ftBlob можно использовать метод SetBlobData:

qInsertResearchData.Params[5].SetBlobData(aData, Length(aData) * SizeOf(aData[0]))

Чтение массива из поля типа TBlobField тоже можно записать коротко:

  // Установка размера динамического массива aData
  SetLength(aData, qResearchDATA.BlobSize div SizeOf(aData[0]));
  // Запись содержимого поля qResearchDATA типа TBlobField в массив aData
  qResearch.GetBlobFieldData(qResearchDATA.FieldNo, TBlobByteData(aData))

    Т.к. размер массива я устанавливаю равным размеру содержимого BLOB-поля, то для исключения лишних проверок в GetBlobFieldData я заменил вызов этого метода на свой код и теперь запись содержимого поля qResearchDATA типа TBlobField в массив aData выглядит так:

  With qResearch.CreateBlobStream(qResearchDATA, bmRead) do
    Try
      ReadBuffer(aData[0], qResearchDATA.BlobSize);
    Finally
      Free;
    End;

Читать на сайте автора.

Шифрование в InterBase — 2

Продолжаем. Я не случайно остановился после установки SEP, поскольку дальнейшие действия возможны в двух «опциях». InterBase поддерживает два алгоритма шифрования. DES и AES. DES можно использовать по умолчанию, в том числе в редакциях Trial и Developer, а вот AES можно включить только в полной (купленной) редакции. Впрочем, в использовании DES или AES нет никакой разницы, кроме, разумеется, факта, что AES является более сильным алгоритмом, и пришел на смену DES (для вскрытия которого несколько лет назад были даже созданы специализированные микросхемы). У DES длина ключа 56 байт, у AES — 128-256 байт.

Тем не менее, для проверки будет достаточно DES. Напомню, что шифровать можно как базу целиком, так и отдельные столбцы, поэтому я на всякий случай создам 3 разных ключа шифрования. Логинимся под SYSDSO, выполняем команды

CREATE ENCRYPTION db_des for DES 
CREATE ENCRYPTION kname_des for DES 
CREATE ENCRYPTION sname_des for DES

все созданные ключи хранятся в таблице RDB$ENCRYPTIONS. Вообще команда CREATE ENCRYPTION сложнее:

create encryption key-name [as default] [for {AES | DES}]
[with length number-ofbits [bits]]
[password {‘user-password’ | system encryption password}]
[init_vector {NULL | random}] [pad {NULL | random}]
[description ‘some user description’]

Length — можно использовать только для AES, указывая длину ключа 128, 192 или 256 бит. 128 по умолчанию для AES.
Password — только для ключей, которыми шифруют столбцы. Можно использовать для дополнительной аутентификации при расшифровке зашифрованных столбцов.
Init-vector — random включает Ciper Block Changing, при которой для одинаковых значений генерируется разный зашифрованный текст. При null для этого используется Electronic Codebook (в DataDef.pdf на странице 214 это указано как Electronic Cookbook). Null по умолчанию.
Pad — при random padding одинаковые значения могут давать разный результат шифрования. Null по умолчанию.

! включение init-vector random или pad random делают невозможным создание индекса по зашифрованному столбцу, при попытке проиндексировать такой столбец сервер выдаст ошибку. Нужно отметить, что и без init-vector и pad с поиском по индексированным зашифрованным столбцам не все хорошо, об этом будет дальше.

Чтобы пользователи могли зашифровать базу или столбцы, SYSDSO должен дать им гранты на использование ключей. Я даю гранты SYSDBA

GRANT ENCRYPT ON ENCRYPTION db_des to SYSDBA; 
GRANT ENCRYPT ON ENCRYPTION kname_des to SYSDBA; 
GRANT ENCRYPT ON ENCRYPTION sname_des to SYSDBA;

в этом месте я рекомендую сделать бэкап базы, а также отсоединиться от нее (и на всякий случай остановить сервис InterBase) и сделать копию файла. Далее мы будем шифровать базу и столбцы, и сравнивать результаты.

Продолжение следует.

Читать на сайте автора.

Хранение массива в BLOB-поле

    Понадобилось мне хранить результаты измерений в базе данных. Просто сохранить их в таблицу не получится, т.к. количество строк с информацией в одном измерении быстро перевалит за миллион, и при сохранении их в одной транзакции пользователь успеет попить кофе. Плодить множество мелких транзакций по несколько тысяч записей тоже не сильно прибавит скорости. Скорость при последующей вычитке из базы данных миллионов строк тоже будет печальной. Поэтому единственный очевидный для меня выход — это сохранить результаты измерения в поле типа BLOB. Измерения у меня хранились в многомерном массиве, но я упрощу код и объявлю динамический одномерный массив целых чисел:

Var
  aData: Array of Integer;

Процедура записи динамического массива в базу данных получилась примерно такая:

Var
  ms: TMemoryStream;
  …
begin
  …
  Try
    ms := TMemoryStream.Create;
    // Запись содержимого массива aData в поток ms
    ms.WriteBuffer(aData[0], Length(aData) * SizeOf(aData[0]));
    // Запись содержимого потока ms в параметр query для вставки данных
    qInsertResearch.Params[5].LoadFromStream(ms, ftBlob);
  Finally
    ms.Free;
  End;
  …

А процедура чтения массива из базы данных не сложнее процедуры записи:

Var
  ms: TMemoryStream;
  …
begin
  …
  Try
    ms := TMemoryStream.Create;
    // Запись содержимого поля qResearchDATA типа TBlobField в поток ms
    qResearchDATA.SaveToStream(ms);
    // Установка размера динамического массива aData
    SetLength(aData, ms.Size div SizeOf(aData[0]));
    ms.Position := 0;
    // Запись содержимого потока ms в массив aData
    ms.ReadBuffer(aData[0], ms.Size);
  Finally
    ms.Free;
  End;
  …

Теперь на запись/чтение нескольких миллионов записей моя программа тратит секунду. Вместо размера первого элемента массива SizeOf(aData[0]) вы можете использовать размер типа элементов массива (для приведенного мной примера — SizeOf(Integer)). Но такой вариант кода будет менее универсальным, т.к. будет зависеть от используемого типа данных.

P.S. При использовании такого способа хранения данных не забывайте, что размер некоторых типов данных зависит от операционной системы, для которой скомпилирована программа. Иначе информация, которую прочтет из базы данных ваша 64-битная программа перекомпилированная из 32-битной, вас неприятно удивит.

Продолжение…

Читать на сайте автора.

Шифрование в InterBase — 1

1 — потому что предыдущая запись была о шифровании соединений в InterBase, а теперь речь пойдет о шифровании баз. О шифровании соединений, впрочем, говорить больше нечего, т.к. то же самое может быть выполнено другими средствами, совершенно не привязанными к InterBase. Например, аппаратное шифрование, программные средства вроде ZeBeDee, и т.п.

Сразу предупреждаю, что шифрование баз — сложная штука, и если кто-то думает, что можно было бы все это сделать тяп-ляп, то он ошибается.
Первым требованием перед включением шифрования БД является включение в базе Embedded User Authentification. Эта штука появилась еще в InterBase 7.5 в 2005 году, и позволяет проводить аутентификацию пользователей и SYSDBA через саму БД, а не через общий admin.ib для всех баз на сервере.
EUA является первым средством, которое позволяет защититься от «украли файл с базой», т.к. если пароль SYSDBA в базе будет не masterkey, то его придется или подбирать, или как-то хакать hex-editor-ом (не пробовал). Но, как минимум, это уже хоть какая-то защита от чайников.

Полностью и детально шифрование БД описано в документации на InterBase, в Data Definition Guide, Глава 13 (однако!), Encrypting Your Data. Это я к тому, что здесь, все же, идет концептуальное описание, без мелких деталей (иначе пришлось бы растянуть это минимум на 10 постов. Тем не менее, вы можете выполнять приводимое здесь по шагам, разве что с учетом того, что для продолжения вам придется остановиться в ожидании следующего поста 🙂

Итак, берем какую-нибудь тестовую базу, которую не жалко в случае ошибки, и в случае чего можно удалить. База должна быть создана не менее чем в InterBase 2009, но эту версию уже можно считать устаревшей, поэтому я настаиваю на XE (для экспериментов можно взять Developer Edition, если ее у вас ее еще нет — выбираем InterBase XE (10.0.4.590) 32-bit Developer Edition — Windows,  English или InterBase XE (10.0.4.590) 64-bit Developer Edition — Windows, English). Иначе часть описываемых функций у вас может не заработать. Логинимся от SYSDBA, включаем в базе EUA, как это описано в статье.

ALTER DATABASE ADD ADMIN OPTION
Меняем пароль SYSDBA  
ALTER USER SYSDBA SET PASSWORD ‘sss’

понятно, что sss и подобные тут просто для того, чтобы не замучил склероз. Предлагаю по мере выполнения действий записывать их в «блокнотик» с цитатами отсюда, или собственными комментариями — получилось, не получилось, и т.п.

Разлогиниваемся, проверяем — пароль masterkey больше не работает, используем sss — ок, подключились.

затем создаем пользователя SYSDSO (его может создать только SYSDBA или владелец БД)

CREATE USER SYSDSO SET PASSWORD ‘ooo’

Этот пользователь является «ключником», и не может выполнять никакие другие функции, кроме:

  1. создания системного пароля шифрования (SEP)
  2. создания ключей шифрования
  3. выдачи прав другим пользователям на использование созданных ключей шифрования для шифрования базы данных или столбцов таблиц

Больше SYSDSO делать ничего не умеет, и не должен.

! При генерации System Encryption Password используется информация, специфичная для текущего компьютера. Поэтому, на этой машине далее при доступе к БД SEP не требуется (хотя такое требование можно включить), а при переносе БД на другой компьютер никто без указания пароля SEP залогиниться не сможет. Можно указывать пароль SEP в параметрах коннекта (isc_dbp_system_encrypt_password), но это доступно только компонентам прямого доступа. Либо, можно указать SEP в переменных среды ОС (переменная ISC_SYSTEM_ENCRYPT_PASSWORD). Лучше сделать так — SYSDSO должен залогиниться к базе используя свой пароль и SEP, и создать новый SEP. Новый SEP будет привязан уже к этому компьютеру, и остальным пользователям указывать его при коннекте не потребуется.

Разлогиниваемся, логинимся как SYSDSO, создаем SEP для базы

ALTER DATABASE SET SYSTEM ENCRYPTION PASSWORD ‘aaa’

Если есть желание, чтобы даже сейчас, на этом компьютере, пользователям требовалось указывать при коннекте пароль SEP (если ваше приложение позволяет указывать этот пароль помимо обычного пароля. Если нет, они обломаются, и так лучше не делать), то к данной команде можно добавить в конце опцию EXTERNAL.

продолжение.

Читать на сайте автора.

Кросс-платформа 2012

Отличная конференция была, все прошло замечательно. Правда, я прочитал какой-то бредовый доклад (с моей точки зрения), спутанный из-за предыдущего доклада Сергея Кузнецова.
В финале Embarcadero раздало какое-то чудовищное количество призов (флэшек, кружек, маек и т.п.) Раздача (розыгрыш по заполненным анкетам) заняла минут 30 минимум, в ускоренном темпе. Такое впечатление, что почти треть посетителей получили призы.
Человек 10 не получили призы, потому что ушли раньше.

Читать на сайте автора.

Вебинар № 3 по InterBase

Завтра, 25 мая в 12:00 в рамках серии вебинаров Эмбаркадеро «Developer Direct: Демонстрации и обсуждения»
http://forms.embarcadero.com/forms/EM12Q2RUWebinarDeveloperDirect

опять я, про InterBase. Часть 3, Средства разработки и компоненты.

Welcome.

Запись предыдущего вебинара (о UDF) пока не выложена, будет скоро.

Читать на сайте автора.

Шифрование в InterBase

Когда вышел InterBase 2009, я увидел в списке новых фич шифрование. Поскольку лично меня эта тема не затрагивает, я ознакомился с возможностями, и на этом все кончилось. Интересно, что даже разработчики, которых эта тема интересует, ее пропустили. Например, один из вопросов, присланный нам перед вебинаром по InterBase, проводимом 14 марта, был «как в InterBase с шифрованием». Простите, но на дворе уже давно XE (с конца 2010 года), а 2009-ая вышла в августе 2008 года.
В общем,  вместе с Embarcadero провели первый вебинар на тему InterBase, и в него вошел общий рассказ про возможности шифрования. Сейчас готовится второй вебинар, а там и третий, но мне кажется, что подробнее эту тему лучше раскрыть в блоге, поэтапно. Здесь и начнем.

Шифрование в InterBase существует в «трех частях»

  • шифрование соединения (Over-the-Wire, OTW)
  • шифрование БД (всей БД или отдельных столбцов таблиц)
  • шифрование бэкапов

Большинство, конечно, хочет просто «шифрования базы», чтобы ее не украли или чтобы не стащили информацию. Но к сожалению, опять же у большинства, представление о шифровании достаточно примитивное, и «зашифровать базу» это как бы как «зашифровать файл или архив». В реальности это не так, и требует определенных усилий по планированию и управлению.
Слова «а зачем оно нам такое, нам бы попроще» отметаются сразу, потому что простое шифрование так же просто вскрывается. В общем, давайте лучше посмотрим, как оно устроено.

Стандарты шифрования
Поддерживается DES (по умолчанию), и AES. DES можно использовать сразу, для AES нужно скачать бесплатную лицензию со своего аккаунта на Embarcadero (при условии, что InterBase куплен и зарегистрирован.

Шифрование соединения

Операционные системы клиента и сервера должны поддерживать SSL v3 и TLS v1. Сертификат и CA файлы должны быть сгенерированы заранее, быть в формате PEM, и размещены на компьютерах клиента (клиентский и публичный серверный ключ) и сервера (серверный ключ).
Строка коннекта при этом получается чудовищная (пример из OpGuide.pdf)
«localhost/gds_ssl?ssl=true?clientPassPhrase=clientkey?clientCertFile=c:InterBaseclientclient.pem?serverPublicFile=c:InterBaseclientserverCAfile.pem??:c:/db/database.ib»

На сервере должен быть файл ibss.config, в котором прописываются параметры для серверной стороны, и если честно, все это настолько страшно, что я не хочу дальше это описывать, и предоставлю вам самостоятельно дочитать об этом в OpGuide.pdf — там приведен максимум информации, включая примеры настроек и конфигураций (без проверки клиента, с проверкой, и т.п.).

Главное, что шифрование коннекта есть, оно настраивается, но требует определенных усилий по его настройке. Собственно, безопасность через тяп-ляп не обеспечивается.

Вот о шифровании БД (всей или столбцов) я расскажу подробнее, но в следующем посте.

Читать на сайте автора.