EncryptTool.mesa; User interface for DES encryption
Copyright © 1985 by Xerox Corporation. All rights reserved.
Edited by McCreight, June 2, 1983 10:44 am
Edited by: Mitchell, May 23, 1983 5:44 pm
Edited by: McGregor, June 2, 1983 3:42 pm
Edited by: McCreight, February 9, 1984 9:18 am
Swinehart, July 5, 1985 2:19:39 pm PDT
DIRECTORY
Buttons,
Containers,
Commander,
Encrypt,
FS,
IO,
Menus,
MessageWindow,
PutGet,
Rope,
TEditDocument,
TiogaExtraOps,
TiogaOps,
ViewerClasses,
ViewerOps,
ViewerTools;
EncryptTool: CEDAR PROGRAM
IMPORTS
Buttons, Commander, Containers, Encrypt, FS, IO, Menus, MessageWindow, PutGet, Rope, TiogaExtraOps, TiogaOps, ViewerOps, ViewerTools =
BEGIN
EncryptHandle: TYPE = REF EncryptToolRec;
EncryptToolRec: TYPE = RECORD [
outer: Containers.Container ← NIL,
key: Rope.ROPENIL,
keyViewer: ViewerClasses.Viewer ← NIL,
files: ViewerClasses.Viewer ← NIL
];
EncryptedText: TYPE = Rope.ROPE;
SelectKey: Buttons.ButtonProc =
BEGIN
handle: EncryptHandle = NARROW[clientData];
ViewerTools.SetContents[handle.keyViewer, handle.key];
ViewerTools.SetSelection[handle.keyViewer];
handle.keyViewer.newVersion ← TRUE; -- forces stars to return on button op
END;
SelectFiles: Buttons.ButtonProc =
BEGIN
handle: EncryptHandle = NARROW[clientData];
ViewerTools.SetSelection[handle.files];
END;
GetKey: PROC [handle: EncryptHandle] RETURNS [Rope.ROPE] =
BEGIN
IF handle.keyViewer.newVersion THEN
BEGIN
handle.key ← ViewerTools.GetContents[handle.keyViewer];
ViewerTools.SetContents[handle.keyViewer, "*****"];
handle.keyViewer.newVersion ← FALSE;
END;
RETURN[handle.key];
END;
EncryptFiles: Buttons.ButtonProc =
BEGIN
handle: EncryptHandle = NARROW[clientData];
key: Rope.ROPE = GetKey[handle];
inputs: IO.STREAM = IO.RIS[ViewerTools.GetContents[handle.files]];
sourceFile: Rope.ROPE;
sourceFile ← inputs.GetTokenRope[IO.IDProc
! IO.EndOfStream => {sourceFile ← NIL; CONTINUE}].token;
IF Rope.Length[key]=0 THEN BEGIN
MessageWindow.Append["Please enter an encryption key", TRUE];
MessageWindow.Blink[];
END
ELSE
WHILE sourceFile#NIL DO
destFile: Rope.ROPE = Rope.Concat[sourceFile, ".des"];
Encrypt.EncryptFile[plain: sourceFile, cipher: destFile, key: key !
FS.Error =>
BEGIN
MessageWindow.Append[IO.PutFR["Trouble encrypting file ""%g"" because %g. Aborting encryption.", IO.rope[sourceFile], IO.rope[error.explanation]], TRUE];
MessageWindow.Blink[];
EXIT;
END;
];
sourceFile ← inputs.GetTokenRope[IO.IDProc
! IO.EndOfStream => {sourceFile ← NIL; CONTINUE}].token;
ENDLOOP;
END;
DecryptFiles: Buttons.ButtonProc =
BEGIN
handle: EncryptHandle = NARROW[clientData];
key: Rope.ROPE = GetKey[handle];
outputs: IO.STREAM = IO.RIS[ViewerTools.GetContents[handle.files]];
destFile: Rope.ROPE;
destFile ← outputs.GetTokenRope[IO.IDProc
! IO.EndOfStream => {destFile ← NIL; CONTINUE}].token;
IF Rope.Length[key]=0 THEN BEGIN
MessageWindow.Append["Please enter an encryption key", TRUE];
MessageWindow.Blink[];
END
ELSE
WHILE destFile#NIL DO
sourceFile: Rope.ROPE = Rope.Concat[destFile, ".des"];
Encrypt.DecryptFile[plain: destFile, cipher: sourceFile, key: key !
FS.Error =>
BEGIN
MessageWindow.Append[IO.PutFR["Trouble encrypting file ""%g"" because %g. Aborting encryption.", IO.rope[sourceFile], IO.rope[error.explanation]], TRUE];
MessageWindow.Blink[];
EXIT;
END;
Encrypt.BadEncryption =>
BEGIN
MessageWindow.Append[IO.PutFR["File ""%g"" isn't properly encrypted or you gave me the wrong key.", IO.rope[destFile]], TRUE];
MessageWindow.Blink[];
EXIT;
END;
];
destFile ← outputs.GetTokenRope[IO.IDProc
! IO.EndOfStream => {destFile ← NIL; CONTINUE}].token;
ENDLOOP;
END;
EncryptSelection: Buttons.ButtonProc =
BEGIN OPEN TiogaOps;
DoEncrypt: PROC [root: TiogaOps.Ref] =
BEGIN
[start: start, end: end, viewer: viewer] ← GetSelection[];
ProcessSelection[root, start.node, end.node, EncryptBranch, key, viewer];
END;
EncryptBranch: PROC [node: TiogaOps.Ref, key: Rope.ROPE] =
BEGIN
IF GetProp[node, $EncryptedChars]=NIL THEN
TRUSTED BEGIN
doNext: BOOL;
cipher: Rope.ROPE;
TiogaOps.SetSelection[viewer, [node, 0], [node, 0], point, TRUE, TRUE];
point selection at start of branch to be encrypted
doNext ← Rope.Size[TiogaOps.GetRope[TiogaOps.GetCaret[].node]] # 0;
TiogaOps.Break[]; -- insert a fake root node in front of the branch
node ← TiogaOps.GetCaret[].node;
IF doNext THEN node ← TiogaOps.Next[node];
TiogaOps.SelectBranches[viewer, node, node, node, TRUE, TRUE]; -- select the branch
TiogaOps.Nest[]; -- nest it under the extra node
node ← TiogaOps.Parent[TiogaOps.GetCaret[].node]; -- get the extra node again
cipher ← Encrypt.EncryptRope[plain: PutGet.ToRope[LOOPHOLE[node]].output, key: key];
TiogaOps.SelectBranches[viewer, node, node, node, TRUE, TRUE];
select the whole thing pending delete
TiogaOps.SetLooks["is", caret];
TiogaOps.InsertRope["...encrypted..."];
PutProp[n: TiogaOps.GetCaret[].node, name: $EncryptedChars, value: cipher];
END
ELSE
BEGIN OPEN MessageWindow;
Append["Node already encrypted", TRUE];
Blink[];
END;
END;
start, end: Location;
viewer: ViewerClasses.Viewer;
handle: EncryptHandle = NARROW[clientData];
key: Rope.ROPE = GetKey[handle];
IF Rope.Length[key]=0 THEN BEGIN
MessageWindow.Append["Please enter an encryption key", TRUE];
MessageWindow.Blink[];
END
ELSE DoTiogaOpsCallWithLocks[DoEncrypt
! TiogaOps.NoSelection => BEGIN
MessageWindow.Append["Please make a text selection", TRUE];
MessageWindow.Blink[];
CONTINUE;
END;
];
END;
DecryptSelection: Buttons.ButtonProc =
BEGIN OPEN TiogaOps;
Decrypt: PROC [root: TiogaOps.Ref] =
BEGIN
[start: start, end: end, viewer: viewer] ← GetSelection[];
ProcessSelection[root, start.node, end.node, DecryptBranch, key, viewer];
END;
DecryptBranch: PROC [node: TiogaOps.Ref, key: Rope.ROPE] =
BEGIN
chars: REF = GetProp[node, $EncryptedChars];
IF chars#NIL THEN
TRUSTED BEGIN
new: TiogaOps.Ref;
encryptedText: EncryptedText = NARROW[chars];
plain: Rope.ROPE = Encrypt.DecryptRope[cipher: encryptedText, key: key];
TiogaExtraOps.RemProp[node, $EncryptedChars];
TiogaOps.SelectNodes[viewer, node, node, node];
new ← LOOPHOLE[PutGet.FromRope[plain]];
TiogaOps.SaveSpanForPaste[[new, 0], TiogaOps.LastLocWithin[new], node];
TiogaOps.Paste[];
new ← TiogaOps.GetSelection[].start.node;
TiogaOps.SelectBranches[viewer, TiogaOps.FirstChild[new], TiogaOps.FirstChild[new], node, TRUE, TRUE];
TiogaOps.UnNest[];
TiogaOps.SelectNodes[viewer, new, new, node]; -- select the fake root node
TiogaOps.Delete[]; -- get rid of it
TiogaOps.SelectNodes[viewer, node, node, node]; -- select the "encrypted" node
TiogaOps.Delete[]; -- get rid of it
END
ELSE
BEGIN OPEN MessageWindow;
Append["Node already unencrypted", TRUE];
Blink[];
END;
END;
start, end: Location;
viewer: ViewerClasses.Viewer;
handle: EncryptHandle = NARROW[clientData];
key: Rope.ROPE = GetKey[handle];
IF Rope.Length[key]=0 THEN BEGIN
MessageWindow.Append["Please enter an encryption key", TRUE];
MessageWindow.Blink[];
RETURN;
END
ELSE DoTiogaOpsCallWithLocks[Decrypt
! TiogaOps.NoSelection => BEGIN
MessageWindow.Append["Please make a text selection", TRUE];
MessageWindow.Blink[];
CONTINUE;
END;
Encrypt.BadEncryption => BEGIN
MessageWindow.Append["It seems you gave me an incorrect key.", TRUE];
MessageWindow.Blink[];
CONTINUE;
END;
];
END;
DoTiogaOpsCallWithLocks: PROC [proc: PROC [root: TiogaOps.Ref], root: TiogaOps.Ref ← NIL] =
BEGIN
IF TiogaOps.SelectionRoot[]=NIL THEN ERROR TiogaOps.NoSelection;
Circumvents bug in Cedar 5.0, to be fixed in 5.1.
TiogaOps.CallWithLocks[proc: proc, root: root];
END;
Level: PROC [node: TiogaOps.Ref] RETURNS [level: INTEGER] = BEGIN
level ← 0;
UNTIL (node ← TiogaOps.Parent[node])=NIL DO level ← level+1; ENDLOOP;
END;
ProcessSelection: PROC [
root: TiogaOps.Ref, start, end: TiogaOps.Ref,
proc: PROC [node: TiogaOps.Ref, key: Rope.ROPE], key: Rope.ROPE,
viewer: ViewerClasses.Viewer] =
BEGIN
node, next, selectAfter, selectUntil: TiogaOps.Ref;
readOnly: BOOLFALSE;
tdd: TEditDocument.TEditDocumentData ← NARROW[viewer.data];
startLevel, endLevel: INTEGER;
startLevel ← Level[start];
endLevel ← Level[end];
IF endLevel<startLevel THEN BEGIN
MessageWindow.Append["Please select a branch", TRUE];
MessageWindow.Blink[];
RETURN;
END;
THROUGH [startLevel..endLevel) DO
end ← TiogaOps.Parent[end];
ENDLOOP;
IF TiogaOps.Parent[start]#TiogaOps.Parent[end] THEN BEGIN
MessageWindow.Append["Please select a branch", TRUE];
MessageWindow.Blink[];
RETURN;
END;
IF tdd.readOnly THEN BEGIN
readOnly ← TRUE;
ViewerTools.EnableUserEdits[viewer];
END;
node ← start;
selectAfter ← TiogaOps.StepBackward[start];
selectUntil ← TiogaOps.Next[end];
DO
next ← TiogaOps.Next[node];
proc[node, key];
IF node=end THEN EXIT;
node ← next;
ENDLOOP;
IF readOnly THEN BEGIN
ViewerTools.InhibitUserEdits[viewer];
viewer.newVersion ← FALSE;
ViewerOps.PaintViewer[viewer, caption];
END;
start ← TiogaOps.StepForward[selectAfter];
end ← start;
UNTIL TiogaOps.Next[end]=selectUntil DO end ← TiogaOps.Next[end]; ENDLOOP;
TiogaOps.SelectBranches[viewer, start, end, node]; -- restore original selection
END;
NewEncryptTool: Commander.CommandProc =
BEGIN
encryptTool: EncryptHandle = NEW[EncryptToolRec];
encryptMenu: Menus.Menu = Menus.CreateMenu[];
keyPrompt, filePrompt: Buttons.Button;
Menus.AppendMenuEntry[
menu: encryptMenu,
entry: Menus.CreateEntry[
name: "EncryptSelection", -- name of the command
proc: EncryptSelection,  -- proc associated with command
clientData: encryptTool
]
];
Menus.AppendMenuEntry[
menu: encryptMenu,
entry: Menus.CreateEntry[
name: "DecryptSelection", -- name of the command
proc: DecryptSelection,  -- proc associated with command
clientData: encryptTool
]
];
Menus.AppendMenuEntry[
menu: encryptMenu,
entry: Menus.CreateEntry[
name: "EncryptFiles",  -- name of the command
proc: EncryptFiles,   -- proc associated with command
clientData: encryptTool
]
];
Menus.AppendMenuEntry[
menu: encryptMenu,
entry: Menus.CreateEntry[
name: "DecryptFiles",  -- name of the command
proc: DecryptFiles,   -- proc associated with command
clientData: encryptTool
]
];
encryptTool.outer ← Containers.Create[[-- construct the outer container
name: "Encryption Tool", -- name displayed in the caption
iconic: TRUE,    -- so tool will be iconic (small) when first created
column: right,    -- initially in the right column
menu: encryptMenu,  -- displaying our menu command
scrollable: FALSE,   -- inhibit user from scrolling contents
openHeight: 73,
data: encryptTool ]];
keyPrompt ← Buttons.Create[
info: [
name: "Encryption key:",
wy: 0,
wh: 15,
parent: encryptTool.outer,
border: FALSE],
proc: SelectKey,
clientData: encryptTool];
encryptTool.keyViewer ← ViewerTools.MakeNewTextViewer[[
parent: encryptTool.outer,
wx: keyPrompt.wx+keyPrompt.ww+10,
wy: 1, -- to align with button baseline
ww: 10,
wh: 15,
data: "",
scrollable: FALSE,
border: FALSE]];
filePrompt ← Buttons.Create[
info: [
name: "File names:",
wy: 16,
wh: 15,
parent: encryptTool.outer,
border: FALSE],
proc: SelectFiles,
clientData: encryptTool];
encryptTool.files ← ViewerTools.MakeNewTextViewer[[
parent: encryptTool.outer,
wx: filePrompt.wx+filePrompt.ww+10,
wy: 17, -- to align with button baseline
ww: 10,
wh: 30,
data: "",
scrollable: TRUE,
border: FALSE]];
Containers.ChildXBound[encryptTool.outer, encryptTool.keyViewer];
Containers.ChildXBound[encryptTool.outer, encryptTool.files];
Containers.ChildYBound[encryptTool.outer, encryptTool.files];
END;
Commander.Register[key: "EncryptTool", proc: NewEncryptTool, doc: "A user interface for U. S. Federal Data Encryption Standard encryption/decryption."];
END.