воскресенье, ноября 15, 2009

DelphiFeeds.ru запущен в тестовом режиме

В тестовом режиме запущен сайт http://www.delphifeeds.ru/. Русскоязычный аналог DelphiFeeds.com.

На текущий момент собираются RSS ленты с десяти сайтов, и еще с трех - в ручном режиме.

Предложения, пожелания, вопросы можно оставить здесь: http://www.delphifeeds.ru/index.php/feed.



Вы можете поддержать проект, разместив у себя в блоге кнопку:

DelphiFeeds.ru - Все Delphi-блоги Рунета

<a href="http://www.delphifeeds.ru/" title="DelphiFeeds.ru - Все Delphi-блоги Рунета"><img src="http://www.delphifeeds.ru/images/stories/baner8.png" alt="DelphiFeeds.ru - Все Delphi-блоги Рунета" width="81" height="31"/></a>

среда, октября 07, 2009

Обновления на блоге

Delphi 2010. Что нового? #5

Изменения в дебаггере.

Смесь бульдога с носорогом

о переводе Delphi проекта на DevExpress.

Delphi 2010. RTTI и атрибуты

Думаю, что в рамках обзора новых возможностей Delphi 2010 будет уместно привести перевод материалов "из первых рук".

Delphi 2010 RTTI – Основы.

Перевод первой части обзора новых возможностей RTTI системы в Delphi 2010.

пятница, августа 14, 2009

Delphi 2010. Что нового? #2

Изменений в IDE новой версии Delphi достаточно много. Хотя большинство из них косметиеские, возможно, о большинстве из них не стоит и упоминать. И, тем не менее, есть среди них и полезные вещи.

Читать дальше...

четверг, августа 13, 2009

Delphi 2010. Что нового? #1

К сожалению, явно не хватает времени плотно потестить бету. Но все же, ознакомиться с нововведениями очередной версии Delphi - дело святое.

Постараюсь по порядку.

четверг, августа 06, 2009

среда, июля 22, 2009

Фреймы, как визуальные компоненты, изменение наследования

Фреймы в Delphi  - интересная штука, которая может создать проблемы "на ровном месте". Попытка перевода статьи на эту тему.

http://delphi2010.ru/?p=71

суббота, июля 18, 2009

Журналы, посвященные Delphi…

Небольшой обзор Delphi прессы. И несколько сумбурные мысли  по этому поводу...

Читать полный текст...

пятница, июля 03, 2009

Будущее Delphi

Третьего дня мне попалась на глаза интересная статья - отчет о выступлении Дэвида И (David I) в Бельгии. Вот попытка ее перевода.

Переезд

Решил я перевести свой блог на собственный хостинг и домен.

К тому же домен безхозный лежал так хорошо, вот я его и подобрал.

Новый адрес блога: http://delphi2010.ru/

Здесь же я буду некоторое время давать линки на посты в новом блоге.

вторник, июня 30, 2009

Delphi 2009 Handbook бесплатно.

Марко Кэнту, автор известных книг Mastering Delphi, в свое время жаловался, что его последняя книга, Delphi 2009 Handbook разошлась по файлообменникам. Он ее лично видел на Рапиде. Теперь ее можно получить бесплатно. Для этого следует просто посмотреть, что из себя представляет RAD Studio 2009 (это для тех, кто еще ее не видел :) ).

Рекомендую.

  1. Скачайте RAD Studio 2009 trial
  2. Установите и зарегистрируйте триал
  3. Скачайте the Delphi 2009 Handbook (линк станет доступен после установки Rad Studio 2009)

Источник

четверг, апреля 30, 2009

ASProtect и Delphi 2009

В принципе все оказалось довольно не сложно.

ASProtect вполне нормально работает с Delphi 2009. Естественно, нужно просто делать преобразование строк при вызове ASProtect API  функций.

Вот преобразованная процедура из стандартного примера:

procedure TfrmRegKey.btnRegOkClick(Sender: TObject);
begin
 
// If CheckKeyAndDecrypt( PChar(eCode.Text), PChar(eName.Text), True ) then
 
