{$codepage utf-8}

unit cl_clamscan;
interface


procedure BeParanoidal(filename: string; ismainexecutable: longbool);


implementation
uses Classes, SysUtils, un_process, cge;



var
  AVResult: WideString = '';
  VFound: boolean = false;

function CheckForViruses(filename: string): longbool;
var
  P: TCgeProcess;
  procedure LogError(r, e: Widestring);
  begin
    AVResult:=RuEn('Ошибка при вызове clamscan:','Error executing clamscan:') + #13#10'  ' + RuEn(r, e);
    AddLog(AVResult);
    Result:=Config.Bool['main', 'ignore_clamscan_errors'];
  end;
begin
  AVResult:='';
  VFound:=false;
  AddLog(RuEn('Дата "%0" изменилась,'#10#13'  проверяю на вирусы.'#10#13'  Ждите, запускается clamscan...', 'Date of "%0" changed,'#10#13'  checking for viruses.'#10#13'  Please wait while clamscan is starting up...'), [filename]);
  _cgeHeartBeat;
  P:=TCgeProcess.Create('"clamscan" '+ filename + ' --detect-broken --verbose');
  P.Execute;
  Result:=Yes;
  case P.ExitStatus of
    0: AddLogOk;
    1: begin
      AVResult:=RuEn('Найден ВИРУС!','A VIRUS found!');
      AddLog(AVResult);
      Result:=No;
      VFound:=true;
    end;


    40: LogError('в командной строке переданы неверные параметры.','unknown option passed.');
    50: LogError('ошибка инициализации базы данных.'#10#13'Убедитесь, что ваша антивирусная база не старше 7 дней!','database initialization error.'#10#13'Make sure your antivirus base isn''t older than 7 days!');
    52: LogError('не поддерживаемый формат файла.','нot supported file type.');
    53..58: LogError('ошибка ввода/вывода, возможно повреждена файловая система.','I/O error, the filesystem may be corrupt.');
    59..60: LogError('проблемы с /etc/passwd','problems with /etc/passwd');
    127: LogError('не установлен ClamAV','ClamAV not installed');

{ "man clamscan" says:

       0 : No virus found.
       1 : Virus(es) found.
       40: Unknown option passed.
       50: Database initialization error.
       52: Not supported file type.
       53: CanвЂ™t open directory.
       54: CanвЂ™t open file. (ofm)
       55: Error reading file. (ofm)
       56: CanвЂ™t stat input file / directory.
       57: CanвЂ™t get absolute path name of current working directory.
       58: I/O error, please check your file system.
       59: CanвЂ™t get information about current user from /etc/passwd.
       60: CanвЂ™t get information about user вЂ™clamavвЂ™ (default name) from /etc/passwd.
       61: CanвЂ™t fork.
       62: CanвЂ™t initialize logger.
}

  else
    LogError('неизвестный код возврата: '+IntToStr(P.ExitStatus),'unknown return code: '+IntToStr(P.ExitStatus));
  end;
  P.Free;
end;


procedure BeParanoidal(filename: string; ismainexecutable: boolean);
var
  fn: string;
  a, oa: integer;
begin
  if Config.Bool['main', 'dontbeparanoidal'] then Exit;
  fn:=ChangeFileExt(ExtractFileName(filename), '');
  oa:=Config.Int['paranoia', fn];
  a:=FileAge(filename);
  if oa = 0 then begin
    Config.Int['paranoia', fn]:=a;
    Exit;
  end;
  if a <> oa then begin
    if not CheckForViruses(filename)
    then begin
      AVResult:=#10#13 + AVResult;
      if ismainexecutable
      then
        Die(RuEn('Основной исполняемый файл не прошёл проверку на вирусы.%0',
            'The main executable didn''t pass the virus check.%0'),[AVResult])
      else
        Die(RuEn('Модуль %0 не прошёл проверку на вирусы.%1',
            'The module %0 didn''t the virus check.%1'),[ExtractFileName(filename), AVResult]);
    end
    else Config.Int['paranoia', fn]:=FileAge(filename);
  end;
end;


end.
