Проверка корректности адреса электронной почты

   Проверить корректность адреса электронной почты очень просто (не только синтаксис, но и его реальное существование). Для этого можно воспользоваться компонентой clEmailValidator из библиотеки Clever Internet Suite. Напишем с ее использованием простую функцию:

Function ValidateMail(const sAddress: String): Boolean;
Var
  clEV: TclEmailValidator;
begin
  clEV := TclEmailValidator.Create(nil);
  Try
    clEV.ValidationLevel := vlMailbox;
    clEV.DnsServer := ‘8.8.8.8’;
    Result := clEV.Validate(sAddress) = vrMailboxOk
  Finally
     clEV.Free;
  End;
end;

Я задал всего лишь два свойства clEmailValidator (остальные можно пропустить). Первое и основное, это ValidationLevel — метод (уровень) проверки правильности адреса, их пять:

  1. vlBlacklist — проверка на вхождение адреса в ваш «чёрный список» (чёрный список хранится у clEmailValidator в свойстве BlackList типа TStrings);
  2. vlSyntax — проверка синтаксиса (проверяется при помощи шаблона RegEx);
  3. vlDomain — проверка существования домена (проверяется запросом DNS-информации для почтового домена);
  4. vlSmtp — проверка доступности почтового сервера (проверяется попыткой установления SMTP-соединения с хостом, указанным в MX-записи DNS);
  5. vlMailbox — проверка существования почтового ящика (проверяется попыткой отправить SMTP-запрос почтовому серверу с указанием проверяемого адреса в поле «RCPT TO»).

   Я расположил эти значения в списке по очереди (в порядке) выполнения. Т.е. если вы хотите проверить существование домена, то clEmailValidator выполнит проверки нижнего уровня — сначала на вхождение в чёрный список, потом проверку синтаксиса адреса, а уж затем проверку существования домена.
   Проверка корректности с уровнем vlDomain и выше требует активного internet-подключения и у clEmailValidator необходимо задать значение свойству DnsServer. DnsServer — это IP-адрес name-сервера вашего internet-провайдера. В примере выше я использовал адрес Google Public DNS.
   При желании для уровня vlSmtp (и выше) можно задать имя которое используется в команде «SMTP HELO» (свойство HostName). А для уровня vlMailbox можно задать еще и адрес электронной почты, который используется в SMTP-запросе свойство EmailFrom). Я написал «при желании», т.к. у меня проверка корректности работает и без них.
   Метод Validate возвращает уровень, до которого проверка адреса электронной почты выполнилась корректно (vrBlacklistOk, vrSyntaxOk, vrDomainOk, vrSmtpOk, vrMailboxOk) или, если вы совсем ерунду подсунули clEmailValidator, то «vrInvalid».

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

Описание у службы Windows

   При написании очередной службы для MS Windows, меня посетила мысль: «А почему у TService нет свойства «Description«?». При этом из своего опыта знаю, что подобное свойство есть у аналогичных компонент: у TNtService из библиотеки SvCom и даже у бесплатной компоненты TDDService от Arno Garrels, а у стандартного TService его нет даже под Delphi XE. Я понимаю, что описание — это не важно, но служба без описания выглядит на фоне других как-то неполноценно.
   Метода для установки описания у TService я не нашел, поэтому ничего другого не оставалось, как добавить описание службе самому.
   Оказалось, у MS Windows для этого есть специальная функция — ChangeServiceConfig2 (в advapi32.dll), которая изменяет дополнительные параметры конфигурации службы. Вместо реализации вызова ChangeServiceConfig2 на Delphi я сделал проще – в событии TService.ServiceAfterInstall записал описание службы напрямую в реестр:

procedure TxyzSvc.ServiceAfterInstall(Sender: TService);
begin
  With TRegistry.Create(KEY_READ or KEY_WRITE) do
    Try
      RootKey := HKEY_LOCAL_MACHINE;
      If OpenKey(‘SYSTEMCurrentControlSetServices’ + Name, False) then
        begin
          WriteString(‘Description’, ‘XYZ Service’);
          CloseKey;
        end;
    Finally
      Free;
    End;
