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/gmohuds1.cpp
2006-05-13 16:15:35 +00:00

382 lines
11 KiB
C++

// This may look like C code, but it is really -*- C++ -*-
// ------------------------------------------------------------------
// The Goldware Library
// Copyright (C) 1990-1999 Odinn Sorensen
// Copyright (C) 1999-2000 Alex. S. Aganichev
// ------------------------------------------------------------------
// 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$
// ------------------------------------------------------------------
// Hudson / Goldbase msgbase handling
// ------------------------------------------------------------------
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::data_open() {
wide = (HudsWide*) (__HUDSON ? (void *)hudsonwide : (void *)goldbasewide);
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::data_close() {
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::exit() {
if(__HUDSON) {
delete hudsonwide->user;
throw_release(hudsonwide->msgidxptr);
}
else {
delete goldbasewide->user;
throw_release(goldbasewide->msgidxptr);
}
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::init() {
GFTRK("HudsInit");
if (WideDebug)
WideLog->printf("- Begin init for %s.", path);
isopen = 0;
islocked = false;
timesposted = 0;
msgidxsize = 0;
msgidxptr = NULL;
pmscan = NULL;
scn = NULL;
// Open complete msgbase, create if none exists
if (not fexist(AddPath(path, __HUDSON ? "msghdr" HUDS_EXT : "msghdr" GOLD_EXT)))
{
WideLog->printf("* Creating new msgbase at %s", path);
raw_open(O_CREAT);
if (fhinf.FileLength() == 0)
{
memset(&msginfo, 0, sizeof(HudsInfo));
fhinf.Write(&msginfo, sizeof(HudsInfo));
}
if (fhlrd.FileLength() == 0)
{
memset(lastrec, 0, sizeof(HudsLast));
fhlrd.Write(lastrec, sizeof(HudsLast));
}
}
else {
raw_open();
}
// Lock msgbase to ensure data integrity
lock();
// Check if MSGTXT.BBS is approaching dangerous size
if (__HUDSON and (fhtxt.FileLength() > sizewarn))
HudsSizewarn();
// Check for mismatch between the header and the index files
uint _hdrsize = fhhdr.FileLength()/sizeof(HudsHdr);
uint _idxsize = fhidx.FileLength()/sizeof(HudsIdx);
uint _toisize = fhtoi.FileLength()/sizeof(HudsToIdx);
if ((_hdrsize != _idxsize) or (_hdrsize != _toisize))
{
raw_close();
HGWarnRebuild();
WideLog->ErrIndex();
WideLog->printf("! The %s msgbase files do not have the same number of records.", __HUDSON ? HUDS_NAME : GOLD_NAME);
WideLog->printf(": %smsghdr%s (%u records).", path, __HUDSON ? HUDS_EXT : GOLD_EXT, _hdrsize);
WideLog->printf(": %smsgidx%s (%u records).", path, __HUDSON ? HUDS_EXT : GOLD_EXT, _idxsize);
WideLog->printf(": %smsgtoidx%s (%u records).", path, __HUDSON ? HUDS_EXT : GOLD_EXT, _toisize);
WideLog->printf("+ Advice: You need to run a msgbase index rebuild utility.");
IndexErrorExit();
}
// Detect USERS.BBS format unless user has configured it
if(__HUDSON and (ra2usersbbs == 0)) {
// Get size of USERS.BBS
int len = fhusr.FileLength();
// Does size match Hudson format?
int hudsmatch = (len % sizeof(HudsUsers)) == 0;
if(hudsmatch)
ra2usersbbs = 1;
// Does size match RA2 format?
int ra2match = (len % sizeof(RA2Users)) == 0;
if(ra2match)
ra2usersbbs = 2;
// If it matches both of them
if (hudsmatch and ra2match)
{
// Check version in CONFIG.RA to make sure
Path rapath, file;
char* ptr = getenv("RA");
if (ptr) AddBackslash(strcpy(rapath, ptr));
MakePathname(file, rapath, "messages.ra");
gfile fh(file, O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
if (fh.isopen())
{
word VersionID = 0;
fh.Read(&VersionID, sizeof(word));
if (VersionID >= 0x200)
ra2usersbbs = 2;
else
ra2usersbbs = 1;
}
}
// If it does not match either of them
if(not hudsmatch and not ra2match) {
WideLog->ErrIndex();
WideLog->printf("! The users.bbs file has an incorrect size.");
WideLog->printf(": %susers.bbs, %u bytes.", path, len);
WideLog->printf(": Should be %u bytes if it's in RA2 format.", (uint)((len/sizeof(RA2Users))*sizeof(RA2Users)));
WideLog->printf(": Should be %u bytes if it's in Hudson format.", (uint)((len/sizeof(HudsUsers))*sizeof(HudsUsers)));
if(ra2usersbbs)
WideLog->printf(": It appears to be in %s format.", (ra2usersbbs == 2) ? "RA2" : "Hudson");
WideLog->printf("+ Advice: Run a userbase packing utility.");
IndexErrorExit();
}
}
if (__HUDSON)
{
if (ra2usersbbs == 2)
{
if (WideDebug)
WideLog->printf("- Using a RA2 format userbase.");
user = new RA2User;
}
else {
if(WideDebug)
WideLog->printf("- Using a Hudson format userbase.");
user = new HudsonUser;
}
}
else
user = new GoldbaseUser;
throw_new(user);
// Open RA2 files
if (__HUDSON and (ra2usersbbs == 2))
{
RA2User* _user2 = (RA2User*)user;
test_open(fhuix, "usersidx.bbs", O_CREAT);
test_open(fhuxi, "usersxi.bbs", O_CREAT);
_user2->idxfh = &fhuix;
_user2->xifh = &fhuxi;
}
// Find user
const char* _username = WideUsername[0];
if (userno == -1)
{
user->gufh = fhusr.fh;
user->find(_username);
if(not user->found) {
WideLog->printf("* User \"%s\" not found in %susers%s.", _username, path, __HUDSON ? HUDS_EXT : GOLD_EXT);
user->add(_username);
WideLog->printf("* Now added with user number %u.", user->index);
}
userno = user->index;
}
if(WideDebug)
WideLog->printf("- Using user record number %u.", userno);
// Close RA2 files
if (__HUDSON and (ra2usersbbs == 2))
{
fhuix.Close();
fhuxi.Close();
}
// Unlock and close
unlock();
raw_close();
if(WideDebug)
WideLog->printf("- End init for %s.", path);
GFTRK(NULL);
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::save_lastread(board_t board, msgn_t msgno) {
GFTRK("HudsSaveLast");
// Update lastread record
msgn_t _lastread = lastrec[board-1] = msgno;
fhlrd.LseekSet(userno*sizeof(HudsLast));
fhlrd.Write(lastrec, sizeof(HudsLast));
// Update user record
user->gufh = fhusr.fh;
user->moveto(userno);
if (user->lastread() < _lastread)
user->lastread(_lastread);
if (timesposted)
{
user->inctimesposted(timesposted);
timesposted = 0;
}
GFTRK(NULL);
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::open() {
GFTRK("HudsOpen");
data_open();
wide->isopen++;
if(wide->isopen == 1) {
wide->raw_open();
wide->refresh();
wide->timesposted = 0;
}
if(wide->isopen > 2) {
WideLog->ErrTest();
goto error;
}
isopen++;
if(isopen > 2) {
WideLog->ErrTest();
goto error;
}
scan();
goto done;
error:
WideLog->printf("! Trying to open a %s msgbase more than twice.", __HUDSON ? HUDS_NAME : GOLD_NAME);
WideLog->printf(": %s, board %u.", echoid(), board());
WideLog->printf("+ Info: This indicates a serious bug.");
WideLog->printf("+ Advice: Report to the Author immediately.");
TestErrorExit();
done:
GFTRK(NULL);
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::close() {
GFTRK("HudsClose");
if(isopen) {
if(isopen == 1) {
wide->save_lastread((board_t)board(), (msgn_t)Msgn->CvtReln(lastread));
Msgn->Reset();
}
isopen--;
}
else {
WideLog->ErrTest();
goto error;
}
if(wide->isopen) {
if(wide->isopen == 1) {
if(wide->islocked)
wide->unlock();
wide->raw_close();
throw_release(wide->msgidxptr);
}
wide->isopen--;
}
else {
WideLog->ErrTest();
goto error;
}
goto done;
error:
WideLog->printf("! Trying to close an already closed %s msgbase.", __HUDSON ? HUDS_NAME : GOLD_NAME);
WideLog->printf(": %s, board %u.", echoid(), board());
WideLog->printf("+ Info: This indicates a potentially serious bug.");
WideLog->printf("+ Advice: Report to the Author immediately.");
TestErrorExit();
done:
data_close();
GFTRK(NULL);
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::suspend() {
GFTRK("HudsSuspend");
wide->save_lastread((board_t)board(), (msgn_t)Msgn->CvtReln(lastread));
wide->raw_close();
GFTRK(NULL);
}
// ------------------------------------------------------------------
template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::resume() {
GFTRK("HudsResume");
wide->raw_open();
GFTRK(NULL);
}
// ------------------------------------------------------------------