home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / 4415 / MAIL.SWG < prev    next >
Text File  |  1993-10-07  |  69KB  |  1 lines

  1. SWAGOLX.EXE (c) 1993 GDSOFT  ALL RIGHTS RESERVED 00007         MAIL/QWK/HUDSON FILE ROUTINES                                     1      05-28-9313:50ALL                      SWAG SUPPORT TEAM        MAILMSGR.PAS             IMPORT              17          {πAfter lots of controversy, and a lot of reteaching myself the meanings ofπa few Words, I've redone my *.MSG reader....π}ππConst MSGPRIVATE  = $0001;πConst MSGConst    = $0002;πConst MSGREAD     = $0004;πConst MSGSENT     = $0008;πConst MSGFile     = $0010;πConst MSGFWD      = $0020;πConst MSGorPHAN   = $0040;πConst MSGKILL     = $0080;πConst MSGLOCAL    = $0100;πConst MSGHOLD     = $0200;πConst MSGCRAP     = $0400;πConst MSGFRQ      = $0800;πConst MSGRRQ      = $1000;πConst MSGCPT      = $2000;πConst MSGARQ      = $4000;πConst MSGURQ      = $8000;ππTypeπ     Fido_FromType    = Array [1..35] of Char;π     Fido_toType      = Array [1..35] of Char;π     Fido_SubType     = Array [1..71] of Char;π     Fido_DateType    = Array [1..19] of Char;ππ     FidoMsgType = Recordπ      From         : Fido_FromType; (* 0   *)π      toWhom       : Fido_toType;   (* 35  *)π      Subject      : Fido_SubType;  (* 71  *)π      AZDate       : Fido_DateType; (* 142 *)π      TimesRead    : Word;          (* 162 *)π      Dest_Node    : Word;          (* 164 *)π      orig_Node    : Word;          (* 166 *)π      Cost         : Word;          (* 168 *)π      orig_Net     : Word;          (* 170 *)π      Dest_Net     : Word;          (* 172 *)π      Date_Written : LongInt;       (* 176 *)π      Date_Arrived : LongInt;       (* 180 *)π      Reply        : Word;          (* 184 *)π      Attr         : Word;          (* 186 *)π      Up           : Word;          (* 188 *)π     end;ππ   MsgTxtPtr  = ^MsgTxtType;π   MsgTxtType = Array [1..65535] of Char;ππVarπ  MessageFile : File;π  Msg         : FidoMsgType;π  MsgTxt      : MsgTxtPtr;ππProcedure ReadMessage(Fname : PathStr);πVarπ  Left : Word;πbeginπ  Assign(MessageFile,FName);π  Reset(MessageFile,1);π  BlockRead(MessageFile,Msg,190);π  Left:=FileSize(MessageFile) - 190;π  New(MsgTxt);π  BlockRead(MessageFile,MsgTxt^,Left);πend;π{πThis will correctly read in a *.MSG File in two parts..THe Header(stored inπMsg), and the Text which is a 64k buffer(stored in Pointer MsgTxt)...π}π                 2      05-28-9313:50ALL                      SWAG SUPPORT TEAM        MSG-FIDO.PAS             IMPORT              63          {π>Could someone post the structures For a QWK mail packet, and couldπ>someone, post how to make a BBS Fido-Net compatible, in other Words theπ>File structures..Thanks in advance..π}ππ{$V-}ππProgram ReadQWKRepFile;ππUsesπ  Crt;ππConstπ  Seperator = '---------------------------------------------------------------------------';ππTypeπ  ConfType = ^Conference;π  Conference = Recordπ    Number : Byte;π    Name   : Array [1..10] of Char;π  end;π  CONDATHdr = Recordπ    BBSName  : Array [1..25] of Char;π    Location : Array [1..25] of Char;π    Number   : Array [1..12] of Char;π    SysopName: Array [1..25] of Char;π    SerialNum: Array [1..5] of Char;π    BBSID    : Array [1..8] of Char;π    Date     : Array [1..10] of Char;π    Time     : Array [1..8] of Char;π    UserName : Array [1..25] of Char;π    NumConfs : Byte;π    Confs    : Array [1..30] of ConfType;π  end;π  MSGDATHdr = Recordπ    Status   : Char;π    MSGNum   : Array [1..7] of Char;π    Date     : Array [1..8] of Char;π    Time     : Array [1..5] of Char;π    UpTO     : Array [1..25] of Char;π    UpFROM   : Array [1..25] of Char;π    Subject  : Array [1..25] of Char;π    PassWord : Array [1..12] of Char;π    ReferNum : Array [1..8] of Char;π    NumChunk : Array [1..6] of Char;π    Alive    : Byte;π    LeastSig : Byte;π    MostSig  : Byte;π    Reserved : Array [1..3] of Char;π  end;π  MSSingle = Array[0..3] of Byte;ππVarπ  F           : File;π  DefSaveFile : String;π  ConfNum     : String [8];π  Number      : Word;ππππFunction Valu2 (S : String) : Word;πVarπ  C  : Word;π  E  : Integer;πbeginπ  Val (S, C, E);π  If E = 0 thenπ    Valu2 := Cπ  elseπ    Valu2 := 0;πend;ππProcedure ParseCommandLine;πVarπ  I : Byte;π  C : Char;π  S : String;πbeginπ  For I := 1 to ParamCount doπ  beginπ    S := ParamStr (I);π    If S [1] = '/' thenπ    beginπ      C := UpCase (S [2]);π      Delete (S, 1, 2);π      Case C ofπ        'C' : ConfNum := S;π        'S' :π              beginπ                While Length (S) <> 3 doπ                  S := '0' + S;π                DefSaveFile := S;π              end;ππ        'N' : Number := Valu2 (S);π      end;π    end;π  end;πend;πππFunction MStoIEEE (MS : MSSingle) : Real;π{ Converts a 4 Byte Microsoft format single precision Real Variable asπ  used in earlier versions of QuickBASIC and GW-BASIC to IEEE 6 Byte Real }πVarπ  r      : Real;π  ieee   : Array[0..5] of Byte Absolute r;πbeginπ  FillChar(r,sizeof(r),0);π  ieee[0] := MS[3];π  ieee[3] := MS[0];π  ieee[4] := MS[1];π  ieee[5] := MS[2];π  MStoIEEE  := r;πend;  { MStoIEEE }ππFunction Valu (S : String) : LongInt;πVarπ  C     : LongInt;π  T, E  : Integer;π  I     : Byte;π  Place : LongInt;πbeginπ  Place := 1;π  C := 0;π  For I := 6 downto 1 doπ  beginπ    Val (S [I], T, E);π    If T <> 0 thenπ    beginπ      C := C + T * Place;π      Place := Place * 10;π    end;π  end;π  Valu := C - 1;πend;ππProcedure ReadMSG (NumChunks : LongInt);πVarπ  Buff : Array [1..128] of Char;π  J    : LongInt;π  I    : Byte;ππbeginπ  For J := 1 to NumChunks doπ  beginπ    BlockRead (F, Buff, 128);π    For I := 1 to 128 doπ      If Buff [I] = #$E3 thenπ        Writelnπ      elseπ        Write (Buff [I]);π  end;πend;ππProcedure ReadWriteHdr (Var HDR : MSGDatHdr);πbeginπ  BlockRead (F, Hdr, SizeOf (Hdr));π  With Hdr doπ  beginπ    Write ('Date: ', Date, ' (', Time, ')');π    Writeln ('' : 23, 'Number: ', MSGNum);π    Write ('From: ', UpFROM);π    Writeln ('' : 14, 'Refer#: ', ReferNum);π    Write ('  To: ', UpTO);π    Write ('' : 15, 'Recvd: ');π    If Status in ['-', '`', '^', '#'] thenπ      Writeln ('YES')π    elseπ      Writeln ('NO');π    Write ('Subj: ', Subject);π    Writeln ('' : 16, 'Conf: ', '(', LeastSig, ')');π    Writeln;π  end;πend;ππProcedure ReadMessage (HDR : MSGDatHdr; REPorDAT : Boolean);πbeginπ  ReadWriteHdr (HDR);π  ReadMsg (Valu (HDR.NumChunk));πend;ππProcedure ReadControlFile (Var Control : CONDatHdr);πVarπ  CFile    : Text;ππ  Procedure ReadToEOLN (Var FNAME; Length : Byte; Down : Boolean);π  Varπ    I : Byte;π    C : Char;π  beginπ    I := 0;π    Repeatπ      Read (CFile, C);π      Mem [Seg (FNAME) : Ofs (FNAME) + I] := Ord (C);π      Inc (I);π    Until EOLN (CFile) or (I > Length) or (Not Down and (C = ','));π    If Not Down thenπ      Dec (I);π    For I := I to Length doπ      Mem [Seg (FNAME) : Ofs (FNAME) + I] :=32;π    If Down thenπ      Readln (CFile);π  end;ππVarπ  TempChar : Char;π  S        : String;π  I        : Byte;πbeginπ  Assign (CFile, 'CONTROL.DAT');π  Reset (CFile);π  With Control doπ  beginπ    ReadToEOLN (BBSName, 25, True);π    ReadToEOLN (Location, 25, True);π    ReadToEOLN (Number, 12, True);π    ReadToEOLN (SysopName, 25, False);π    Readln (CFile);π    ReadToEOLN (SerialNum, 5, False);π    ReadToEOLN (BBSID, 8, True);π    ReadToEOLN (Date, 10, False);π    ReadToEOLN (Time, 8, True);π    ReadToEOLN (UserName, 25, True);π    For I := 1 to 4 doπ      Readln (CFile, S);π    NumConfs := Valu (S) + 1;π    For I := 1 to NumConfs doπ    beginπ      New (Confs [I]);π      Readln (CFile, S);π      Confs [I]^.Number := Valu2 (S);π      ReadToEOLN (Confs [I]^.Name, 10, True);π    end;π  end;π  Close (CFile);πend;ππFunction GetSaveFile : String;πVarπ  S : String;πbeginπ  Writeln ('Enter the name of the File to save it in (GIVE A DIRECTORY!) or [Return] for');π  Writeln ('C:\SLMR\SAVE.TXT');π  Readln (S);π  If S = '' thenπ    S := 'C:\SLMR\SAVE.TXT';π  GetSaveFile := S;πend;ππFunction GetYN (S : String) : Boolean;πVarπ  X  : Char;πbeginπ  Repeatπ    Write (S);π    X := UpCase (ReadKey);π    Writeln (X);π  Until X in ['Y', 'N'];π  GetYN := X = 'Y';πend;ππProcedure ScanMessages (REPorDAT : Boolean);πVarπ    HDR : MSGDatHdr;π    S  : String [3];π    I  : Byte;π    F2 : File;π    MS : MSSingle;π    YN  : Boolean;πbeginπ  ClrScr;π  Repeatπ    If ConfNum = '' thenπ    beginπ      Writeln;π      Write ('Enter the name/number For the conference : ');π      Readln (ConfNum);π      Writeln;π    end;π    While (Length (ConfNum) < 3) doπ      ConfNum := '0' + ConfNum;π    Writeln (ConfNum);π    Assign (F2, ConfNum + '.NDX');π    {$I-}π    Reset (F2, 1);π    {$I+}π    If IOResult <> 0 thenπ      RunError (2);ππ    Repeatπ      Repeatππ        Writeln;π        If Number = 0 thenπ        beginπ          Writeln ('Enter the SLMR number ( ??? / XXX ) of the message to pull, or 0 to quit : ');π          Readln (Number);π        end;π        If Number = 0 thenπ        beginπ          Close (F2);π          Close (F);π          Halt;π        end;ππ        Writeln;π        Seek (F2, (Number - 1) * 5);π        BlockRead (F2, MS, 4);ππ        Seek (F, Round (MStoIEEE (MS) - 1) * 128);π        ReadWriteHdr (HDR);ππ        YN := GetYN ('Capture this message ? ');π        Number := 0;ππ      Until YN;ππ      Seek (F, Round (MStoIEEE (MS) - 1) * 128);π      Writeln;π      Writeln;π      If Not GetYN ('Extract to Screen ? [Y/N] (N sends to File): ') thenπ        Assign (Output, GetSaveFile);π      {$I-}π      Reset (Output);π      {$I+}π      If IOResult <> 0 thenπ        ReWrite (Output)π      elseπ        Append (Output);π      Writeln;π      Writeln (Seperator);π      Writeln;π      ReadMessage (Hdr, REPorDAT);π      Writeln;π      Writeln;π      Close (Output);π      Assign (Output, '');π      ReWrite (Output);π      YN := GetYN ('Extract more messages? [Y/N] ');π    Until Not YN;ππ    Close (F2);π    YN := GetYN ('Select another message base? [Y/N] ');π  Until Not YN;πend;πππVarπ  Control  : CONDatHdr;π  MSGHdr   : MSGDatHdr;π  REPorDAT : Boolean;ππbeginπ  DefSaveFile := '';π  ConfNum := '';π  Number := 0;π  ParseCommandLine;π  DirectVideo := False;π  ReadControlFile (Control);π  { Assign (F, Control.BBSID + '.MSG');}π  Assign (F, 'MESSAGES.DAT');π  Reset (F, 1);π  BlockRead (F, MSGHdr, SizeOf (MSGHdr));π  REPorDAT := (MSGHdr.Status + MSGHdr.MSGNum = Control.BBSID);π  ScanMessages (REPorDAT);π  { While Not EOF (F) do ReadMessage (MSGHdr, REPorDAT);}π  Close (F);πend.π      3      05-28-9313:50ALL                      SWAG SUPPORT TEAM        MSGINFO.PAS              IMPORT              32          Program VERBOSITY_INDEX;π{πJUSTIN MARQUEZππ  Reads a FidoNet *.MSG File areas and logs info about authorship andπ  "verbosity" found in the messages.ππ  Requires Turbo Pascal 7.xx or Borland Pascal 7.xx (for the StringS Unit)ππ  OutPut is redirectable.  Can be quickly sorted With Dos's SORT.COMπ  Here is a batch File you may find useful:ππrem YAK.BATπverbose %1 > zap.txtπsort < zap.txt > yak.txt /+37 /Rπdel zap.txtππ   This Program is written by Justin Marquez, FidoNet 106/100π   It is being donated to all as a PUBLIC DOMAIN Program, which may beπ   freely used, copied and modified as you please.ππ   "if you improve on it, I'd like a copy of the modifications For myπ   own edification!"π}ππUsesπ  Strings,π  Dos;ππTypeπ  FidoMessageHeader = Recordπ    FromUser  : Array[0..35] of Char ;π    ToUser    : Array[0..35] of Char ;π    Subject   : Array[0..71] of Char ;π    DateTime  : Array[0..19] of Char ;π    TimesRead : Word ;π    DestNode  : Word ;π    OrigNode  : Word ;π    Cost      : Word ;π    OrigNet   : Word ;π    DestNet   : Word ;π    Filler    : Array[0..7] of Byte ;π    Replyto   : Word ;π    Attribute : Word ;π    NextReply : Word ;π  end;ππ  Entry = Recordπ    Author : String[36];π    Count  : Integer;π    Bytes  : LongInt;π  end;ππVarπ  MsgDir,π  fn       : String;π  SR       : SearchRec;π  tmp      : FidoMessageHeader;π  Who_From : String[36];π  n,π  i        : Integer;π  HiNum    : Integer;π  rec      : Array [1..512] of Entry;π  TotBytes : LongInt;ππProcedure GetMsgInfo (fname : String; Var Hdr : FidoMessageHeader);πVarπ  HFile : File of FidoMessageHeader;π  MFile : Text;πbeginπ  FillChar(Hdr, SizeOf(Hdr), #0);  { clear it out initially }π  { get msg hdr only }π  Assign(HFile,fname);π  Reset(HFile);π  Seek(HFile, 0);π  Read(HFile, Hdr);π  Close(HFile);πend;ππProcedure Pad_Path(Var s : String);πbeginπ  if s[length(s)] <> '\' thenπ    s := s + '\';πend;ππProcedure Process_Name;πVarπ  k : Integer;π  Found : Boolean;πbeginπ  Found := False;π  if n > 0 thenπ    For k := 1 to n doπ      if Who_From = rec[k].author thenπ      beginπ        inc(rec[k].count);π        rec[k].Bytes := rec[k].Bytes + SR.Size;π        Found := True;π      endπ  elseπ  beginπ    rec[1].author := Who_From;π    rec[1].count  := 1;π    rec[1].Bytes := rec[1].Bytes + SR.Sizeπ  end;π  if not Found thenπ  beginπ    inc(n);π    Rec[n].Author := Who_From;π    Rec[n].Count  := 1;π    rec[n].Bytes  := rec[n].Bytes + SR.Size;π  end;πend;ππProcedure Intro_And_Init;πbeginπ  FillChar(rec,SizeOf(rec),#0);  { clear it out initially }π  HiNum    := 0;π  TotBytes := 0;π  n        := 0;π  if ParamCount > 0 thenπ    MsgDir := ParamStr(1)π  elseπ  beginπ    WriteLn(' VERBOSE <path> >');π    WriteLn('EXAMPLE:');π    WriteLn;π    WriteLn('VERBOSE C:\OPUS\HOUSYSOP\ ');π    WriteLn(' reads all msg Files in the area and reports findings.');π    WriteLn;π    WriteLn(' Note: can be redirected to a File or device.');π    WriteLn;π    WriteLn('Public Domain from 106/100. Request as VERBOSE.ZIP.');π    Halt(2);π  end;πend;ππProcedure Process_Files;πbeginπ  Pad_Path(MsgDir);π  fn := MsgDir + '*.MSG';π  FindFirst(fn, AnyFile, SR);π  While DosError = 0 doπ  beginπ    fn := MsgDir + SR.Name;π    GetMsgInfo (fn, tmp);π    Who_From := '';π    Who_From := StrPas(StrUpper(tmp.FromUser));π    Inc(HiNum);π    TotBytes := TotBytes + SR.Size;π    Process_Name;π    FindNext(SR);π  end;πend;ππProcedure Report_Results;πbeginπ  For i := 1 to n doπ    WriteLn(rec[i].Author : 36, Rec[i].Count : 4,π           (100 * Rec[i].Count / HiNum) : 6 : 1, '% ',π            Rec[i].Bytes : 6, ' Bytes or',π           (100 * Rec[i].Bytes / TotBytes) : 5 : 1, '% by size' );π  WriteLn(' Total messages found: ' : 36, HiNum : 4);π  WriteLn(' Total Bytes found   : ' : 36, TotBytes : 18);π  WriteLn(n, ' different Writers found in ', MsgDir, '.');πend;ππbeginπ  Intro_And_Init;π  Process_Files;π  Report_Results;πend.π                                                                  4      05-28-9313:50ALL                      SWAG SUPPORT TEAM        QWKMAIL.PAS              IMPORT              285                                  QWK Mail Packet File Layoutπ                              by Patrick Y. Leeπ                       Version 1.0 - February 23, 1992ππThis document is Copyright 1992 by Patrick Y. Lee.ππThe QWK-format is Copyright 1987 by Sparkware.ππAll Program names mentioned in this document are either Copyrightπor Trade- mark of respective owner(s).ππThe author provides this File as-is without warranty of any kind,πeither expressed or implied.  You are using the information inπthis File at your own discretion.  The author assumes noπresponsibilities For damages, either physically or financially,πfrom the use of this information.ππThis document may be freely distributed by any meansπ(electronically, pa- per, etc.), provided that it is distributedπin its entirety.  Portions of this document may be reproducedπwithout credit.ππ                              Table of Contentsππ1.  Introductionπ    1.1.  Intentπ    1.2.  Historyπ    1.3.  Questions, corrections, etc.π2.  Conventions & overviewπ    2.1.  The BBS IDπ    2.2.  Packet compressionπ    2.3.  Packet transfer & protocolsπ    2.4.  Limitationsπ3.  QWK Filesπ    3.1.  Naming conventionπ    3.2.  Control File (CONTROL.DAT)π    3.3.  Welcome Fileπ    3.4.  Goodbye Fileπ    3.5.  News Fileπ    3.6.  Qmail DeLuxe menu Fileπ    3.7.  New uploads listing (NEWFileS.DAT)π    3.8.  Bulletin File(s) (BLT-x.y)π    3.9.  Message File (MESSAGES.DAT)π    3.10.  Index Files (*.NDX)π        3.10.1.  Conference indicesπ        3.10.2.  Personal index (PERSONAL.NDX)π    3.11.  Pointer Fileπ    3.12.  SESSION.TXTπ4.  REP Filesπ    4.1.  Naming conventionπ    4.2.  Message File (BBSID.MSG)π    4.3.  Door control messagesπ    4.3.1.  DOOR.ID Fileπ    4.3.2.  Qmailπ    4.3.3.  MarkMailπ    4.3.4.  KMailπ    4.3.5.  RoseMailπ    4.3.6.  Complete Mail Doorπ    4.4.  Turning off the echo flagπ    4.5.  Tag-linesπ5.  Net mailπA.  Credits & contributionsπB.  Sample Turbo Pascal and C codeπC.  Sample messageπD.  Sample index Fileππ                        -=-=-=-=-=-=-<>-=-=-=-=-=-=-ππTo search For a specific section, look For "[x.x]" using yourπeditor or viewer.  For example, to jump to the tag-lines portionπof this File, search For "[4.5]" With your editor or Text viewer.ππ                        -=-=-=-=-=-=-<>-=-=-=-=-=-=-ππ[1]  Introductionππ[1.1]  IntentππThis document is written to facilitate Programmers who want toπWrite QWK-format mail doors or readers.  It is intended to be aπcomprehen- sive reference covering all areas of QWK-format mailπprocessing.  De- tailed break down of each File is included, asπare Implementation information.  In addition, door and readerπspecific information may be included, when such information areπavailable to me.ππ[1.2]  HistoryππThe QWK-format was invented by Mark "Sparky" Herring in 1987.  Itπwas based on Clark Development Corporation's PCBoard version 12.0πmessage base format.  Off-line mail reading has become popularπonly in recent years.  Prior to summer of 1990, there were onlyπtwo QWK-format off- line mail reader Programs.  They were QmailπDeLuxe by Mark Herring and EZ-Reader by Eric Cockrell.  Similarlyπfor the doors, there were only two -- Qmail by Mark Herring andπMarkMail by Mark Turner.  They were both For PCBoard systems.ππA lot has changed in both off-line reader and mail door marketsπsince summer 1990.  Now, there are more than a dozen off-lineπmail readers For the PC.  Readers For the Macintosh, Amiga, andπAtari exist as well.  There are over a half dozen doors forπPCBoard, and QWK-format doors exist For virtually all of theπpopular BBS softwares.  All of these happened in less than twoπyears!  More readers and doors are in development as I Writeπthis, keep up the excellent work.  In addition to doors, some BBSπsoftwares has QWK-format mail facility built in.ππOff-line mail reading is an integral part of BBS calling.πConference traffic and selection on all networks have grownπdramatically in re- cent years that on-line reading is a thing ofπthe past.  Off-line mail reading offers an alternative to readingπmail on-line -- It offers speed that cannot be achieved withπon-line mail reading.ππThe reason why QWK-format readers and doors seem to have gainedπpopu- larity is probably dued to its openness.  The format isπreadily avail- able to any Programmer who wishes to Write aπProgram that utilize it. Proprietary is a thing of the past, itπdoes not work!  Openness is here to stay and QWK-format is a partπof it.ππ[1.3]  Questions, corrections, etc.ππMost of the message networks today have a conference/echo devotedπto discussion of off-line readers and mail doors.  The ones Iπknow are on FidoNet, ILink, Intelec, and RIME.  If you haveπquestions after read- ing anything in here, feel free to drop byπany of the above confer- ence/echo and I am sure other QWKπauthors will try to help.ππI can be reached in the Off-line conferences on RIME, ILink, andπIntelec, as well as the Common conference on RIME.  Mail can beπrouted to node RUNNINGB.  I can be reached on the Internet atπ"p.lee@green.cooper.edu".  Any corrections, extensions, comments,πand criticisms are welcomed.ππ[2]  Conventions & overviewπAll offsets referenced in this document will be relative to 1.  Iπam not a computer, I start counting at one, not zero!ππWords which are enclosed in quotes should be entered as-is.  Theπquo- tations are not part of the String unless noted.ππYou may have noticed I use the phrase "mail Program" or "mailπfacili- ty" instead of mail doors.  This is because some BBSπsoftwares offer the option of creating QWK-format mail packetsπright from the BBS. With those, there is no need For an externalπmail door.ππ[2.1]  The BBS IDππThe BBS ID (denoted as BBSID) is a 1-8 Characters Word thatπidentifies a particular BBS.  This identifier should be obtainedπfrom line 5 of the CONTROL.DAT File (see section 3.2.1).ππ[2.2]  Packet compressionππMost mail packets are compressed when created by the mail door inπorder to save download time and disk space.  However, manyπoff-line reader Programs allow the user to unarchive a mailπpacket outside of the reader Program, so the reader will not haveπto unarchive it.  Upon Exit, the reader will not call theπarchiver to save it.  It is up to the user to archive theπreplies.  This is useful if the user has lim- ited memory andπcannot shell out to Dos to run the unarchive Program. For readersπbased on non-PC equipment, the user may be using less commonπcompression Program that does not have command line equivalent.ππ[2.3]  Packet transfer & protocolsππThere is no set rule on what transfer protocol should be used.πHowev- er, it would be nice For the mail Program on the BBS toπprovide the Sysop With options as to what to offer.  This shouldπbe a configura- tion option For the user.ππ[2.4]  Specifications & limitationsππThere aren't many known limits in the QWK specification.πHowever, Various networks seem to impose artificial limits.  Onπmany of the PC- based networks, 99-lines appears to be the upperπlimit For some softwares.  However, most of the readers canπhandle more than that. Reader authors reading this may want toπoffer the option to split replies into n lines each (the actualπlength should be user definable so when the network softwareπpermits, the user can increase this num- ber).ππ[3]  QWK Filesππ[3.1]  Naming conventionππGenerally, the name of the mail packet is BBSID.QWK.  However,πthis does not have to be the case.  When the user downloads moreπthan one mail packet at one time, either the mail Program or theπtransfer pro- tocol Program will rename the second and subsequentπmail packets to other names.  They will either change the Fileπextension or add a number to the end of the Filename.  In eitherπcase, you should not rely on the name of the QWK File as theπBBSID.  The BBSID, as men- tioned before, should be obtained fromπline 5 of the CONTROL.DAT File. In addition, mail packets do notπhave to end With QWK extension ei- ther.  The user may choose toπname them With other File extensions.ππ[3.2]  Control File (CONTROL.DAT)ππThe CONTROL.DAT File is a simple ASCII File.  Each line isπterminated With a carriage return and line feed combination.  Allπlines should start on the first column.ππLine #π 1   My BBS                   BBS nameπ 2   New York, NY             BBS city and stateπ 3   212-555-1212             BBS phone numberπ 4   John Doe, Sysop          BBS Sysop nameπ 5   20052,MYBBS              Mail door registration #, BBSIDπ 6   01-01-1991,23:59:59      Mail packet creation timeπ 7   JANE DOE                 User name (upper case)π 8                            Name of menu For Qmail, blank if noneπ 9   0                        ? Seem to be always zeroπ10   0                        ? Seem to be always zeroπ11   121                      Total number of conference minus 1π12   0                        1st conf. numberπ13   Main Board               1st conf. name (13 Characters or less)π14   1                        2nd conf. numberπ15   General                  2nd conf. nameπ..   3                        etc. onward Until it hits max. conf.π..   123                      Last conf. numberπ..   Amiga_I                  Last conf. nameπ..   HELLO                    Welcome screen Fileπ..   NEWS                     BBS news Fileπ..   SCRIPT0                  Log off screenππSome mail doors, such as MarkMail, will send additionalπinformation about the user from here on.ππ0                             ?π25                            Screen length on the BBSπJANE DOE                      User name in uppercaseπJane                          User first name in mixed caseπNEW YORK, NY                  User city informationπ718 555-1212                  User data phone numberπ718 555-1212                  User home phone numberπ108                           Security levelπ00-00-00                      Expiration dateπ01-01-91                      Last log on dateπ23:59                         Last log on timeπ999                           Log on countπ0                             Current conference number on the BBSπ0                             Total KB downloadedπ999                           Download countπ0                             Total KB uploadedπ999                           Upload countπ999                           Minutes per dayπ999                           Minutes remaining todayπ999                           Minutes used this callπ32767                         Max. download KB per dayπ32767                         Remaining KB todayπ0                             KB downloaded todayπ23:59                         Current time on BBSπ01-01-91                      Current date on BBSπMy BBS                        BBS network tag-lineπ0                             ?ππSome mail doors will offer the option of sending an abbreviatedπcon- ference list.  That means the list will contain onlyπconferences the user has selected.  This is done because someπmail readers cannot handle more than n conferences at this time.πUsers using those read- ers will need this option if the BBS theyπcall have too many confer- ences.ππ[3.3]  Welcome FileππThis File usually contains the log on screen from the BBS.  Theπexact Filename is specified in the CONTROL.DAT File, after theπconference list.  This File may be in any format the Sysopπchooses it be -- usu- ally either in plain ASCII or With ANSIπscreen control code.  Some Sysops (notably PCBoard Sysops) mayπuse BBS-specific color change code in this File as well.  Currentπmail Programs seem to handle the trans- lations betweenπBBS-specific code to ANSI based screen control codes.πEven if the CONTROL.DAT File contains the Filename of this File,πit may not actually exist in the mail packet.  Sometimes, usersπwill manually delete this File before entering the mail reader.πSome off- line readers offer the option to not display thisπwelcome screen; some will display this File regardless.  Someπdoors, similarly, will offer option to the user to not send thisπFile.ππ[3.4]  Goodbye FileππSimilar to the welcome File above, the Filename to the goodbyeπFile is in the CONTROL.DAT File.  This is the File the BBSπdisplays when the user logs off the board.  It is optional, asπalways, to send this File or to display it.ππ[3.5]  News FileππMany mail doors offer the option to send the news File from theπBBS. Most will only send this when it has been updated.  Like theπwelcome and goodbye Files, the Filename to the news File is foundπin the CON- TROL.DAT File.  It can be in any format the Sysopπchooses, but usually in either ASCII or ANSI.  Like the welcomeπscreen, current mail facil- ities seem to handle translationπbetween BBS-specific control codes to ANSI screen control codes.ππ[3.6]  Qmail DeLuxe menu FileππThis File is of use only For Qmail DeLuxe mail reader byπSparkware. The Filename is found on line 8 of the CONTROL.DATπFile.ππ[3.7]  New uploads listing (NEWFileS.DAT)ππMost mail Programs on the BBS will offer the option to scan newπFiles uploaded to the BBS.  The result is found in a File namedπNEWFileS.DAT.  The mail Program, if implementing this, shouldπupdate the last File scan field in the user's proFile, if thereπis such a field, as well as other information required by theπBBS.  The mail Program should, of course, scan new Files only inπthose areas the user is allowed access.ππ[3.8]  Bulletin Files (BLT-x.y)ππMost mail Programs will also offer the option to include updatedπbul- letin Files found on the BBS in the mail packet.  Theπbulletins are named BLT-x.y, where x is the conference/echo theπbulletin came from, and y the bulletin's actual number.  The mailπProgram will have to take care of updating the last read date onπthe bulletins in the user Record.ππ[3.9]  Message File (MESSAGES.DAT)ππThe MESSAGES.DAT File is the most important.  This is where allπof the messages are contained in.  The QWK File format is basedπon PCBoard 12.0 message base format from Clark DevelopmentπCorporation (maker of PCBoard BBS software).ππThe File has a logical Record length of 128-Bytes.  The firstπRecord of MESSAGES.DAT always contain a copyright notice sayingπ"Produced by Qmail...Copyright (c) 1987 by Sparkware.  All RightsπReserved".  The rest of the Record is space filled.  Actualπmessages consist of a 128- Bytes header, plus one or moreπ128-Bytes block With the message Text. Actual messages start inπRecord 2.  The header block is layed out as follows:ππOffset  Length  Descriptionπ------  ------  ----------------------------------------------------π    1       1   Message status flag (unsigned Character)π                ' ' = public, unreadπ                '-' = public, readπ                '+' = private, unreadπ                '*' = private, readπ                '~' = comment to Sysop, unreadπ                '`' = comment to Sysop, readπ                '%' = passWord protected, unreadπ                '^' = passWord protected, readπ                '!' = group passWord, unreadπ                '#' = group passWord, readπ                '$' = group passWord to allπ    2       7   Message number (in ASCII)π    9       8   Date (mm-dd-yy, in ASCII)π   17       5   Time (24 hour hh:mm, in ASCII)π   22      25   To (uppercase, left justified)π   47      25   From (uppercase, left justified)π   72      25   Subject of message (mixed case)π   97      12   PassWord (space filled)π  109       8   Reference message number (in ASCII)π  117       6   Number of 128-Bytes blocks in message (including theπ                header, in ASCII; the lowest value should be 2, headerπ                plus one block message; this number may not be leftπ                flushed within the field)π  123       1   Flag (ASCII 225 means message is active; ASCII 226π                means this message is to be killed)π  124       2   Conference number (unsigned Word)π  126       2   Not used (usually filled With spaces or nulls)π  128       1   Indicates whether the message has a network tag-lineπ                or not.  A value of '*' indicates that a network tag-π                line is present; a value of ' ' (space) indicatesπ                there isn't one.  Messages sent to readers (non-net-π                status) generally leave this as a space.  Only networkπ                softwares need this information.ππFields such as To, From, Subject, Message #, Reference #, and theπlike are space padded if they are shorter than the field'sπlength.ππThe message Text starts in the next Record.  You can find out howπmany blocks make up one message by looking at the value ofπ"Number of 128 Byte blocks".  Instead of carriage return and lineπfeed combination, each line in the message end With an ASCII 227π(pi Character) symbol. There are reports that some (buggy)πreaders have problems With mes- sages which do not end the lastπline in the message With an ASCII 227. If a message does notπcompletely occupy the 128-Bytes block, the re- mainder of theπblock is padded With space or null.ππNote that there seems to exist old doors which will use one Byteπto represent the conference number and pad the other one With anπASCII 32 Character.  The Program reading this information willπhave to deter- mine whether the ASCII 32 in Byte 125 of theπheader is a filler or part of the unsigned Word.  One method isπto look in the CONTROL.DAT File to determine the highestπconference number.ππEven though most mail Programs will generate MESSAGES.DAT Filesπthat appear in conference order, this is not always the case.πTomcat! (mail door For Wildcat! BBS) generates MESSAGES.DAT thatπis not in conference order.  This is due to how Wildcat! itselfπstores mail on the BBS.ππNote that some mail doors offer the option of sending a mailπpacket even though there may be no messages to send -- thus anπempty MESSAG- ES.DAT File.  This was tested With Qmail 4.0 doorπand it sent a MES- SAGES.DAT File that contains a few emptyπ128-Bytes blocks.ππ[3.10]  Index Files (*.NDX)ππ[3.10.1]  Conference indicesππThe index Files contain a list of Pointers pointing to theπbeginning of messages in the MESSAGES.DAT File.  The Pointer isπin terms of the 128-Bytes block logical Record that theπMESSAGES.DAT File is in.  Each conference has its own xxx.NDXπFile, where xxx is the conference num- ber left padded withπzeroes.  Some mail Programs offer the user the option to notπgenerate index Files.  So the mail readers need to cre- ate theπindex Files if they are missing.πEZ-Reader 1.xx versions will convert the NDX Files from MicrosoftπMKS format into IEEE long Integer format.  The bad part aboutπthis is that the user may store those index Files back into theπQWK File.  When another reader reads the index Files, it will beπvery confused!ππSpecial note For BBSes With more than 999 conferences: IndexπFiles For conferences With four digit conference numbers is namedπxxxx.NDX, where xxxx is the conference number (left padded withπzeroes).  The Filenames For three digit conferences are stillπnamed xxx.NDX on these boards.  I would assume Filenames forπconferences in the five digit range is xxxxx.NDX, but I have notπseen a BBS With 10,000 or more conferences yet!ππEach NDX File Uses a five Bytes logical Record length and isπformatted to:ππOffset  Length  Descriptionπ------  ------  ------------------------------------------------------π    1       4   Record number pointing to corresponding message inπ                MESSAGES.DAT.  This number is in the Microsoft MKS$π                BASIC format.π    5       1   Conference number of the message.  This Byte shouldπ                not be used because it duplicates both the Filename ofπ                the index File and the conference # in the header.  Itπ                is also one Byte long, which is insufficient to handleπ                conferences over 255.ππPlease refer to appendix B For routines to deal With MKS numbers.ππ[3.10.2]  Personal index (PERSONAL.NDX)ππThere is a special index File named PERSONAL.NDX.  This Fileπcontains Pointers to messages which are addressed to the user,πi.e. personal messages.  Some mail door and utility Programs alsoπallow the selec- tion of other messages to be flagged as personalπmessages.ππ[3.11]  Pointer FileππPointer File is generally included so that the user can reset theπlast read Pointers on the mail Program, in Case there is a crashπon the BBS or some other mishaps.  There should be little reasonπfor the reader Program to access the Pointer File.ππThe Pointer Files I have seen are:ππQmail          BBSID.PTRπMarkMail       BBSID.PNTπKMail          BBSID.PNTπSFMailQwk      BBSID.SFPππAdditions to this list are welcomed.ππ[3.12]  SESSION.TXTππThis File, if included, will contain the message scanning screenπthe user sees from the door.ππ[4]  REP Filesππ[4.1]  Naming conventionππThe reply File is named BBSID.MSG, where BBSID is the ID code forπthe BBS found on line 5 of the CONTROL.DAT File.  Once this Fileπhas been created, the mail reader can archive it up into a Fileπwith REP exten- sion.ππ[4.2]  Message File (BBSID.MSG)ππReplies use the same format as the MESSAGES.DAT File, except thatπmes- sage number field will contain the conference numberπinstead.  In other Words, the conference number will be placed inπthe two Bytes (binary) starting at offset 124, as well as theπmessage number field (ASCII) at offset 2.ππThe first 128-Bytes Record of the File is the header.  Instead ofπthe copyright notice, it contains the BBSID of the BBS.  This 1-8πCharac- ter BBSID must start at the very first Byte and mustπmatch what the BBS has.  The rest of the Record is space padded.πThe replies start at Record 2.  Each reply message will have aπ128-Bytes header, plus one or more For the message Text; followedπby another header, and so on.ππThe mail Program must check to make sure the BBSID in the firstπblock of the BBSID.MSG File matches what the BBS has!ππ[4.3]  Door control messagesππThese messages allow the user to change their setup on the BBS byπsimply entering a message.  The goal is to allow the user to beπable to control most areas of the BBS via the mail door.πDifferent mail doors have different capabilities.  Most all ofπthem offer the ability to add and drop a conference, as well asπreset the last read Pointers in a conference.ππ[4.3.1]  DOOR.ID FileππThe DOOR.ID File was first introduced by Greg Hewgill withπTomcat! mail door and SLMR mail reader.  Since then, many otherπauthors have picked up this idea and use the format.  This Fileπprovides the neces- sary identifiers a reader needs to send add,πdrop, etc. messages to the mail door.  It tells the reader who toπaddress the message to and what can be put in the subject line.ππDOOR = <doorname>             This is the name of the door that creat-π                              ed the QWK packet, i.e. <doorname> =π                              Tomcat.πVERSION = <doorversion>       This is the version number of the doorπ                              that created the packet, i.e.π                              <doorversion> = 2.9.πSYSTEM = <systemType>         This is the underlying BBS system Typeπ                              and version, i.e. <systemType> = Wildcatπ                              2.55.πCONTROLNAME = <controlname>   This is the name to which the readerπ                              should send control messages, eg.π                              <controlname> = TOMCAT.πCONTROLType = <controlType>   This can be one of ADD, DROP, REQUEST,π                              or others.  ADD and DROP are prettyπ                              obvious (they work as in MarkMail), andπ                              REQUEST is For use With BBS systems thatπ                              support File attachments.  Try out SLMRπ                              With CONTROLType = REQUEST and use the Qπ                              Function.  (This seems to be a Wildcat!π                              BBS feature.)πRECEIPT                       This flag indicates that the door/BBS isπ                              capable of return receipts when a mes-π                              sage is received.  If the first threeπ                              letters of the subject are RRR, then theπ                              door should strip the RRR and set theπ                              'return-receipt-requested' flag on theπ                              corresponding message.ππNone of the lines are actually required and they may appear inπany order.  Of course, you would need a CONTROLNAME if you haveπany CONTROLType lines.ππ[4.3.2]  QmailππSend a message addressed to "QMAIL" With a subject of "CONFIG".πThen, enter any of the commands listed below inside the Text ofπyour mes- sage.  Remember to use one command per line.πADD <confnum>            Add a conference into the Qmail Door scanningπ                         list.  "YOURS" can also be added to the com-π                         mand if the user wishes to receive messagesπ                         only addressed them.  i.e. "ADD 1 YOURS"πDROP <confnum>           Drop a conference from the Qmail Door scan-π                         ning list.πRESET <confnum> <value>  Resets a conference to a particular value.π                         The user can use "HIGH-xxx" to set the con-π                         ference to the highest message in the base.πCITY <value>             Changes the "city" field in the user'sπ                         PCBoard entry.πPASSWord <value>         Changes the user's login passWord.πBPHONE <value>           Business/data phone numberπHPHONE <value>           Home/voice phone numberπPCBEXPERT <on|off>       Turns the PCBoard expert mode ON or OFF.πPCBPROT <value>          PCBoard File transfer protocol (A-Z).πPAGELEN <value>          Set page length inside PCBoard.πPCBCOMMENT <value>       Set user maintained comment.πAUTOSTART <value>        Qmail Door autostart command.πPROTOCOL <value>         Qmail Door File transfer protocol (A-Z).πEXPERT <ON or OFF>       Turns the Qmail Door expert mode ON or OFF.πMAXSIZE <value>          Maximum size of the user's .QWK packet (inπ                         Bytes)πMAXNUMBER <value>        Maximum number of messages per conference.ππ[4.3.3]  MarkMailππSend a message addressed to "MARKMAIL" With the subject line saying:ππADD [value]         in the conference you want to addπDROP                in the conference you want to dropπYOUR [value]        in the conference you want only your mail sentπYA [value]          in the conference you want only your mail + mailπ                    addressed to "ALL"πFileS ON or OFF     in any conference to tell MarkMail whether to scanπ                    For new Files or not.πBLTS ON or OFF      to turn on and off, respectively, of receivingπ                    bulletins.πOWN ON or OFF       to turn on and off, respectively, of receivingπ                    messages you sentπDELUXE ON or OFF    to turn on and off, respectively, of receivingπ                    DeLuxe menuπLIMIT <size>        to set the maximum size of MESSAGES.DAT File canπ                    be, it cannot exceed what the Sysop has set upππAn optional number can be added onto the commands "ADD", "YOUR",πand "YA".  If this number is positive, then it will be treated asπan abso- lute message number.  MarkMail will set your last readπPointer to that number.  If it is negative, MarkMail will setπyour last read Pointer to the highest minus that number.  Forπexample: "ADD -50" will add the conference and set the last readπPointer to the highest in the confer- ence minus 50.ππ[4.3.4]  KMailππSend a private message addressed to "KMAIL" in the conferenceπthat you want to add, drop, or reset.  The commands are "ADD",π"DROP", and "RESET #", respectively.  The "#" is the messageπnumber you want your last read Pointer in the conference be setπto.ππ[4.3.5]  RoseMailππThe RoseMail door allows configuration information be placed inπeither the subject line or message Text.  The message must beπaddressed to "ROSEMAIL".  For only one command, it can be placedπin the subject line.  For more than one changes, the subject lineπmust say "CONFIG" and each change be placed in the message Text.πEvery line should be left justified.  Valid commands are:ππCommand                                           ExampleππADD <Conference> [<Message #>] [<Yours>]          ADD 2 -3 YπDROP <Conference>                                 DROP 2πRESET <Conference> <Message #>                    RESET 12 5000πPCBEXPERT <ON | OFF> - PCBoard expert mode        PCBEXPERT ONπEXPERT <ON | OFF>    - RoseMail expert mode       EXPERT OFFπPCBPROT <A - Z>      - PCBoard protocol           PCBPROT ZπPROT <A - Z>         - RoseMail protocol          PROT GπPAGELEN <Number>     - Page length                PAGELEN 20πMAXSIZE <KBytes>     - Max packet size in Kb      MAXSIZE 100πMAXNUMBER <max msgs/conference>                   MAXNUMBER 100πJUMPSTART <Sequence or OFF>                       JUMPSTART D;Y;QπMAXPACKET <max msgs/packet>                       MAXPACKET 500πAUTOSTART <Sequence or OFF> - same as jumpstart   AUTOSTART OFFπOPT <##> <ON | OFF>  - set door option            OPT 2 OFFππ[4.3.6]  Complete Mail DoorππSend message to "CMPMAIL", the commands are "ADD" and "DROP".πThis message must be sent in the conference that you want to addπor drop.ππ[4.4]  Turning off the echo flagππIn order to send a non-echoed message (not send out to otherπBBSes), a user can enter "NE:" in front of the subject line.  Theπmail Program will strip this "NE:" and turn off the echo flag.πThis feature may not be offered in all mail doors.ππ[4.5]  Tag-linesππThe most common format For a reader tag-line is:ππ[---π * My reader v1.00 * The rest of the tag-line.ππThe three dashes is called a tear-line.  The tag-line is appendedπto the end of the message and is usually one line only.  It isπpreferred that tag-lines conform to this format so thatπnetworking softwares such as QNet and RNet will not add anotherπtearline to the message when they process it.ππSoftwares on FidoNet does not like mail readers adding aπtear-line of their own, so if your mail reader offers a FidoNetπmode, you will need to get rid of the tear-line.  Another itemπwhich differs between the FidoNet and PC-based networks is thatπFidoNet does not like extended ASCII Characters.  So your readerπmay want to strip high ASCII if the user has FidoNet mode on.πAcceptable tag-line style, I believe, is just this:ππ * My Reader v1.00 * The rest of the tag-line.ππ[5]  Net mailππI do not have complete information of net-mail Implementationπusing QWK-format.  Someone please fill me in the details.ππ                     -=-=-=-=-=-=-<>-=-=-=-=-=-=-ππ[A]  Credits and ContributionsππMark "Sparky" Herring, who originated the QWK-format.ππTim Farley, who started this documentation back in the summer ofπ1990. The general outline here is the work of Tim.  I filled inπthe blanks.ππJeffery Foy, who gave us the format For Microsoft single binaryπversus IEEE format.ππGreg Hewgill, who (if I remember correctly) wrote the TurboπPascal routines (included in here) to convert between MKS and TPπLongInt.πDennis McCunney, who is the host of the Off-line conference onπRIME, is very knowledgeable in off-line reading concept andπPrograms.  His goal is to have one reader that can read mailπpacket from any source.ππAll those who have been around the Off-line conferences on ILinkπ(the oldest of the three I participate), RIME, and Intelec, whoπhave pro- vided great help over the past two years.  The bulk ofπthe information presented here are from messages in thoseπconferences.  These people include, but are no limited to, theπfollowings: Dane Beko, Joseph Carnage, Marcos Della, Joey Lizzi,πMark May, and Jim Smith.ππ[B]  Sample Turbo Pascal and C codeππHere are a few routines in Turbo Pascal and C to convertπMicrosoft BASIC MKS format to usable IEEE long Integer.  Theseπare collected over the networks and there is no guarantee thatπthey will work For you!ππTurbo Pascal (Greg Hewgill ?):ππTypeπ     bsingle = Array [0..3] of Byte;ππ{ converts TP Real to Microsoft 4 Bytes single }ππProcedure Real_to_msb (pReal : Real; Var b : bsingle);πVarπ     r : Array [0 .. 5] of Byte Absolute pReal;πbeginπ     b [3] := r [0];π     move (r [3], b [0], 3);πend; { Procedure Real_to_msb }ππ{ converts Microsoft 4 Bytes single to TP Real }ππFunction msb_to_Real(b : bsingle) : Real;πVarπ     pReal : Real;π     r : Array [0..5] of Byte Absolute pReal;πbeginπ     r [0] := b [3];π     r [1] := 0;π     r [2] := 0;π     move (b [0], r [3], 3);π     msb_to_Real := pReal;πend; { Procedure msb_to_Real }ππC (identify yourself if you originated this routine):ππ/* converts 4 Bytes Microsoft MKS format to long Integer */ππunsigned long mbf_to_int (m1, m2, m3, exp)πunsigned int m1, m2, m3, exp;π{π     return (((m1 + ((unsigned long) m2 << 8) + ((unsigned long) m3 <<π     16)) | 0x800000L) >> (24 - (exp - 0x80)));π}ππMicrosoft binary (by Jeffery Foy):ππ   31 - 24    23     22 - 0        <-- bit positionπ+-----------------+----------+π| exponent | sign | mantissa |π+----------+------+----------+ππIEEE (C/Pascal/etc.):ππ   31     30 - 23    22 - 0        <-- bit positionπ+----------------------------+π| sign | exponent | mantissa |π+------+----------+----------+ππIn both cases, the sign is one bit, the exponent is 8 bits, and theπmantissa is 23 bits.  You can Write your own, optimized, routine toπconvert between the two formats using the above bit layout.ππ[C]  Sample messageππHere is a sample message in hex and ASCII format:ππ019780  20 34 32 33 32 20 20 20 30 32 2D 31 35 2D 39 32   4232   02-15-92π019790  31 33 3A 34 35 52 49 43 48 41 52 44 20 42 4C 41  13:45RICharD BLAπ0197A0  43 4B 42 55 52 4E 20 20 20 20 20 20 20 20 53 54  CKBURN        STπ0197B0  45 56 45 20 43 4F 4C 45 54 54 49 20 20 20 20 20  EVE COLETTIπ0197C0  20 20 20 20 20 20 20 51 45 44 49 54 20 48 41 43         QEDIT HACπ0197D0  4B 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  Kπ0197E0  20 20 20 20 20 20 20 20 20 20 20 20 34 30 33 36              4036π0197F0  20 20 20 20 37 20 20 20 20 20 E1 0A 01 00 00 20      7π019800  2A 20 49 6E 20 61 20 6D 65 73 73 61 67 65 20 64  * In a message dπ019810  61 74 65 64 20 30 32 2D 30 39 2D 39 32 20 74 6F  ated 02-09-92 toπ019820  20 53 74 65 76 65 20 43 6F 6C 65 74 74 69 2C 20   Steve Coletti,π019830  52 69 63 68 61 72 64 20 42 6C 61 63 6B 62 75 72  RiChard Blackburπ019840  6E 20 73 61 69 64 3A E3 E3 52 42 3E 53 43 20 AF  n said:ππRB>SCπ019850  20 65 64 69 74 6F 72 20 69 6E 20 74 68 65 20 28   editor in the (π019860  6D 61 69 6E 66 72 61 6D 65 29 20 56 4D 2F 43 4D  mainframe) VM/CMπ019870  53 20 70 72 6F 64 75 63 74 20 6C 69 6E 65 20 69  S product line iπ[ etc. ]π019A00  6E 6F 74 20 61 20 44 6F 63 74 6F 72 2C 20 62 75  not a Doctor, buπ019A10  74 20 49 20 70 6C 61 79 20 6F 6E 65 20 61 74 20  t I play one atπ019A20  74 68 65 20 48 6F 73 70 69 74 61 6C 2E E3 20 20  the Hospital.ππ019A30  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20π019A40  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20π019A50  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20π019A60  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20π019A70  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20π019A80  E3 50 43 52 65 6C 61 79 3A 4D 4F 4F 4E 44 4F 47πPCRelay:MOONDOGπ019A90  20 2D 3E 20 23 33 35 20 52 65 6C 61 79 4E 65 74   -> #35 RelayNetπ019AA0  20 28 74 6D 29 E3 34 2E 31 30 20 20 20 20 20 20   (tm)π4.10π019AB0  20 20 20 20 20 20 20 20 20 48 55 42 4D 4F 4F 4E           HUBMOONπ019AC0  2D 4D 6F 6F 6E 44 6F 67 20 42 42 53 2C 20 42 72  -MoonDog BBS, Brπ019AD0  6F 6F 6B 6C 79 6E 2C 4E 59 20 37 31 38 20 36 39  ooklyn,NY 718 69π019AE0  32 2D 32 34 39 38 E3 20 20 20 20 20 20 20 20 20  2-2498ππ019AF0  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20ππ[D]  Sample index FileππHere is a sample index File in hex format:ππ000000  00 00 28 87 19 00 00 30 87 19 00 00 38 87 19 00π000010  00 7E 87 19 00 00 07 88 19 00 00 0B 88 19 00 00π000020  0F 88 19 00 00 14 88 19 00 00 19 88 19 00 00 1Eπ000030  88 19 00 00 22 88 19 00 00 27 88 19 00 00 2C 88π000040  19 00 00 31 88 19 00 00 3B 88 19 00 00 40 88 19π000050  00 00 46 88 19 00 00 49 88 19 00 00 4D 88 19 00π000060  00 52 88 19 00 00 55 88 19 00 00 59 88 19 00 00π000070  60 88 19 00 00 66 88 19 00 00 70 88 19πππ                                                                                                     5      08-27-9321:20ALL                      KELLY DROWN              FIDONET *.MSG format     IMPORT              91     n¼   {π> I am trying to write a program.  Does anyone have the structures for theπ> FIDONET *.MSG format.  ANy help would be greatly appreciated.π}ππUnit FidoNet; { Beta Copy - Rev 6/5/89 - Tested 6/20/89  Ver. 0.31 }ππ           { FIDONET UNIT by Kelly Drown, Copyright (C)1988,89-LCP  }π           {                                   All rights reserved  }π           { If you use this unit in your own programming, I ask    }π           { only that you give me credit in your documentation.    }π           { I ask this instead of money. All of the following code }π           { is covered under the copyright of Laser Computing Co.  }π           { and may be used in your own programming provided the   }π           { terms above have been satisfactorily met.              }ππINTERFACEππUsesπ  Dos,π  Crt,π  StrnTTT5,  { TechnoJocks Turbo Toolkit v5.0 }π  MiscTTT5;πππTypeπ  NetMsg = Record        { NetMessage Record Structure }π    From,π    Too        : String[35];π    Subject    : String[71];π    Date       : String[19];π    TimesRead,π    DestNode,π    OrigNode,π    Cost,π    OrigNet,π    DestNet,π    ReplyTo,π    Attr,π    NextReply  : Word;π    AreaName   : String[20];π  End;ππ  PktHeader = Record        { Packet Header of Packet }π    OrigNode,π    DestNode,π    Year,π    Month,π    Day,π    Hour,π    Minute,π    Second,π    Baud,π    OrigNet,π    DestNet  : Word;π  End;ππ  PktMessage = Record        { Packet Header of each individual message }π    OrigNode,π    DestNode,π    OrigNet,π    DestNet,π    Attr,π    Cost     : Word;π    Date     : String[19];π    Too      : String[35];π    From     : String[35];π    Subject  : String[71];π    AreaName : String[20];π  End;ππ  ArchiveName = Record        { Internal Record Structure used for     }π    MyNet,                    { determining the name of of an echomail }π    MyNode,                   { archive. i.e. 00FA1FD3.MO1             }π    HisNet,π    HisNode : Word;π  End;ππConst                        { Attribute Flags }π  _Private  = $0001;π  _Crash    = $0002;π  _Recvd    = $0004;π  _Sent     = $0008;π  _File     = $0010;π  _Forward  = $0020;     { Also know as In-Transit }π  _Orphan   = $0040;π  _KillSent = $0080;π  _Local    = $0100;π  _Hold     = $0200;π  _Freq     = $0800;ππ  Status    : Array[1..12] Of String[3] =π                ('Jan','Feb','Mar','Apr','May','Jun',π                 'Jul','Aug','Sep','Oct','Nov','Dec');ππVarπ  Net  : NetMsg;π  PH   : PktHeader;π  PM   : PktMessage;π  ArcN : ArchiveName;ππFunction  PacketName : String;πFunction  PacketMessage : String;πFunction  PacketHeader : String;πFunction  NetMessage : String;πFunction  GetPath(Var FName : String) : Boolean;πFunction  GetNet(GN : String) : String;πFunction  GetNode(GN : String) : String;πFunction  MsgDateStamp : String;πFunction  LastMsgNum(_NetPath : String) : Integer;πFunction  Hex(n : word) : String;πFunction  ArcName : String;πProcedure ExpandNodeNumbers(Var List : String; VAR TotalNumber : Integer);πProcedure Conv_NetNode(NetNode : String; VAR Net, Node : Word);ππIMPLEMENTATIONππ{-------------------------------------------------------------------------}πFunction PacketName : String;π{ Creates and returns a unique Packet name }πVarπ  h, m, s,π  hs, yr,π  mo, da,π  dow     : Word;π  WrkStr  : String;πBeginπ  WrkStr := '';π  GetTime(h, m, s, hs);π  GetDate(yr, mo, da, dow);ππ  WrkStr := PadRight(Int_To_Str(da), 2, '0')π           + PadRight(Int_To_Str(h), 2, '0')π           + PadRight(Int_To_Str(m), 2, '0')π           + PadRight(Int_To_Str(s), 2, '0');ππ  PacketName := WrkStr + '.PKT';πEnd;π{-------------------------------------------------------------------------}πFunction PacketMessage : String;π{ Returns a Packet message header }πVarπ  Hdr : String;πBeginπ  Hdr := '';ππ  Hdr := #2#0 { Type #2 packets... Type #1 is obsolete }π         + Chr(Lo(PM.OrigNode)) + Chr(Hi(PM.OrigNode))π         + Chr(Lo(PM.DestNode)) + Chr(Hi(PM.DestNode))π         + Chr(Lo(PM.OrigNet)) + Chr(Hi(PM.OrigNet))π         + Chr(Lo(PM.DestNet)) + Chr(Hi(PM.DestNet))π         + Chr(Lo(PM.Attr)) + Chr(Hi(PM.Attr))π         + Chr(Lo(PM.Cost)) + Chr(Hi(PM.Cost))π         + PM.Date + #0 + PM.Too + #0 + PM.From + #0 + PM.Subject + #0π         + Upper(PM.AreaName);ππ  PacketMessage := Hdr;πEnd;π{-------------------------------------------------------------------------}πFunction PacketHeader : String;π{ Returns a Packet Header String }πVarπ  Hdr : String;πBeginπ  Hdr := '';ππ  Hdr := Chr(Lo(PH.OrigNode)) + Chr(Hi(PH.OrigNode))π         + Chr(Lo(PH.DestNode)) + Chr(Hi(PH.DestNode))π         + Chr(Lo(PH.Year)) + Chr(Hi(PH.Year))π         + Chr(Lo(PH.Month)) + Chr(Hi(PH.Month))π         + Chr(Lo(PH.Day)) + Chr(Hi(PH.Day))π         + Chr(Lo(PH.Hour)) + Chr(Hi(PH.Hour))π         + Chr(Lo(PH.Minute)) + Chr(Hi(PH.Minute))π         + Chr(Lo(PH.Second)) + Chr(Hi(PH.Second))π         + Chr(Lo(PH.Baud)) + Chr(Hi(PH.Baud))π         + #2#0 + Chr(Lo(PH.OrigNet)) + Chr(Hi(PH.OrigNet))π         + Chr(Lo(PH.DestNet)) + Chr(Hi(PH.DestNet))π         + #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0   { Null Field Fill Space }π         + #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0;ππ  PacketHeader := Hdr;πEnd;π{-------------------------------------------------------------------------}πFunction NetMessage : String;π{ Returns a NetMessage header string }πVarπ  Hdr : String;πBeginπ  Hdr := '';ππ  Hdr := PadLeft(Net.From, 36, #0);π  Hdr := Hdr + PadLeft(Net.Too, 36, #0)π             + PadLeft(Net.Subject, 72, #0)π             + PadRight(Net.Date, 19, ' ') + #0π             + Chr(Lo(Net.TimesRead)) + Chr(Hi(Net.TimesRead))π             + Chr(Lo(Net.DestNode)) + Chr(Hi(Net.DestNode))π             + Chr(Lo(Net.OrigNode)) + Chr(Hi(Net.OrigNode))π             + Chr(Lo(Net.Cost)) + Chr(Hi(Net.Cost))π             + Chr(Lo(Net.OrigNet)) + Chr(Hi(Net.OrigNet))π             + Chr(Lo(Net.DestNet)) + Chr(Hi(Net.DestNet))π             + #0#0#0#0#0#0#0#0π             + Chr(Lo(Net.ReplyTo)) + Chr(Hi(Net.ReplyTo))π             + Chr(Lo(Net.Attr)) + Chr(Hi(Net.Attr))π             + Chr(Lo(Net.NextReply)) + Chr(Hi(Net.NextReply))π             + Upper(Net.AreaName);ππ  NetMessage := Hdr;πEnd;π{-------------------------------------------------------------------------}πFunction GetPath(Var FName : String) : Boolean;π{ Returns the FULL Path and filename for a filename if the file  }π{ is found in the path. }πVarπ  Str1,π  Str2    : String;π  NR      : Byte;π  HomeDir : String;πBeginπ  HomeDir := FExpand(FName);π  If Exist(HomeDir) Thenπ  Beginπ    FName   := HomeDir;π    GetPath := True;π    Exit;π  End;ππ  Str1 := GetEnv('PATH');π  For NR := 1 to Length(Str1) DOπ    IF Str1[NR] = ';' Thenπ      Str1[NR] := ' ';ππ  For NR := 1 to WordCnt(Str1) DOπ  Beginπ    Str2 := ExtractWords(NR, 1, Str1) + '\' + FName;π    IF Exist(Str2) Thenπ    Beginπ      FName   := Str2;π      GetPath := True;π      Exit;π    End;π  End;π  GetPath := False;πEnd;ππ{-------------------------------------------------------------------------}πFunction MsgDateStamp : String;  { Creates Fido standard- 01 Jan 89 21:05:18 }πVar                              { Standard message header time/date stamp   }π  h, m, s,π  hs, y, mo,π  d, dow    : Word;π  Tmp, o1,π  o2, o3    : String;ππBeginπ  o1  := '';π  o2  := '';π  o3  := '';π  tmp := '';π  GetDate(y, mo, d, dow);π  GetTime(h, m, s, hs);π  o1  := PadRight(Int_To_Str(d), 2, '0');π  o2  := Status[mo];π  o3  := Last(2,Int_To_Str(y));π  Tmp := Concat(o1, ' ', o2, ' ', o3,'  ');π  o1  := PadRight(Int_To_Str(h), 2, '0');π  o2  := PadRight(Int_To_Str(m), 2, '0');π  o3  := PadRight(Int_To_Str(s), 2, '0');π  Tmp := Tmp + Concat(o1, ':', o2, ':', o3);π  MsgDateStamp := Tmp;πEnd;ππ{-------------------------------------------------------------------------}πFunction MsgToNum(Fnm : String) : Integer; { Used Internally by LastMsgNum }πVarπ  p : Byte;πBeginπ  p        := Pos('.', Fnm);π  Fnm      := First(p - 1, Fnm);π  MsgToNum := Str_To_Int(Fnm);πEnd;π{-------------------------------------------------------------------------}ππFunction LastMsgNum(_NetPath : String) : Integer;π{ Returns the highest numbered xxx.MSG in NetPath directory }πVarπ  _Path,π  Temp1,π  Temp2   : String;π  Len     : Byte;π  DxirInf : SearchRec;π  Num,π  Num1    : Integer;ππBeginπ  Num   := 0;π  Num1  := 0;π  Temp1 := '';π  Temp2 := '';π  _Path := '';π  _Path := _NetPath + '\*.MSG';ππ  FindFirst(_Path, Archive, DxirInf);π  While DosError = 0 DOπ  Beginπ    Temp1 := DxirInf.Name;π    Num1 := MsgToNum(Temp1);π    IF Num1 > Num Thenπ      Num := Num1;π    FindNext(DxirInf);π  End;ππ  IF Num = 0 Thenπ    Num := 1;π  LastMsgNum := Num;πEnd;ππ{-------------------------------------------------------------------------}πFunction Hex(N : Word) : String;π{ Converts an integer or word to it's Hex equivelent }πVarπ  L   : string[16];π  BHi,π  BLo : byte;ππBeginπ  L   := '0123456789ABCDEF';π  BHi := Hi(n);π  BLo := Lo(n);π  Hex := copy(L,succ(BHi shr 4),  1) +π         copy(L,succ(BHi and 15), 1) +π         copy(L,succ(BLo shr 4),  1) +π         copy(L,succ(BLo and 15), 1);πEnd;ππ{-------------------------------------------------------------------------}πFunction ArcName : String;π{ Returns the proper name of an echomail archive }πVarπ  C1, C2 : LongInt;πBeginπ  C1 := 0;π  C2 := 0;π  C1 := ArcN.MyNet - ArcN.HisNet;π  C2 := ArcN.MyNode - ArcN.HisNode;π  If C1 < 0 Thenπ    C1 := 65535 + C1;π  If C2 < 0 Thenπ    C2 := 65535 + C2;π  ArcName := Hex(C1) + Hex(C2);πEnd;ππ{-------------------------------------------------------------------------}πFunction GetNet(GN : String) : String;π{ Returns the NET portion of a Net/Node string }πVarπ  P : Byte;πBeginπ  P := Pos('/', GN);π  GetNet := First(P - 1, GN);πEnd;ππ{-------------------------------------------------------------------------}πFunction GetNode(GN : String) : String;π{ Returns the NODE portion of a Net/Node string }πVarπ  P : Byte;πBeginπ  P := Pos('/', GN);π  GetNode := Last(Length(GN) - P, GN);πEnd;π{-------------------------------------------------------------------------}πProcedure ExpandNodeNumbers(Var List : String; VAR TotalNumber : Integer );π{ Expands a list of short form node numbers to thier proper       }π{ Net/Node representations. Example:                              }π{ The string: 170/100 101 102 5 114/12 15 17 166/225 226          }π{ Would return: 170/100 170/101 170/102 170/5 114/12 114/15 etc.. }πVarπ  Net,π  NetNode  : String[10];π  HoldStr,π  WS1      : String;π  N1       : Integer;ππBeginπ  Net := '';π  NetNode := '';π  HoldStr := '';π  WS1 := '';π  N1  := 0;π  TotalNumber := 0;π  TotalNumber := WordCnt(List);ππ  For N1 := 1 to TotalNumber DOπ  Beginπ    WS1 := ExtractWords(N1, 1, List);π    IF Pos('/', WS1) <> 0 Thenπ    Beginπ      Net := GetNet(WS1) + '/';π      NetNode := WS1;π    Endπ    ELSEπ      NetNode := Net + WS1;π    HoldStr := HoldStr + ' ' + Strip('A', ' ', NetNode);π  End;πEnd;ππ{-------------------------------------------------------------------------}πProcedure Conv_NetNode(NetNode : String; VAR Net, Node : Word);π{ Returns NET and NODE as words from a Net/Node string }πVarπ  WStr : String[6];πBeginπ  Wstr := GetNet(NetNode);π  Net  := Str_To_Int(Wstr);π  Wstr := GetNode(NetNode);π  Node := Str_To_Int(Wstr);πEnd;π{-------------------------------------------------------------------------}ππBeginπ  { Initialize the data structures }ππ  FillChar(Net, SizeOf(Net), #0);π  FillChar(PM, SizeOf(PM), #0);π  FillChar(PH, SizeOf(PH), #0);π  FillChar(ArcN, SizeOf(ArcN), #0);ππEnd. {Unit}π                                                        6      08-27-9321:32ALL                      MARK LEWIS               Making a FIDO Message    IMPORT              20     n¼   {πMARK LEWISππ> I've been playing with those files in MKMSG101.ZIP ... I've hadπ> them for awhile, but cannot get them to work.π > All I'm trying to do is make a simple message in FIDO format forπ > my BBS.  Does anyone have any examples?ππlittle to no error checking... tossed together from part(s) of the sampleπWRITEMSG.PAS example that comes with MKMSGSRC...π}ππprogram sample_MKMSG_code;ππ{ reads a text file specified on the command line and posts itπ  to specified directory in *.MSG format. }ππUsesπ  DOS, CRT, MKString, MKGlobt,π  MKMsgAbs, MKFile, MKDos, MKMsgFid;ππVarπ  TheMSG  : AbsMsgPtr;π  Error   : Boolean;π  MSGDir,π  TheName,π  TheLine : String;π  TheFile : Text;π  MSGNum  : Word;ππBeginπ  If ParamCount < 2 Thenπ  Beginπ    Writeln('Usage : ' + Paramstr(0) + ' <MSG Dir> <Text file to post>');π    halt(1);π  End;π  Error   := False;π  MSGDir  := WithBackSlash(Upper(Paramstr(1)));π  TheName := Upper(Paramstr(2));π  Assign(TheFile, TheName);π  {$I-}π  Reset(TheFile);π  {$I+}π  Error := IOResult <> 0;π  If Not Error Thenπ  Beginπ    TheMSG := New(FidoMsgPtr, Init);π    TheMSG^.SetMsgPath(MSGDir);π    Error := (TheMSG^.OpenMsgBase <> 0);π    If Not Error Thenπ    Beginπ      TheMSG^.SetMailType(mmtNormal);π      TheMSG^.StartNewMsg;π      TheMSG^.SetFrom('SysOp');π      TheMSG^.SetTo('ALL');π      TheMSG^.SetSubj(TheName);π      TheMSG^.SetPriv(False);π      TheMSG^.SetDate(DateStr(GetDosDate));π      TheMSG^.SetTime(TimeStr(GetDosDate));π      TheMSG^.SetLocal(True);π      TheMSG^.SetEcho(False);π      TheMSG^.SetRefer(0);π      While Not EOF(TheFile) Doπ      Beginπ        ReadLn(TheFile, TheLine);π        TheMSG^.DoStringLn(TheLine);π      End;π      Error := TheMSG^.WriteMsg <> 0;π      If Not Error Thenπ      Beginπ        MsgNum := TheMSG^.GetMsgNum;π        Writeln('File ', TheName, ' posted to Area ', MSGDir, ' as MSG # ',π                MSGNum,'.');π      Endπ      Elseπ      Beginπ        Writeln('Message Creation Error!');π        Halt(4);π      End;π      If TheMSG^.CloseMsgBase <> 0 Then; {Close msg base}π    Endπ    Elseπ    Beginπ      Writeln('Cannot Open Message Area ', MSGDir, '!');π      Dispose(TheMSG, Done); {Dispose of the object pointer}π      Halt(3);π    End;π    Dispose(TheMSG, Done); {Dispose of the object pointer}π  Endπ  Elseπ    Writeln('OOPS! Cannot Locate File ', TheName, '!');πEnd.π                                                                     7      08-27-9321:44ALL                      MARK LEWIS               Reading MSG Header       IMPORT              32     n¼   { MARK LEWIS }ππUsesπ  Dos;ππTypeπ  ti = Recordπ    Var1 : Word;π    Var2 : Word;π  end;ππ  MsgInfo = Recordπ    From_Name : Array[1..36] of Char;π    To_Name   : Array[1..36] of Char;π    Subject   : Array[1..72] of Char;π    DateTime  : Array[1..20] of Char;π    timesread : Word;π    destnode  : Word;π    orignode  : Word;π    cost      : Word;π    orignet   : Word;π    destnet   : Word;π    field1    : ti;    { these two have at least two seperate }π    field2    : ti;    { Uses. time sent/rcvd or zone/point info }π    replyto   : Word;π    attribute : Word;π    nextmsg   : Word;π  end;ππ{πahhh... what the heck... the following will read the MSG header and displayπit... i'll leave the processing of the messagebody as an exercise For theπreader(s)... it's a lot of fun... make sure you get/have the FTSC documentsπhandy... there is one that talks about hints to follow when processing messagesπ(in .PKT's and in .MSG's) like filtering out all CR's, LF's and softcarriageπreturns -=B-)π}ππVarπ  MInfo    : MsgInfo;π  MSGName  : PathStr;π  MSGFile  : File;π  i        : Byte;π  t1,t2    : datetime;π  notdate  : Boolean;π  numread  : Word;ππ{-------------------------------------------------------------------------}πbegin  { Main Body }π  assign(output, '');π  reWrite(output);π  Filemode := 64;π  MSGName  := ParamStr(1); { Get message Filename from command line }π  if (MSGName = '') Thenπ  beginπ    WriteLn('Name of *.MSG must be specified on command line.');π    Halt;π  end;π  FillChar(Minfo,SizeOf(Minfo),#0);π  Assign(MSGFile,MSGName);π  {$I-} Reset(MSGFile,1); {$I+}π  if IOResult <> 0 Thenπ  beginπ    Writeln('Unable to open the *.MSG!');π    halt;π  end;π  { Read in header... }π  BlockRead(MSGFile,Minfo,SizeOf(Minfo),NumRead);π  { decode time/date fields For FrontDoor/OPUS }π  { i think this is a UNIX time/date format but not sure }π  t1.min   := (minfo.field1.Var2 and $07e0) shr 5;π  t1.hour  := (minfo.field1.Var2 and 63488) shr 11;π  t1.sec   := 0;π  t1.year  := 1980 + (minfo.field1.Var1 and $fe00) shr 9;π  t1.month := (minfo.field1.Var1 and $01e0) shr 5;π  t1.day   := (minfo.field1.Var1 and $001f);π  t2.min   := (minfo.field2.Var2 and $07e0) shr 5;π  t2.hour  := (minfo.field2.Var2 and 63488) shr 11;π  t2.sec   := 0;π  t2.year  := 1980 + (minfo.field2.Var1 and $fe00) shr 9;π  t2.month := (minfo.field2.Var1 and $01e0) shr 5;π  t2.day   := (minfo.field2.Var1 and $001f);π  if (t1.year < 1990) and (t2.year < 1990) thenπ    notdate := Trueπ  elseπ    notdate := False;π    { if the years are over three years ago, then we are probably }π    { processing a message that is using these fields For their }π    { other documented use. }π  Write('From: ');π  For i := 1 to 36 doπ    Write(minfo.from_name[i]);π  Writeln;π  Write('To  : ');π  For i := 1 to 36 doπ    Write(minfo.to_name[i]);π  Writeln;π  Write('Subj: ');π  For i := 1 to 72 doπ    Write(minfo.subject[i]);π  Writeln;π  Write('Date: ');π  For i := 1 to 20 doπ    Write(minfo.datetime[i]);π  Writeln;π  Writeln('timesread : ',minfo.timesread);π  Writeln(' destnode : ',minfo.destnode );π  Writeln(' orignode : ',minfo.orignode );π  Writeln('     cost : ',minfo.cost     );π  Writeln('  orignet : ',minfo.orignet  );π  Writeln('  destnet : ',minfo.destnet  );π  if notdate thenπ  beginπ    Writeln(' destzone : ',minfo.field1.Var1);π    Writeln(' origzone : ',minfo.field1.Var2);π    Writeln('destpoint : ',minfo.field2.Var1);π    Writeln('origpoint : ',minfo.field2.Var2);π  endπ  elseπ  beginπ    Writeln('    time1 : ',t1.month,'/',t1.day,'/',t1.year,'   ',π                           t1.hour,':',t1.min,':',t1.sec);π    Writeln('    time2 : ',t2.month,'/',t2.day,'/',t2.year,'   ',π                           t2.hour,':',t2.min,':',t2.sec);π  end;π  Writeln('  replyto : ',minfo.replyto  );π  Writeln('attribute : ',minfo.attribute);π  Writeln('  nextmsg : ',minfo.nextmsg  );π  Close(MSGFile);πend.ππ