DIRECTORY IO, IOTioga, MailBasics, MailBasicsItemTypes, MailBasicsMoreItemTypes, MailMessage, MailRetrieve, MailUtils, NodeProps, Rope, TextEdit, Tioga, TiogaAccess, TiogaIO, UserProfile USING [Boolean]; MailRetrieveOneImpl: CEDAR MONITOR IMPORTS IO, IOTioga, MailRetrieve, MailUtils, NodeProps, Rope, TextEdit, TiogaAccess, TiogaIO, UserProfile EXPORTS MailMessage ~ BEGIN STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; ReadOneMessageX: PUBLIC PROC [handle: MailRetrieve.Handle, timeStamp: MailBasics.Timestamp, sender: ROPE, stream: IO.STREAM ¬ NIL] RETURNS [m, formatting: ROPE ¬ NIL, bodyLength, formatLen, formatPos: INT ¬ 0] ~ { [m, formatting, bodyLength, formatLen, formatPos] ¬ DoReadOne[FALSE, handle, timeStamp, sender, stream] }; ReadOneMessage: PUBLIC PROC [handle: MailRetrieve.Handle, timeStamp: MailBasics.Timestamp, sender: ROPE, stream: IO.STREAM ¬ NIL] RETURNS [m, formatting: ROPE ¬ NIL, bodyLength, formatLen, formatPos: INT ¬ 0] ~ { [m, formatting, bodyLength, formatLen, formatPos] ¬ DoReadOne[TRUE, handle, timeStamp, sender, stream] }; DoReadOne: PROC [deleteLeadingCR: BOOL, handle: MailRetrieve.Handle, timeStamp: MailBasics.Timestamp, sender: ROPE, stream: IO.STREAM ¬ NIL] RETURNS [m, formatting: ROPE ¬ NIL, bodyLength, formatLen, formatPos: INT ¬ 0] ~ { ENABLE MailRetrieve.Failed => { GOTO failed }; header, plainText, formattedHeader, bodies: ROPE ¬ NIL; sysMessage, attachments, unknowns: ROPE ¬ NIL; buttonRope: ROPE ¬ NIL; buttonType: MailBasics.ItemType; MakeButton: PROC[type: MailBasics.ItemType] ~ { IF UserProfile.Boolean["MailUser.MakeButtonForSerializedFile", FALSE] THEN { buttonRope _ MailRetrieve.GetItemAsRope[handle]; buttonType _ type } ELSE bodies _ bodies.Concat[MailRetrieve.GetItemAsRope[handle] ]; }; DO item: MailBasics.ItemHeader ~ MailRetrieve.NextItem[handle]; SELECT item.type FROM MailBasicsItemTypes.envelope => { NULL; }; MailBasicsItemTypes.header => header ¬ MailRetrieve.GetItemAsRope[handle]; MailBasicsItemTypes.plainTextForFormatting => plainText ¬ MailRetrieve.GetItemAsRope[handle]; MailBasicsItemTypes.formattedHeader => formattedHeader ¬ MailRetrieve.GetItemAsRope[handle]; MailBasicsItemTypes.systemMessage => sysMessage ¬ sysMessage.Concat[MailRetrieve.GetItemAsRope[handle] ]; MailBasicsItemTypes.ia5Note, MailBasicsItemTypes.text, MailBasicsItemTypes.multinationalNote => bodies ¬ bodies.Concat[MailRetrieve.GetItemAsRope[handle] ]; MailBasicsMoreItemTypes.hasAttachment => MakeButton[item.type]; MailBasicsItemTypes.fullFormatting => formatting ¬ formatting.Concat[MailRetrieve.GetItemAsRope[handle] ]; MailBasicsItemTypes.tioga1 => formatting ¬ formatting.Concat[MailRetrieve.GetItemAsRope[handle] ]; MailBasicsItemTypes.gGW => { NULL }; MailBasicsItemTypes.lastItem => { EXIT }; ENDCASE => unknowns ¬ unknowns.Concat[IO.PutFR["\r\r==>Discarded ItemType: %g (length %g bytes)<==\r", [rope[MailUtils.RopeFromItemType[item.type]]], [integer[item.length]] ] ]; ENDLOOP; { next: ROPE; IF formatting # NIL THEN unknowns ¬ NIL; SELECT TRUE FROM attachments # NIL => { next ¬ attachments; attachments ¬ NIL }; unknowns # NIL => { next ¬ unknowns; unknowns ¬ NIL }; ENDCASE => { next ¬ bodies; bodies ¬ NIL }; SELECT TRUE FROM sysMessage # NIL => { foo: ROPE ¬ IO.PutFR["Date: %g\rSender: %g\r", [time[MailUtils.GetTimeFromPostmark[timeStamp]]], [rope[sender]] ]; pos: INT ¬ sysMessage.Find["Report-Type: DL name:"]; dlOK: BOOL ¬ FALSE; IF pos # -1 THEN { pos2: INT ¬ sysMessage.Find[" (", pos]; IF pos2 # -1 THEN { foo ¬ foo.Cat["Subject: Report for dl: ", sysMessage.Substr[pos, pos2-pos+1], "\r"]; dlOK ¬ TRUE; }; }; IF NOT dlOK THEN foo ¬ foo.Concat["Subject: Delivery / Non-Delivery Report information\r"]; foo ¬ foo.Cat[sysMessage, "\r"]; IF stream # NIL THEN stream.PutRope[foo] ELSE m ¬ foo.Cat[sysMessage, "\r"]; bodyLength ¬ foo.Length[]; IF header # NIL THEN header ¬ IO.PutFR1["---------- Original-Header:\r%g\r----------\r", [rope[header]] ]; bodies ¬ header.Concat[bodies]; formatting ¬ NIL; -- won't be correct so toss }; plainText # NIL => { -- don't want headers in this case ch: CHAR ~ plainText.Fetch[0]; IF deleteLeadingCR THEN IF ( ch = '\r ) OR ( ch = '\l ) THEN plainText ¬ plainText.Substr[1]; -- tioga stuff IF stream # NIL THEN stream.PutRope[plainText] ELSE m ¬ plainText; bodyLength ¬ plainText.Length[]; next ¬ NIL; -- kill multinationalnote part of message }; ENDCASE => { hL: INT = header.Length[]; numCRs: INT ¬ 0; IF header # NIL THEN { IF header.Fetch[hL-2] = '\r THEN numCRs ¬ numCRs + 1; IF header.Fetch[hL-1] = '\r THEN numCRs ¬ numCRs + 1; IF ( next # NIL ) AND ( next.Fetch[0] = '\r ) THEN numCRs ¬ numCRs + 1; IF numCRs < 2 THEN header ¬ header.Concat["\r"]; IF stream # NIL THEN stream.PutRope[header] ELSE m ¬ header; bodyLength ¬ header.Length[]; }; }; IF stream # NIL THEN stream.PutRope[next] ELSE m ¬ m.Concat[next]; bodyLength ¬ bodyLength + next.Length[]; IF attachments # NIL THEN { IF stream # NIL THEN stream.PutRope[attachments] ELSE m ¬ m.Concat[attachments]; bodyLength ¬ bodyLength + attachments.Length[]; }; IF unknowns # NIL THEN { IF stream # NIL THEN stream.PutRope[unknowns] ELSE m ¬ m.Concat[unknowns]; bodyLength ¬ bodyLength + unknowns.Length[]; }; IF bodies # NIL THEN { IF stream # NIL THEN stream.PutRope[bodies] ELSE m ¬ m.Concat[bodies]; bodyLength ¬ bodyLength + bodies.Length[]; }; }; IF buttonRope # NIL THEN { props: IOTioga.PropList; out: STREAM; reader: TiogaAccess.Reader; root: Tioga.Node; posSlash, posAfter: INT; fullRope: ROPE; cr: ROPE ~ "\r"; pair: TiogaIO.Pair; IF formatting # NIL THEN ERROR MailRetrieve.Failed[$malformedMsg, "a message has both a buttonRope and formatting"]; out _ IOTioga.CreateTiogaAccessStream[]; out.PutRope[m]; posSlash _ Rope.Find[buttonRope, "/"]; posAfter _ Rope.Find[buttonRope, "(", posSlash]; out.PutRope[buttonRope.Substr[0, posSlash]]; props _ IOTioga.PropPut[NIL, $Postfix, thePostfixValue]; props _ IOTioga.PropPut[props, $ButtonData, theButtonDataValue]; IOTioga.SetCharProps[out, props]; out.PutRope[Rope.Substr[buttonRope, posSlash, posAfter-posSlash-1]]; IOTioga.SetCharProps[out, NIL]; out.PutRope[Rope.Substr[buttonRope, posAfter-1]]; root _ TiogaAccess.WriteNode[IOTioga.WriterFromStream[out]]; TextEdit.PutProp[node: root, name: $NewlineDelimiter, value: cr]; pair ¬ TiogaIO.ToPair[root]; m ¬ pair.contents; formatting ¬ pair.formatting; }; IF stream # NIL THEN { stream.PutRope[m]; bodyLength ¬ bodyLength + m.Length[]; }; IF ( formatting # NIL ) AND ( stream # NIL ) THEN { formatPos ¬ stream.GetIndex[]; stream.PutRope[formatting]; formatLen ¬ formatting.Length[] }; IF stream # NIL THEN stream.PutChar['\r]; RETURN; EXITS failed => RETURN[NIL, NIL, -1, -1, -1]; }; theButtonDataRope: ROPE ~ "Poppy1 Class: PopUpButton MessageHandler: CommandTool Menu: ( ( \" \" > > \"Display ViewPoint Document\" \"Execute CVV.command\") ( > \"Deserialize\" \"Deserialize file\") ( \"\\\"\">> \"Stuff filename\" \"Stuff filename at the current insertion point\") () () () ( > \"Delete\" \"Delete file\") ) Feedback: ( (MouseMoved ) )"; theButtonDataValue: REF ~ NodeProps.DoSpecs[$ButtonData, theButtonDataRope]; thePostfixRope: ROPE ~ "1.0 outlineBoxBearoff 1.0 outlineBoxThickness"; thePostfixValue: REF ~ NodeProps.DoSpecs[$Postfix, thePostfixRope]; END. ψ MailRetrieveOneImpl.mesa Copyright Σ 1988, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Doug Terry, December 12, 1988 6:06:03 pm PST Wes Irish, December 22, 1988 6:11:51 pm PST Willie-sue, November 3, 1992 11:41 am PST Operations for retrieval of electronic mail messages. Modules register procs for particular mail services. Exported procedures MailBasicsItemTypes.pilotFile => { NULL }; MailBasicsItemTypes.tioga2 => { NULL }; MailBasicsItemTypes.walnutLog => { NULL }; MailBasicsItemTypes.capability => { NULL }; MailBasicsItemTypes.audio => { NULL }; -- we may use this someday MailBasicsItemTypes.messageComposer => { NULL }; assemble the message from its parts this is a hack so that formatting from SmallTalk will work Κ’•NewlineDelimiter –(cedarcode) style™code•Mark outsideHeaderšΟb™Kšœ ΟeœI™TKšœ)Οk™,Kšœ+™+K™)K™Kšœk™kK™—šŸ ˜ KšŸœ˜Kšœ˜Kšœ ˜ K˜K˜K˜ Kšœ ˜ K˜ K˜ K˜K˜ K˜K˜ K˜Kšœ Ÿœ ˜—K˜šΡblnœŸœŸ˜"KšŸœŸœ`˜jKšŸœ ˜KšœŸ˜K˜KšŸœŸœŸœŸœ˜KšŸœŸœŸœ˜—head™šΟnœŸœŸœHŸœ ŸœŸœŸœŸœŸœŸœ$Ÿœ ˜ΥKšœ>Ÿœ$˜gK˜K˜—š‘œŸœŸœHŸœ ŸœŸœŸœŸœŸœŸœ$Ÿœ ˜ΤKšœ>Ÿœ$˜fK˜K˜—š‘ œŸœŸœHŸœ ŸœŸœŸœŸœŸœŸœ$Ÿœ ˜ίKšŸœŸœ ˜.Kšœ,ŸœŸœ˜7Kšœ#ŸœŸœ˜.Kšœ ŸœŸœ˜Kšœ ˜ š‘ œŸœ˜/šŸœ=ŸœŸœ˜LK˜0Kšœ˜K˜KšŸœ=˜A—K˜—K˜šŸ˜K˜<šŸœ Ÿ˜˜!KšŸœ˜K˜—K˜JK˜]K˜\K˜iK˜K˜K˜eK˜?K˜jK˜bK™KšœŸœ˜$Kšœ#Ÿœ™*Kšœ Ÿœ™'Kšœ#Ÿœ™*Kšœ$Ÿœ™+KšœŸœΟc™AKšœ)Ÿœ™0˜#KšŸ˜K˜——šŸœ˜ KšœŸœ‰˜¦—KšŸœ˜—Kšœ#™#˜KšœŸœ˜ K™:KšŸœŸœŸœ Ÿœ˜(šŸœŸœŸ˜KšœŸœ(Ÿœ˜?Kšœ Ÿœ"Ÿœ˜6KšŸœŸœ˜+—K˜šŸœŸœŸ˜šœ Ÿœ˜KšœŸœŸœd˜rKšœŸœ,˜4KšœŸœŸœ˜šŸœ Ÿœ˜KšœŸœ˜'šŸœ Ÿœ˜K˜TKšœŸœ˜ K˜—K˜—KšŸœŸœŸœK˜[K˜ KšŸœ ŸœŸœŸœ˜LK˜KšŸœ ŸœŸœ ŸœJ˜jK˜Kšœ Ÿœ’˜-K˜—šœ Ÿœ’"˜7KšœŸœ˜Kš ŸœŸœŸœŸœŸœ#’˜mKšŸœ ŸœŸœŸœ˜BK˜ KšœŸœ’)˜5K˜—šŸœ˜ KšœŸœ˜KšœŸœ˜šŸœ ŸœŸœ˜KšŸœŸœ˜5KšŸœŸœ˜5KšŸœ ŸœŸœŸœ˜GKšŸœ Ÿœ˜0KšŸœ ŸœŸœŸœ ˜