-- GrapevineUser (Cedar) - sending mail --

-- GVSendImpl.mesa

-- Andrew Birrell August 27, 1982 3:49 pm

DIRECTORY
BodyDefs USING[ maxRNameLength, Password, RName ],
ConvertUnsafe USING[ AppendRope, ToRope ],
GVBasics USING[ ItemType, MakeKey, Password, RName ],
GVSend USING[],
Rope USING[ Length, ROPE, Substr ],
SendDefs;

GVSendImpl: CEDAR PROGRAM
IMPORTS ConvertUnsafe, GVBasics, Rope, SendDefs
EXPORTS GVSend =

BEGIN

ROPE: TYPE = Rope.ROPE;

Handle: TYPE = REF Object;

Object: PUBLIC TYPE = RECORD[h: SendDefs.Handle];

Create: PUBLIC PROC RETURNS[handle: Handle] = TRUSTED
{ RETURN[NEW[Object ← [SendDefs.Create[]]]] };

Close: PUBLIC PROC[ handle: Handle ] = TRUSTED
{ SendDefs.Destroy[handle.h]; handle.h ← LOOPHOLE[NIL]--Sorry!-- };


SendFailed: PUBLIC ERROR [ notDelivered: BOOLEAN ] = CODE;

StartSend: PUBLIC PROC[ handle: Handle,
   senderPwd: ROPE,
   sender: GVBasics.RName,
   returnTo: GVBasics.RName ← NIL,
   validate: BOOLEAN ]
RETURNS[ SendDefs.StartSendInfo ] =
{ RETURN[SendFromClient[handle: handle, senderKey: GVBasics.MakeKey[senderPwd],
sender: sender, returnTo: returnTo, validate: validate]] };


SendFromClient: PUBLIC PROC[ handle: Handle,
   fromNet: [0..256) ← 0,
   fromHost: [0..256) ← 0,
   senderKey: GVBasics.Password,
   sender: GVBasics.RName,
   returnTo: GVBasics.RName,
   validate: BOOLEAN ]
  RETURNS[ SendDefs.StartSendInfo ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
s: BodyDefs.RName = [BodyDefs.maxRNameLength];
r: BodyDefs.RName = [BodyDefs.maxRNameLength];
IF Rope.Length[sender] > BodyDefs.maxRNameLength THEN RETURN[badSender];
IF Rope.Length[returnTo] > BodyDefs.maxRNameLength THEN RETURN[badReturnTo];
ConvertUnsafe.AppendRope[s, sender];
ConvertUnsafe.AppendRope[r, returnTo];
RETURN[SendDefs.SendFromClient[handle.h, fromNet, fromHost,
senderKey, s, IF returnTo = NIL THEN s ELSE r, validate] ]
END;


AddRecipient: PUBLIC PROC[ handle: Handle, recipient: GVBasics.RName ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
r: BodyDefs.RName = [BodyDefs.maxRNameLength];
IF Rope.Length[recipient] > BodyDefs.maxRNameLength
THEN ConvertUnsafe.AppendRope[r, "Recipient-whose-length-is-greater-than-64-characters"]
ELSE ConvertUnsafe.AppendRope[r, recipient];
SendDefs.AddRecipient[handle.h, r];
END;


CheckValidity: PUBLIC PROC[ handle: Handle,
   notify: PROCEDURE[LONG INTEGER,GVBasics.RName] ]
  RETURNS[ ok: LONG INTEGER ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
MyNotify: UNSAFE PROC[i: CARDINAL, n: BodyDefs.RName] =
{ notify[i, ConvertUnsafe.ToRope[n]] };
RETURN[ SendDefs.CheckValidity[handle.h, MyNotify] ]
END;


StartItem: PUBLIC PROC[ handle: Handle, type: GVBasics.ItemType ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
SendDefs.StartItem[handle.h, type];
END;


AddToItem: PUBLIC PROC[ handle: Handle, buffer: ROPE ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
total: INT = Rope.Length[buffer];
start: INT ← 0;
WHILE total > start
DO sLength: CARDINAL = 120; -- non-critical number; choose to ensure small frame --
s: STRING = [sLength];
ConvertUnsafe.AppendRope[s, Rope.Substr[base:buffer, start: start, len: MIN[total,sLength]]];
SendDefs.AddToItem[handle.h, DESCRIPTOR[@s.text, s.length]];
start ← start + s.length;
ENDLOOP;
END;


Send: PUBLIC PROC[ handle: Handle ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
SendDefs.Send[handle.h];
END;


Abort: PUBLIC PROC[ handle: Handle ] = TRUSTED
BEGIN
ENABLE SendDefs.SendFailed => ERROR SendFailed[notDelivered];
SendDefs.Abort[handle.h];
END;

ExpandFailed: PUBLIC ERROR = CODE;

Expand: PUBLIC UNSAFE PROC[name: GVBasics.RName, work: PROC[GVBasics.RName]]
RETURNS[ SendDefs.ExpandInfo ] = TRUSTED
BEGIN
ENABLE SendDefs.ExpandFailed => ERROR ExpandFailed[];
MyWork: PROC[m: BodyDefs.RName] = TRUSTED
{ work[ConvertUnsafe.ToRope[m]] };
n: BodyDefs.RName = [BodyDefs.maxRNameLength];
IF Rope.Length[name] > BodyDefs.maxRNameLength THEN RETURN[notFound];
ConvertUnsafe.AppendRope[n, name];
RETURN[ SendDefs.Expand[n, MyWork] ]
END;

END.