unit Pswdu;
interface
uses
  {v0.50}
  Classes,
  {/v0.50}
  PswdDlg, Desu, Language, Msgu, PropUtl;

{v0.50}
type
  TPasswordString = string[20];
{/v0.50}

function PasswordCheck: boolean;
  { Checks if password requiered:
      if yes (i.e. some password was set by EncryptedPasswordSet method
              or using PasswordChange method),
         checks if already entered ,
           if not entered yet prompts for it,
             if not entered correctly returns false
             if entered correctly returns true
           if entered previously returns true
      if no, returns true }

procedure PasswordChange;
  { invokes dialog for changing a password }

procedure EncryptedPasswordSet(const APassword: string);
  { use to set value from e.g. ini file }

function EncryptedPasswordGet: string;
  { use to get value for storing in ini file }

{v0.50}
type
  TPassword = class(TComponent)
  private
    FChecked: boolean;
    FTitle: string;
    FEncryptedPassword : TPasswordString;
    FIniLoaded: boolean;
    FIniFile: string;
    {v2.02}{/v2.02
    procedure CheckIniLoaded;}
    procedure EncryptedSet(const APassword: string);
      { use to set value from e.g. ini file }
    function EncryptedGet: string;
      { use to get value for storing in ini file }
    procedure SetDecrypted(const APassword: string);
    procedure SetChecked(OnOff: boolean);
  public
    constructor Create(Owner: TComponent); reintroduce;
    destructor Destroy; override;
    {v2.02}
    procedure CheckIniLoaded;
    {/v2.02}
    function Check: boolean;
      { Checks if password requiered:
          if yes (i.e. some password was:
             - set by assigning to Encrypted, or Decrypted
               property
             - read from inifile (Encrypted)
             - set using interactive Change method )
             checks if already entered,
               if not entered yet prompts for it,
               if not entered correctly returns false
               if entered correctly returns true
               if entered previously returns true
          if no password required, returns true }
    procedure Change;
      { invokes dialog for changing a password }
    property Decrypted: string write SetDecrypted;
    property Checked: boolean read FChecked write SetChecked;
    property IniFile: string read FIniFile write FIniFile;
  published
    property Encrypted: string read EncryptedGet write EncryptedSet;
    property Title: string read FTitle write FTitle;
  end;

function CheckForPassword(const ATitle: string; const ARequired: string; var AUsrSupplied: string): boolean;
  { Returns true if Required = AUsrSuplied, if not asks user for entering
    of password, returns false if Required value not entered. Both
    are decrypted strings. }
{/v0.50}

function EncryptPassword(s:string):string;

implementation

{v0.50}{/v0.50
type
  TPasswordString = string[20];}
const
  EncryptedPassword : TPasswordString = '';
  PasswordEntered: boolean = false;

function EncryptPassword(s:string):string;
var
  e:{v0.50}shortstring{/v0.50 string};
  k:string[20];
  {v0.50}
  s1:shortstring;
  {/v0.50}
begin
  {v0.50}
  s1 := s;
  {/v0.50}
  e := s;
  k := 'a;ls493ru';
  {desu}EncryptBuffer(s1[1], e[1], length(s1), k[1], length(k));
  EncryptPassword := e;
end;

function PasswordCheck: boolean;
var s: string;
begin
  Result := false;
  if EncryptedPassword = '' then begin
    PasswordEntered := true;
    Result := true;
    exit;
  end;
  if not PasswordEntered then begin
    repeat
      if not EnterPassword('', s) then
        exit;
    until EncryptPassword(s) = EncryptedPassword;
    PasswordEntered := true;
  end;
  Result := true;
end;

procedure PasswordChange;
var
  s, s1: string;
