EncryptHandle: TYPE = REF EncryptToolRec;
EncryptToolRec:
TYPE =
RECORD [
outer: Containers.Container ← NIL,
key: Rope.ROPE ← NIL,
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 ← inputs.GetToken[
IO.IDProc
! IO.EndOfStream => sourceFile ← NIL];
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"];
EncryptFile[plain: sourceFile, cipher: destFile, key: key];
sourceFile ← inputs.GetToken[
IO.IDProc
! IO.EndOfStream => sourceFile ← NIL];
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 ← outputs.GetToken[
IO.IDProc
! IO.EndOfStream => destFile ← NIL];
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"];
DecryptFile[plain: destFile, cipher: sourceFile, key: key
! BadEncryption =>
BEGIN OPEN MessageWindow;
Append["File """, TRUE];
Append[sourceFile, FALSE];
Append[""" does not have the form of a DES encrypted file.", FALSE];
Blink[];
CONTINUE;
END;
];
destFile ← outputs.GetToken[
IO.IDProc
! IO.EndOfStream => destFile ← NIL];
ENDLOOP;
END;
EncryptSelection: Buttons.ButtonProc =
BEGIN OPEN TiogaOps;
Encrypt:
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 ← 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 TiogaOps.CallWithLocks[Encrypt
! 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 = 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 TiogaOps.CallWithLocks[Decrypt
! TiogaOps.NoSelection =>
BEGIN
MessageWindow.Append["Please make a text selection", TRUE];
MessageWindow.Blink[];
CONTINUE;
END;
];
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: BOOL ← FALSE;
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;
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];