home *** CD-ROM | disk | FTP | other *** search
- {$A-,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
-
- unit eco_sqsh;
- interface
- uses
- crt, dos,
- eco_lib, eco_lock
-
- ;
-
-
-
- type
- _fido_fromtype = string[35];
- _fido_totype = string[35];
- _fido_subtype = string[71];
- _fido_datetype = string[19];
-
-
- _fidomsgtype = record
- from : _fido_fromtype; (* 0 *)
- towhom : _fido_totype; (* 35 *)
- subject : _fido_subtype; (* 71 *)
- azdate : _fido_datetype; (* 142 obsolete/unused ascii date information *)
- timesread : word; (* 162 fido<tm>: number of times read *)
- dest_node : word; (* 164 destination node *)
- orig_node : word; (* 166 origination node number *)
- cost : word; (* 168 unit cost charged to send the message *)
- orig_net : word; (* 170 origination network number *)
- dest_net : word; (* 172 destination network number *)
-
- date_written : longint; (* 176 when user wrote the msg *)
- date_arrived : longint; (* 180 when msg arrived on-line *)
- reply : word; (* 184 current msg is a reply to this msg number *)
- attr : word; (* 186 attribute (behavior) of the message *)
- up : word; (* 188 Next message in the thread *)
- end;
-
-
-
-
- const
- msgprivate = $0001; (* for addressee *only* * 0000 0000 0000 0001 *)
- msgcrash = $0002; (* high priority * 0000 0000 0000 0010 *)
- msgread = $0004; (* was read by addressee * 0000 0000 0000 0100 *)
- msgsent = $0008; (* was sent by fidomail 0000 0000 0000 1000 *)
- msgfile = $0010; (* subj=file(s) to send * 0000 0000 0001 0000 *)
- msgfwd = $0020; (* msg from & to elsewhere 0000 0000 0010 0000 *)
- msgorphan = $0040; (* msg destination unknown 0000 0000 0100 0000 *)
- msgkill = $0080; (* delete after sending * 0000 0000 1000 0000 *)
- msglocal = $0100; (* msg is local, not net 0000 0001 0000 0000 *)
- msghold = $0200; (* hold msg for pickup * 0000 0010 0000 0000 *)
- msgcrap = $0400; (* ---------------------- x 0000 0100 0000 0000 *)
- msgfrq = $0800; (* subj=file(s) to get * 0000 1000 0000 0000 *)
- msgrrq = $1000; (* msg receipt requested x* 0001 0000 0000 0000 *)
- msgcpt = $2000; (* msg is a msg receipt x* 0010 0000 0000 0000 *)
- msgarq = $4000; (* audit trail requested x* 0100 0000 0000 0000 *)
- msgurq = $8000; (* subj=files(s) to upd x* 1000 0000 0000 0000 *)
- (*------------------------*)
- (* ^^ *)
- (* || *)
- (* ||* = preserved by *)
- (* || the network *)
- (* ||? = stripped by the *)
- (* | net (ftsc spec) *)
- (* | but preserved *)
- (* | by seadog<tm> *)
- (* |x = not used by opus *)
- (*------------------------*)
-
-
- const
- sysmail = $0001; (* is a mail area *)
- p_rep = $0002; (* opus: net mail private echomail back *)
- nopublic = $0004; (* opus: disallow public messages *)
- noprivate = $0008; (* opus: disallow private messages *)
- anon_ok = $0010; (* opus: enable anonymous messages *)
- echomail = $0020; (* opus: set=echomail clear=not echomail *)
- opus_ualias = $0040; (* opus170: use user's alias in this area *)
- highbit = $0040; (* max: allow high-bit chars in this area *)
- passthrough = $0080; (* opus170: passthough area only *)
- inbound = $0100; (* opus170: inbound only area *)
- nrealname = $0200; (* max: don't use ^aREALNAME for this area *)
- userealname = $0400; (* max: use usr.name instead of alias *)
- conf = $0800; (* max: conference-type area (no origin/sb's) *)
- max_ualias = $1000; (* max: use usr.alias instead of usr.name *)
-
-
-
- type
- umsgid_type = longint;
- recpos_type = longint;
- _address = record zone,net,node,point : word end;
- msgbuftype = array[0..0] of char;
- msgbufptrtype = ^msgbuftype;
-
-
- const
- sqhdrid = $afae4453; (* squish headers must have this number *)
- linknext = 0;
- linkprev = 1;
- nullframe = 0;
- frame_msg = 0; (* it's a live message *)
- frame_free = 1; (* the message is dead, avail for new msg *)
- frame_rle = 2; (* type of compression, not implemented *)
- frame_lzw = 3; (* type of compression, not implemented *)
- sqmsg_from_size = 36;
- sqmsg_to_size = 36;
- sqmsg_subj_size = 72;
- max_reply = 10; (* max number of stored replies to one msg *)
-
- (* this is the first record in the *.sqd file *)
-
- type
- _sqbasetype = record
- len : word; (* length of this structure! 0 2 *)
- rsvd1 : word; (* reserved word 2 4 *)
- num_msg, (* number of msgs 4 8 *)
- high_msg, (* highest msg - always equal to num_msg 8 12 *)
- skip_msg: longint; (* # of msgs to keep in beginning of area 12 16 *)
- high_water : umsgid_type; (* high water marker (umsgid) 16 20 *)
- uid : umsgid_type; (* last usmgid 20 24 *)
- base : string[79]; (* base name for squishfile 24 104 *)
- begin_frame, (* offset of first frame in file 104 108 *)
- last_frame, (* offset to last frame in file 108 112 *)
- first_free, (* offset of first free frame in file 112 116 *)
- last_free, (* ofs of the last free frame 116 120 *)
- end_frame : recpos_type; (* pointer to end of file 120 124 *)
- max_msg : longint; (* maximum number of messages 124 128 *)
- keep_days : word; (* max age of messages 128 130 *)
- sz_sqhdr : word; (* size of fram header 130 132 *)
- rsvd2 : array[1..124] of byte (* reserved area 132 256 *)
- end;
-
-
- (*
- After thge BASE record, follows a frame record for EACH message. The
- begin_frame in the base should point to the first frame header, and
- the next_frame in the frame header should point to the next one, etc.
- *)
-
- _sqfhdrtype = record
- id : longint; (* sqhdr.id must always equal sqhdrid *)
- next_frame, (* pointer to next msg in base *)
- prev_frame : recpos_type; (* pointer to prior msg in base *)
- frame_length, (* length of this frame (not counting header) *)
- msg_length, (* length of msg in frame. may be less than
- frame_length if this frame has been recycled. *)
- clen : longint; (* length of the control information. *)
- frame_type : word; (* Either FRAME_MESSAGE or FRAME_FREE. The API
- has been designed to allow things such
- as FRAME_LZSS or FRAME_LZH to be hacked on
- later, without changing the application. *)
- rsvd : word; (* reserved *)
- end;
-
-
- (*
-
- But right after each frame header, follows the squish message header,
- then the control info, then the text.
-
- *)
-
- _sqmhdrtype = record
- attr : longint;
- fromwhom : string[sqmsg_from_size-1];
- towhom : string[sqmsg_to_size-1];
- subj : string[sqmsg_subj_size-1];
- orig,
- dest : _address; (* origination and destination addresses *)
- date_written, (* when user wrote the msg (utc) *)
- date_arrived : longint; (* when msg arrived on-line (utc) *)
- utc_ofs : word; (* minutes offset from utc of message writer *)
- replyto : umsgid_type;
- replies : array[1..max_reply] of umsgid_type;
- azdate : string[19]; (* ascii date *)
- end;
-
-
- (*
- Each SQD file has a SQI FILES. The message number YOU see (the user)
- in MAX is really the counter starting from 1 of each record in SQI.
- But the TRUE UNIQUE Message ID is in umsgid. The ofs value will
- point to the frame header in SQD. These files are small and you
- may read them into a array SqiPtrArrayType using the functions
- below.
-
- *)
-
- _sqidxtype = record
- ofs : recpos_type; (* offset of frame header *)
- umsgid : umsgid_type; (* unique message identifier *)
- hash : longint; (* 'To' name hash value *)
- end;
-
- sqiptrarraytype = array[1..1] of _sqidxtype;
- sqiptrtype = ^sqiptrarraytype;
-
-
- (*
-
- Sizes of various structures. WARNING, alot of the routines use these
- variables. You should be more dynamic and reading the true sizes SCOTT
- puts in the squish structures (if any).
-
- *)
-
-
- const
- _sqbsize : word = sizeof(_sqbasetype);
- _sqfsize : word = sizeof(_sqfhdrtype);
- _sqmsize : word = sizeof(_sqmhdrtype);
- _sqisize : word = sizeof(_sqidxtype);
- _sdmsize : word = sizeof(_fidomsgtype);
-
-
- (*
-
- Function Prototypes in this unit.
-
- *)
-
-
-
- function sqsetsqbsize(var fd: file): integer;
- function sqopensqd(name: string; var fd: file; lock : boolean): integer;
- function sqclosesqd(var fd: file): integer;
- function sqreadbhdr(var fd: file; var sb: _sqbasetype): integer;
- function sqwritebhdr(var fd: file; var sb: _sqbasetype): integer;
- function sqreadfhdr(var fd: file; var sf: _sqfhdrtype; fp: longint): integer;
- function sqwritefhdr(var fd: file; var sf: _sqfhdrtype; fp: longint): integer;
- function sqreadmhdr(var fd: file; var sm: _sqmhdrtype; fp: longint): integer;
- function sqwritemhdr(var fd: file; var sm: _sqmhdrtype; fp: longint): integer;
- function sqreadmtxt(var fd: file; var st; fp: longint; ml: longint): integer;
- function sqwritemtxt(var fd: file; var st; fp: longint; ml: longint): integer;
- function sqopensqi(name: string; var fd: file): integer;
- function sqclosesqi(var fd: file): integer;
- function sqreadsqi(var fd: file; var si: _sqidxtype; fp: longint): integer;
- function sqwritesqi(var fd: file; var si: _sqidxtype; fp: longint): integer;
- function sdmread(name: string; var mh: _fidomsgtype; var mb: msgbufptrtype; var mz: longint): integer;
- function squnlinkframe(var fd: file; var sf: _sqfhdrtype): integer;
- function sqlinkframe(var fd: file; var sf: _sqfhdrtype; tp, lp: longint; op: word): integer;
- function sqfreeframe(var fd: file; var sb: _sqbasetype; rp: longint): integer;
- function sqfindframe(var fd: file; var sb: _sqbasetype; var fl, rp: longint): integer;
- function sqnewframe(var fd: file; var sb: _sqbasetype; var sf: _sqfhdrtype; var ml, rp: longint): integer;
- function sqreplaceframe(var fd: file; var sb: _sqbasetype; var sf: _sqfhdrtype; var rp, ml: longint): integer;
-
- function sqazhashname(var s): longint;
- function sqhashname (name : string) : longint;
- procedure squishsqiptr(var sqiptr : sqiptrtype; fn :pathstr; var sqisize : longint);
- function squishmsgntouid(var sqiptr : sqiptrtype; msgn : word ; totalsqi : word) : longint;
- function squishuidtomsgn(var sqiptr : sqiptrtype; uid : longint; totalsqi : word) : word;
- function getsquishbaserec(fn : pathstr; var sqbaserec : _sqbasetype) : integer;
- function setsquishmsgattribute(var fvsqd : file; var fpos : longint; newattr : longint) : integer;
-
-
- { conversion from MSG to Squish }
- function sdmtosqd(
- mname,
- sname: string;
- var mh : _fidomsgtype;
- var newnum : word;
- lockit : boolean
- ): integer;
-
- procedure arrangetxt(var msg: msgbufptrtype; var msiz, csiz: longint);
-
-
-
-
-
- implementation
-
-
-
-
-
-
-
- (* open a "*.SQD" file *)
-
- const _sqd_file_locked : boolean = false; (* dont fuss with this variable *)
-
- function sqopensqd(name: string; var fd: file; lock : boolean): integer;
- var
- r : integer;
- ax : integer;
- cnt : integer;
- begin
- r := fopen(fd,__set_ext(name,'SQD'),_readwrite+_denynone);
- ax := r;
- if (r = 0) and lock and (not _sqd_file_locked) then
- begin
- cnt := 1500;
- repeat
- if not filelock(filerec(fd).handle,lockregion,0,1,ax) then
- begin
- case ax of
- 33, (* lock voilation *)
- 32, (* share voilation *)
- 5, (* access denied *)
- 167 (* hardware share voilation *)
- : delay(10);
- end;
- dec(cnt);
- end
- else begin
- ax := 0;
- _sqd_file_locked := true;
- end;
- until (cnt=0) or (ax=0);
- end;
- sqopensqd := ax;
- end;
-
- (* close a "*.SQD" file *)
-
- function sqclosesqd(var fd: file): integer;
- var
- r: integer;
- ax : integer;
-
- begin
- r := 5;
- if _sqd_file_locked then
- if not filelock(filerec(fd).handle,unlockregion,0,1,ax)
- then writeln(#13#10'>>ERR#', ax, ' :FAILED TO UNLOCK ', __mat2str(filerec(fd).name,50))
- else _sqd_file_locked := false;
- r := fclose(fd);
- sqclosesqd := r
- end;
-
- (* read any data from a "*.SQD" file *)
-
- function sqreaddata(var fd: file; var da; fp: longint; sz: word): integer;
- var
- r: integer;
- begin
- seek(fd,fp);
- r := ioresult;
- if (r = 0) then
- begin
- blockread(fd,da,sz,r);
- r := ioresult
- end;
- sqreaddata := r
- end;
-
- (* write any data to a "*.SQD" file *)
-
- function sqwritedata(var fd: file; var da; fp: longint; sz: word): integer;
- var
- r: integer;
- begin
- seek(fd,fp);
- r := ioresult;
- if (r = 0) then
- begin
- blockwrite(fd,da,sz,r);
- r := ioresult
- end;
- sqwritedata := r
- end;
-
- (* Read a "*.SQD" base header. MAKE SURE SQBSIZE IS SET CURRENTLY FOR
- the version max *)
-
- function sqreadbhdr(var fd: file; var sb: _sqbasetype): integer;
- begin
- sqreadbhdr := sqreaddata(fd,sb,0,_sqbsize)
- end;
-
- (*
- Read a "*.SQD" base header structure SIZE. Once you call the SqOPENSQB
- you should call this function to make sure the SQBSIZE variable is
- current.
- *)
-
- function sqsetsqbsize(var fd: file): integer;
- begin
- sqsetsqbsize := sqreaddata(fd,_sqbsize,0,sizeof(word))
- end;
-
- (* write a "*.SQD" base header *)
-
- function sqwritebhdr(var fd: file; var sb: _sqbasetype): integer;
- begin
- sqwritebhdr := sqwritedata(fd,sb,0,_sqbsize)
- end;
-
- (* read a "*.SQD" frame header *)
-
- function sqreadfhdr(var fd: file; var sf: _sqfhdrtype; fp: longint): integer;
- begin
- sqreadfhdr := sqreaddata(fd,sf,fp,_sqfsize)
- end;
-
- (* write a "*.SQD" frame header *)
-
- function sqwritefhdr(var fd: file; var sf: _sqfhdrtype; fp: longint): integer;
- begin
- sqwritefhdr := sqwritedata(fd,sf,fp,_sqfsize)
- end;
-
- (* read a "*.SQD" message header *)
-
- function sqreadmhdr(var fd: file; var sm: _sqmhdrtype; fp: longint): integer;
- begin
- sqreadmhdr := sqreaddata(fd,sm,fp+_sqfsize,_sqmsize)
- end;
-
- (* write a "*.SQD" message header *)
-
- function sqwritemhdr(var fd: file; var sm: _sqmhdrtype; fp: longint): integer;
- begin
- sqwritemhdr := sqwritedata(fd,sm,fp+_sqfsize,_sqmsize)
- end;
-
- (* read a "*.SQD" message text *)
-
- function sqreadmtxt(var fd: file; var st; fp: longint; ml: longint): integer;
- begin
- sqreadmtxt := sqreaddata(fd,st,fp+_sqfsize+_sqmsize,ml-_sqmsize)
- end;
-
- (* write a "*.SQD" message text *)
-
- function sqwritemtxt(var fd: file; var st; fp: longint; ml: longint): integer;
- begin
- sqwritemtxt := sqwritedata(fd,st,fp+_sqfsize+_sqmsize,ml-_sqmsize)
- end;
-
- (* open a "*.SQI" file *)
-
- function sqopensqi(name: string; var fd: file): integer;
- begin
- sqopensqi := fopen(fd,__set_ext(name,'SQI'),_readwrite+_denynone);
- end;
-
- (* close a "*.SQI" file *)
-
- function sqclosesqi(var fd: file): integer;
- begin
- sqclosesqi := fclose(fd);
- end;
-
- (* read a "*.SQI" index record *)
-
- function sqreadsqi(var fd: file; var si: _sqidxtype; fp: longint): integer;
- var
- r: integer;
- begin
- seek(fd,fp*_sqisize);
- r := ioresult;
- if (r = 0) then
- begin
- blockread(fd,si,_sqisize,r);
- r := ioresult
- end;
- sqreadsqi := r
- end;
-
- (* write a "*.SQI" index record *)
-
- function sqwritesqi(var fd: file; var si: _sqidxtype; fp: longint): integer;
- var
- r: integer;
- begin
- seek(fd,fp*_sqisize);
- r := ioresult;
- if (r = 0) then
- begin
- blockwrite(fd,si,_sqisize,r);
- r := ioresult
- end;
- sqwritesqi := r
- end;
-
- (* open and read a "*.MSG" file *)
-
- function sdmread(name: string; var mh: _fidomsgtype; var mb: msgbufptrtype; var mz: longint): integer;
- var
- rc: integer;
- br: word;
- fd: file;
- begin
- assign(fd,name);
- reset(fd,1);
- rc := ioresult;
- mb := nil;
- if (rc = 0) then
- begin
- blockread(fd,mh,_sdmsize,br);
- mz := filesize(fd) - _sdmsize;
- getmem(mb,mz);
- blockread(fd,mb^,mz,br);
- if (mb^[br] <> #0) then mb^[br] := #0; (* force a null terminator *)
- close(fd)
- end;
- sdmread := rc
- end;
-
- (* unlink a frame from the chain *)
-
- function squnlinkframe(var fd: file; var sf: _sqfhdrtype): integer;
- var
- r: integer;
- sh: _sqfhdrtype;
- begin
- r := 0;
- if (sf.prev_frame <> 0) then
- begin
- r := sqreadfhdr(fd,sh,sf.prev_frame);
- if (r = 0) then
- begin
- sh.next_frame := sf.next_frame;
- r := sqwritefhdr(fd,sh,sf.prev_frame)
- end
- end;
- if ((r = 0) and (sf.next_frame <> 0)) then
- begin
- r := sqreadfhdr(fd,sh,sf.next_frame);
- if (r = 0) then
- begin
- sh.prev_frame := sf.prev_frame;
- r := sqwritefhdr(fd,sh,sf.next_frame)
- end
- end;
- squnlinkframe := r
- end;
-
- function sqlinkframe(var fd: file; var sf: _sqfhdrtype; tp, lp: longint; op: word): integer;
- var
- r: integer;
- nxt: longint;
- sh: _sqfhdrtype;
- begin
- r := 0;
- if (tp <> nullframe) then
- begin
- r := sqreadfhdr(fd,sh,tp);
- if (r = 0) then
- begin
- if (op = linknext) then
- begin
- sf.prev_frame := tp;
- nxt := sh.next_frame;
- sh.next_frame := lp
- end
- else
- begin
- sf.next_frame := tp;
- nxt := sh.prev_frame;
- sh.prev_frame := lp
- end;
- r := sqwritefhdr(fd,sh,tp);
- tp := nxt
- end;
- if ((r = 0) and (tp <> nullframe)) then
- begin
- r := sqreadfhdr(fd,sh,tp);
- if (r = 0) then
- begin
- if (op = linknext) then
- begin
- sh.prev_frame := lp;
- sf.next_frame := tp
- end
- else
- begin
- sf.prev_frame := tp;
- sh.next_frame := lp
- end;
- r := sqwritefhdr(fd,sh,tp)
- end
- end
- end;
- sqlinkframe := r
- end;
-
- function sqrelinkframe(var fd: file; var sf: _sqfhdrtype; rp: longint): integer;
- var
- r: integer;
- begin
- if (sf.next_frame = nullframe) then
- r := sqlinkframe(fd,sf,sf.prev_frame,rp,linknext)
- else
- r := sqlinkframe(fd,sf,sf.next_frame,rp,linkprev);
- sqrelinkframe := r
- end;
-
- function sqfreeframe(var fd: file; var sb: _sqbasetype; rp: longint): integer;
- var
- r: integer;
- sqn,
- sqn1: _sqfhdrtype;
- begin
- r := sqreadfhdr(fd,sqn,rp);
- if (r = 0) then
- begin
- r := squnlinkframe(fd,sqn);
- if (r = 0) then
- begin
- if (sb.begin_frame = rp) then
- sb.begin_frame := sqn.next_frame;
- if (sb.last_frame = rp) then
- sb.last_frame := sqn.prev_frame;
- sqn.frame_type := word(frame_free);
- if (sb.first_free = nullframe) then
- begin
- sb.first_free := rp;
- sb.last_free := rp;
- sqn.prev_frame := nullframe;
- sqn.next_frame := nullframe
- end
- else
- begin
- r := sqreadfhdr(fd,sqn1,sb.last_free);
- if (r = 0) then
- begin
- sqn1.next_frame := rp;
- r := sqwritefhdr(fd,sqn1,sb.last_free);
- sqn.prev_frame := sb.last_free;
- sqn.next_frame := nullframe
- end
- end;
- if (r = 0) then
- begin
- sb.last_free := rp;
- r := sqwritefhdr(fd,sqn,rp)
- end
- end
- end;
- sqfreeframe := r
- end;
-
- function sqfindframe(var fd: file; var sb: _sqbasetype; var fl, rp: longint): integer;
- var
- r: integer;
- sqn: _sqfhdrtype;
- break: boolean;
- begin
- r := 0;
- break := false;
- rp := sb.first_free;
- while ((rp > nullframe) and (not break)) do
- begin
- r := sqreadfhdr(fd,sqn,rp);
- if ((r = 0) and (fl < sqn.frame_length)) then
- break := true
- else
- rp := sqn.next_frame
- end;
- if (r = 0) then
- begin
- if (rp = nullframe) then
- begin
- fl := 0;
- rp := sb.end_frame
- end
- else
- begin
- r := squnlinkframe(fd,sqn);
- if (r = 0) then
- begin
- if (sqn.prev_frame = nullframe) then
- sb.first_free := sqn.next_frame;
- if (sqn.next_frame = nullframe) then
- sb.last_free := sqn.prev_frame;
- fl := sqn.frame_length
- end
- end
- end;
- sqfindframe := r
- end;
-
- function sqnewframe(var fd: file; var sb: _sqbasetype; var sf: _sqfhdrtype; var ml, rp: longint): integer;
- var
- r: integer;
- sqn: _sqfhdrtype;
- begin
- r := sqfindframe(fd,sb,ml,rp);
- if (r = 0) then
- begin
- if (sb.last_frame <> nullframe) then
- begin
- r := sqreadfhdr(fd,sqn,sb.last_frame);
- if (r = 0) then
- begin
- sqn.next_frame := rp;
- r := sqwritefhdr(fd,sqn,sb.last_frame)
- end
- end
- else
- sb.begin_frame := rp;
- if (r = 0) then
- begin
- sf.id := sqhdrid;
- sf.frame_type := word(frame_msg);
- sf.prev_frame := sb.last_frame;
- sb.last_frame := rp;
- sf.next_frame := nullframe
- end
- end;
- sqnewframe := r
- end;
-
- function sqreplaceframe(var fd: file; var sb: _sqbasetype; var sf: _sqfhdrtype; var rp, ml: longint): integer;
- var
- r: integer;
- begin
- r := sqreadfhdr(fd,sf,rp);
- if (r = 0) then
- begin
- if (ml > sf.frame_length) then
- begin
- r := sqfreeframe(fd,sb,rp);
- if (r = 0) then
- begin
- sf.frame_length := ml;
- r := sqfindframe(fd,sb,sf.frame_length,rp);
- if (r = 0) then
- begin
- if (sf.prev_frame = nullframe) then
- sb.begin_frame := rp;
- if (sf.next_frame = nullframe) then
- sb.last_frame := rp
- end
- end
- end
- end;
- sqreplaceframe := r
- end;
-
- (* Convert a asciiz username into a hash value for the index. The logic
- used in this code (pointer arithmetic) is ok to use because we are
- dealing with small lengths and will never exceed 64k.
- *)
-
- function sqazhashname(var s): longint;
- var
- p: ^char;
- g,
- hash: longint;
- begin
- hash := 0;
- p := @s;
- while (p^ <> #0) do
- begin
- hash := (hash shl 4) + byte(locase(p^));
- g := (hash and $f0000000);
- if (g <> 0) then
- begin
- hash := (hash or (g shr 24));
- hash := (hash or g)
- end;
- inc(longint(p))
- end;
- sqazhashname := (hash and $7fffffff)
- end;
-
- (* Convert a Pascal username into a hash value for the index.
- *)
-
- function sqhashname (name : string) : longint;
- var p : integer;
- hash,g : longint;
- begin
- hash := 0;
- for p := 1 to length(name) do
- begin
- hash := (hash shl 4) + ord(locase(name[p]));
- g := hash and $f0000000;
- if (g <> 0) then
- begin
- hash := hash or (g shr 24);
- hash := hash or g;
- end;
- end;
- sqhashname := hash and $7fffffff;
- end;
-
- (*
- The following functions are used convert back and forth between between
- the msg number and the unique msg id in the sqi files. You should use
- these for lastread pointers, reply links, etc.
- *)
-
-
- function squishuidtomsgn(var sqiptr : sqiptrtype; uid : longint; totalsqi : word) : word;
- var idx : word;
- begin
- squishuidtomsgn := 0;
- if (sqiptr <> nil) and (totalsqi > 0) and (uid > 0) then
- begin
- idx := 1;
- while (uid > sqiptr^[idx].umsgid) and ((idx) <= totalsqi) do inc(idx);
- if idx > totalsqi then idx := totalsqi;
- squishuidtomsgn := idx;
- end;
- end;
-
- function squishmsgntouid(var sqiptr : sqiptrtype; msgn : word ; totalsqi : word) : longint;
- begin
- squishmsgntouid := 0;
- if (sqiptr <> nil) and (totalsqi > 0) then
- begin
- if msgn > totalsqi then msgn := totalsqi;
- if msgn = 0 then msgn := 1;
- squishmsgntouid := sqiptr^[msgn].umsgid;
- end;
- end;
-
- (*
- Open SQI file and read in the entire file. This is your INDEX system
- to the SQD files. Once in memory, you can cycle thru this list by
- msg #, UID # or user name (hash) and get the offset to the Squish header
- record in the SQD file. (Double check the SQHDR_ID value to make sure
- the record is valid).
-
- ie, Var sqiptr : sqpptrtype;
- sqisize : longint;
- actrecs : word;
-
- SquishSQIPtr(sqiptr,'XPRESS.SQI',sqisize);
- actrecs := sqisize div _SQISIZE;
-
- .
- .
- .
-
- FreeMem(sqiptr,sqisize);
-
- Don't forget to FREE the the Sqiptr pointer variable using the sqisize
- passed.
-
- *)
-
- procedure squishsqiptr(var sqiptr : sqiptrtype; fn :pathstr; var sqisize : longint);
- var fv : stream;
- abytes : word;
-
- begin
- sqiptr := nil;
- sqisize := 0;
- if fopen(fv,fn,_readonly+_denynone) <> 0 then exit;
- sqisize := filesize(fv);
- if sqisize = 0 then
- begin
- fclose(fv);
- exit;
- end;
- getmem(sqiptr,sqisize);
- if sqiptr <> nil then blockread(fv,sqiptr^,sqisize,abytes);
- fclose(fv);
- end;
-
- function getsquishbaserec(fn : pathstr; var sqbaserec : _sqbasetype) : integer;
- var fv : stream;
- ax : integer;
- ab : word;
- begin
- ax := fopen(fv,fn,_readonly+_denynone);
- getsquishbaserec := ax;
- if ax = 0 then
- begin
- (* sq base *)
- blockread(fv,sqbaserec,_sqbsize,ab);
- fclose(fv);
- end;
- end;
-
-
-
-
- (* Given message frame position, read message header and set the message
- attribute bit. The newattr is ORed to the previous value. *)
-
- function setsquishmsgattribute(
- var fvsqd : file;
- var fpos : longint;
- newattr : longint
- ) : integer;
-
- var
- xmsg : _sqmhdrtype;
-
- begin
- setsquishmsgattribute := -1;
- if sqreadmhdr(fvsqd,xmsg,fpos) = 0 then begin
- xmsg.attr := xmsg.attr or newattr;
- setsquishmsgattribute := sqwritemhdr(fvsqd,xmsg,fpos);
- end;
- end;
-
-
-
-
- (* Function, given ptr to buffer and size , will arrange the control info
- and message test, and return the new sizes for both sections *)
-
- procedure arrangetxt(var msg: msgbufptrtype; var msiz, csiz: longint);
- var
- mpos, cpos,
- tsize : word;
-
- begin
- mpos := 0; cpos := 0; tsize := msiz;
- while (msg^[mpos] = #10) do inc(mpos);
- while (msg^[mpos] = #1) do begin
- if (mpos > cpos) then begin
- move(msg^[mpos],msg^[cpos],msiz - mpos);
- dec(msiz,mpos - cpos); cpos := mpos
- end;
- while (not (msg^[cpos] in [#0,#13])) do inc(cpos);
- if (msg^[cpos] = #13) then begin
- msg^[cpos] := #0;
- mpos := cpos + 1;
- while (msg^[mpos] = #10) do inc(mpos)
- end else mpos := cpos
- end;
- if (msg^[msiz] <> #0) then msg^[msiz] := #0;
- csiz := 0;
- if (msg^[0] = #1) then begin
- while (msg^[csiz] <> #0) do inc(csiz);
- inc(csiz)
- end;
- if (csiz = 0) then begin
- move(msg^[csiz],msg^[csiz+1],msiz);
- inc(msiz);
- msg^[0] := #0;
- csiz := 1
- end
- end;
-
-
-
- (* convert "*.MSG" header to squish message header *)
-
-
- procedure sdmtosqmhdr(var mh: _fidomsgtype; var sh: _sqmhdrtype);
- begin
- fillchar(sh,sizeof(_sqmhdrtype),#0);
- move(mh.towhom, sh.towhom, 36);
- move(mh.from, sh.fromwhom,36);
- move(mh.subject, sh.subj,72);
- move(mh.azdate, sh.azdate,20);
- sh.orig.zone := 0;
- sh.dest.zone := 0;
- sh.orig.net := mh.orig_net;
- sh.dest.net := mh.dest_net;
- sh.orig.node := mh.orig_node;
- sh.dest.node := mh.dest_node;
- sh.attr := mh.attr;
- sh.date_written := mh.date_written;
- sh.date_arrived := mh.date_arrived;
- sh.replyto := mh.reply
- end;
-
-
-
-
- function sdmtosqd(
- mname,
- sname: string;
- var mh : _fidomsgtype;
- var newnum : word;
- lockit : boolean
- ): integer;
-
- var
- mb : msgbufptrtype;
- fo, fz, mz, cz : longint;
- sb : _sqbasetype;
- sf : _sqfhdrtype;
- sm : _sqmhdrtype;
- si : _sqidxtype;
- rc : integer;
- fi, fd : file;
- msize : longint;
-
- begin
- rc := sdmread(mname,mh,mb,msize);
- if (rc = 0) then begin
- mz := msize;
- arrangetxt(mb,mz,cz);
- inc(mz,_sqmsize);
- rc := sqopensqd(sname,fd,lockit);
- if (rc = 0) then begin
- rc := sqreadbhdr(fd,sb);
- if (rc = 0) then begin
- fz := mz;
- rc := sqnewframe(fd,sb,sf,fz,fo);
- if (rc = 0) then begin
- sf.frame_length := fz;
- sf.msg_length := mz;
- sf.clen := cz;
- if (sf.frame_length = 0) then begin
- sf.frame_length := sf.msg_length;
- sb.end_frame := fo + _sqfsize + _sqmsize + sf.frame_length
- end;
- rc := sqwritefhdr(fd,sf,fo);
- if (rc = 0) then begin
- sdmtosqmhdr(mh,sm);
- rc := sqwritemhdr(fd,sm,fo);
- if (rc = 0) then begin
- rc := sqwritemtxt(fd,mb^,fo,mz);
- if (rc = 0) then begin
- si.ofs := fo;
- si.umsgid := sb.uid;
- si.hash := sqazhashname(sm.towhom);
- inc(sb.num_msg);
- sb.high_msg := sb.num_msg;
- inc(sb.uid);
- rc := sqwritebhdr(fd,sb);
- if (rc = 0) then begin
- rc := sqopensqi(sname,fi);
- if (rc = 0) then begin
- rc := sqwritesqi(fi,si,sb.num_msg-1);
- rc := sqclosesqi(fi);
- newnum := sb.num_msg;
- end
- end
- end
- end
- end
- end
- end;
- rc := sqclosesqd(fd)
- end
- end;
- if mb <> nil then freemem(mb,msize);
- sdmtosqd := rc
- end;
-
-
-
-
-
- end.
-
-
- The BASE RECORD and the FRAME RECORD are potentially dynamic records.
- When a squish file SQD is open, you should call SQSetSQBSize to reset
- the SQBSIZE variable to proper the length, and when do you read in the
- BASE RECORD, set the SBFSIZE variable to the value defined in the base
- record. Doing so, will atleast conform to the way MAX today is setup for
- the future changes in the base structure.
-
- There is no critical error trap routines here. It is your programming
- responsibility to TRAP and CLOSE, and especially UNLOCK any open SQUISH
- file if a critical error occurs. There is a local unit variable
- _SQD_FILE_LOCKED which is used here to determine if a message based is
- locked when a closing function is called. It is suggested that you test
- for this variable's logical state in your critical error trap routine.
-
- Description:
-
- Squish has four files:
-
- *.SQL - the lastread pointers are stored for the user. The lastus00.dat
- file has the user's record number. Seek to it and read a word
- to get lastread value for the user for the message base.
-
- *.SQI - is a index of LIVE MESSAGES in the Squish *.SQD file. It
- basically stores the 'unique' message id for each message,
- the offset of the SQUISH messahe header (sqhdr) and the
- HASH of the TOWHOM user's name.
-
- *.SQD - has all the mail. The basic layout is:
-
- BASE_RECORD
-
- then for each message
-
- SQUISH MESSAGE HEADER
- CONTROL INFORMATION Where all ^A stuff is stored
- TEXT MESSAGE may not always be null terminated
-
- The base record will tell you where the first squish msg header
- is at, and each msg header will point to the next or prev one.
-
- In addition, the base record also will point to the first FREE
- (one that was marked deleted) Squish Message Header and so on.
-
- So from the base record, you can get a "Doublely linked list"
- of both the live messages and free messages.
-
- *.SQB - something to do with dupe checking and I think it's for the
- squish mail processor. Not discussed or used in the this API.
-
-
-