// Для Delphi 2009 будет так:
If CheckKeyAndDecrypt( PChar(ansistring(eCode.Text)), PChar(ansistring(eName.Text)), True ) then
begin
MessageBox(Handle, 'Thank you for your registration!', 'Registration', MB_ICONINFORMATION);
Close;
end else
MessageBox(Handle, 'Key is not valid, please contact manufacture!','Registration', MB_ICONWARNING);
 
end;

К слову, месяц назад вышел ASProtect SKE 2.5 Release. Так, что слухи о том, что продукт умер – преувеличены.

  • Improved map-files parsing
  • Various Help file corrections
  • Fixed application termination instead of displaying Trial Reminder if no trial counters have been used
  • Fixed aspr_ide crash under Delphi IDE.

суббота, апреля 04, 2009

Благими намерениями

В одном из форумов вычитал...
Подскажите компонент для работы с фискальными кассовыми устройствами (IO). Желательно с сырцами. Спасибо.

Тут же захотелось попросить компонент для посадки льва в клетку.
Хотя, может действительно есть и такие компоненты...
Но по -моему, подобные посты ни что иное, как нормальная идея, доведенная до абсурда.

воскресенье, марта 15, 2009

Использование Vista UAC в Delphi: Часть 3

Это заключительная часть серии из трех частей о UAC и Delphi.
Перейти к части 1
Перейти к части 2

Здесь я затрону наиболее интересные подходы к обеспечению подлинного UAC соответствия – в том виде, в каком вероятно, следует реализовывать большинство Vista-совместимых приложений.

Повышение прав по запросу с использованием COM Elevation Moniker

Первая вещь, которую в которой вы должны быть уверены, это то, что исполняемый файл приложения содержит UAC манифест. Манифест, практически идентичный тому, который вы могли видеть в части 2, с одним, но очень важным отличием: атрибут requestedExecutionLevel должен иметь значение "asInvoker":

  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  3. <assemblyIdentity
  4. version="1.0.0.0"
  5. processorArchitecture="*"
  6. name="UACAwareApplication"
  7. type="win32"/>
  8. <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
  9. <security>
  10. <requestedPrivileges>
  11. <requestedExecutionLevel level="asInvoker"/>
  12. </requestedPrivileges>
  13. </security>
  14. </trustInfo>
  15. </assembly>

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

Прежде чем продолжить, я объясню, как повышение привилегий работает изнутри…