end;

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

ImageEn – кто не успел, тот опоздал

   Год назад компания HiComponents сделала бесплатной свою библиотеку компонент для работы с картинками – ImageEn. Исходные коды, хоть и было обещано, выложены не были, но любой желающий, после несложной регистрации, мог скачать новую версию библиотеки (3.12), скомпилированную под любую версию Delphi и C++Builder и насладиться её мощным функционалом бесплатно.
   Но теперь халява закончилась. Права на ImageEn переданы новозеландской компании Xequte Software и библиотека снова стала платной. Вот такой поворот в условиях лицензии. Взглянув на список продуктов компании (сплошь утилиты для работы с картинками, видео и музыкой), становится очевидной причина смены хозяина. Предполагаю, что для разработки многих продуктов компании используется ImageEn и, после того как ее автор (итальянец Fabrizio) утратил к библиотеке коммерческий интерес, ей просто не дали умереть.
   По заявлению представителя компании Xequte Software они планируют развивать библиотеку и даже задумываются над 64-х битной версией, а над исходными кодами ImageEn по-прежнему трудится Fabrizio.
   Со сменой хозяина и лицензии изменились и цены. У Xequte Software лицензия на исходные коды ImageEn и подписка на их бесплатное 12-ти месячное обновление стоит 299.50$ (на одного разработчика). Эта цена почти вдвое больше, чем у HiComponents (175$)! А лицензия на скомпилированную версию ImageEn не продается(у HiComponents она стоила 59$), но её владельцы могут приобрести новую версию по сниженной цене – за 249.50$.
   Если Xequte Software снова не выложит бесплатно скомпилированную версию ImageEn, то тот, кто не успел её скачать, попал на деньги.

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

FastReport. Вывод данных в внизу страницы

   Недавно коллега обратился с вопросом «Как в FastReport сделать так, чтобы бэнд с данными выводился внизу страницы?».
   Первая моя мысль была положить SubReport на PageFooter. Но такое решение естественно не сработало, и я стал пробовать управлять положением бэнда на странице с помощью скрипта. В результате я нашел решение данного вопроса с помощью дополнительного бэнда и одной строчки скрипта. Поясню на примере.
   Например, вверху отчета нам нужно вывести какую-то информацию (добавляем на страницу бэнд MasterData1) и внизу отчета нам нужно вывести какую-то информацию (добавляем на страницу бэнд MasterData2). А между ними положим еще один бэнд (MasterData3), который заполнит пространство между MasterData1 и MasterData2. Его не будем подключать к данным, а просто укажем количество строк RowCount = 1.
   В скрипте, при старте отчета зададим размер MasterData3:

MasterData3.Height := Engine.PageHeight — MasterData1.Height * MasterData1.RowCount – MasterData2.Height * MasterData2.RowCount

т.е., от высоты страницы отнимаем высоту бэндов с данными. Высоту бэндов с данными вычисляем следующим образом: высоту одной строки бэнда умножаем на количество строк, которые будут в нём выводиться. У меня здесь в скрипте количество строк – это RowCount, а в примере отчета для моего коллеги я использовал количество строк в запросе (DataSet.RecordCount).
   Вот такими нехитрыми манипуляциями мне удалось решить поставленную задачу.

Может быть, вы знаете способ проще?

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

Object Pascal для Java и Android

   На прошедшей в Лас-Вегасе конференции Developer Solutions Conference, компания RemObjects Software впервые представила свой новый проект – «Cooper«. Cooper – это новый компилятор языка RemObjects Oxygene для платформ Java и Android (RemObjects Oxygene – это реализация языка Object Pascal для .NET и Mono, третья версия которого была выпущена как Embarcadero Delphi Prism). Cooper подключает стандартные библиотеки Java-классов и создает 100% байт-код для виртуальных машин Java и Dalvik (Dalvik – виртуальная машина Java для Android).
   В ролике показано, как под Mac-OS в командной строке скомпилировали паскалевский код консольной программы и калькулятора, использующего swing-контролы, а затем запустили полученные jar-файлы.

   Планируется интеграция Cooper в Visual Studio и MonoDevelop (аналогично с компилятором для .NET). Обещают выпустить это чудо уже в этом году.

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

