1003 lines
22 KiB
C++
1003 lines
22 KiB
C++
#define Use_MsgBase
|
||
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <time.h>
|
||
#include <stdio.h>
|
||
#include "proboard.hpp"
|
||
#include "jam.hpp"
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static dword
|
||
PbDate2JamDate( const Date& pbd , const Time& pbt)
|
||
{
|
||
int years = pbd.year() - 70;
|
||
|
||
dword unixtime = dword(years) * 365L + (dword(years + 1) / 4L);
|
||
|
||
return ((unixtime + pbd.dayNum() - 1) * 86400L + long(pbt));
|
||
}
|
||
|
||
|
||
|
||
static
|
||
void JamDate2PbDate( Date &pbd,
|
||
Time& pbt ,
|
||
dword jamdate )
|
||
{
|
||
struct tm *tms = localtime( (long *) & jamdate );
|
||
long seconds = long( jamdate ) % 86400L;
|
||
|
||
|
||
jamdate -= seconds;
|
||
|
||
pbt = seconds;
|
||
|
||
|
||
pbd[ 0 ] = tms->tm_mday;
|
||
pbd[ 1 ] = tms->tm_mon+1;
|
||
pbd[ 2 ] = tms->tm_year; // Y2K - LOOKS OK, BUT CHECK IT OUT
|
||
}
|
||
|
||
|
||
|
||
static void
|
||
JamMsg2Message(JamHeader *jam,JamExtHeader *xjam,Message *msg)
|
||
{
|
||
strcpy(msg->from , xjam->from);
|
||
strcpy(msg->to , xjam->to);
|
||
strcpy(msg->subj , xjam->subject);
|
||
|
||
msg->origZone = xjam->fromZone;
|
||
msg->origNet = xjam->fromNet;
|
||
msg->origNode = xjam->fromNode;
|
||
msg->origPoint = xjam->fromPoint;
|
||
msg->destZone = xjam->toZone;
|
||
msg->destNet = xjam->toNet;
|
||
msg->destNode = xjam->toNode;
|
||
msg->destPoint = xjam->toPoint;
|
||
|
||
JamDate2PbDate( msg->postDate, msg->postTime , jam->dateWritten );
|
||
JamDate2PbDate( msg->recvDate, msg->recvTime , jam->dateReceived);
|
||
|
||
msg->num = jam->messageNumber;
|
||
msg->id = msg->num;
|
||
|
||
msg->prev = jam->replyTo;
|
||
msg->next = jam->reply1St;
|
||
|
||
msg->attr = 0;
|
||
|
||
if(jam->attribute & JAM_MSG_LOCAL ) msg->attr |= MSGATTR_LOCAL;
|
||
if(jam->attribute & JAM_MSG_INTRANSIT ) msg->attr |= MSGATTR_TRANSIT;
|
||
if(jam->attribute & JAM_MSG_PRIVATE ) msg->attr |= MSGATTR_PRIVATE;
|
||
if(jam->attribute & JAM_MSG_READ ) msg->attr |= MSGATTR_RECEIVED;
|
||
if(jam->attribute & JAM_MSG_SENT ) msg->attr |= MSGATTR_SENT;
|
||
if(jam->attribute & JAM_MSG_KILLSENT ) msg->attr |= MSGATTR_KILL;
|
||
if(jam->attribute & JAM_MSG_HOLD ) msg->attr |= MSGATTR_HOLD;
|
||
if(jam->attribute & JAM_MSG_CRASH ) msg->attr |= MSGATTR_CRASH;
|
||
if(jam->attribute & JAM_MSG_IMMEDIATE ) msg->attr |= MSGATTR_IMMEDIATE;
|
||
if(jam->attribute & JAM_MSG_DIRECT ) msg->attr |= MSGATTR_DIRECT;
|
||
if(jam->attribute & JAM_MSG_FILEREQUEST) msg->attr |= MSGATTR_FILEREQ;
|
||
if(jam->attribute & JAM_MSG_FILEATTACH ) msg->attr |= MSGATTR_FILE;
|
||
if(jam->attribute & JAM_MSG_TRUNCFILE ) msg->attr |= MSGATTR_TRUNCFILE;
|
||
if(jam->attribute & JAM_MSG_KILLFILE ) msg->attr |= MSGATTR_DELFILE;
|
||
if(jam->attribute & JAM_MSG_RECEIPTREQ ) msg->attr |= MSGATTR_RECEIPTREQ;
|
||
if(jam->attribute & JAM_MSG_ORPHAN ) msg->attr |= MSGATTR_ORPHAN;
|
||
if(jam->attribute & JAM_MSG_NODISP ) msg->attr |= MSGATTR_NODISP;
|
||
if(jam->attribute & JAM_MSG_LOCKED ) msg->attr |= MSGATTR_LOCKED;
|
||
if(jam->attribute & JAM_MSG_DELETED ) msg->attr |= MSGATTR_DELETED;
|
||
|
||
if(jam->attribute & JAM_MSG_TYPEECHO ) msg->attr |= MSGATTR_ECHOMAIL;
|
||
if(jam->attribute & JAM_MSG_TYPENET ) msg->attr |= MSGATTR_NETMAIL;
|
||
}
|
||
|
||
static void
|
||
Message2JamMsg(JamHeader *jam,JamExtHeader *xjam,Message *msg)
|
||
{
|
||
if(xjam != NULL)
|
||
{
|
||
strcpy(xjam->from , msg->from);
|
||
strcpy(xjam->to , msg->to );
|
||
strcpy(xjam->subject , msg->subj);
|
||
|
||
xjam->fromZone = msg->origZone ;
|
||
xjam->fromNet = msg->origNet ;
|
||
xjam->fromNode = msg->origNode ;
|
||
xjam->fromPoint = msg->origPoint;
|
||
xjam->toZone = msg->destZone ;
|
||
xjam->toNet = msg->destNet ;
|
||
xjam->toNode = msg->destNode ;
|
||
xjam->toPoint = msg->destPoint;
|
||
}
|
||
|
||
if(msg->postDate.ok())
|
||
jam->dateWritten = PbDate2JamDate( msg->postDate, msg->postTime );
|
||
|
||
jam->dateReceived = 0;
|
||
|
||
if(msg->attr & MSGATTR_RECEIVED && msg->recvDate.ok())
|
||
jam->dateReceived = PbDate2JamDate( msg->recvDate, msg->recvTime );
|
||
|
||
jam->messageNumber = msg->num;
|
||
|
||
jam->replyTo = msg->prev;
|
||
jam->reply1St = msg->next;
|
||
|
||
jam->attribute = 0;
|
||
|
||
if(msg->attr & MSGATTR_LOCAL ) jam->attribute |= JAM_MSG_LOCAL ;
|
||
if(msg->attr & MSGATTR_TRANSIT ) jam->attribute |= JAM_MSG_INTRANSIT ;
|
||
if(msg->attr & MSGATTR_PRIVATE ) jam->attribute |= JAM_MSG_PRIVATE ;
|
||
if(msg->attr & MSGATTR_RECEIVED ) jam->attribute |= JAM_MSG_READ ;
|
||
if(msg->attr & MSGATTR_SENT ) jam->attribute |= JAM_MSG_SENT ;
|
||
if(msg->attr & MSGATTR_KILL ) jam->attribute |= JAM_MSG_KILLSENT ;
|
||
if(msg->attr & MSGATTR_HOLD ) jam->attribute |= JAM_MSG_HOLD ;
|
||
if(msg->attr & MSGATTR_CRASH ) jam->attribute |= JAM_MSG_CRASH ;
|
||
if(msg->attr & MSGATTR_IMMEDIATE ) jam->attribute |= JAM_MSG_IMMEDIATE ;
|
||
if(msg->attr & MSGATTR_DIRECT ) jam->attribute |= JAM_MSG_DIRECT ;
|
||
if(msg->attr & MSGATTR_FILEREQ ) jam->attribute |= JAM_MSG_FILEREQUEST;
|
||
if(msg->attr & MSGATTR_FILE ) jam->attribute |= JAM_MSG_FILEATTACH ;
|
||
if(msg->attr & MSGATTR_TRUNCFILE ) jam->attribute |= JAM_MSG_TRUNCFILE ;
|
||
if(msg->attr & MSGATTR_DELFILE ) jam->attribute |= JAM_MSG_KILLFILE ;
|
||
if(msg->attr & MSGATTR_RECEIPTREQ) jam->attribute |= JAM_MSG_RECEIPTREQ ;
|
||
if(msg->attr & MSGATTR_ORPHAN ) jam->attribute |= JAM_MSG_ORPHAN ;
|
||
if(msg->attr & MSGATTR_NODISP ) jam->attribute |= JAM_MSG_NODISP ;
|
||
if(msg->attr & MSGATTR_LOCKED ) jam->attribute |= JAM_MSG_LOCKED ;
|
||
if(msg->attr & MSGATTR_DELETED ) jam->attribute |= JAM_MSG_DELETED ;
|
||
|
||
if(msg->attr & MSGATTR_ECHOMAIL ) jam->attribute |= JAM_MSG_TYPEECHO ;
|
||
if(msg->attr & MSGATTR_NETMAIL ) jam->attribute |= JAM_MSG_TYPENET ;
|
||
|
||
if(!(msg->attr & (MSGATTR_ECHOMAIL|MSGATTR_NETMAIL)))
|
||
jam->attribute |= JAM_MSG_TYPELOCAL;
|
||
}
|
||
|
||
static bool
|
||
SubFields2ExtHeader( byte *subfields , word size , JamExtHeader& ext_hdr )
|
||
{
|
||
JamSubField *sub;
|
||
word pos;
|
||
|
||
for(pos = 0 ; pos < size ; )
|
||
{
|
||
sub = (JamSubField *)(&subfields[pos]);
|
||
|
||
pos += sizeof(JamSubField);
|
||
|
||
byte *buf = new byte[word(sub->datLen)+1];
|
||
memcpy(buf , &subfields[pos] , word(sub->datLen));
|
||
buf[word(sub->datLen)] = '\0';
|
||
|
||
pos += sub->datLen;
|
||
|
||
// At this point we have all data!
|
||
|
||
switch(sub->loId)
|
||
{
|
||
case JAMID_SENDERNAME:
|
||
{
|
||
strncpy( ext_hdr.from , buf , 35 );
|
||
ext_hdr.from[35] = '\0';
|
||
}
|
||
break;
|
||
case JAMID_RECEIVERNAME:
|
||
{
|
||
strncpy( ext_hdr.to , buf , 35 );
|
||
ext_hdr.to[35] = '\0';
|
||
}
|
||
break;
|
||
case JAMID_SUBJECT:
|
||
{
|
||
strncpy( ext_hdr.subject , buf , 71 );
|
||
ext_hdr.subject[71] = '\0';
|
||
}
|
||
break;
|
||
case JAMID_PID:
|
||
{
|
||
strncpy( ext_hdr.pid , buf , 79 );
|
||
ext_hdr.pid[79] = '\0';
|
||
}
|
||
break;
|
||
case JAMID_OADDRESS:
|
||
{
|
||
char *s = strtok( buf , ":");
|
||
|
||
ext_hdr.fromZone = 0;
|
||
ext_hdr.fromNet = 0;
|
||
ext_hdr.fromNode = 0;
|
||
ext_hdr.fromPoint = 0;
|
||
|
||
if(s)
|
||
{
|
||
ext_hdr.fromZone = atoi(s);
|
||
s = strtok( NULL , "/");
|
||
if(s)
|
||
{
|
||
ext_hdr.fromNet = atoi(s);
|
||
s = strtok( NULL , ".");
|
||
if(s)
|
||
{
|
||
ext_hdr.fromNode = atoi(s);
|
||
s = strtok( NULL , "@");
|
||
if(s)
|
||
{
|
||
ext_hdr.fromPoint = atoi(s);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case JAMID_DADDRESS:
|
||
{
|
||
char *s = strtok( buf , ":");
|
||
|
||
ext_hdr.toZone = 0;
|
||
ext_hdr.toNet = 0;
|
||
ext_hdr.toNode = 0;
|
||
ext_hdr.toPoint = 0;
|
||
|
||
if(s)
|
||
{
|
||
ext_hdr.toZone = atoi(s);
|
||
s = strtok( NULL , "/");
|
||
if(s)
|
||
{
|
||
ext_hdr.toNet = atoi(s);
|
||
s = strtok( NULL , ".");
|
||
if(s)
|
||
{
|
||
ext_hdr.toNode = atoi(s);
|
||
s = strtok( NULL , ".");
|
||
if(s)
|
||
{
|
||
ext_hdr.toPoint = atoi(s);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
delete [] buf;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
word
|
||
ExtHeader2SubFields(byte *subfields, JamExtHeader& xjam)
|
||
{
|
||
char addr_buf[30];
|
||
|
||
JamSubField *sub;
|
||
word index = 0;
|
||
|
||
sub = (JamSubField *) &subfields[index];
|
||
|
||
sub->loId = JAMID_SENDERNAME;
|
||
sub->hiId = 0;
|
||
sub->datLen = strlen(xjam.from);
|
||
|
||
index += sizeof(JamSubField);
|
||
|
||
strcpy(&subfields[index] , xjam.from);
|
||
|
||
index += sub->datLen;
|
||
|
||
sub = (JamSubField *) &subfields[index];
|
||
|
||
sub->loId = JAMID_RECEIVERNAME;
|
||
sub->hiId = 0;
|
||
sub->datLen = strlen(xjam.to);
|
||
|
||
index += sizeof(JamSubField);
|
||
|
||
strcpy(&subfields[index] , xjam.to);
|
||
|
||
index += sub->datLen;
|
||
|
||
sub = (JamSubField *) &subfields[index];
|
||
|
||
sub->loId = JAMID_SUBJECT;
|
||
sub->hiId = 0;
|
||
sub->datLen = strlen(xjam.subject);
|
||
|
||
index += sizeof(JamSubField);
|
||
|
||
strcpy(&subfields[index] , xjam.subject);
|
||
|
||
index += sub->datLen;
|
||
|
||
if(xjam.fromZone)
|
||
{
|
||
sprintf(addr_buf,"%d:%d/%d.%d",xjam.fromZone,xjam.fromNet,xjam.fromNode,xjam.fromPoint);
|
||
|
||
sub = (JamSubField *) &subfields[index];
|
||
|
||
sub->loId = JAMID_OADDRESS;
|
||
sub->hiId = 0;
|
||
sub->datLen = strlen(addr_buf);
|
||
|
||
index += sizeof(JamSubField);
|
||
|
||
strcpy(&subfields[index] , addr_buf);
|
||
|
||
index += sub->datLen;
|
||
}
|
||
|
||
if(xjam.toZone)
|
||
{
|
||
sprintf(addr_buf,"%d:%d/%d.%d",xjam.toZone,xjam.toNet,xjam.toNode,xjam.toPoint);
|
||
|
||
sub = (JamSubField *) &subfields[index];
|
||
|
||
sub->loId = JAMID_DADDRESS;
|
||
sub->hiId = 0;
|
||
sub->datLen = strlen(addr_buf);
|
||
|
||
index += sizeof(JamSubField);
|
||
|
||
strcpy(&subfields[index] , addr_buf);
|
||
|
||
index += sub->datLen;
|
||
}
|
||
|
||
if(xjam.pid[0])
|
||
{
|
||
sub = (JamSubField *) &subfields[index];
|
||
|
||
sub->loId = JAMID_PID;
|
||
sub->hiId = 0;
|
||
sub->datLen = strlen(xjam.pid);
|
||
|
||
index += sizeof(JamSubField);
|
||
|
||
strcpy(&subfields[index] , xjam.pid);
|
||
|
||
index += sub->datLen;
|
||
}
|
||
|
||
return index;
|
||
}
|
||
|
||
|
||
JamMsgBase::JamMsgBase()
|
||
{
|
||
lastAreaNum = -1;
|
||
|
||
jamHeader = new JamFileHeader;
|
||
|
||
CLEAR_OBJECT(*jamHeader);
|
||
}
|
||
|
||
JamMsgBase::~JamMsgBase()
|
||
{
|
||
close();
|
||
|
||
delete jamHeader;
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::open()
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
void
|
||
JamMsgBase::close()
|
||
{
|
||
f_jhr.close();
|
||
f_jdt.close();
|
||
f_jdx.close();
|
||
f_jlr.close();
|
||
|
||
lastAreaNum = -1;
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::jamLock()
|
||
{
|
||
return f_jhr.lock(0,1);
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::jamUnLock()
|
||
{
|
||
return f_jhr.unlock(0,1);
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::readHeader()
|
||
{
|
||
f_jhr.rewind();
|
||
|
||
return (f_jhr.read( jamHeader , sizeof(JamFileHeader) ) == sizeof(JamFileHeader));
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::writeHeader()
|
||
{
|
||
f_jhr.rewind();
|
||
|
||
return (f_jhr.write( jamHeader , sizeof(JamFileHeader) ) == sizeof(JamFileHeader));
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::openArea(MsgArea& ma)
|
||
{
|
||
if(ma.areaNum == lastAreaNum)
|
||
return TRUE;
|
||
|
||
lastAreaNum = -1;
|
||
|
||
FileName fn_jhr( ma.path , ".JHR" );
|
||
FileName fn_jdt( ma.path , ".JDT" );
|
||
FileName fn_jdx( ma.path , ".JDX" );
|
||
FileName fn_jlr( ma.path , ".JLR" );
|
||
|
||
f_jhr.close();
|
||
f_jdt.close();
|
||
f_jdx.close();
|
||
f_jlr.close();
|
||
|
||
if(!f_jhr.open( fn_jhr , fmode_rw | fmode_shared , 4096))
|
||
{
|
||
if(!f_jhr.open( fn_jhr , fmode_create | fmode_rw | fmode_shared , 4096))
|
||
return FALSE;
|
||
|
||
CLEAR_OBJECT(*jamHeader);
|
||
|
||
jamHeader->signature = JAM_SIGNATURE;
|
||
jamHeader->baseMsgNum = 1;
|
||
jamHeader->passwordCrc = dword(-1);
|
||
jamHeader->dateCreated = PbDate2JamDate( Date(TODAY) , Time(NOW) );
|
||
|
||
if(!writeHeader())
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
if(!readHeader())
|
||
return FALSE;
|
||
}
|
||
|
||
if( !f_jdt.open( fn_jdt , fmode_rw | fmode_copen | fmode_shared , 512 )
|
||
|| !f_jdx.open( fn_jdx , fmode_rw | fmode_copen | fmode_shared , 2048 )
|
||
|| !f_jlr.open( fn_jlr , fmode_rw | fmode_copen | fmode_shared , 512 )
|
||
)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
lastAreaNum = ma.areaNum;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::readMsg(Message &msg,long id)
|
||
{
|
||
int order = 1;
|
||
JamIndex idx;
|
||
|
||
if(id < 0)
|
||
{
|
||
order = -1;
|
||
id = -id;
|
||
}
|
||
|
||
if(!openArea(*msg.msgArea))
|
||
return -1;
|
||
|
||
long num_found = findIdx( idx , id , order );
|
||
|
||
if(num_found < 0)
|
||
return -1;
|
||
|
||
JamHeader hdr;
|
||
JamExtHeader ext_hdr;
|
||
|
||
f_jhr.seek(idx.offset);
|
||
if(f_jhr.read( &hdr , sizeof(JamHeader) ) != sizeof(JamHeader))
|
||
return -1;
|
||
|
||
if(hdr.signature != JAM_SIGNATURE)
|
||
return -1;
|
||
|
||
byte *subfields = new byte[word(hdr.subFieldLen)];
|
||
|
||
if(f_jhr.read( subfields , hdr.subFieldLen ) != hdr.subFieldLen)
|
||
return -1;
|
||
|
||
SubFields2ExtHeader( subfields , word(hdr.subFieldLen) , ext_hdr );
|
||
|
||
JamMsg2Message( &hdr , &ext_hdr , &msg );
|
||
|
||
delete [] subfields;
|
||
|
||
return num_found;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::lowMsg(MsgArea &ma)
|
||
{
|
||
if(!openArea(ma))
|
||
return -1;
|
||
|
||
readHeader();
|
||
|
||
return jamHeader->baseMsgNum;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::numMsgs(MsgArea &ma)
|
||
{
|
||
if(!openArea(ma))
|
||
return -1;
|
||
|
||
readHeader();
|
||
|
||
return jamHeader->activeMsgs;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::highMsg(MsgArea &ma)
|
||
{
|
||
if(!openArea(ma))
|
||
return -1;
|
||
|
||
readHeader();
|
||
|
||
return (f_jdx.len() / sizeof(JamIndex) + jamHeader->baseMsgNum - 1);
|
||
}
|
||
|
||
word
|
||
JamMsgBase::readMsgText(Message& msg,char *ptr,long offset,word size)
|
||
{
|
||
JamIndex idx;
|
||
|
||
long num_found = findIdx( idx , msg.num , 0 );
|
||
|
||
if(num_found != msg.num)
|
||
return 0;
|
||
|
||
JamHeader hdr;
|
||
|
||
f_jhr.seek(idx.offset);
|
||
if(f_jhr.read( &hdr , sizeof(JamHeader) ) != sizeof(JamHeader))
|
||
return 0;
|
||
|
||
if(hdr.signature != JAM_SIGNATURE)
|
||
return 0;
|
||
|
||
if(offset + size > hdr.txtLen)
|
||
{
|
||
if(offset > hdr.txtLen)
|
||
return 0;
|
||
|
||
size = hdr.txtLen - offset;
|
||
}
|
||
|
||
f_jdt.seek(hdr.offset + offset);
|
||
|
||
return f_jdt.read( ptr , size );
|
||
}
|
||
|
||
|
||
long
|
||
JamMsgBase::appendMsg(Message& msg)
|
||
{
|
||
JamIndex j_idx;
|
||
JamHeader j_hdr;
|
||
JamExtHeader j_ext_hdr;
|
||
|
||
if(!openArea(*msg.msgArea))
|
||
return -1;
|
||
|
||
jamLock();
|
||
readHeader();
|
||
|
||
long next_num = f_jdx.len() / sizeof(JamIndex);
|
||
|
||
j_idx.crc32 = JamCrc(msg.to);
|
||
j_idx.offset = f_jhr.len();
|
||
|
||
f_jdx.seek(next_num * sizeof(JamIndex));
|
||
f_jdx.write(&j_idx , sizeof(JamIndex));
|
||
|
||
byte *subfields = new char[1024];
|
||
|
||
CLEAR_OBJECT( j_hdr );
|
||
CLEAR_OBJECT( j_ext_hdr );
|
||
|
||
j_hdr.signature = JAM_SIGNATURE;
|
||
j_hdr.revision = 1;
|
||
j_hdr.passwordCrc = dword(-1);
|
||
j_hdr.offset = f_jdt.len();
|
||
|
||
msg.num = next_num + jamHeader->baseMsgNum;
|
||
msg.id = msg.num;
|
||
|
||
Message2JamMsg(&j_hdr,&j_ext_hdr,&msg);
|
||
|
||
strcpy(j_ext_hdr.pid,PID_STRING_JAM);
|
||
|
||
j_hdr.subFieldLen = ExtHeader2SubFields(subfields, j_ext_hdr);
|
||
|
||
File f_txt;
|
||
|
||
if(f_txt.open("MSGTMP",fmode_read,512))
|
||
{
|
||
f_jdt.seek( j_hdr.offset );
|
||
|
||
for(int len = 0;;)
|
||
{
|
||
int c = f_txt.readByte();
|
||
|
||
if(c < 0)
|
||
break;
|
||
|
||
if(char(c) == '<EFBFBD>' || char(c) == '\n')
|
||
continue;
|
||
|
||
f_jdt << char(c);
|
||
len++;
|
||
}
|
||
|
||
j_hdr.txtLen = len;
|
||
}
|
||
|
||
f_jhr.seek ( j_idx.offset );
|
||
f_jhr.write( &j_hdr , sizeof(JamHeader));
|
||
f_jhr.write( subfields , j_hdr.subFieldLen);
|
||
|
||
delete [] subfields;
|
||
|
||
jamHeader->activeMsgs++;
|
||
jamHeader->modCounter++;
|
||
|
||
writeHeader();
|
||
jamUnLock();
|
||
|
||
return msg.num;
|
||
}
|
||
|
||
bool
|
||
JamMsgBase::updateMsg(Message& msg)
|
||
{
|
||
JamIndex idx;
|
||
JamHeader hdr;
|
||
|
||
if(!openArea(*msg.msgArea))
|
||
return FALSE;
|
||
|
||
if(!jamLock())
|
||
return FALSE;
|
||
|
||
readHeader();
|
||
|
||
long found = findIdx( idx , msg.num , 0 );
|
||
|
||
if(found != msg.num)
|
||
{
|
||
jamUnLock();
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
f_jhr.seek(idx.offset);
|
||
if(f_jhr.read( &hdr , sizeof(JamHeader) ) != sizeof(JamHeader))
|
||
{
|
||
jamUnLock();
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
Message2JamMsg( &hdr , NULL , &msg );
|
||
|
||
f_jhr.seek(idx.offset);
|
||
f_jhr.write( &hdr , sizeof(JamHeader) );
|
||
|
||
jamHeader->modCounter++;
|
||
|
||
writeHeader();
|
||
|
||
jamUnLock();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::msgNum(MsgArea&,long id)
|
||
{
|
||
return id;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::msgId(MsgArea&,long num)
|
||
{
|
||
return num;
|
||
}
|
||
|
||
|
||
bool
|
||
JamMsgBase::deleteMsg(Message &msg)
|
||
{
|
||
JamIndex idx;
|
||
JamHeader hdr;
|
||
|
||
if(!openArea(*msg.msgArea))
|
||
return FALSE;
|
||
|
||
if(!jamLock())
|
||
return FALSE;
|
||
|
||
readHeader();
|
||
|
||
long found = findIdx( idx , msg.num , 0 );
|
||
|
||
if(found != msg.num)
|
||
{
|
||
jamUnLock();
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
f_jhr.seek(idx.offset);
|
||
if(f_jhr.read( &hdr , sizeof(JamHeader) ) != sizeof(JamHeader))
|
||
{
|
||
jamUnLock();
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
if(hdr.attribute & JAM_MSG_DELETED)
|
||
{
|
||
jamUnLock();
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
hdr.attribute |= JAM_MSG_DELETED;
|
||
hdr.txtLen = 0;
|
||
|
||
f_jhr.seek(idx.offset);
|
||
f_jhr.write( &hdr , sizeof(JamHeader) );
|
||
|
||
idx.crc32 = dword(-1);
|
||
|
||
f_jdx.seek ( (found - jamHeader->baseMsgNum) * sizeof(JamIndex) );
|
||
f_jdx.write( &idx , sizeof(JamIndex) );
|
||
|
||
jamHeader->activeMsgs--;
|
||
jamHeader->modCounter++;
|
||
|
||
writeHeader();
|
||
|
||
jamUnLock();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
static void
|
||
showbusy()
|
||
{
|
||
static int x = 0;
|
||
|
||
char *ss[] = {
|
||
"|",
|
||
"/",
|
||
"-",
|
||
"\\",
|
||
NULL
|
||
};
|
||
|
||
io << '\b' << ss[x] << char(0xFF);
|
||
|
||
x = ++x % 4;
|
||
}
|
||
|
||
word
|
||
JamMsgBase::scanMail(MessageIndex *msgidx,word maxmsgs)
|
||
{
|
||
MsgArea ma;
|
||
int index = 0;
|
||
|
||
io << "\3 ";
|
||
|
||
for(int i = 1; i <= MsgArea::highAreaNum() ; i++)
|
||
{
|
||
if(!ma.read(i)) continue;
|
||
|
||
if(ma.msgBaseType != MSGBASE_JAM) continue;
|
||
|
||
if(!user.mailCheckBoards.connected(i)) continue;
|
||
|
||
if(!check_access(ma.readLevel,ma.readFlags,ma.readFlagsNot)) continue;
|
||
|
||
dword name_crc = JamCrc(user.name);
|
||
dword alias_crc = JamCrc(user.alias);
|
||
|
||
if(!openArea(ma))
|
||
continue;
|
||
|
||
long lr = ma.lastRead(user_recnr);
|
||
|
||
showbusy();
|
||
|
||
f_jdx.rewind();
|
||
long rec = 0;
|
||
|
||
while( index < maxmsgs )
|
||
{
|
||
JamIndex jamidx;
|
||
|
||
if(f_jdx.read(&jamidx,sizeof(JamIndex)) != sizeof(JamIndex)) break;
|
||
|
||
if(jamidx.crc32 == name_crc || jamidx.crc32 == alias_crc || (ma.msgType == MSG_TOALL && (rec+jamHeader->baseMsgNum) > lr))
|
||
{
|
||
Message msg(ma.areaNum);
|
||
|
||
//*msg.msgArea = ma;
|
||
|
||
long msgread = readMsg( msg , rec + jamHeader->baseMsgNum );
|
||
|
||
if(msgread == rec + jamHeader->baseMsgNum && !(msg.attr & MSGATTR_RECEIVED))
|
||
{
|
||
if(( !stricmp(msg.to,user.name)
|
||
|| (!stricmp(msg.to,user.alias) && ma.flags && strcmp(user.name,user.alias))
|
||
|| (ma.msgType == MSG_TOALL && (rec+jamHeader->baseMsgNum) > lr)
|
||
)
|
||
&& (check_access(ma.readLevel,ma.readFlags,ma.readFlagsNot) || ma.sysopAccess())
|
||
)
|
||
{
|
||
msgidx[index].num = msgread;
|
||
msgidx[index].area = ma.areaNum;
|
||
index++;
|
||
}
|
||
}
|
||
|
||
f_jdx.seek( (rec+1) * sizeof(JamIndex) );
|
||
}
|
||
|
||
rec++;
|
||
}
|
||
}
|
||
|
||
io << '\b';
|
||
|
||
return index;
|
||
}
|
||
|
||
long
|
||
JamMsgBase::lastRead(MsgArea& ma,long)
|
||
{
|
||
if(!openArea(ma))
|
||
return -1;
|
||
|
||
dword crc = JamCrc(user.name);
|
||
|
||
JamLastRead jlr;
|
||
|
||
f_jlr.rewind();
|
||
|
||
for(;;)
|
||
{
|
||
if(f_jlr.read( &jlr , sizeof(JamLastRead) ) != sizeof(JamLastRead))
|
||
break;
|
||
|
||
if(crc == jlr.userCrc)
|
||
return jlr.highReadMsg;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void
|
||
JamMsgBase::setLastRead(MsgArea& ma,long,long num)
|
||
{
|
||
if(!openArea(ma))
|
||
return;
|
||
|
||
dword crc = JamCrc(user.name);
|
||
|
||
JamLastRead jlr;
|
||
|
||
f_jlr.rewind();
|
||
|
||
for(long rec = 0 ;; rec++)
|
||
{
|
||
if(f_jlr.read( &jlr , sizeof(JamLastRead) ) != sizeof(JamLastRead))
|
||
break;
|
||
|
||
if(crc == jlr.userCrc)
|
||
{
|
||
f_jlr.seek( rec * sizeof(JamLastRead) );
|
||
|
||
jlr.highReadMsg = num;
|
||
|
||
f_jlr.write( &jlr , sizeof(JamLastRead) );
|
||
|
||
return;
|
||
}
|
||
}
|
||
|
||
jlr.userCrc = crc;
|
||
jlr.userId = crc;
|
||
jlr.lastReadMsg = num;
|
||
jlr.highReadMsg = num;
|
||
|
||
f_jlr.seek( rec * sizeof(JamLastRead) );
|
||
f_jlr.write( &jlr , sizeof(JamLastRead) );
|
||
}
|
||
|
||
long
|
||
JamMsgBase::findIdx( JamIndex &mi,long num,int order )
|
||
{
|
||
JamIndex local_idx;
|
||
|
||
if(order < 0)
|
||
order = -1;
|
||
|
||
if(order > 0)
|
||
order = 1;
|
||
|
||
if(num < jamHeader->baseMsgNum)
|
||
{
|
||
if(order <= 0)
|
||
return -1;
|
||
|
||
num = jamHeader->baseMsgNum;
|
||
}
|
||
|
||
f_jdx.seek((num - jamHeader->baseMsgNum) * sizeof(JamIndex));
|
||
|
||
if(f_jdx.read( &local_idx , sizeof(JamIndex) ) != sizeof(JamIndex))
|
||
{
|
||
if(order >= 0) // exact or forward
|
||
return -1;
|
||
|
||
num = f_jdx.len() / sizeof(JamIndex) + jamHeader->baseMsgNum - 1;
|
||
|
||
f_jdx.seek((num - jamHeader->baseMsgNum) * sizeof(JamIndex));
|
||
if(f_jdx.read( &local_idx , sizeof(JamIndex) ) != sizeof(JamIndex))
|
||
return -1;
|
||
|
||
if(num <= 0)
|
||
return -1;
|
||
}
|
||
|
||
if(local_idx.crc32 != dword(-1))
|
||
{
|
||
mi = local_idx;
|
||
|
||
return num;
|
||
}
|
||
|
||
if(!order)
|
||
return -1;
|
||
|
||
while( local_idx.crc32 == dword(-1) )
|
||
{
|
||
num += order;
|
||
|
||
if(order < 0)
|
||
{
|
||
f_jdx.seek((num - jamHeader->baseMsgNum) * sizeof(JamIndex));
|
||
}
|
||
|
||
if(f_jdx.read( &local_idx , sizeof(JamIndex) ) != sizeof(JamIndex))
|
||
return -1;
|
||
}
|
||
|
||
mi = local_idx;
|
||
|
||
return (local_idx.crc32 != dword(-1)) ? num : -1;
|
||
}
|