Когда процесс стартует, ему присваивается уровень доступа Windows, который контролирует то, что этот процесс может или не может сделать, с некоторыми объектами, такими как файлы и каталоги, имеющими списки управления доступом (Access Control Lists или ACL's, для краткости) к себе. Что здесь важно, так это то, что уровень доступа, который присваивается фактически единожды, в момент запуска процесса, не может быть изменен на более поздних этапах жизни процесса. Следовательно, повышение привилегий, возможно одним единственным способом - порождением нового процесса с более высоким уровнем привилегий. Зная об этом, менее требовательные приложения, которые не нуждаются в использовании сложных состояний пользовательского интерфейса, могут просто перезапускать себя в админском режиме и работать.

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


Вместо этого, есть другое решение для таких случаев. Код приложения может быть разбит на две части – не привилегированный код размещается в основном исполняемом файле, в то время, как код, требующий привилегий выносится в отдельную dll, оформленную как один или несколько COM объектов. COM объекты могут вызываться COM посредствам Elevation Moniker в контексте выделенного COM-сервера, который и повышает привилегии.

Довольно теории. Выполним некоторые действия.

Здесь мы должны сделать следующее:

написать dll, которая будет загружаться выделенным COM – сервером;

добавить COM-объект, реализующий функциональность, требующую привилегий;

добавить COM class factory, которая будет использоваться для создания экземпляра COM объекта и регистрации библиотеки, и

написать какой-то код для вызова COM объекта из главного исполняемого файла, который изначально не обладает привилегиями.

До настоящего момента, ничего не говорилось о создании dll. Эта обычная COM библиотека может быть создана в Delphi путем следующих действий:

"New" -> "Other..." -> "Delphi Projects"\"ActiveX" -> "ActiveX Library", как это показано на скриншоте.

clip_image002[1]

Как только мы создали и сохранили новый COM library проект, нам необходимо добавить новый COM объект, в котором мы реализуем функционал повышения привилегий.


clip_image004[1]

В демонстрационных целях мы определим единственный метод COM объекта, и опишем его с помощью интерфейса объекта по умолчанию:


  1. IMyPrivilegedObject = interface(IUnknown)
  2. ['{04004D01-2115-40D5-991F-D258C8CEF07E}']
  3. function CreateFile(const aFileName: WideString): HResult; stdcall;
  4. end;

Этот метод позволит нам проверить, действительно ли COM объект привязывается к процессу повышения привилегий.

Теперь нам нужно создать пользовательскую фабрику классов (Class Factory) для нашего COM объекта. Это нужно по той причине, что Class Factory отвечает за регистрацию и удаление (unregistering) COM объекта в системном реестре. Мы не можем просто по умолчанию использовать TTypedComObjectFactory, потому существуют некоторые специальные значения, которые должны быть прописаны в реестре, для того, чтобы сделать возможным размещение вне процесса и независимое повышение привилегий.

Приложения не могут просто запрашивать у Windows повышение привилегий подобно тому, как это делает любой OLE код. Если бы оно могло делать это, это была бы серьезная дыра в системе безопасности. Любой код, который должен быть выполнен с повышенными привилегиями, должен быть помещен в COM объект, расположенный в dll, который должен быть подготовлен к повышению привилегий.

Здесь основная часть реализации фабрики классов.

  1. type
  2. TPrivilegedClassFactory = class(TTypedComObjectFactory)
  3. private
  4. fResourceId: AnsiString;
  5. public
  6. constructor Create(
  7. const aResourceId: AnsiString;
  8. aComServer: TComServerObject;
  9. aTypedComClass: TTypedComClass; const aClassID: TGUID;
  10. aInstancing: TClassInstancing;
  11. aThreadingModel: TThreadingModel = tmSingle
  12. );
  13. procedure UpdateRegistry(aRegister: Boolean); override;
  14. end;
  15.  
  16. implementation
  17.  
  18. constructor TPrivilegedClassFactory.Create(const aResourceId: AnsiString;
  19. aComServer: TComServerObject; aTypedComClass: TTypedComClass;
  20. const aClassID: TGUID; aInstancing: TClassInstancing;
  21. aThreadingModel: TThreadingModel);
  22. begin
  23. inherited Create(
  24. aComServer, aTypedComClass, aClassID, aInstancing, aThreadingModel
  25. );
  26. { Save the id of the string resource, that holds the application name. }
  27. fResourceId := aResourceId;
  28. end;
  29.  
  30. procedure TPrivilegedClassFactory.UpdateRegistry(aRegister: Boolean);
  31. var
  32. ID, ClassKey, FullFileName, FileName: AnsiString;
  33. begin
  34. ID := GUIDToString(Self.ClassID);
  35. ClassKey := 'CLSID\' + ID;
  36. FullFileName := ComServer.ServerFileName;
  37. FileName := ExtractFileName(FullFileName);
  38. try
  39. if aRegister then begin
  40. inherited UpdateRegistry(aRegister);
  41. { DLL out-of-process hosting requirements. }
  42. CreateRegKey('AppID\' + ID, '', Description);
  43. CreateRegKey('AppID\' + ID, 'DllSurrogate', '');
  44. CreateRegKey('AppID\' + FileName, 'AppID', ID);
  45. { Over-The-Shoulder activation requirements. }
  46. SetAccessPermissionsForLUAServer('AppID\' + ID, 'AccessPermission');
  47. { COM object elevation requirements. }
  48. CreateRegKey(ClassKey, 'AppID', ID);
  49. CreateRegKey(ClassKey, 'LocalizedString', '@' + FullFileName + ',-' + fResourceId);
  50. CreateRegKeyEx(ClassKey + '\Elevation', 'Enabled', '1', nil, 0, REG_DWORD);
  51. end else begin
  52. DeleteRegKey(ClassKey + '\Elevation');
  53. DeleteRegKey('AppID\' + ID);
  54. DeleteRegKey('AppID\' + FileName);
  55. inherited UpdateRegistry(aRegister);
  56. end;
  57.  
  58. except
  59. on E: EOleRegistrationError do raise;
  60. on E: Exception do raise EOleRegistrationError.Create(E.Message);
  61. end;
  62. end;

Как отмечено в комментариях, существуют три требования, которые должны быть удовлетворены: регистрация размещения вне процесса, регистрация «обратной» (Over-The-Shoulder) активации, регистрация превышения привилегий. Вы можете найти объяснение каждого из требований здесь, поэтому нет необходимости дублировать информацию.

Я только хочу отметить, что такие фабрики классов являются типичными, и могут быть использованы в любых Delphi приложениях, требующих повышения привилегий. Параметр aResourceId хранит ID ресурсной строки, которая будет отображаться в запросе на превышение в качестве имени приложения. Будьте готовы использовать валидный ID из строковой таблицы dll!

Теперь мы должны использовать новую фабрику классов для создания COM объекта, и встроить строковый ресурс в нашу dll:

  1. initialization
  2. TPrivilegedClassFactory.Create(
  3. '101', // resource string id
  4. ComServer, TMyPrivilegedObject, Class_MyPrivilegedObject,
  5. ciMultiInstance, tmApartment
  6. );
Это файл ресурсов со строкой, которая будет отображаться в запросе на превышение привилегий.

STRINGTABLE

{

101, "Delphi Elevation Demo"

}

Последняя вещь, которую осталось сделать, это написать процедуру, которая будет вызываться из не привилегированного исполняемого файла в процессе вызова COM  объекта. Вот она:
  1. procedure CoCreateInstanceAsAdmin(
  2. aHWnd: HWND; // parent for elevation prompt window
  3. const aClassID: TGUID; // COM class guid
  4. const aIID: TGUID; // interface id implemented by class
  5. out aObj // interface pointer
  6. );
  7.  
  8. implementation
  9.  
  10. procedure CoCreateInstanceAsAdmin(aHWnd: HWND; const aClassID, aIID: TGUID;
  11. out aObj);
  12. var
  13. BO: BIND_OPTS3;
  14. MonikerName: WideString;
  15. begin
  16. if (not IsElevated) then begin
  17. { Request elevated out-of-process instance. }
  18. MonikerName := 'Elevation:Administrator!new:' + GUIDToString(aClassID);
  19. FillChar(BO, SizeOf(BIND_OPTS3), 0);
  20. BO.cbStruct := SizeOf(BIND_OPTS3);
  21. BO.dwClassContext := CLSCTX_LOCAL_SERVER;
  22. BO.hwnd := aHWnd;
  23. OleCheck(CoGetObject(PWideChar(MonikerName), @BO, aIID, aObj));
  24. end else
  25. { Request normal in-process instance. }
  26. OleCheck(CoCreateInstance(aClassID, nil, CLSCTX_ALL, aIID, aObj));
  27. end;

Здесь находится полный исходный код ElevationDemo в формате Delphi 2006 for Win32 проекта вмести с скомпилированными и подписанными бинарниками, так что вы можете протестировать их без компиляции. Конечно, вы для этого должны использовать Windows Vista. Когда вы запустите исполняемый файл, вы увидите нечто подобное:
clip_image006[1]

Чекбокс определяет будет ли вызываться COM объект, запрашивающий повышение привилегий или локальный COM объект, в случае вызова CreateFile(). Вы можете поэкспериментировать, вводя разные имена файлов в поле ввода.

Исходный код создан с использованием некоторых специфических Vista-структур, но для простоты я не включал код проверки ОС, пусть это будет домашним заданием для читателя.

Не забудьте сначала зарегистрировать DLL (для этого вам понадобятся привилегии Admin’а), в противном случае приложение не заработает. Обычно, это задача инсталлятора, но вы это можете сделать вручную:

regsvr32.exe PrivilegedLib.dll

здесь показано, как будет выглядеть ваш реестр после полной инсталляции:


  1. HKEY_LOCAL_MACHINE\SOFTWARE\Classes
  2. {
  3. AppID\PrivilegedLib.dll
  4. {
  5. (Default): REG_SZ = null
  6. AppID: REG_SZ = '{6BCFB187-C1DD-4807-96AD-F91AB4AB08AC}'
  7. }
  8. AppID\{6BCFB187-C1DD-4807-96AD-F91AB4AB08AC}
  9. {
  10. (Default): REG_SZ = 'MyPrivilegedObject'
  11. AccessPermission: REG_BINARY = <BINARY VALUE>
  12. DllSurrogate: REG_SZ = ''
  13.  
  14. }

Если все прошло нормально, вы должны будете увидеть один из следующих диалогов, после того, как вы выполните вызов запроса на превышение привилегий – вид диалога зависит от ваших настроек безопасности.

clip_image007[1]

clip_image008[1]

Ну вот и все. Я надеюсь, что вам понравилась эта серия. Я уверен, что показал все важнейшие шаги по созданию UAC-aware приложения в Delphi. Естественно, что я опустил массу деталей, чтобы не слишком вас утомлять – но это тема для отдельной публикации на будущее. Как всегда, присылайте свои комментарии и пожелания.

воскресенье, февраля 15, 2009

Delphi 14 лет

14 февраля 1995 г. вышел официальный релиз Delphi 1.

Поздравления всему Delphi сообществу!

Источник.

четверг, февраля 12, 2009

Использование Vista UAC в Delphi: Часть 2

Оригинал.

Это вторая часть серии статей о UAC и Delphi, состоящей из трех частей.
Перейти к части 1.

Полное описание логики работы UAC выходит за рамки данной статьи. Здесь я собираюсь только обозначить несколько относящихся к делу моментов.

По сути, UAC это все об уровнях привилегий. По умолчанию, обычное Windows приложение не требует администраторских привилегий. Вот почему под Vista, даже административные аккаунты, не используют полный доступ по умолчанию. Цель нормального UAC-приложения – запуск с доступом определяемым текущим аккаунтом, и лишь при реальной необходимости запрашивать повышенные права доступа. Сам процесс запроса повышения прав называется повышение привилегий (privilege elevation), и он требует, что бы пользователь подтвердил действие, перед тем, как это действие будет выполнено. Запрос на повышение может быть представлен либо в форме простого диалога Продолжить/Отменить (режим одобрения Админом), либо полноценного диалога логина (пользователи должны явным образом ввести свои полномочия), в зависимости от типа текущего аккаунта и настроек безопасности. Существует еще пара вариаций запроса в зависимости от того используется ли исполняемым файлом цифровая подпись или нет.

Следует помнить, что Vista поощряет использование цифровых подписей, показывая более дружелюбный запрос на повышение привилегий (далее elevation диалог) для подписанных исполняемых файлов.

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

Использование эвристики Vista.

Windows Vista имеет множество встроенных приемов для облегчения возможности поддержки UAC. Один из них фактически основывается на том, что инсталлеры и апдейтеры, как правило, вынуждены писать в защищенную директорию Programm Files и/или ветвь реестра HKLM. Vista распознает такие приложения с помощью эвристического метода определения и автоматически выводит elevation диалог, в тот момент, когда пользователь пытается выполнить их.

Есть целый ряд вещей, которые при этом проверяются, но я хотел бы отметить, единственную вещь, которую довольно легко реализовать и проверить – elevation диалог вызывается, если имя исполняемого файла или информация о его версии содержат такие строки, как, например, “settings”, “install” или “update”.

В результате, такой подход является весьма полезным для автоматического обновления приложений, которые, как правило, самостоятельно скачивают новую версию, а затем запускают внешние утилиты для замены старых файлов приложений. Если эта утилита названа примерно так: 'MyAppUpdater.exe' (и снабжена цифровой подписью), то приложения могут инициировать вызов красивого elevation диалога и запускать ее (утилиту) с полными правами доступа.

Очевидно, что такой подход применяется в отношении любого приложения, независимо от языка, на котором оно было разработано. Вам только нужно выбрать правильное название для исполняемого файла и все! Получите elevation диалог!

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

Выполнение от имени администратора.

Другим способом достижения того же результата является выбор опции "Выполнять эту программу от имени администратора" (Run this program as an administrator) на вкладке «Совместимость» в свойствах приложения. Обратная сторона медали будет та же, что и предыдущего подхода, приложение всегда будет выполняться с завышенными правами.

Манифест приложения.

Несколько более сложный вариант предыдущего подхода заключается в том, чтобы вставить следующий манифест в исполняемый файл своего приложения:





Ключевой информацией здесь проявляется значение атрибута requestedExecutionLevel. Если атрибут примет значение "requireAdministrator", то это послужит сигналом для Vista отобразить elevation диалог в момент запуска приложения.

Предварительно, манифест может быть связан с исполняемым файлом, вам необходимо скомпилировать его в RES формате, используя следующий RC файл (я предполагаю, что вы достаточно знаете о файлах ресурсов и знаете что такое RC и RES файлы):

1 24 "UAC.manifest"


Где 1 – индекс ресурса, 24 – тип ресурса (RT_MANIFEST), и "UAC.manifest" – актуальное имя файла манифеста, который будет скомпилирован. Замечу, что вы можете использовать другой индекс ресурса, убедившись при этом, что отсутствуют совпадения с индексами других ресурсов, например XP манифестом.

Наконец, вы должны связать полученный RES файл с исполняемым файлом, используя директиву компилятора Delphi $R.

Такой подход имеет точно те же недостатки, сто и предыдущие. Он увеличивает права заранее, а не в случае необходимости.

OK, это был краткий обзор основ UAC совместимости. Теперь мы готовы вигаться в правильном направлении…

среда, февраля 11, 2009

Использование Vista UAC в Delphi: Часть 1

 

Наконец-то произошло то, чего я так боялся. Сейчас мне придется адаптировать приложение для работы в Windows Vista. Первая и главная проблема здесь, это UAC. Поэтому я решил почитать матчасть. Возможно, кому-нибудь пригодится моя попытка перевода.

 

В настоящее время сотни технических блогов и статей, упоминают о возможностях User Account Control в Vista. К сожалению, многие авторы приуменьшают полезность этой функции.

Я говорю «к сожалению», потому, что мне нравится эта функция. И я считаю, неверным приуменьшать ее значимость. Я также считаю неверным то, что многие технические on-line источники и журналы с раздражением описывают UAC и даже предоставляют своим читателям инструкции по его отключению. Я думаю, что подобное отношение может впоследствии «обернутся боком».

Да, возможно, реализация UAC могла бы быть и лучшей. Но это не повод просто отключать его. При правильной настройке списки контроля доступа на объекты файловой системы UAC могут быть приведены к такому виду, что он уже не просто раздражает, а становится действительно полезным.

Но это не то, о чем я хочу поговорить. В свете моих мнений, я хочу показать вам, как использовать функции UAC в ваших Delphi приложениях. Так сказать, научить вас игратькрасиво, ...

Ввиду объемности статьи, я бы разделил ее на три части. Во второй части, я опишу некоторые наиболее общие UAC концепции, плюс бегло ознакомлю вас с тремя основными простыми методами, которые позволят вашим приложениям соответствовать им. В третьей, заключительной части, я сделаю упор на наиболее продвинутом подходе, включая написание определенного Delphi кода.

Ну что же, приступим…

понедельник, января 26, 2009

TurboPower сomponents for Delphi 2009

http://www.songbeamer.com/delphi/
На этом сайте вложен набор старых, хорошо известных компонентов, портированных под Delphi 2009.
Поддержка большинства этих компонентов (а возможно и всех) была давно прекращена разработчиками. В представленном наборе можно найти хорошо известные компоненты производства TurboPower, код которых был открыт, после того, как компания прекратила существование, и еще много чего полезного. Учитывая серьезные изменения, произошедшие в Delphi 2009 по части работы со строками, остается только снять шляпу перед авторами данных портов.

RESPECT!