Сохранение в базу данных отчета FastReport в формате PDF

   Недавно пришлось писать DLL, одна из функций которой должна была:

1. сформировать отчет в FastReport;
2. экспортировать отчет в файл PDF-формата и сохранить его в базе данных;
3. возвратить идентификатор сохраненного в базе данных файла.

Предположим, что исходная структура таблицы для хранения файла в базе данных была такая (MS SQLServer 2000):

CREATE TABLE X.FILES (
  ID BIGINT IDENTITY NOT NULL,
  FILE_BODY IMAGE NULL,
  CONSTRAINT PK_FILES PRIMARY KEY (ID)),

где FILE_BODY – это поле, в которое сохраняется файл, а ID – идентификатор файла.
   Для начала я создал процедуру, которая будет вставлять файл в базу данных и возвращать идентификатор вставленного файла.

CREATE PROCEDURE X.InsertFile
 @FILE image,
 @ID bigint OUTPUT
AS
 INSERT INTO X.FILES(FILE_BODY) VALUES(@FILE)
 SET @ID = SCOPE_IDENTITY()
GO

   Потом сел писать код DLL. В Delphi вся работа с файлами реализована с помощью потоков, поэтому я немного удивился, когда оказалось, что метод Export у TfrxReport экспортирует отчет только в файл (честно сказать, я ожидал увидеть, что-то в стиле ExportToStream). Т.е. вместо прямой передачи отчета через поток в базу данных, необходимо было сначала сохранить отчет во временный файл, а потом этот файл загрузить в базу данных. Мне это не понравилось, т.к. файловые операции (сначала записи, потом чтения) должны были хоть немного, но тормозить работу. Но нужно было срочно отдать DLL, поэтому я не стал разбираться с экспортом и сделал через файл:


 db: TSDDatabase; // база данных SQLDirect
 spInsertFile: TSDStoredProc; // вызов X.InsertFile
 frxReport: TfrxReport;
 frxPDFExport: TfrxPDFExport;

Function GetDoc(const sDotName: String; …): Integer;
begin
 Result := -1;
 // загружаем шаблон отчета
 If frxReport.LoadFromFile(sDotName)
  then begin
   // устанавливаем параметры отчета
   …
   If frxReport.PrepareReport
    then try
     // получаем имя временного файла
     frxPDFExport.FileName := GetTempFileName;
     Try
      // экспортируем отчет во временный файл
      frxReport.Export(frxPDFExport);
      // загружаем PDF-файл в параметр процедуры
      // из временного файла
      spInsertFile.Params[1].LoadFromFile(frxPDFExport.FileName, ftBlob);
     Except
      on E: Exception do
       WriteErrorMessage(E.Message);
     End;
     // сохраняем PDF-файл в базу данных
     Try
      db.StartTransaction;
      spInsertFile.ExecProc;
      db.Commit;
      Result := spInsertFile.Params[2].AsInteger;
     Except
      on E: ESDEngineError do
       begin
        db.Rollback;
        WriteErrorMessage(E.Message);
       end;
     End;
    Finally
     // удаляем временный файл
     DeleteFile(frxPDFExport.FileName)
    End
    else WriteErrorMessage(‘Ошибка подготовки отчета’)
  end
  else WriteErrorMessage(‘Файл шаблона не найден’)
end;

   После передачи DLL другому программисту, мысли о лишних файловых операциях при сохранении отчета в базу через временный файл, не давала мне покоя. Вечером, не найдя решения в документации по FastReport, я, прежде чем смотреть исходный код экспорта, решил еще раз пройтись по методам и свойствам экспорта. Глаз сразу же зацепился за свойство Stream. Я создал для этого свойства поток и метод Export у TfrxReport выгрузил отчет не в файл, а в поток.

