This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gmb3/gmojamm4.cpp
2006-05-14 11:45:05 +00:00

542 lines
16 KiB
C++

// This may look like C code, but it is really -*- C++ -*-
// ------------------------------------------------------------------
// The Goldware Library
// Copyright (C) 1990-1999 Odinn Sorensen
// ------------------------------------------------------------------
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307, USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// JAM msgbase implementation, save/delete.
// ------------------------------------------------------------------
#include <gmemdbg.h>
#include <gdbgtrk.h>
#include <gdbgerr.h>
#include <gcrcall.h>
#include <gstrall.h>
#include <gtxtpara.h>
#include <gutlmisc.h>
#include <gmojamm.h>
// ------------------------------------------------------------------
void JamArea::lock() {
GFTRK("JamArea::lock");
if(not data->islocked and WideCanLock) {
long _tries = 0;
// Try to get the lock
while(::lock(data->fhjhr, 0, 1) == -1) {
// Tell the world
if(PopupLocked(++_tries, true, real_path()) == false) {
WideLog->ErrLock();
raw_close();
WideLog->printf("! A JAM msgbase file could not be locked.");
WideLog->printf(": %s.jhr.", real_path());
WideLog->ErrOSInfo();
LockErrorExit();
}
}
// Remove the popup window
if(_tries)
PopupLocked(0, 0, NULL);
data->islocked = true;
}
// Load fresh copy of the header info
lseekset(data->fhjhr, 0);
read(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
if(not jamwide->smapihw) {
if(data->fhjhw == -1) {
Path file;
sprintf(file, "%s.cmhw", real_path()); data->fhjhw = ::sopen(file, O_RDWR|O_BINARY, WideSharemode, S_STDRW);
}
if(data->fhjhw != -1) {
lseek(data->fhjhw, 0, SEEK_SET);
read(data->fhjhw, &data->highwater, sizeof(int32_t));
}
else
data->highwater = -1;
}
else
data->highwater = -1;
GFTRK(0);
}
// ------------------------------------------------------------------
void JamArea::unlock() {
GFTRK("JamArea::unlock");
if(data->islocked) {
::unlock(data->fhjhr, 0, 1);
data->islocked = false;
}
GFTRK(0);
}
// ------------------------------------------------------------------
void JamArea::add_subfield(JamHdr& __hdr, byte*& __subfield, word __loid, word __hiid, char* __data, uint32_t __maxlen) {
uint32_t _datlen = strlen(__data);
__subfield = (byte*)throw_realloc(__subfield, (uint)__hdr.subfieldlen+sizeof(JamSubFieldHdr)+_datlen);
JamSubField* _subfieldptr = (JamSubField*)(__subfield + (uint)__hdr.subfieldlen);
_subfieldptr->loid = __loid;
_subfieldptr->hiid = __hiid;
_subfieldptr->datlen = MinV(_datlen, __maxlen);
memcpy(_subfieldptr->buffer, __data, _subfieldptr->datlen);
__hdr.subfieldlen += sizeof(JamSubFieldHdr) + _subfieldptr->datlen;
}
// ------------------------------------------------------------------
void JamArea::save_message(int __mode, gmsg* __msg, JamHdr& __hdr) {
int _was_locked = data->islocked;
if(not _was_locked)
lock();
// Reset header
memset(&__hdr, 0, sizeof(JamHdr));
// Init paragraph class
GParagraph _para;
if(WideDispsoftcr)
_para.softcr = SOFTCR;
// Set default msg text offset and length
__hdr.offset = __msg->txtstart;
__hdr.txtlen = __msg->txtlength;
// Get message text size
char* _txtcpy = NULL;
if(__msg->txt and (__mode & GMSG_TXT)) {
// Work on a copy of the original msg text
_txtcpy = throw_strdup(__msg->txt);
// Convert message text to a paragraph list
_para.ConvertText(_txtcpy, strlen(_txtcpy));
// Mark control lines and calculate pure message text size
__hdr.txtlen = _para.CheckCtrlLines();
}
// Determine where to write the message text
if((__mode & GMSG_NEW) or (__hdr.txtlen > __msg->txtlength))
__hdr.offset = filelength(data->fhjdt);
byte* _subfield = NULL;
char _buf[1024];
__hdr.subfieldlen = __msg->jam.subfieldlen;
if(__mode & GMSG_TXT) {
// Build the subfields
__hdr.subfieldlen = 0;
// Process addressing kludges
int _line = 0;
GParaData* _pdptr = _para.paraidx;
while(_line < _para.lines) {
if(_pdptr->control > CTRL_KLUDGE) {
word fmpt, topt;
char buf1[201], buf2[201];
switch(_pdptr->control) {
case CTRL_INTL:
fmpt = __msg->orig.point;
topt = __msg->dest.point;
sscanf(_pdptr->text+6, "%s %s", buf1, buf2);
__msg->dest.set(buf1);
__msg->orig.set(buf2);
__msg->orig.point = fmpt;
__msg->dest.point = topt;
break;
case CTRL_FMPT:
__msg->orig.point = atow(_pdptr->text+6);
break;
case CTRL_TOPT:
__msg->dest.point = atow(_pdptr->text+6);
break;
case CTRL_MSGID:
__msg->msgid.reset(_pdptr->text+8, __msg->odom);
break;
}
}
_pdptr++;
_line++;
}
if(*__msg->by)
add_subfield(__hdr, _subfield, JAMSUB_SENDERNAME, 0, __msg->by, JAMSUB_SENDERNAME_LEN);
if(__msg->orig.net) {
__msg->orig.make_string(_buf, __msg->odom);
add_subfield(__hdr, _subfield, JAMSUB_OADDRESS, 0, _buf, JAMSUB_OADDRESS_LEN);
}
if(*__msg->to)
add_subfield(__hdr, _subfield, JAMSUB_RECEIVERNAME, 0, __msg->to, JAMSUB_RECEIVERNAME_LEN);
if(__msg->dest.net) {
__msg->dest.make_string(_buf, __msg->ddom);
add_subfield(__hdr, _subfield, JAMSUB_DADDRESS, 0, _buf, JAMSUB_DADDRESS_LEN);
}
if(*__msg->re)
add_subfield(__hdr, _subfield, JAMSUB_SUBJECT, 0, __msg->re, JAMSUB_SUBJECT_LEN);
// Convert kludges
_line = 0;
_pdptr = _para.paraidx;
while(_line < _para.lines) {
if(_pdptr->control > CTRL_KLUDGE) {
uint _offset = 0;
word _loid = 0;
uint32_t _maxlen = 0;
switch(_pdptr->control) {
case CTRL_INTL:
case CTRL_FMPT:
case CTRL_TOPT:
// Strip these. Data is stored in the address subfields
break;
case CTRL_MSGID:
_loid = JAMSUB_MSGID;
_maxlen = JAMSUB_MSGID_LEN;
_offset = 8;
strxcpy(__msg->msgids, _pdptr->text+_offset, sizeof(__msg->msgids));
break;
case CTRL_REPLY:
_loid = JAMSUB_REPLYID;
_maxlen = JAMSUB_REPLYID_LEN;
_offset = 8;
strxcpy(__msg->replys, _pdptr->text+_offset, sizeof(__msg->replys));
break;
case CTRL_PID:
_loid = JAMSUB_PID;
_maxlen = JAMSUB_PID_LEN;
_offset = 6;
break;
case CTRL_VIA:
_loid = JAMSUB_TRACE;
_maxlen = JAMSUB_TRACE_LEN;
_offset = 5;
break;
case CTRL_SEENBY:
_loid = JAMSUB_SEENBY2D;
_maxlen = JAMSUB_SEENBY2D_LEN;
_offset = 9;
break;
case CTRL_SEENBY1:
_loid = JAMSUB_SEENBY2D;
_maxlen = JAMSUB_SEENBY2D_LEN;
_offset = 10;
break;
case CTRL_PATH:
_loid = JAMSUB_PATH2D;
_maxlen = JAMSUB_PATH2D_LEN;
_offset = 7;
break;
case CTRL_FLAGS:
_loid = JAMSUB_FLAGS;
_maxlen = JAMSUB_FLAGS_LEN;
_offset = 7;
break;
default:
_loid = JAMSUB_FTSKLUDGE;
_maxlen = JAMSUB_FTSKLUDGE_LEN;
_offset = 1;
}
if(_offset)
add_subfield(__hdr, _subfield, _loid, 0, _pdptr->text+_offset, _maxlen);
}
_pdptr++;
_line++;
}
}
JamIndex _idx;
bool was_deleted = false;
if(__mode & GMSG_NEW) {
__msg->msgno = data->hdrinfo.basemsgnum + (filelength(data->fhjdx)/sizeof(JamIndex));
__hdr.messagenumber = __msg->msgno;
_idx.hdroffset = filelength(data->fhjhr);
}
else {
__hdr.messagenumber = __msg->msgno;
lseekset(data->fhjdx, __hdr.messagenumber-data->hdrinfo.basemsgnum, sizeof(JamIndex));
read(data->fhjdx, &_idx, sizeof(JamIndex));
if(_idx.hdroffset != 0xFFFFFFFFL) {
lseekset(data->fhjhr, _idx.hdroffset);
JamHdr oldhdr;
read(data->fhjhr, &oldhdr, sizeof(JamHdr));
was_deleted = make_bool(oldhdr.attribute & JAMATTR_DELETED);
if(oldhdr.subfieldlen != __hdr.subfieldlen) {
oldhdr.attribute |= JAMATTR_DELETED;
oldhdr.txtlen = 0;
lseekset(data->fhjhr, _idx.hdroffset);
write(data->fhjhr, &oldhdr, sizeof(JamHdr));
_idx.hdroffset = filelength(data->fhjhr);
}
}
}
if(_idx.hdroffset != 0xFFFFFFFFL) {
memcpy(__hdr.signature, JAM_SIGNATURE, 4);
__hdr.revision = JAM_REVISION;
__hdr.replyto = __msg->link.to();
__hdr.reply1st = __msg->link.first();
__hdr.replynext = __msg->link.next();
__hdr.cost = __msg->cost;
__hdr.timesread = __msg->timesread;
__hdr.passwordcrc = 0xFFFFFFFFL;
__hdr.msgidcrc = strCrc32(jamstrlwr(strcpy(_buf, __msg->msgids)), NO, CRC32_MASK_CCITT);
__hdr.replycrc = strCrc32(jamstrlwr(strcpy(_buf, __msg->replys)), NO, CRC32_MASK_CCITT);
_idx.usercrc = strCrc32(jamstrlwr(strcpy(_buf, __msg->to)), NO, CRC32_MASK_CCITT);
__hdr.datewritten = __msg->written;
__hdr.datereceived = __msg->received;
__hdr.dateprocessed = __msg->arrived;
__hdr.attribute |= __msg->attr.loc() ? JAMATTR_LOCAL : 0;
__hdr.attribute |= __msg->attr.trs() ? JAMATTR_INTRANSIT : 0;
__hdr.attribute |= __msg->attr.pvt() ? JAMATTR_PRIVATE : 0;
__hdr.attribute |= __msg->attr.rcv() ? JAMATTR_READ : 0;
__hdr.attribute |= __msg->attr.snt() ? JAMATTR_SENT : 0;
__hdr.attribute |= __msg->attr.k_s() ? JAMATTR_KILLSENT : 0;
__hdr.attribute |= __msg->attr.a_s() ? JAMATTR_ARCHIVESENT : 0;
__hdr.attribute |= __msg->attr.hld() ? JAMATTR_HOLD : 0;
__hdr.attribute |= __msg->attr.cra() ? JAMATTR_CRASH : 0;
__hdr.attribute |= __msg->attr.imm() ? JAMATTR_IMMEDIATE : 0;
__hdr.attribute |= __msg->attr.dir() ? JAMATTR_DIRECT : 0;
__hdr.attribute |= __msg->attr.zon() ? JAMATTR_GATE : 0;
__hdr.attribute |= __msg->attr.frq() ? JAMATTR_FILEREQUEST : 0;
__hdr.attribute |= __msg->attr.att() ? JAMATTR_FILEATTACH : 0;
__hdr.attribute |= __msg->attr.tfs() ? JAMATTR_TRUNCFILE : 0;
__hdr.attribute |= __msg->attr.kfs() ? JAMATTR_KILLFILE : 0;
__hdr.attribute |= __msg->attr.rrq() ? JAMATTR_RECEIPTREQ : 0;
__hdr.attribute |= __msg->attr.cfm() ? JAMATTR_CONFIRMREQ : 0;
__hdr.attribute |= __msg->attr.orp() ? JAMATTR_ORPHAN : 0;
__hdr.attribute |= __msg->attr.lok() ? JAMATTR_LOCKED : 0;
__hdr.attribute |= __msg->attr.del() ? JAMATTR_DELETED : 0;
if(isnet())
__hdr.attribute |= JAMATTR_TYPENET;
else if(isecho())
__hdr.attribute |= JAMATTR_TYPEECHO;
else
__hdr.attribute |= JAMATTR_TYPELOCAL;
lseekset(data->fhjhr, _idx.hdroffset);
write(data->fhjhr, &__hdr, sizeof(JamHdr));
// Only write subfields if the msg body is written
if(__mode & GMSG_TXT)
write(data->fhjhr, _subfield, (uint)__hdr.subfieldlen);
// Delete msg if requested
if(__mode & GMSG_DELETE) {
if(not was_deleted)
data->hdrinfo.activemsgs--;
__hdr.attribute |= JAMATTR_DELETED;
_idx.usercrc = 0xFFFFFFFFL;
if(wide->harddelete)
_idx.hdroffset = 0xFFFFFFFFL;
}
// Write msg index
lseekset(data->fhjdx, __hdr.messagenumber-data->hdrinfo.basemsgnum, sizeof(JamIndex));
write(data->fhjdx, &_idx, sizeof(JamIndex));
// Free subfield buffer
throw_release(_subfield);
// Update the header info
if((__mode & GMSG_NEW) or (was_deleted and not __msg->attr.del()))
data->hdrinfo.activemsgs++;
data->hdrinfo.modcounter++;
lseekset(data->fhjhr, 0);
write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
// If message text is used
if(__mode & GMSG_TXT) {
char* _txt = (char*)throw_malloc((uint)(__hdr.txtlen+256));
// Copy text paragraphs, excluding kludges
int _line = 0;
char* _tptr = _txt;
GParaData* _pdptr = _para.paraidx;
while(_line < _para.lines) {
if(_pdptr->control < CTRL_KLUDGE) {
memcpy(_tptr, _pdptr->text, _pdptr->length);
_tptr += _pdptr->length;
*_tptr++ = CR;
}
_pdptr++;
_line++;
}
*_tptr = NUL;
// Seek to start position of the message text
lseekset(data->fhjdt, __hdr.offset);
// Write the message text
write(data->fhjdt, _txt, (uint)__hdr.txtlen);
// Release the memory we have used
throw_free(_txtcpy);
throw_free(_txt);
}
// Update internals if new
if(__mode & GMSG_NEW) {
// Count our msgs
data->timesposted++;
// Update internal array
Msgn->Append(__msg->msgno);
}
// Adjust the highwatermark if required
if(jamwide->smapihw and __msg->attr.uns()) {
if(data->hdrinfo.highwatermark >= __msg->msgno)
data->hdrinfo.highwatermark = __msg->msgno - 1;
}
else if((data->highwater != -1) and (data->fhjhw != -1)) {
if(data->highwater >= __msg->msgno) {
data->highwater = __msg->msgno - 1;
lseek(data->fhjhw, 0, SEEK_SET);
write(data->fhjhw, &data->highwater, sizeof(int32_t));
}
}
}
else {
scan();
}
if(not _was_locked) {
lseekset(data->fhjhr, 0);
write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
unlock();
}
GFTRK(0);
}
// ------------------------------------------------------------------
void JamArea::save_hdr(int __mode, gmsg* __msg) {
GFTRK("JamArea::save_hdr");
JamHdr _hdr;
save_message(__mode | GMSG_HDR, __msg, _hdr);
}
// ------------------------------------------------------------------
void JamArea::save_msg(int __mode, gmsg* __msg) {
GFTRK("JamArea::save_msg");
JamHdr _hdr;
save_message(__mode | GMSG_HDRTXT, __msg, _hdr);
}
// ------------------------------------------------------------------
void JamArea::del_msg(gmsg* __msg) {
GFTRK("JamArea::del_msg");
JamHdr _hdr;
save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
}
// ------------------------------------------------------------------
void JamArea::new_msgno(gmsg* __msg) {
GFTRK("JamArea::new_msgno");
__msg->msgno = data->hdrinfo.basemsgnum + (filelength(data->fhjdx)/sizeof(JamIndex));
GFTRK(0);
}
// ------------------------------------------------------------------
void JamArea::update_timesread(gmsg* msg) {
GFTRK("JamArea::update_timesread");
lock();
lseekset(data->fhjdx, msg->msgno-data->hdrinfo.basemsgnum, sizeof(JamIndex));
JamIndex idx;
read(data->fhjdx, &idx, sizeof(JamIndex));
JamHdr hdr;
lseekset(data->fhjhr, idx.hdroffset);
read(data->fhjhr, &hdr, sizeof(JamHdr));
hdr.timesread = msg->timesread;
lseekset(data->fhjhr, idx.hdroffset);
write(data->fhjhr, &hdr, sizeof(JamHdr));
data->hdrinfo.modcounter++;
lseekset(data->fhjhr, 0);
write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
unlock();
GFTRK(0);
}
// ------------------------------------------------------------------