-- File: PasswordTool.mesa,  Last Edit: HGM,  December 8, 1980  7:16 AM

DIRECTORY
  Storage USING [String, FreeString],
  String USING [
    AppendChar, AppendNumber, InvalidNumber, StringToOctal, SubString,
    SubStringDescriptor],

  Password USING [Check, Encrypted, Encrypt],

  CmFile USING [GetNextToken],
  FormSW USING [
    AllocateItemDescriptor, ClientItemsProcType, CommandItem, Display, newLine,
    ProcType, StringItem],
  Tool USING [Create, MakeSWsProc, MakeFormSW],
  ToolWindow USING [TransitionProcType],
  UserTerminal USING [BlinkDisplay],
  Window USING [Handle];

PasswordTool: PROGRAM
  IMPORTS Storage, String, Password, CmFile, FormSW, Tool, UserTerminal =
  BEGIN

  password, encrypted: STRING ← NIL;
  form: Window.Handle;

  Init: FormSW.ProcType =
    BEGIN
    [] ← Tool.Create[
      name: "Password Tool of December 4, 1980"L, makeSWsProc: MakeSWs,
      clientTransition: ClientTransition];
    END;

  Encrypt: FormSW.ProcType =
    BEGIN
    e: Password.Encrypted ← Password.Encrypt["Gateway"L, password];
    p: POINTER ← @e;
    encrypted.length ← 0;
    FOR i: CARDINAL IN [0..SIZE[Password.Encrypted]) DO
      IF i # 0 THEN String.AppendChar[encrypted, ' ];
      String.AppendNumber[encrypted, (p + i)↑, 8];
      ENDLOOP;
    FormSW.Display[form];
    END;

  GetOctal: PROCEDURE [ss: String.SubString] RETURNS [CARDINAL] =
    BEGIN
    token: STRING = [100];
    IF ~CmFile.GetNextToken[ss, token] THEN SIGNAL String.InvalidNumber;
    RETURN[String.StringToOctal[token]];
    END;

  Check: FormSW.ProcType =
    BEGIN
    e: Password.Encrypted;
    p: POINTER ← @e;
    ss: String.SubStringDescriptor;
    IF encrypted = NIL THEN BEGIN UserTerminal.BlinkDisplay[]; RETURN; END;
    ss ← [base: encrypted, offset: 0, length: encrypted.length];
    BEGIN
    ENABLE
      String.InvalidNumber => BEGIN UserTerminal.BlinkDisplay[]; CONTINUE; END;
    FOR i: CARDINAL IN [0..SIZE[Password.Encrypted]) DO
      (p + i)↑ ← GetOctal[@ss]; ENDLOOP;
    IF ~Password.Check[password, e] THEN UserTerminal.BlinkDisplay[];
    END;
    END;


  MakeSWs: Tool.MakeSWsProc =
    BEGIN form ← Tool.MakeFormSW[window: window, formProc: MakeForm]; END;

  MakeForm: FormSW.ClientItemsProcType =
    BEGIN
    nParams: CARDINAL = 4;
    items ← FormSW.AllocateItemDescriptor[nParams];
    items[0] ← FormSW.CommandItem[
      tag: "Encrypt"L, proc: Encrypt, place: FormSW.newLine];
    items[1] ← FormSW.CommandItem[tag: "Check"L, proc: Check];
    items[2] ← FormSW.StringItem[
      tag: "Password"L, string: @password, place: FormSW.newLine,
      feedback: password];
    items[3] ← FormSW.StringItem[
      tag: "Encrypted"L, string: @encrypted, place: FormSW.newLine];
    RETURN[items, TRUE];
    END;

  ClientTransition: ToolWindow.TransitionProcType =
    BEGIN
    SELECT TRUE FROM
      old = inactive =>
	BEGIN
	password ← Storage.String[20];
	encrypted ← Storage.String[10*8];
	END;
      new = inactive =>
	BEGIN Storage.FreeString[password]; Storage.FreeString[encrypted]; END;
      ENDCASE;
    END;

  Init[];
  END.