1430 lines
26 KiB
C++
1430 lines
26 KiB
C++
|
#define Use_MsgBase
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include "proboard.hpp"
|
||
|
|
||
|
|
||
|
|
||
|
struct HudsonMsgInfo
|
||
|
{
|
||
|
int low;
|
||
|
int high;
|
||
|
int total;
|
||
|
int active[ 200 ];
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
struct HudsonMsgIdx
|
||
|
{
|
||
|
int num;
|
||
|
byte area;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
struct HudsonMsgToIdx
|
||
|
{
|
||
|
char to[ 36 ];
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
struct HudsonMsgHdr
|
||
|
{
|
||
|
int msgNum;
|
||
|
int prevMsg;
|
||
|
int nextMsg;
|
||
|
int tRead;
|
||
|
word startRec;
|
||
|
int numRecs;
|
||
|
int destNet;
|
||
|
int destNode;
|
||
|
int orgNet;
|
||
|
int orgNode;
|
||
|
char destZone;
|
||
|
char orgZone;
|
||
|
int cost;
|
||
|
byte msgAttr;
|
||
|
byte netAttr;
|
||
|
byte area;
|
||
|
char postTime[ 6 ];
|
||
|
char postDate[ 9 ];
|
||
|
char to [ 36 ];
|
||
|
char from[ 36 ];
|
||
|
char subj[ 67 ];
|
||
|
Date recvDate;
|
||
|
Time recvTime;
|
||
|
|
||
|
void operator=( Message& );
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
const byte QMSGATTR_DELETED = 0x01;
|
||
|
const byte QMSGATTR_UNMOVED_NET = 0x02;
|
||
|
const byte QMSGATTR_NET = 0x04;
|
||
|
const byte QMSGATTR_PVT = 0x08;
|
||
|
const byte QMSGATTR_RECEIVED = 0x10;
|
||
|
const byte QMSGATTR_UNMOVED_ECHO = 0x20;
|
||
|
const byte QMSGATTR_LOCAL = 0x40;
|
||
|
|
||
|
const byte QNETATTR_KILL = 0x01;
|
||
|
const byte QNETATTR_SENT = 0x02;
|
||
|
const byte QNETATTR_ATTACH = 0x04;
|
||
|
const byte QNETATTR_CRASH = 0x08;
|
||
|
const byte QNETATTR_REQ = 0x10;
|
||
|
const byte QNETATTR_AUD = 0x20;
|
||
|
const byte QNETATTR_RET = 0x40;
|
||
|
|
||
|
const int CACHE_NEXT = 1;
|
||
|
const int CACHE_PREV = 2;
|
||
|
const int CACHE_START = 3;
|
||
|
|
||
|
|
||
|
|
||
|
HudsonMsgBase::HudsonMsgBase()
|
||
|
{
|
||
|
lastMsgIdx = new HudsonMsgIdx;
|
||
|
lastReadArray = NULL;
|
||
|
highArray = NULL;
|
||
|
|
||
|
open();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HudsonMsgBase::~HudsonMsgBase()
|
||
|
{
|
||
|
close();
|
||
|
|
||
|
delete lastMsgIdx;
|
||
|
|
||
|
|
||
|
if ( highArray )
|
||
|
{
|
||
|
delete [] highArray;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastReadArray )
|
||
|
{
|
||
|
delete [] lastReadArray;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgHdr::operator=( Message &msg )
|
||
|
{
|
||
|
msg.to[ 35 ] = msg.from[ 35 ]
|
||
|
= msg.subj[ 65 ] = '\0'; // Safety measure
|
||
|
|
||
|
|
||
|
msgNum = int( msg.id );
|
||
|
prevMsg = int( msg.prev );
|
||
|
nextMsg = int( msg.next );
|
||
|
tRead = 0;
|
||
|
destNet = msg.destNet;
|
||
|
destZone = msg.destZone;
|
||
|
destNode = msg.destNode;
|
||
|
orgNet = msg.origNet;
|
||
|
orgZone = msg.origZone;
|
||
|
orgNode = msg.origNode;
|
||
|
cost = msg.cost;
|
||
|
area = msg.areaNum();
|
||
|
|
||
|
msgAttr = 0;
|
||
|
netAttr = 0;
|
||
|
|
||
|
|
||
|
if ( msg.attr & MSGATTR_ECHOMAIL &&
|
||
|
! ( msg.attr & MSGATTR_SENT ) &&
|
||
|
msg.attr & MSGATTR_LOCAL )
|
||
|
{
|
||
|
msgAttr |= QMSGATTR_UNMOVED_ECHO;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( msg.attr & MSGATTR_NETMAIL &&
|
||
|
! ( msg.attr & MSGATTR_SENT ) &&
|
||
|
msg.attr & MSGATTR_LOCAL )
|
||
|
{
|
||
|
msgAttr |= QMSGATTR_UNMOVED_NET;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( msg.attr & MSGATTR_DELETED ) msgAttr |= QMSGATTR_DELETED;
|
||
|
// if ( msg.attr & MSGATTR_UNSENT_NET ) msgAttr |= QMSGATTR_UNMOVED_NET;
|
||
|
if ( msg.attr & MSGATTR_NETMAIL ) msgAttr |= QMSGATTR_NET;
|
||
|
if ( msg.attr & MSGATTR_PRIVATE ) msgAttr |= QMSGATTR_PVT;
|
||
|
if ( msg.attr & MSGATTR_RECEIVED ) msgAttr |= QMSGATTR_RECEIVED;
|
||
|
// if ( msg.attr & MSGATTR_UNSENT_ECHO ) msgAttr |= QMSGATTR_UNMOVED_ECHO;
|
||
|
if ( msg.attr & MSGATTR_LOCAL ) msgAttr |= QMSGATTR_LOCAL;
|
||
|
|
||
|
if ( msg.attr & MSGATTR_KILL ) netAttr |= QNETATTR_KILL;
|
||
|
if ( msg.attr & MSGATTR_CRASH ) netAttr |= QNETATTR_CRASH;
|
||
|
if ( msg.attr & MSGATTR_SENT ) netAttr |= QNETATTR_SENT;
|
||
|
if ( msg.attr & MSGATTR_FILE ) netAttr |= QNETATTR_ATTACH;
|
||
|
if ( msg.attr & MSGATTR_FILEREQ ) netAttr |= QNETATTR_REQ;
|
||
|
if ( msg.attr & MSGATTR_AUDITREQ ) netAttr |= QNETATTR_AUD;
|
||
|
if ( msg.attr & MSGATTR_RECEIPTREQ ) netAttr |= QNETATTR_RET;
|
||
|
|
||
|
|
||
|
sprintf( postTime,
|
||
|
"%02d:%02d",
|
||
|
msg.postTime[ 0 ],
|
||
|
msg.postTime[ 1 ] );
|
||
|
|
||
|
c2pas( postTime );
|
||
|
|
||
|
|
||
|
sprintf( postDate,
|
||
|
"%02d-%02d-%02d",
|
||
|
msg.postDate[ 1 ],
|
||
|
msg.postDate[ 0 ],
|
||
|
// msg.postDate[ 2 ] ); // Y2K BUG!
|
||
|
msg.postDate[ 2 ] % 100 ); // JDR: Y2K FIXED!
|
||
|
|
||
|
c2pas( postDate );
|
||
|
|
||
|
|
||
|
strcpy( to, msg.to );
|
||
|
|
||
|
c2pas( to );
|
||
|
|
||
|
|
||
|
strcpy( from, msg.from );
|
||
|
|
||
|
c2pas( from );
|
||
|
|
||
|
|
||
|
strcpy( subj, msg.subj );
|
||
|
|
||
|
c2pas( subj );
|
||
|
|
||
|
|
||
|
recvDate = msg.recvDate;
|
||
|
recvTime = msg.recvTime;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void Message::operator=( HudsonMsgHdr& mh )
|
||
|
{
|
||
|
num = mh.msgNum;
|
||
|
id = mh.msgNum;
|
||
|
prev = mh.prevMsg;
|
||
|
next = mh.nextMsg;
|
||
|
destNet = mh.destNet;
|
||
|
destZone = mh.destZone;
|
||
|
destNode = mh.destNode;
|
||
|
origNet = mh.orgNet;
|
||
|
origZone = mh.orgZone;
|
||
|
origNode = mh.orgNode;
|
||
|
cost = mh.cost;
|
||
|
|
||
|
attr = 0;
|
||
|
|
||
|
|
||
|
if ( mh.msgAttr & QMSGATTR_DELETED ) attr |= MSGATTR_DELETED;
|
||
|
if ( mh.msgAttr & QMSGATTR_UNMOVED_NET ) attr |= MSGATTR_NETMAIL;
|
||
|
if ( mh.msgAttr & QMSGATTR_NET ) attr |= MSGATTR_NETMAIL;
|
||
|
if ( mh.msgAttr & QMSGATTR_PVT ) attr |= MSGATTR_PRIVATE;
|
||
|
if ( mh.msgAttr & QMSGATTR_RECEIVED ) attr |= MSGATTR_RECEIVED;
|
||
|
if ( mh.msgAttr & QMSGATTR_UNMOVED_ECHO ) attr |= MSGATTR_ECHOMAIL;
|
||
|
if ( mh.msgAttr & QMSGATTR_LOCAL ) attr |= MSGATTR_LOCAL;
|
||
|
|
||
|
if ( mh.netAttr & QNETATTR_KILL ) attr |= MSGATTR_KILL;
|
||
|
if ( mh.netAttr & QNETATTR_SENT ) attr |= MSGATTR_SENT;
|
||
|
if ( mh.netAttr & QNETATTR_ATTACH ) attr |= MSGATTR_FILE;
|
||
|
if ( mh.netAttr & QNETATTR_CRASH ) attr |= MSGATTR_CRASH;
|
||
|
if ( mh.netAttr & QNETATTR_REQ ) attr |= MSGATTR_FILEREQ;
|
||
|
if ( mh.netAttr & QNETATTR_AUD ) attr |= MSGATTR_AUDITREQ;
|
||
|
if ( mh.netAttr & QNETATTR_RET ) attr |= MSGATTR_RECEIPTREQ;
|
||
|
|
||
|
|
||
|
if ( attr & MSGATTR_LOCAL )
|
||
|
{
|
||
|
if ( ! ( mh.msgAttr & QMSGATTR_UNMOVED_ECHO ) &&
|
||
|
! ( mh.msgAttr & QMSGATTR_UNMOVED_NET ) )
|
||
|
{
|
||
|
attr |= MSGATTR_SENT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
setArea( mh.area );
|
||
|
|
||
|
|
||
|
mh.postTime[ 0 ] = min( (byte) mh.postTime[ 0 ], 5 );
|
||
|
|
||
|
pas2c( mh.postTime );
|
||
|
|
||
|
|
||
|
postTime[ 0 ] = atoi( strtok( mh.postTime, ":" ) );
|
||
|
postTime[ 1 ] = atoi( strtok( NULL, ":" ) );
|
||
|
postTime[ 2 ] = 0;
|
||
|
|
||
|
|
||
|
mh.postDate[ 0 ] = min( (byte) mh.postDate[ 0 ], 8 );
|
||
|
|
||
|
pas2c( mh.postDate );
|
||
|
|
||
|
|
||
|
postDate[ 1 ] = atoi( strtok( mh.postDate, "-" ) );
|
||
|
postDate[ 0 ] = atoi( strtok( NULL, "-" ) );
|
||
|
// postDate[ 2 ] = atoi( strtok( NULL, "-" ) ); // Y2K BUG!
|
||
|
postDate[ 2 ] = atoi( strtok( NULL, "-" ) ) % 100; // JDR: Y2K FIX!
|
||
|
|
||
|
|
||
|
mh.to[ 0 ] = min( (byte) mh.to[ 0 ], 35 );
|
||
|
|
||
|
pas2c( mh.to );
|
||
|
strcpy( to, mh.to );
|
||
|
|
||
|
|
||
|
mh.from[ 0 ] = min( (byte) mh.from[ 0 ], 35 );
|
||
|
|
||
|
pas2c( mh.from );
|
||
|
strcpy( from, mh.from );
|
||
|
|
||
|
|
||
|
mh.subj[ 0 ] = min( (byte) mh.subj[ 0 ], 65 );
|
||
|
|
||
|
pas2c( mh.subj );
|
||
|
strcpy( subj, mh.subj );
|
||
|
|
||
|
|
||
|
recvDate = mh.recvDate;
|
||
|
recvTime = mh.recvTime;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool HudsonMsgBase::open()
|
||
|
{
|
||
|
FileName fn_msghdr( cfg.msgpath, "MSGHDR.BBS" );
|
||
|
FileName fn_msgtxt( cfg.msgpath, "MSGTXT.BBS" );
|
||
|
FileName fn_msgtoidx( cfg.msgpath, "MSGTOIDX.BBS" );
|
||
|
FileName fn_msgidx( cfg.msgpath, "MSGIDX.BBS" );
|
||
|
FileName fn_msginfo( cfg.msgpath, "MSGINFO.BBS" );
|
||
|
|
||
|
|
||
|
if ( ! f_msghdr .open( fn_msghdr, fmode_rw | fmode_copen ) ||
|
||
|
! f_msgtxt .open( fn_msgtxt, fmode_rw | fmode_copen ) ||
|
||
|
! f_msgtoidx.open( fn_msgtoidx, fmode_rw | fmode_copen, 2048 ) ||
|
||
|
! f_msgidx .open( fn_msgidx, fmode_rw | fmode_copen, 1024 ) ||
|
||
|
! f_msginfo .open( fn_msginfo, fmode_rw | fmode_copen ) )
|
||
|
{
|
||
|
if ( f_msghdr .error() ) file_error( fn_msghdr );
|
||
|
if ( f_msgtxt .error() ) file_error( fn_msgtxt );
|
||
|
if ( f_msgtoidx.error() ) file_error( fn_msgtoidx );
|
||
|
if ( f_msgidx .error() ) file_error( fn_msgidx );
|
||
|
if ( f_msginfo .error() ) file_error( fn_msginfo );
|
||
|
|
||
|
fatalerror( "Error creating Hudson message base" );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
flushCache();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::close()
|
||
|
{
|
||
|
flushCache();
|
||
|
|
||
|
f_msghdr .close();
|
||
|
f_msgtxt .close();
|
||
|
f_msgtoidx.close();
|
||
|
f_msgidx .close();
|
||
|
f_msginfo .close();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::highMsg( MsgArea& ma )
|
||
|
{
|
||
|
readHighArray();
|
||
|
|
||
|
return long( highArray[ ma.areaNum - 1 ] );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::lowMsg( MsgArea& )
|
||
|
{
|
||
|
HudsonMsgInfo mi;
|
||
|
|
||
|
readInfo( mi );
|
||
|
|
||
|
return long( mi.low );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::numMsgs( MsgArea& ma )
|
||
|
{
|
||
|
HudsonMsgInfo mi;
|
||
|
|
||
|
readInfo( mi );
|
||
|
|
||
|
return long( mi.active[ ma.areaNum - 1 ] );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::totalMsgs()
|
||
|
{
|
||
|
HudsonMsgInfo mi;
|
||
|
|
||
|
readInfo( mi );
|
||
|
|
||
|
return long( mi.total );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::readInfo( HudsonMsgInfo &mi )
|
||
|
{
|
||
|
CLEAR_OBJECT( mi );
|
||
|
|
||
|
f_msginfo.rewind();
|
||
|
f_msginfo.flush();
|
||
|
|
||
|
f_msginfo.read( & mi,
|
||
|
sizeof( mi ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::writeInfo( HudsonMsgInfo &mi )
|
||
|
{
|
||
|
f_msginfo.rewind();
|
||
|
|
||
|
f_msginfo.write( & mi,
|
||
|
sizeof( mi ) );
|
||
|
|
||
|
f_msginfo.flush();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::readMsg( Message &msg,
|
||
|
long num )
|
||
|
{
|
||
|
HudsonMsgIdx mi;
|
||
|
int order = 1;
|
||
|
|
||
|
|
||
|
f_msgidx.rewind();
|
||
|
|
||
|
|
||
|
if ( num < 0 )
|
||
|
{
|
||
|
order = -1;
|
||
|
num = -num;
|
||
|
}
|
||
|
|
||
|
|
||
|
long index = findIdx( mi,
|
||
|
int( num ),
|
||
|
msg.areaNum(),
|
||
|
order );
|
||
|
|
||
|
|
||
|
if ( index < 0 )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
HudsonMsgHdr hdr;
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( hdr ) );
|
||
|
|
||
|
|
||
|
if ( f_msghdr.read( & hdr,
|
||
|
sizeof( hdr ) ) != sizeof( hdr ) )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
msg = hdr; // Conversion applied!
|
||
|
|
||
|
return msg.id;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::flushCache()
|
||
|
{
|
||
|
lastReadRecord = -1;
|
||
|
lastIndex = -1;
|
||
|
lastMsgIdx->num = -1;
|
||
|
lastMsgIdx->area = 0;
|
||
|
|
||
|
|
||
|
if ( highArray != NULL )
|
||
|
{
|
||
|
delete [] highArray;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastReadArray != NULL )
|
||
|
{
|
||
|
delete [] lastReadArray;
|
||
|
}
|
||
|
|
||
|
|
||
|
highArray = NULL;
|
||
|
lastReadArray = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::readHighArray()
|
||
|
{
|
||
|
if ( highArray )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
highArray = new int[ 200 ];
|
||
|
|
||
|
|
||
|
HudsonMsgIdx mi;
|
||
|
|
||
|
|
||
|
memset( highArray,
|
||
|
0,
|
||
|
sizeof( *highArray ) * 200 );
|
||
|
|
||
|
f_msgidx.seek( 0 );
|
||
|
|
||
|
|
||
|
for ( ; ; )
|
||
|
{
|
||
|
if ( f_msgidx.read( & mi,
|
||
|
sizeof( mi ) ) != sizeof( mi ) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( mi.num > 0 &&
|
||
|
mi.area > 0 &&
|
||
|
mi.area < 200 &&
|
||
|
mi.num > highArray[ mi.area - 1 ] )
|
||
|
{
|
||
|
highArray[ mi.area - 1 ] = mi.num;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::findIdx( HudsonMsgIdx &mi,
|
||
|
int num,
|
||
|
int area,
|
||
|
int order )
|
||
|
{
|
||
|
long idx = -1;
|
||
|
|
||
|
|
||
|
if ( order < 0 )
|
||
|
{
|
||
|
idx = f_msgidx.len() / 3;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastMsgIdx->num == num &&
|
||
|
lastMsgIdx->area == area )
|
||
|
{
|
||
|
mi = *lastMsgIdx;
|
||
|
|
||
|
return lastIndex;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( order == 0 )
|
||
|
{
|
||
|
flushCache();
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastMsgIdx->num > 0 )
|
||
|
{
|
||
|
if ( num > lastMsgIdx->num &&
|
||
|
order > 0 )
|
||
|
{
|
||
|
idx = lastIndex;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( num < lastMsgIdx->num &&
|
||
|
order < 0 )
|
||
|
{
|
||
|
idx = lastIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( order < 0 )
|
||
|
{
|
||
|
f_msgidx.disableBuffer();
|
||
|
|
||
|
|
||
|
for ( idx--; idx >= 0; idx-- )
|
||
|
{
|
||
|
f_msgidx.seek( idx * sizeof( HudsonMsgIdx ) );
|
||
|
|
||
|
f_msgidx.read( lastMsgIdx, sizeof( *lastMsgIdx ) );
|
||
|
|
||
|
|
||
|
if ( lastMsgIdx->num < 1 )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastMsgIdx->num <= num &&
|
||
|
lastMsgIdx->area == area )
|
||
|
{
|
||
|
lastIndex = idx;
|
||
|
mi = *lastMsgIdx;
|
||
|
|
||
|
f_msgidx.enableBuffer();
|
||
|
|
||
|
return idx;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
f_msgidx.enableBuffer();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//----
|
||
|
// >=0
|
||
|
//----
|
||
|
|
||
|
for ( idx++; ; idx++ )
|
||
|
{
|
||
|
f_msgidx.seek( idx * sizeof( HudsonMsgIdx ) );
|
||
|
|
||
|
|
||
|
if ( f_msgidx.read( lastMsgIdx,
|
||
|
sizeof( *lastMsgIdx ) ) != sizeof( *lastMsgIdx ) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastMsgIdx->area == area )
|
||
|
{
|
||
|
if (
|
||
|
lastMsgIdx->num == num ||
|
||
|
(
|
||
|
lastMsgIdx->num >= num &&
|
||
|
order > 0
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
lastIndex = idx;
|
||
|
mi = *lastMsgIdx;
|
||
|
|
||
|
return idx;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
flushCache();
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
word HudsonMsgBase::readMsgText( Message &msg,
|
||
|
char *ptr,
|
||
|
long offset,
|
||
|
word size )
|
||
|
{
|
||
|
HudsonMsgIdx mi;
|
||
|
HudsonMsgHdr hdr;
|
||
|
long index = findIdx( mi,
|
||
|
int( msg.id ),
|
||
|
msg.areaNum(),
|
||
|
0 );
|
||
|
|
||
|
|
||
|
if ( index < 0 )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( HudsonMsgHdr ) );
|
||
|
|
||
|
|
||
|
if ( f_msghdr.read( & hdr,
|
||
|
sizeof( hdr ) ) != sizeof( hdr ) )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
byte buf[ 256 ];
|
||
|
long rec = hdr.startRec + offset / 255;
|
||
|
word bytescopied = 0;
|
||
|
int buf_index = int( offset % 255 );
|
||
|
|
||
|
|
||
|
for ( ;
|
||
|
|
||
|
rec < ( hdr.startRec + hdr.numRecs ) &&
|
||
|
bytescopied < size;
|
||
|
|
||
|
rec++ )
|
||
|
{
|
||
|
f_msgtxt.seek( rec * 256 );
|
||
|
f_msgtxt.read( buf, 256 );
|
||
|
|
||
|
|
||
|
int l = int( buf[ 0 ] );
|
||
|
|
||
|
pas2c( buf );
|
||
|
|
||
|
l -= buf_index;
|
||
|
|
||
|
|
||
|
if ( l < 1 )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( l > size-bytescopied )
|
||
|
{
|
||
|
l = size - bytescopied;
|
||
|
}
|
||
|
|
||
|
|
||
|
memcpy( ptr + bytescopied,
|
||
|
& buf[ buf_index ],
|
||
|
l );
|
||
|
|
||
|
bytescopied += l;
|
||
|
buf_index = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
return bytescopied;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
word HudsonMsgBase::scanMail( MessageIndex *mi,
|
||
|
word maxmsgs )
|
||
|
{
|
||
|
f_msgtoidx.rewind();
|
||
|
|
||
|
|
||
|
int i;
|
||
|
int num_found;
|
||
|
long index;
|
||
|
MsgArea ma;
|
||
|
|
||
|
|
||
|
for ( index = 0, i = 0; i < maxmsgs; index++ )
|
||
|
{
|
||
|
HudsonMsgToIdx h_mti;
|
||
|
HudsonMsgIdx h_mi;
|
||
|
|
||
|
|
||
|
if ( f_msgtoidx.read( & h_mti,
|
||
|
sizeof( h_mti ) ) != sizeof( h_mti ) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
pas2c( h_mti.to );
|
||
|
|
||
|
|
||
|
if ( stricmp( user.name, h_mti.to ) &&
|
||
|
stricmp( user.alias, h_mti.to ) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
f_msgidx.seek( index * 3 );
|
||
|
|
||
|
|
||
|
if ( f_msgidx.read( & h_mi,
|
||
|
sizeof( h_mi ) ) == sizeof( h_mi ) )
|
||
|
{
|
||
|
mi[ i ].num = h_mi.num;
|
||
|
mi[ i ].area = h_mi.area;
|
||
|
|
||
|
|
||
|
if ( ! ma.read( mi[ i ].area ) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ! stricmp( user.alias,
|
||
|
h_mti.to ) &&
|
||
|
|
||
|
! ma.flags &&
|
||
|
|
||
|
strcmp( user.name, user.alias ) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( mi[ i ].num > 1 &&
|
||
|
user.mailCheckBoards.connected( mi[ i ].area ) &&
|
||
|
ma.msgBaseType == MSGBASE_HUDSON &&
|
||
|
(
|
||
|
check_access( ma.readLevel,
|
||
|
ma.readFlags,
|
||
|
ma.readFlagsNot ) ||
|
||
|
|
||
|
ma.sysopAccess()
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
num_found = i;
|
||
|
|
||
|
bool *to_all_areas = new bool[ 200 ];
|
||
|
|
||
|
|
||
|
for ( i = 0; i < 200; i++ )
|
||
|
{
|
||
|
to_all_areas[ i ] = FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
for ( i = 1; i <= 200 && i <= MsgArea::highAreaNum(); i++ )
|
||
|
{
|
||
|
if ( ! ma.read( i ) ||
|
||
|
! check_access( ma.readLevel,
|
||
|
ma.readFlags,
|
||
|
ma.readFlagsNot ) ||
|
||
|
|
||
|
ma.msgBaseType != MSGBASE_HUDSON ||
|
||
|
ma.msgType != MSG_TOALL )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
to_all_areas[ i - 1 ] = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
f_msgidx.rewind();
|
||
|
|
||
|
|
||
|
while ( num_found < 200 )
|
||
|
{
|
||
|
HudsonMsgIdx tmp_mi;
|
||
|
|
||
|
|
||
|
if ( f_msgidx.read( & tmp_mi,
|
||
|
sizeof( tmp_mi ) ) != sizeof( tmp_mi ) )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( tmp_mi.num < 1 )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( tmp_mi.area < 1 ||
|
||
|
tmp_mi.area > 200 ||
|
||
|
! to_all_areas[ tmp_mi.area - 1 ] )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ! ma.read( tmp_mi.area ) )
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( tmp_mi.num > ma.lastRead( user_recnr ) )
|
||
|
{
|
||
|
mi[ num_found ].num = tmp_mi.num;
|
||
|
mi[ num_found ].area = tmp_mi.area;
|
||
|
|
||
|
num_found++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
delete [] to_all_areas;
|
||
|
|
||
|
return num_found;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::appendMsg( Message &msg )
|
||
|
{
|
||
|
File ft;
|
||
|
HudsonMsgIdx midx;
|
||
|
HudsonMsgToIdx mtidx;
|
||
|
HudsonMsgInfo minfo;
|
||
|
long startrec;
|
||
|
long numrecs;
|
||
|
long index;
|
||
|
|
||
|
|
||
|
if ( msg.areaNum() < 1 ||
|
||
|
msg.areaNum() > 200 )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
readInfo( minfo );
|
||
|
|
||
|
|
||
|
if ( ! lock() )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
msg.id = ++minfo.high;
|
||
|
msg.num = msg.id;
|
||
|
|
||
|
|
||
|
minfo.total++;
|
||
|
|
||
|
minfo.active[ msg.areaNum() - 1 ]++;
|
||
|
|
||
|
|
||
|
midx.num = int( msg.id );
|
||
|
midx.area = msg.areaNum();
|
||
|
|
||
|
|
||
|
index = word( f_msghdr.len() / sizeof( HudsonMsgHdr ) );
|
||
|
|
||
|
|
||
|
if ( ! ft.open( "MSGTMP" ) )
|
||
|
{
|
||
|
unlock();
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
startrec = f_msgtxt.len() / 256L;
|
||
|
|
||
|
f_msgtxt.seek( 256L * startrec );
|
||
|
|
||
|
|
||
|
for ( numrecs = 0; ; numrecs++ )
|
||
|
{
|
||
|
char x[ 256 ];
|
||
|
int l = 0;
|
||
|
|
||
|
|
||
|
if ( ! numrecs )
|
||
|
{
|
||
|
//----------------------------
|
||
|
// JDR: REGISTRATION REFERENCE
|
||
|
//----------------------------
|
||
|
|
||
|
sprintf( x,
|
||
|
"\1PID: " PID_STRING_HUDSON "%c\r\n" ,
|
||
|
registered
|
||
|
? 'r'
|
||
|
: 'u' );
|
||
|
|
||
|
l = strlen( x );
|
||
|
}
|
||
|
|
||
|
|
||
|
l += ft.read( & x[ l ],
|
||
|
255 - l );
|
||
|
|
||
|
x[ l ] = 0;
|
||
|
|
||
|
|
||
|
if ( l < 1 )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
c2pas( x );
|
||
|
|
||
|
f_msgtxt.write( x, 256 );
|
||
|
}
|
||
|
|
||
|
|
||
|
ft.close();
|
||
|
|
||
|
msg.postDate.today();
|
||
|
msg.postTime.now();
|
||
|
|
||
|
|
||
|
HudsonMsgHdr hdr;
|
||
|
|
||
|
|
||
|
hdr = msg; // Conversion applied
|
||
|
|
||
|
|
||
|
hdr.startRec = word( startrec );
|
||
|
hdr.numRecs = int( numrecs );
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( HudsonMsgHdr ) );
|
||
|
f_msghdr.write( & hdr,
|
||
|
sizeof( hdr ) );
|
||
|
|
||
|
|
||
|
strcpy( mtidx.to, msg.to );
|
||
|
|
||
|
c2pas( mtidx.to );
|
||
|
|
||
|
|
||
|
f_msgtoidx.seek( index * sizeof( HudsonMsgToIdx ) );
|
||
|
f_msgtoidx.write( & mtidx,
|
||
|
sizeof( mtidx ) );
|
||
|
|
||
|
f_msgidx.seek( index * sizeof( HudsonMsgIdx ) );
|
||
|
f_msgidx.write( & midx,
|
||
|
sizeof( midx ) );
|
||
|
|
||
|
|
||
|
writeInfo( minfo );
|
||
|
|
||
|
unlock();
|
||
|
|
||
|
flushCache();
|
||
|
|
||
|
|
||
|
return msg.id;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool HudsonMsgBase::updateMsg( Message &msg )
|
||
|
{
|
||
|
HudsonMsgIdx midx;
|
||
|
HudsonMsgToIdx mtidx;
|
||
|
long index;
|
||
|
|
||
|
|
||
|
if ( msg.areaNum() < 1 ||
|
||
|
msg.areaNum() > 200 )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
index = findIdx( midx,
|
||
|
int( msg.id ),
|
||
|
msg.areaNum(),
|
||
|
0 );
|
||
|
|
||
|
|
||
|
if ( index < 0 )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
HudsonMsgHdr hdr;
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( hdr ) );
|
||
|
|
||
|
|
||
|
if ( f_msghdr.read( & hdr,
|
||
|
sizeof( hdr ) ) != sizeof( hdr ) )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ! lock() )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
hdr = msg;
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( hdr ) );
|
||
|
f_msghdr.write( & hdr,
|
||
|
sizeof( hdr ) );
|
||
|
|
||
|
|
||
|
strcpy( mtidx.to, msg.to );
|
||
|
|
||
|
|
||
|
if ( msg.attr & MSGATTR_RECEIVED )
|
||
|
{
|
||
|
strcpy( mtidx.to, "* Received *" );
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( msg.attr & MSGATTR_DELETED )
|
||
|
{
|
||
|
strcpy( mtidx.to, "* Deleted *" );
|
||
|
}
|
||
|
|
||
|
|
||
|
c2pas( mtidx.to );
|
||
|
|
||
|
|
||
|
f_msgtoidx.seek( index * sizeof( HudsonMsgToIdx ) );
|
||
|
f_msgtoidx.write( & mtidx,
|
||
|
sizeof( mtidx ) );
|
||
|
|
||
|
unlock();
|
||
|
|
||
|
flushCache();
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool HudsonMsgBase::deleteMsg( Message &msg )
|
||
|
{
|
||
|
HudsonMsgIdx midx;
|
||
|
HudsonMsgToIdx mtidx;
|
||
|
HudsonMsgInfo minfo;
|
||
|
long index;
|
||
|
|
||
|
|
||
|
if ( msg.areaNum() < 1 ||
|
||
|
msg.areaNum() > 200 )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
index = findIdx( midx,
|
||
|
int( msg.id ),
|
||
|
msg.areaNum(),
|
||
|
0 );
|
||
|
|
||
|
|
||
|
if ( index < 0 )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
HudsonMsgHdr hdr;
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( hdr ) );
|
||
|
|
||
|
|
||
|
if ( f_msghdr.read( & hdr,
|
||
|
sizeof( hdr ) ) != sizeof( hdr ) )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ! lock() )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
msg.attr |= MSGATTR_DELETED;
|
||
|
hdr = msg;
|
||
|
|
||
|
|
||
|
f_msghdr.seek( index * sizeof( hdr ) );
|
||
|
f_msghdr.write( & hdr,
|
||
|
sizeof( hdr ) );
|
||
|
|
||
|
|
||
|
strcpy( mtidx.to, "* Deleted *" );
|
||
|
|
||
|
c2pas( mtidx.to );
|
||
|
|
||
|
|
||
|
f_msgtoidx.seek( index * sizeof( HudsonMsgToIdx ) );
|
||
|
f_msgtoidx.write( & mtidx,
|
||
|
sizeof( mtidx ) );
|
||
|
|
||
|
|
||
|
midx.num = -1;
|
||
|
|
||
|
|
||
|
f_msgidx.seek( index * 3 );
|
||
|
f_msgidx.write( & midx, 3 );
|
||
|
|
||
|
readInfo( minfo );
|
||
|
|
||
|
|
||
|
minfo.total--;
|
||
|
|
||
|
minfo.active[ msg.areaNum() - 1 ]--;
|
||
|
|
||
|
|
||
|
writeInfo( minfo );
|
||
|
|
||
|
unlock();
|
||
|
|
||
|
flushCache();
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool HudsonMsgBase::lock()
|
||
|
{
|
||
|
static bool lock_error = FALSE;
|
||
|
|
||
|
|
||
|
if ( lock_error )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
f_msghdr.flush();
|
||
|
f_msgtxt.flush();
|
||
|
f_msginfo.flush();
|
||
|
f_msgtoidx.flush();
|
||
|
f_msgidx.flush();
|
||
|
|
||
|
|
||
|
if ( ! cfg.multiline )
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ! f_msginfo.lock( 407, 1 ) )
|
||
|
{
|
||
|
int errno = f_msginfo.error();
|
||
|
|
||
|
|
||
|
lock_error = TRUE;
|
||
|
|
||
|
fatalerror( form( "FILE LOCK ERROR (%d - %s)",
|
||
|
errno,
|
||
|
dos_error_message( errno ) ) );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool HudsonMsgBase::unlock()
|
||
|
{
|
||
|
static bool lock_error = FALSE;
|
||
|
|
||
|
|
||
|
if ( lock_error )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
f_msghdr.flush();
|
||
|
f_msgtxt.flush();
|
||
|
f_msginfo.flush();
|
||
|
f_msgtoidx.flush();
|
||
|
f_msgidx.flush();
|
||
|
|
||
|
|
||
|
if ( ! cfg.multiline )
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ! f_msginfo.unlock( 407, 1 ) )
|
||
|
{
|
||
|
int errno = f_msginfo.error();
|
||
|
|
||
|
|
||
|
lock_error = TRUE;
|
||
|
|
||
|
fatalerror( form( "FILE UNLOCK ERROR (%d - %s)",
|
||
|
errno,
|
||
|
dos_error_message( errno ) ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
long HudsonMsgBase::lastRead( MsgArea &ma,
|
||
|
long rec )
|
||
|
{
|
||
|
readLastRead( rec );
|
||
|
|
||
|
|
||
|
if ( ma.areaNum < 1 ||
|
||
|
ma.areaNum > 200 )
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
return long( lastReadArray[ ma.areaNum - 1 ] );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::setLastRead( MsgArea &ma,
|
||
|
long rec,
|
||
|
long num )
|
||
|
{
|
||
|
File f;
|
||
|
|
||
|
|
||
|
readLastRead( rec );
|
||
|
|
||
|
|
||
|
if ( ! f.open( FileName( cfg.msgpath,
|
||
|
"LASTREAD.BBS" ),
|
||
|
fmode_rw | fmode_copen ) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( f.len() < ( rec + 1 ) * 400 )
|
||
|
{
|
||
|
word n = 0;
|
||
|
long r = f.len() / 400 * 400;
|
||
|
|
||
|
f.seek( r );
|
||
|
|
||
|
|
||
|
for( ; r < ( rec + 1 ) * 400; r += 2 )
|
||
|
{
|
||
|
f.write( & n, 2 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( ma.areaNum < 1 ||
|
||
|
ma.areaNum > 200 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
long pos = rec * 400 + ( ma.areaNum - 1 ) * 2;
|
||
|
|
||
|
|
||
|
f.seek( pos );
|
||
|
|
||
|
f.write( & num, 2 );
|
||
|
|
||
|
|
||
|
lastReadArray[ ma.areaNum - 1 ] = int( num );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void HudsonMsgBase::readLastRead( long recno )
|
||
|
{
|
||
|
static dword ticks = clockticks();
|
||
|
|
||
|
|
||
|
if ( clockdiff( ticks ) > 1000 )
|
||
|
{
|
||
|
ticks = clockticks();
|
||
|
|
||
|
flushCache();
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastReadArray &&
|
||
|
recno == lastReadRecord )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( lastReadArray == NULL )
|
||
|
{
|
||
|
lastReadArray = new int[ 200 ];
|
||
|
|
||
|
memset( lastReadArray,
|
||
|
0,
|
||
|
400 );
|
||
|
}
|
||
|
|
||
|
|
||
|
lastReadRecord = recno;
|
||
|
|
||
|
|
||
|
File f;
|
||
|
|
||
|
|
||
|
if ( ! f.open( FileName( cfg.msgpath,
|
||
|
"LASTREAD.BBS" ) ) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
f.seek( recno * 400 );
|
||
|
|
||
|
|
||
|
if ( f.read( lastReadArray, 400 ) != 400 )
|
||
|
{
|
||
|
lastReadRecord = -1;
|
||
|
|
||
|
memset( lastReadArray,
|
||
|
0,
|
||
|
400 );
|
||
|
}
|
||
|
}
|