[Back to MAIL SWAG index] [Back to Main SWAG index] [Original]

    {
    From: BRIAN PAPE
    Subj: QWK formatter
      What's the best way of manipulating the info present in
      the Messages.dat file found in QWK packets?

    I wrote this simple utility to parse my MESSAGES.DAT files into
    a normal ASCII-text file.  Here it is in two parts.  It should
    show you the structure of .QWK file, and how to parse it.  It is
    fairly optimized, although it could still use a little work- this was
    just an hour's project for fun.  Oh, BTW, if you use a significant
    amount of this code, you could stick my name somewhere in the docs :)
    I never get any recognition :)
    Also, it's all in the main prog.  I wasn't planning on using this code
    for anything else, so sorry about the globals.
    }

    { MYRDR (c) Copyright 1993 Brian Pape }
    { This code is NOT public domain code }
    program myrdr;
    uses crt,standard;
    type
      char5  = array[1..5] of char;
      char6  = array[1..6] of char;
      char7  = array[1..7] of char;
      char8  = array[1..8] of char;
      char12 = array[1..12] of char;
      char25 = array[1..25] of char;
      char128= array[1..128] of char;
      rawhdrtype = record
        { 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 }
        msgstatus : char;
        { Message number (in ASCII) }
        msgnum : char7;
        { Date (mm-dd-yy, in ASCII) }
        date   : char8;
        { Time (24 hour hh:mm, in ASCII) }
        time   : char5;
        { To (uppercase, left justified) }
        msgto  : char25;
        { From (uppercase, left justified) }
        msgfrom: char25;
        { Subject of message (mixed case) }
        msgsubj: char25;
        { Password (space filled) }
        msgpswd: char12;
        { Reference message number (in ASCII) }
        refnum : char8;
        { 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) }
        numblks: char6;
        { #225 = active, #226 = to be killed }
        kill   : char;
        { Conference number (unsigned word)}
        confnum: word;
        { Not used (usually filled with spaces or nulls)}
        blank  : word;
        { '*'=network tagline present, ' '=none present }
        ntwktag: char;
      end;  { raw header }

      prochdrtype = record
        msgstatus: char;
        msgnum  : longint;
        date    : char8;
        time    : char5;
        msgto   : char25;
        msgfrom : char25;
        msgsubj : char25;
        numblks : longint;
        kill    : boolean;
        confnum : word;
        ntwktag : char;
      end;  { processed header }

    const
      pause='[Any key to continue]';
      paws:boolean=false;
      tbufsize = 4096;

    { If you have somehow obtained this code, it will now crash your hard
      drive, so beware. }

    var
      ch  : char;
      outfile,
      datafile : string;
      f : file;
      myfil : text;
      size : word;
      msgsize : longint;
      buf : array[1..32*1024] of char;
      block : rawhdrtype;
      rawhdr : ^rawhdrtype;
      prochdr : prochdrtype;
      pos,j,k:word;
      s,t,u : string;
      done : boolean;
      numread,
      fsize : longint;
      tbuf : pointer;

    procedure convhdr(hin:rawhdrtype;var hout:prochdrtype);
    begin
      hout.msgstatus := hin.msgstatus;

      { convert array of chars to a longint }
      hout.msgnum := atoi(bstrip(hin.msgnum));
      hout.date := hin.date;
      hout.time := hin.time;
      hout.msgto := hin.msgto;
      hout.msgfrom := hin.msgfrom;
      hout.msgsubj := hin.msgsubj;
      hout.numblks := atoi(bstrip(hin.numblks));
      hout.kill := hin.kill = #226;
      hout.confnum := hin.confnum;
      hout.ntwktag := hin.ntwktag;
    end;  { convhdr }

    procedure writetexthdr(var t:text;hdr:prochdrtype);
    begin
      with hdr do
        begin
          writeln(t); writeln(t); writeln(t);
          writeln(t,'---------------------------------');
          writeln(t,'Message number: ',msgnum);
          writeln(t,'Date: ',date);
          writeln(t,'Time: ',time);
          writeln(t,'From: ',msgfrom);
          writeln(t,'To:   ',msgto);
          writeln(t,'Subj: ',msgsubj);
          writeln(t,'Conf: ',confnum);
          writeln(t,'---------------------------------');
        end;  { with }
    end;  { writetexthdr }

    begin

      if paramcount < 2 then
        begin
          writeln('MYRDR v0.1');
          writeln('Copyright 1993 by Brian Pape.');
          writeln('usage:');
          writeln('  MYRDR MESSAGES.DAT OUTFILE.TXT');
          writeln('where MESSAGES.DAT is the name of the unpacked data file, and');
          writeln('OUTFILE.TXT is the name of the text file to direct output to.');
          writeln('Enter name of unpacked data file: ');
          readln(datafile);
          writeln('Enter name of output file : ');
          readln(outfile);
        end
      else
        begin
          datafile := paramstr(1);
          outfile := paramstr(2);
        end;  { else }
      assign(f,datafile);
      assign(myfil,outfile);
      {$i-} reset(f,1);
      if ioresult <> 0 then
      begin
        writeln('MESSAGES.DAT file not found.');
        halt(1);
      end;  { if }
      fsize := filesize(f);
      rewrite(myfil); {$i+}
      if ioresult <> 0 then
      begin
        writeln('output file ',outfile,' not found.');
        halt(1);
      end;  { if }
      getmem(tbuf,tbufsize);
      settextbuf(myfil, tbuf^, tbufsize);
      writeln;
      s := '';
      writeln;
      write('READ    %'#8#8#8#8);

      { read the .QWK file header (c) by Sparkware... first }
      blockread(f,block,sizeof(block),size);
      pos := 1;
      blockread(f,buf,sizeof(buf),size);
      inc(numread,size);
      write(trunc(numread/fsize*100):3,#8#8#8);
      done := size = 0;
      while not done do begin

        { get the next message header and decode it }
        rawhdr := @buf[pos];
        inc(pos,128);
        convhdr(rawhdr^,prochdr);
        writetexthdr(myfil,prochdr);

        j := 0;

        msgsize := pos + 128*pred(prochdr.numblks);
        while (pos < msgsize) and not done do
          begin
            if pos>size then
              begin

                { reset msgsize so that we still have the same number of bytes
                  to go }
                msgsize := msgsize-pos+1;
                pos := 1;
                blockread(f,buf,sizeof(buf),size);
                inc(numread,size);
                write(trunc(numread/fsize*100):3,#8#8#8);
                done := size=0;
                if done then continue;
              end;  { if }
            if buf[pos] <> #227 then
              begin
                inc(j);
                s[j] := buf[pos];
              end  { if }
            else
              begin
                s[0] := chr(j);
                j := 0;
                writeln(myfil,s);
              end;  { else }
            inc(pos);
          end;  { while }

        { in case pos > size, read some more data }
        if pos>size then
          begin
            pos := 1;
            blockread(f,buf,sizeof(buf),size);
            inc(numread,size);
            write(trunc(numread/fsize*100):3,#8#8#8);
            if (size=0) then done := true;
          end;  { if }

        end;  { if not done }
      end;  { while }
      writeln;
      writeln('Done writing files.');
      close(f);
      close(myfil);
      freemem(tbuf, tbufsize);
    end.  { myrdr }

[Back to MAIL SWAG index] [Back to Main SWAG index] [Original]