Function GetDoc(const sDotName: String; …): Integer;
begin
 Result := -1;
 // загружаем шаблон отчета
 If frxReport.LoadFromFile(sDotName)
  then begin
   // устанавливаем параметры отчета
   …
   If frxReport.PrepareReport
    then begin
     Try
      Try
       // создаём поток в памяти
       frxPDFExport.Stream := TMemoryStream.Create;
       // экспортируем отчет в поток
       frxReport.Export(frxPDFExport);
       // загружаем PDF-файл в параметр процедуры
       // из потока в памяти
       spInsertFile.Params[1].LoadFromStream(frxPDFExport.Stream, ftBlob);
      Except
       on E: Exception do
        WriteErrorMessage(E.Message);
      End;
     Finally
      frxPDFExport.Stream.Free;
     End;
     // сохраняем PDF-файл в базу данных
     Try
      db.StartTransaction;
      spInsertFile.ExecProc;
      db.Commit;
      Result := spInsertFile.Params[2].AsInteger;
     Except
      on E: ESDEngineError do
       begin
        db.Rollback;
        WriteErrorMessage(E.Message);
       end;
     End;
    end
    else WriteErrorMessage(‘Ошибка подготовки отчета’)
  end
  else WriteErrorMessage(‘Файл шаблона не найден’)
end;

   Часто решение задачи лежит на поверхности и нет нужды копаться в чужом коде. Нужно лишь быть внимательным и никогда не сдавайтесь – «ищите и обрящите».

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

Часть антивируса Касперского написана на Delphi

   В конце этой недели в интернет были выложены исходные тексты антивируса Касперского, которые были украдены одним из сотрудников компании в 2008 году (последние изменения датируются декабрём 2007-го года). Как сообщает сайт Softpedia, часть антивируса написано на Delphi 🙂

Ссылки по теме:
1. Кому выгодно раскручивать тему утечки кодов из Лаборатории Касперского?
2. Kaspersky Anti-Virus Source Code Leaks online

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

Delphi и C++Builder Starter Edition

   По информации SD Times, Embarcadero Technologies собирается продавать новую редакцию Delphi и C++Builder – Starter Edition. Эта редакция будет включать: полноценную IDE с 32-разрядным компилятором, отладчик и библиотеку визуальных компонент (VCL), содержащую сотни компонент для создания пользовательского интерфейса (от стандартных Windows-контролов до контролов в стиле Office Ribbon и touch-интерфейса) и работы с различными Internet протоколами и стандартами. До публикации обновленного «Delphi Feature Matrix» трудно, что то понять о функциональных возможностях новой редакции, но по короткому описанию она очень напоминает Professional Edition.
   Стоимость Delphi и C++Builder Starter Edition – всего 199$ (для сравнения, Professional Edition стоит около 899$)! Пользователи Turbo Edition и других конкурирующих IDE могут получить обновление на Delphi и C++Builder Starter Edition за 149$. Ограничения только юридические: не более пяти подобных лицензий в пределах одной локальной сети и общий доход с сервиса или организации не более 1000$ в год. Кто превысит этот порог или хочет больше возможностей, то должен обновить свой Starter Edition до Professional, Enterprise или Architect со скидкой в 100$.
   Думаю, от данного предложения мало радости большинству пользователей Delphi. Но оно вполне подходит тем, кто только учится программировать, для кого программирование – это хобби (например, разработчикам open-source проектов), разработчикам бесплатных продуктов или тем, кто только начинают разработку своего продукта.
   Принесет ли этот маркетинговый ход Embarcadero какие-нибудь плоды? Увеличит ли это количество пользователей Delphi и C++Builder? Думаю, что нет. Причина этому то, что Microsoft раздает Visual Studio Express бесплатно. А бесплатно и 199$ – это большая разница.
   Конечно, некоторые объемы продаж этой редакции будут. Думаю, что большинство продаж будет только для легализации своих продуктов. Не в каждой стране будут разбираться в тонкостях лицензии, поэтому лицензии на Starter Edition будет достаточно, чтобы узаконить свою деятельность (например, при получении лицензии на разработку ПО чиновнику будет наплевать на редакцию средств разработки).
   Остается надеяться, что Embarcadero не будет разочарована в Delphi и C++Builder Starter Edition.

