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/gmopcbd4.cpp
2005-10-07 12:41:11 +00:00

443 lines
13 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$
// ------------------------------------------------------------------
// PCBoard msgbase handling.
// ------------------------------------------------------------------
// ------------------------------------------------------------------
#include <gdbgerr.h>
#include <gdbgtrk.h>
#include <gstrall.h>
#include <gutlmisc.h>
#include <gmopcbd.h>
// ------------------------------------------------------------------
void PcbArea::lock() {
GFTRK("PcbLock");
if(not data->islocked) {
if(WideCanLock) {
long _tries = 0;
while(::lock(data->fhmsg, 16, 6) == -1) {
if(PopupLocked(++_tries, true, real_path()) == false) {
WideLog->ErrLock();
raw_close();
WideLog->printf("! A PCBoard msgbase file could not be locked.");
WideLog->printf(": %s.", real_path());
WideLog->ErrOSInfo();
LockErrorExit();
}
}
if(_tries)
PopupLocked(0, 0, NULL);
}
lseekset(data->fhmsg, 0);
read(data->fhmsg, &data->base, sizeof(PcbBase));
lseekset(data->fhmsg, 0);
memcpy(data->base.locked, "LOCKED", 6);
write(data->fhmsg, &data->base, sizeof(PcbBase));
data->base.highmsgno = B2L(data->base.highmsgno);
data->base.lowmsgno = B2L(data->base.lowmsgno);
data->base.active = B2L(data->base.active);
data->islocked = true;
}
GFTRK(NULL);
}
// ------------------------------------------------------------------
void PcbArea::unlock() {
GFTRK("PcbUnlock");
if(WideCanLock and data->islocked)
::unlock(data->fhmsg, 16, 6);
lseekset(data->fhmsg, 0);
memset(data->base.locked, ' ', 6);
data->base.highmsgno = L2B(data->base.highmsgno);
data->base.lowmsgno = L2B(data->base.lowmsgno);
data->base.active = L2B(data->base.active);
write(data->fhmsg, &data->base, sizeof(PcbBase));
data->base.highmsgno = B2L(data->base.highmsgno);
data->base.lowmsgno = B2L(data->base.lowmsgno);
data->base.active = B2L(data->base.active);
data->islocked = false;
GFTRK(NULL);
}
// ------------------------------------------------------------------
void PcbArea::save_message(int __mode, gmsg* __msg, PcbHdr& __hdr) {
// Lock and refresh base
int _was_locked = data->islocked;
if(not _was_locked)
lock();
// Reset header
memset(&__hdr, 0, sizeof(PcbHdr));
// Find msgno and index offset
PcbIdx _idx;
uint32_t oldmsgno = __msg->msgno;
int32_t oldtxtstart = __msg->txtstart;
int32_t oldtxtlength = __msg->txtlength;
if(__mode & GMSG_TXT) {
if(data->base.lowmsgno == 0)
data->base.lowmsgno = 1;
data->base.highmsgno++;
data->base.active++;
__msg->msgno = data->base.highmsgno;
Msgn->Append(__msg->msgno);
}
int32_t _idxoffset = (__msg->msgno-data->base.lowmsgno)*sizeof(PcbIdx);
__hdr.blocks = (byte)__msg->txtblocks;
_idx.num = __msg->msgno;
_idx.reserved[0] = _idx.reserved[1] = _idx.reserved[2] = 0;
// Convert msgno and replylinks
__hdr.msgno = L2B(__msg->msgno);
__hdr.refno = L2B(__msg->link.to());
// Convert attributes
char _status = __msg->pcboard.status;
int _pvt = __msg->attr.pvt();
int _rcv = __msg->attr.rcv();
if(_rcv) {
switch(_status) {
case '$': __hdr.status = '#'; break;
case '!': __hdr.status = '#'; break;
case '%': __hdr.status = '^'; break;
case '~': __hdr.status = '`'; break;
case '*': __hdr.status = '+'; break;
case ' ': __hdr.status = '-'; break;
default: __hdr.status = _pvt ? '+' : '-';
}
}
else {
if(_status and not _pvt)
__hdr.status = _status;
else if(_pvt)
__hdr.status = '*';
else
__hdr.status = ' ';
}
_idx.status = __hdr.status;
__hdr.activestatus = (__mode & GMSG_DELETE) ? '\xE2' : '\xE1';
__hdr.echoed = ((isnet() or isecho()) and not isinternet()) ? 'E' : ' ';
// Convert dates and times
char _dtbuf[9];
struct tm* _tm = gmtime(&__msg->written);
memcpy(__hdr.date, strftimei(_dtbuf, 9, __msg->attr.uns() ? "%d-%m-%y" : "%d-%m\xC4%y", _tm), 8);
memcpy(__hdr.time, strftimei(_dtbuf, 6, "%H:%M", _tm), 5);
_idx.date = (word)YMD2JDN(1900+_tm->tm_year, _tm->tm_mon+1, _tm->tm_mday);
if(__msg->link.first()) {
__hdr.hasreply = 'R';
_tm = gmtime(&__msg->pcboard.reply_written);
int _year = _tm->tm_year % 100;
__hdr.replydate = L2B((10000L*_year) + (100L*(_tm->tm_mon+1)) + _tm->tm_mday);
memcpy(__hdr.replytime, strftimei(_dtbuf, 6, "%H:%M", _tm), 5);
}
else {
__hdr.hasreply = ' ';
__hdr.replydate = L2B(0);
memcpy(__hdr.replytime, " ", 5);
}
// Convert names, subject and password
char tobuf[150];
char bybuf[150];
strcpy(tobuf, __msg->to);
strcpy(bybuf, __msg->by);
int _tolen = strlen(tobuf);
int _bylen = strlen(bybuf);
int _relen = strlen(__msg->re);
int _pwlen = strlen(__msg->pcboard.password);
memset(__hdr.destname, ' ', 25);
memset(__hdr.origname, ' ', 25);
memset(__hdr.subject, ' ', 25);
memset(__hdr.password, ' ', 12);
strncpy(__hdr.destname, tobuf, MinV(_tolen, 25));
strncpy(__hdr.origname, bybuf, MinV(_bylen, 25));
strncpy(__hdr.subject, __msg->re, MinV(_relen, 25));
strncpy(__hdr.password, __msg->pcboard.password, MinV(_pwlen, 12));
memcpy(_idx.to, __hdr.destname, 25);
memcpy(_idx.from, __hdr.origname, 25);
if(isnet()) {
char toaddr[40];
char byaddr[40];
__msg->dest.make_string(toaddr);
strcpy(byaddr, " [");
__msg->orig.make_string(byaddr+2);
strcat(byaddr, "]");
sprintf(tobuf+strlen(tobuf), "@%s%s%s%s",
toaddr,
__msg->attr.cra() ? " +C" : "",
__msg->attr.dir() ? " +D" : "",
byaddr
);
_tolen = strlen(tobuf);
_bylen = strlen(bybuf);
}
// Determine size of the msg text including extended headers
uint _txtlen = 0;
if(__mode & GMSG_TXT) {
__msg->txtlength = _txtlen = strlen(__msg->txt);
if((_tolen > 25) or isnet()) {
__msg->txtlength += sizeof(PcbExtHdr);
__hdr.exthdrflags |= 0x01;
}
if((_bylen > 25) or isnet()) {
__msg->txtlength += sizeof(PcbExtHdr);
__hdr.exthdrflags |= 0x02;
}
if(_relen > 25) {
__msg->txtlength += sizeof(PcbExtHdr);
__hdr.exthdrflags |= 0x04;
}
// Translate msg text to PCB linefeeds if running non-foreign system
if(not wide->foreign)
strchg(__msg->txt, 0x0D, 0xE3);
// Calculate new number of blocks
__hdr.blocks = (byte)(1 + (__msg->txtlength/128) + ((__msg->txtlength%128)?1:0));
// Determine where to write the message text
__msg->txtstart = filelength(data->fhmsg);
__msg->txtblocks = __hdr.blocks;
}
// Write index
_idx.offset = (__mode & GMSG_DELETE) ? -__msg->txtstart : __msg->txtstart;
lseekset(data->fhidx, _idxoffset);
write(data->fhidx, &_idx, sizeof(PcbIdx));
// Write header
lseekset(data->fhmsg, AbsV(_idx.offset));
write(data->fhmsg, &__hdr, sizeof(PcbHdr));
// Writing msg text?
if(__mode & GMSG_TXT) {
uint _txtlenwritten = 0;
// Write extended headers
if((_tolen > 25) or isnet()) {
PcbExtHdr _ehdr;
_ehdr.id = 0x40FF;
_ehdr.colon = ':';
_ehdr.status = 'N';
_ehdr.separator = wide->foreign ? '\x0D' : '\xE3';
memcpy(_ehdr.function, "TO ", 7);
memset(_ehdr.desc, ' ', 60);
memcpy(_ehdr.desc, tobuf, MinV(60,_tolen));
write(data->fhmsg, &_ehdr, sizeof(PcbExtHdr));
_txtlenwritten += sizeof(PcbExtHdr);
if(_tolen > 60) {
memcpy(_ehdr.function, "TO2 ", 7);
memset(_ehdr.desc, ' ', 60);
memcpy(_ehdr.desc, tobuf+60, MinV(60,(_tolen-60)));
write(data->fhmsg, &_ehdr, sizeof(PcbExtHdr));
_txtlenwritten += sizeof(PcbExtHdr);
}
}
if((_bylen > 25) or isnet()) {
PcbExtHdr _ehdr;
_ehdr.id = 0x40FF;
_ehdr.colon = ':';
_ehdr.status = 'N';
_ehdr.separator = wide->foreign ? '\x0D' : '\xE3';
memcpy(_ehdr.function, "FROM ", 7);
memset(_ehdr.desc, ' ', 60);
memcpy(_ehdr.desc, bybuf, MinV(60,_bylen));
write(data->fhmsg, &_ehdr, sizeof(PcbExtHdr));
_txtlenwritten += sizeof(PcbExtHdr);
if(_bylen > 60) {
memcpy(_ehdr.function, "FROM2 ", 7);
memset(_ehdr.desc, ' ', 60);
memcpy(_ehdr.desc, bybuf+60, MinV(60,(_bylen-60)));
write(data->fhmsg, &_ehdr, sizeof(PcbExtHdr));
_txtlenwritten += sizeof(PcbExtHdr);
}
}
if(_relen > 25) {
PcbExtHdr _ehdr;
_ehdr.id = 0x40FF;
memcpy(_ehdr.function, "SUBJECT", 7);
_ehdr.colon = ':';
memset(_ehdr.desc, ' ', 60);
memcpy(_ehdr.desc, __msg->re, MinV(60,_relen));
_ehdr.status = 'N';
_ehdr.separator = wide->foreign ? '\x0D' : '\xE3';
write(data->fhmsg, &_ehdr, sizeof(PcbExtHdr));
_txtlenwritten += sizeof(PcbExtHdr);
}
// Special handling of netmails
#if 0
if(isnet()) {
// Write destination address in netmail for FidoPCB
char _abuf[40], _sbuf[45];
sprintf(_sbuf, "(%s)%c",
__msg->dest.make_string(_abuf),
wide->foreign ? '\x0D' : '\xE3'
);
uint _sbuflen = strlen(_sbuf);
write(data->fhmsg, _sbuf, _sbuflen);
_txtlenwritten += _sbuflen;
// Write flags
int _hld = __msg->attr.hld();
int _imm = __msg->attr.imm();
int _cra = __msg->attr.cra();
int _zon = __msg->attr.zon();
if(_hld or _imm or _cra or _zon) {
strcpy(_sbuf, "(" /*)*/);
if(_hld)
strcat(_sbuf, "HOLD,");
if(_imm)
strcat(_sbuf, "IMM,");
if(_cra)
strcat(_sbuf, "CRASH,");
if(_zon)
strcat(_sbuf, "INTL,");
_sbuf[strlen(_sbuf)] = /*(*/ ')';
_sbuflen = strlen(_sbuf);
write(data->fhmsg, _sbuf, _sbuflen);
_txtlenwritten += _sbuflen;
}
}
#endif
// Write message text
write(data->fhmsg, __msg->txt, _txtlen);
_txtlenwritten += _txtlen;
// Write remainder of the last message block (if any)
uint _remainlen = ((__hdr.blocks-1)*128) - _txtlenwritten;
if(_remainlen) {
byte _remainrecord[128];
memset(_remainrecord, ' ', 128);
write(data->fhmsg, _remainrecord, _remainlen);
}
// Translate back
if(not wide->foreign)
strchg(__msg->txt, 0xE3, 0x0D);
}
if(not (__mode & GMSG_DELETE)) {
// Set the mail waiting flag
int _status = true;
// Reset it if the msg is being received
if((__mode & GMSG_UPDATE) and __msg->attr.rcv())
_status = false;
// Don't touch the flag if the msg was already received
if(not (_status and __msg->attr.rcv()))
pcbwide->user->update_mail_waiting(__msg->to, board(), _status);
}
if((__mode & GMSG_TXT) and (__mode & GMSG_UPDATE)) {
__msg->msgno = oldmsgno;
__msg->txtstart = oldtxtstart;
__msg->txtlength = oldtxtlength;
del_msg(__msg);
}
// Unlock and update base
if(not _was_locked)
unlock();
GFTRK(NULL);
}
// ------------------------------------------------------------------
void PcbArea::save_hdr(int __mode, gmsg* __msg) {
GFTRK("PcbSaveHdr");
PcbHdr _hdr;
save_message(__mode|GMSG_HDR, __msg, _hdr);
}
// ------------------------------------------------------------------
void PcbArea::save_msg(int __mode, gmsg* __msg) {
GFTRK("PcbSaveMsg");
PcbHdr _hdr;
save_message(__mode|GMSG_HDRTXT, __msg, _hdr);
}
// ------------------------------------------------------------------
void PcbArea::del_msg(gmsg* __msg) {
GFTRK("PcbDelMsg");
PcbHdr _hdr;
save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
}
// ------------------------------------------------------------------
void PcbArea::new_msgno(gmsg* msg) {
GFTRK("PcbNewMsgno");
msg->msgno = data->base.highmsgno + 1;
GFTRK(NULL);
}
// ------------------------------------------------------------------
void PcbArea::update_timesread(gmsg*) {
}
// ------------------------------------------------------------------