-- Copyright (C) 1982, 1984 by Xerox Corporation. All rights reserved. -- Readmail.mesa, Transport Mechanism Mail Server - client reading mail -- -- HGM, 18-Nov-84 0:35:59 -- Andrew Birrell 25-Oct-82 10:53:32 -- DIRECTORY BodyDefs USING [maxRNameLength, Password, RName], LogDefs USING [ShowLine], MailboxDefs USING [ Close, DeleteMessage, FlushAndClose, InaccessibleArchive, MBXHandle, NextMessage, Open, ReadTOC, SendBody, WriteTOC], NameInfoDefs USING [AuthenticateInfo, AuthenticateKey], PolicyDefs USING [CheckOperation, EndOperation], ProtocolDefs USING [ Failed, Handle, mailServerOutputSocket, maxRemarkLength, MSOperation, ReceiveMSOperation, ReceivePassword, ReceiveRemark, ReceiveRName, Remark, SendAck, SendBoolean, SendByte, SendCount, SendNow, SendRemark], PupStream USING [ CreatePupByteStreamListener, PupAddress, RejectThisRequest, SecondsToTocks], RestartDefs USING [] --EXPORT only-- , String USING [AppendNumber, AppendString, EquivalentSubStrings, SubStringDescriptor]; ReadMail: PROGRAM IMPORTS LogDefs, MailboxDefs, NameInfoDefs, PolicyDefs, ProtocolDefs, PupStream, String EXPORTS RestartDefs --PROGRAM-- = BEGIN EndsWith: PROC [s: STRING, b: STRING] RETURNS [BOOLEAN] = BEGIN pattern: String.SubStringDescriptor ← [b, 0, b.length]; target: String.SubStringDescriptor ← [s, s.length - b.length, b.length]; RETURN[ s.length >= b.length AND String.EquivalentSubStrings[@pattern, @target]] END; Receive: PROCEDURE [str: ProtocolDefs.Handle, where: PupStream.PupAddress] = BEGIN OPEN ProtocolDefs; client: BodyDefs.RName = [BodyDefs.maxRNameLength]; state: {closed, open, inMessage} ← closed; mbx: MailboxDefs.MBXHandle; found: BOOLEAN ← FALSE; Open: PROC = BEGIN count: CARDINAL; [found, count, mbx] ← MailboxDefs.Open[client]; IF found THEN state ← open; ProtocolDefs.SendCount[str, IF found THEN count ELSE 0]; END; DO ENABLE ProtocolDefs.Failed, MailboxDefs.InaccessibleArchive => EXIT; op: ProtocolDefs.MSOperation; op ← ProtocolDefs.ReceiveMSOperation[ str ! ProtocolDefs.Failed => IF why = noData AND EndsWith[client, ".gv"] THEN RETRY -- i.e. if caller is an R-Server -- ]; SELECT op FROM openMBX => BEGIN key: BodyDefs.Password; info: NameInfoDefs.AuthenticateInfo; ProtocolDefs.ReceiveRName[str, client]; key ← ProtocolDefs.ReceivePassword[str, [0, 0, 0, 0]]; IF state # closed THEN EXIT; info ← NameInfoDefs.AuthenticateKey[client, key]; ProtocolDefs.SendByte[str, LOOPHOLE[info]]; IF info = individual THEN Open[]; END; nextMessage => BEGIN msgExists, archived, deleted: BOOLEAN; IF state = inMessage THEN state ← open; -- pretend that not found means empty mailbox -- IF found THEN IF state # open THEN EXIT ELSE BEGIN [msgExists, archived, deleted] ← MailboxDefs.NextMessage[mbx]; state ← IF deleted THEN open ELSE inMessage; END ELSE msgExists ← archived ← deleted ← FALSE; ProtocolDefs.SendBoolean[str, msgExists]; ProtocolDefs.SendBoolean[str, archived]; ProtocolDefs.SendBoolean[str, deleted]; END; readTOC => BEGIN remark: ProtocolDefs.Remark = [ProtocolDefs.maxRemarkLength]; IF state # inMessage THEN EXIT; MailboxDefs.ReadTOC[mbx, remark]; ProtocolDefs.SendRemark[str, remark]; END; readMessage => BEGIN IF state # inMessage THEN EXIT; MailboxDefs.SendBody[mbx, str]; END; writeTOC => BEGIN remark: ProtocolDefs.Remark = [ProtocolDefs.maxRemarkLength]; ProtocolDefs.ReceiveRemark[str, remark]; IF state # inMessage THEN EXIT; MailboxDefs.WriteTOC[mbx, remark]; ProtocolDefs.SendAck[str]; END; deleteMessage => BEGIN IF state # inMessage THEN EXIT; MailboxDefs.DeleteMessage[mbx]; ProtocolDefs.SendAck[str]; END; flushMBX => BEGIN IF found THEN BEGIN IF state = closed THEN EXIT; MailboxDefs.FlushAndClose[mbx]; state ← closed; END ELSE NULL; ProtocolDefs.SendAck[str]; END; ENDCASE => EXIT; ProtocolDefs.SendNow[str]; ENDLOOP; IF state # closed THEN MailboxDefs.Close[mbx]; str.delete[str]; PolicyDefs.EndOperation[readMail]; END; ReadMailFilter: PROCEDURE [from: PupStream.PupAddress] = BEGIN IF NOT PolicyDefs.CheckOperation[readMail] THEN BEGIN s: STRING = [100]; String.AppendString[s, "Rejected ReadMail connection from "L]; String.AppendNumber[s, from.net, 8]; String.AppendString[s, "#"L]; String.AppendNumber[s, from.host, 8]; String.AppendString[s, "#"L]; LogDefs.ShowLine[s]; ERROR PupStream.RejectThisRequest["Server full"L]; END END; [] ← PupStream.CreatePupByteStreamListener[ ProtocolDefs.mailServerOutputSocket, Receive, PupStream.SecondsToTocks[120], ReadMailFilter]; END.