begin
  if not PasswordCheck then
    exit;
  repeat
    if not EnterPassword(GetTxt({#}'Enter new password'), s) then
      exit; {'Zadejte nové heslo'}
    if not EnterPassword(GetTxt({#}'Enter new password again'), s1) then
      exit; {'Zadejte podruhé nové heslo'}
    if s <> s1 then begin
      ShowMessage(GetTxt({#}'Error, enter new password again'), smError, 0);
         {Chyba, zadejte znovu nové heslo'}
    end else begin
      ShowMessage(GetTxt({#}'Password was changed'), smInfo, 0);
        {'Heslo bylo změněno.'}
      break;
    end;
  until false;
  EncryptedPassword := EncryptPassword(s);
end;

procedure EncryptedPasswordSet(const APassword: string);
  { use to set value from e.g. ini file }
begin
  EncryptedPassword := APassword;
end;

function EncryptedPasswordGet: string;
  { use to get value for storing in ini file }
begin
  Result := EncryptedPassword;
end;

{procedure PasswordSet(const APassword: string);
begin
  EncryptedPassword := EncryptPassword(APassword);
end;}

{v0.50}
constructor TPassword.Create(Owner: TComponent);
begin
  inherited;
end;

procedure TPassword.CheckIniLoaded;
begin
  if FIniLoaded then
    exit;
  ClassReadWriteIniFile(Self, 0, IniFile, true);
  FIniLoaded := true;
end;

destructor TPassword.Destroy;
begin
  if FIniLoaded then
    ClassReadWriteIniFile(Self, 0, IniFile, false);
  inherited;
end;

function TPassword.Check: boolean;
  { Checks if password requiered:
      if yes (i.e. some nonempty password was:
         - set by assigning to Encrypted, or Decrypted
           property
         - read from inifile (Encrypted)
         - set using interactive Change method )
         checks if already entered,
           if not entered yet prompts for it,
           if not entered correctly returns false
           if entered correctly returns true
           if entered previously returns true
      if no password required, returns true }
var
  s:string;
begin
  Result := false;
  CheckIniLoaded;
  if FEncryptedPassword = '' then begin
    FChecked := true;
    Result := true;
    exit;
  end;
  if not FChecked then begin
    repeat
      if not EnterPassword(Title, s) then
        exit;
    until EncryptPassword(s) = FEncryptedPassword;
    FChecked := true;
  end;
  Result := true;
end;

procedure TPassword.Change;
var
  s, s1: string;
begin
  if not Check then
    exit;
  repeat
    if not EnterPassword(GetTxt({#}'Enter new password'), s) then
      exit; {'Zadejte nové heslo'}
    if not EnterPassword(GetTxt({#}'Enter new password again'), s1) then
      exit; {'Zadejte podruhé nové heslo'}
    if s <> s1 then begin
      ShowMessage(GetTxt({#}'Error, enter new password again'), smError, 0);
         {Chyba, zadejte znovu nové heslo'}
    end else begin
      ShowMessage(GetTxt({#}'Password was changed'), smInfo, 0);
        {'Heslo bylo změněno.'}
      break;
    end;
  until false;
  FEncryptedPassword := EncryptPassword(s);
end;
                  
procedure TPassword.EncryptedSet(const APassword: string);
  { use to set value from e.g. from other ini file }
begin
  FEncryptedPassword := APassword;
end;

function TPassword.EncryptedGet: string;
  { use to get value for stored in ini file }
begin
  CheckIniLoaded;
  Result := FEncryptedPassword;
end;

procedure TPassword.SetDecrypted(const APassword: string);
begin
  CheckIniLoaded;
  Encrypted := EncryptPassword(APassword)
end;

procedure TPassword.SetChecked(OnOff: boolean);
begin
  FChecked := OnOff;
end;

function CheckForPassword(const ATitle: string; const ARequired: string; var AUsrSupplied: string): boolean;
var p: TPassword;
begin
  Result := (ARequired = AUsrSupplied);
  if not Result then begin
    p := TPassword.Create(nil);{pswdu}
    try
      p.Decrypted := ARequired;
      if ATitle = '' then
        p.Title := GetTxt({#}'Enter password')
      else
        p.Title := ATitle;
      Result := p.Check;
      if Result then
        AUsrSupplied := ARequired;
    finally
      p.Free;
    end;
  end;
end;
{/v0.50}

begin
{  AddGlobalVar('[Security]','EncryptedPassword',@EncryptedPassword, ptString, sizeof(EncryptedPassword));}
end.