Дополнено 31.01.2011:
На сайте Embarcadero открыли странички посвященные Delphi XE Starter Edition / C++Builder XE Starter Edition и опубликовали Delphi XE Starter Edition and C++Builder XE Starter Edition FAQs (перевод FAQ).

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

Интернет на халяву

   Сегодня заменил свой старый ADSL-модем на новенький с Wi-Fi. Кроме моей точки доступа ноутбук сразу нашел ещё четыре. Одна из них была помечена, как «Unsecured wireless network». Проверив работу своей точки доступа, я отключил её и проверил «соседскую». Через «соседскую» я без проблем вышел в интернет, открыл для тестирования пару сайтов и отключился. Предположим, что на моём месте оказался бы другой любопытный, но менее честный человек. Что тогда? В лучшем случае, он потихоньку приворовывал бы трафик бороздя просторы интернета, а в худшем — забил бы весь чужой канал каким-нибудь торрентом (если там модем без шейпера).
   «Граждане, храните деньги в сберегательной кассе!», — сказал Жорж Милославский, герой всенародно любимого кинофильма «Иван Васильевич меняет профессию», запихивая в карман пухлую пачку денег, похищенную из квартиры доктора Шпака. Так и я таким же поучительным тоном скажу: «Граждане, защитите свою беспроводную сеть! Хотя бы ограничьте подключения к вашей точке доступа по MAC-адресу устройств».

P.S. Вечером на кухне ноутбук находил уже 15 точек доступа, две из которых были открыты для общего пользования…

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

Delphi Team обидела очередного приверженца Delphi

   Разработчики Delphi все больше ударов наносят по остаткам Delphi-сообщества: постоянные срывы roadmap, кучи багов, минимальное развитие от версии к версии, зашкаливающие цены на обновления… Всем своим поведением они стараются отталкнуть от себя людей. И это им удается!
   Например, в начале ноября 2007-го года Питер Моррис (Peter Morris), весьма известный человек в Delphi-сообществе (автор нескольких open-source библиотек (deAudio, deBold, DIB Controls и FastStrings); автор множества статей по Delphi, Bold и ECO; в феврале 2007-го анонсировал свою книгу, посвященную ECO…), поссорился с CodeGear (Borland) из-за лицензии на Delphi. Менеджеры CodeGear пожадничали, и в результате Питер Моррис закрыл свой сайт (Droopy Eyes Software), отказался от использования Delphi и прекратил поддержку своих open-source проектов.
   Сегодня другая известная личность в Delphi Community — Андреас Хаусладен (Andreas Hausladen) опубликовал на своем блоге заметку XE Update 1 the death of DDevExtensions. Андреас Хаусладен известен своими расширениями для Delphi IDE: DelphiSpeedUp (ускоряет загрузку IDE), DDevExtensions (делает более удобной работу в IDE), IDE Fix Pack (набор патчей для IDE исправляющих баги, до которых у R&D Team нет дела), dcc32Speed (ускоряет работу компилятора (dcc32.exe)) и прочие. Кроме этого он участвует в Project JEDI и разрабатывает собственные библиотеки (VCL Fix Pack, Midas Speed Fix, AsyncCalls и NvAPI). Проблема в том, что R&D Team сильно увлеклась защитой от пиратов, тем самым мешает работе разработчиков расширений для Delphi IDE. Пираты и так найдут, как украсть, а страдают, как всегда, честные люди. Delphi XE Update 1, если установлен DDevExtensions, случайным образом останавливает работу и отправляется на http://www.embarcadero.com/how-to-buy. Думаю, что после прочтения слов Андреаса «Это означает, что DDevExtensions для Delphi XE умер» многочисленные пользователи DDevExtensions по всему миру дружно сказали «фуцк».
   Год от года Delphi-сообщество уменьшается… Только, похоже, что это не волнует ее разработчиков и скоро Delphi, как и Borland, станет достоянием истории.

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