mysticbbs/mystic/mutil_msgpack.pas

292 lines
8.3 KiB
ObjectPascal

// ====================================================================
// Mystic BBS Software Copyright 1997-2013 By James Coyle
// ====================================================================
//
// This file is part of Mystic BBS.
//
// Mystic BBS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Mystic BBS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Mystic BBS. If not, see <http://www.gnu.org/licenses/>.
//
// ====================================================================
Unit MUTIL_MsgPack;
{$I M_OPS.PAS}
Interface
Procedure uPackMessageBases;
Implementation
Uses
m_Strings,
m_FileIO,
mUtil_Common,
mUtil_Status,
BBS_DataBase,
bbs_MsgBase_ABS,
bbs_MsgBase_JAM,
bbs_MsgBase_Squish;
{$I RECORDS.PAS}
Procedure uPackMessageBases;
Type
RecMsgLink = Record
OldNum : Cardinal;
NewNum : Cardinal;
End;
Var
LinkFile : TFileBuffer;
BaseKills : Cardinal = 0;
BaseTotal : Cardinal = 0;
TotalKills : Cardinal = 0;
Function GetMessageLink (OldNum: Cardinal; Zero: Boolean) : Cardinal;
Var
L : RecMsgLink;
Res : LongInt;
Begin
LinkFile.SeekRaw(0);
While Not LinkFile.EOF Do Begin
LinkFile.ReadBlock (L, SizeOf(L), Res);
If L.OldNum = OldNum Then Begin
Result := L.NewNum;
Exit;
End;
End;
If Zero Then
Result := 0
Else
Result := OldNum;
End;
Procedure PackOneBase (Var MsgBase: RecMessageBase);
Const
TempName = 'msgpacktemp';
Var
MsgData : PMsgBaseABS;
NewData : PMsgBaseABS;
SaveMsg : Boolean = False;
UserTotal : Cardinal;
Link : RecMsgLink;
Count : Cardinal;
Begin
FileMode := 66;
BaseKills := 0;
Inc (BaseTotal);
Case MsgBase.BaseType of
0 : Begin
MsgData := New(PMsgBaseJAM, Init);
NewData := New(PMsgBaseJAM, Init);
End;
1 : Begin
MsgData := New(PMsgBaseSquish, Init);
NewData := New(PMsgBaseSquish, Init);
End;
End;
MsgData^.SetMsgPath (MsgBase.Path + MsgBase.FileName);
MsgData^.SetTempFile (TempPath + 'msgbuf.old');
NewData^.SetMsgPath (TempPath + TempName);
NewData^.SetTempFile (TempPath + 'msgbuf.new');
If Not MsgData^.OpenMsgBase Then Begin
Dispose (MsgData, Done);
Dispose (NewData, Done);
Exit;
End;
If Not NewData^.CreateMsgBase (MsgBase.MaxMsgs, MsgBase.MaxAge) Then Begin
Dispose (MsgData, Done);
Dispose (NewData, Done);
Exit;
End;
If Not NewData^.OpenMsgBase Then Begin
Dispose (MsgData, Done);
Dispose (NewData, Done);
Exit;
End;
LinkFile := TFileBuffer.Create (8 * 1024);
LinkFile.OpenStream (TempPath + TempName + '.tmp', 1, fmCreate, fmRWDN);
MsgData^.SeekFirst(1);
While MsgData^.SeekFound Do Begin
MsgData^.MsgStartUp;
SaveMsg := True;
// option:
// if private/netmail message area check to make sure users are valid
// and delete if they are not.
// also do kludges make it successfully? replyID etc?
If SaveMsg Then Begin
NewData^.StartNewMsg;
NewData^.SetFrom (MsgData^.GetFrom);
NewData^.SetTo (MsgData^.GetTo);
NewData^.SetSubj (MsgData^.GetSubj);
NewData^.SetDate (MsgData^.GetDate);
NewData^.SetTime (MsgData^.GetTime);
NewData^.SetLocal (MsgData^.IsLocal);
NewData^.SetPriv (MsgData^.IsPriv);
NewData^.SetSent (MsgData^.IsSent);
NewData^.SetCrash (MsgData^.IsCrash);
NewData^.SetRcvd (MsgData^.IsRcvd);
// NewData^.SetHold (MsgData^.IsHold);
NewData^.SetEcho (Not MsgData^.IsEchoed);
NewData^.SetKillSent (MsgData^.IsKillSent);
NewData^.SetRefer (MsgData^.GetRefer);
NewData^.SetSeeAlso (MsgData^.GetSeeAlso);
Case MsgBase.NetType of
0 : NewData^.SetMailType(mmtNormal);
1..2 : NewData^.SetMailType(mmtEchoMail);
3 : NewData^.SetMailType(mmtNetMail);
End;
NewData^.SetOrig (MsgData^.GetOrigAddr);
NewData^.SetDest (MsgData^.GetDestAddr);
MsgData^.MsgTxtStartUp;
While Not MsgData^.EOM Do
NewData^.DoStringLn(MsgData^.GetString(79));
NewData^.WriteMsg;
Link.OldNum := MsgData^.GetMsgNum;
Link.NewNum := NewData^.GetHighMsgNum;
LinkFile.WriteBlock (Link, SizeOf(Link));
End;
MsgData^.SeekNext;
End;
// cycle through old lastread pointers and generate new ones
UserTotal := GetUserBaseSize;
For Count := 1 to UserTotal Do Begin
Link.OldNum := MsgData^.GetLastRead (Count);
NewData^.SetLastRead (Count, GetMessageLink(Link.OldNum, False));
End;
// cycle through all messages and update referto/seealso
NewData^.SeekFirst(1);
While NewData^.SeekFound Do Begin
NewData^.MsgStartUp;
Link.OldNum := NewData^.GetRefer;
Link.NewNum := NewData^.GetSeeAlso;
If (Link.OldNum <> 0) Then Link.OldNum := GetMessageLink(Link.OldNum, True);
If (Link.NewNum <> 0) Then Link.NewNum := GetMessageLink(Link.NewNum, True);
If (Link.OldNum <> NewData^.GetRefer) or (Link.NewNum <> NewData^.GetSeeAlso) Then Begin
NewData^.SetRefer (Link.OldNum);
NewData^.SetSeeAlso (Link.NewNum);
NewData^.ReWriteHdr;
End;
NewData^.SeekNext;
End;
BaseKills := MsgData^.GetHighMsgNum - NewData^.GetHighMsgNum;
Inc (TotalKills, BaseKills);
MsgData^.CloseMsgBase;
NewData^.CloseMsgBase;
Dispose (MsgData, Done);
Dispose (NewData, Done);
LinkFile.Free;
FileErase (TempPath + TempName + '.tmp');
Case MsgBase.BaseType of
0 : Begin
FileErase (MsgBase.Path + MsgBase.FileName + '.jhr');
FileErase (MsgBase.Path + MsgBase.FileName + '.jdt');
FileErase (MsgBase.Path + MsgBase.FileName + '.jdx');
FileErase (MsgBase.Path + MsgBase.FileName + '.jlr');
FileRename (TempPath + TempName + '.jhr', MsgBase.Path + MsgBase.FileName + '.jhr');
FileRename (TempPath + TempName + '.jdt', MsgBase.Path + MsgBase.FileName + '.jdt');
FileRename (TempPath + TempName + '.jdx', MsgBase.Path + MsgBase.FileName + '.jdx');
FileRename (TempPath + TempName + '.jlr', MsgBase.Path + MsgBase.FileName + '.jlr');
End;
1 : Begin
FileErase (MsgBase.Path + MsgBase.FileName + '.sqd');
FileErase (MsgBase.Path + MsgBase.FileName + '.sqi');
FileErase (MsgBase.Path + MsgBase.FileName + '.sql');
FileRename (TempPath + TempName + '.sqd', MsgBase.Path + MsgBase.FileName + '.sqd');
FileRename (TempPath + TempName + '.sqi', MsgBase.Path + MsgBase.FileName + '.sqi');
FileRename (TempPath + TempName + '.sql', MsgBase.Path + MsgBase.FileName + '.sql');
End;
End;
Log (2, '+', ' Removed ' + strI2S(BaseKills) + ' msgs');
End;
Var
BaseFile : File of RecMessageBase;
Base : RecMessageBase;
Begin
ProcessName ('Packing Message Bases', True);
ProcessResult (rWORKING, False);
Assign (BaseFile, bbsCfg.DataPath + 'mbases.dat');
If ioReset (BaseFile, SizeOf(Base), fmRWDN) Then Begin
While Not Eof(BaseFile) Do Begin
Read (BaseFile, Base);
ProcessStatus (Base.Name, False);
BarOne.Update (FilePos(BaseFile), FileSize(BaseFile));
PackOneBase (Base);
End;
Close (BaseFile);
End;
ProcessStatus ('Removed |15' + strI2S(TotalKills) + ' |07msgs in |15' + strI2S(BaseTotal) + ' |07bases', True);
ProcessResult (rDONE, True);
End;
End.