389 lines
9.7 KiB
C++
389 lines
9.7 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, scanning.
|
|
// ------------------------------------------------------------------
|
|
|
|
#include <cerrno>
|
|
#include <gdbgerr.h>
|
|
#include <gmemdbg.h>
|
|
#include <gdbgtrk.h>
|
|
#include <gstrall.h>
|
|
#include <gcrcall.h>
|
|
#include <gmojamm.h>
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::data_open() {
|
|
|
|
wide = jamwide;
|
|
data = jamdata + (jamdatano++);
|
|
data->fhjhr = data->fhjdt = data->fhjdx = data->fhjlr = data->fhjhw = -1;
|
|
data->islocked = false;
|
|
data->timesposted = 0;
|
|
data->lastpos = 0;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::data_close() {
|
|
|
|
jamdatano--;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
int JamArea::test_open(const char* file) {
|
|
|
|
GFTRK("JamArea::test_open");
|
|
|
|
int fh;
|
|
long tries = 0;
|
|
|
|
do {
|
|
|
|
fh = ::sopen(file, O_RDWR|O_CREAT|O_BINARY, WideSharemode, S_STDRW);
|
|
if(fh == -1) {
|
|
|
|
// Tell the world
|
|
if((errno != EACCES) or (PopupLocked(++tries, false, file) == false)) {
|
|
WideLog->ErrOpen();
|
|
raw_close();
|
|
WideLog->printf("! A JAM msgbase file could not be opened.");
|
|
WideLog->printf(": %s.", file);
|
|
WideLog->ErrOSInfo();
|
|
OpenErrorExit();
|
|
}
|
|
}
|
|
} while(fh == -1);
|
|
|
|
// Remove the popup window
|
|
if(tries)
|
|
PopupLocked(0, 0, NULL);
|
|
|
|
GFTRK(NULL);
|
|
|
|
return fh;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::raw_open() {
|
|
|
|
GFTRK("JamArea::raw_open");
|
|
|
|
Path file;
|
|
sprintf(file, "%s.jhr", real_path()); data->fhjhr = test_open(file);
|
|
sprintf(file, "%s.jdx", real_path()); data->fhjdx = test_open(file);
|
|
sprintf(file, "%s.jlr", real_path()); data->fhjlr = test_open(file);
|
|
if(not just_scanning) {
|
|
sprintf(file, "%s.jdt", real_path()); data->fhjdt = test_open(file);
|
|
if(not jamwide->smapihw) {
|
|
sprintf(file, "%s.cmhw", real_path()); data->fhjhw = ::sopen(file, O_RDWR|O_BINARY, WideSharemode, S_STDRW);
|
|
}
|
|
}
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::raw_close() {
|
|
|
|
GFTRK("JamArea::raw_close");
|
|
|
|
if(data->fhjlr != -1) { ::close(data->fhjlr); data->fhjlr = -1; }
|
|
if(data->fhjdx != -1) { ::close(data->fhjdx); data->fhjdx = -1; }
|
|
if(data->fhjdt != -1) { ::close(data->fhjdt); data->fhjdt = -1; }
|
|
if(data->fhjhr != -1) { ::close(data->fhjhr); data->fhjhr = -1; }
|
|
if(data->fhjhw != -1) { ::close(data->fhjhw); data->fhjhw = -1; }
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::open_area() {
|
|
|
|
GFTRK("JamArea::open_area");
|
|
|
|
// Open the msgbase files
|
|
raw_open();
|
|
|
|
// Read the header info
|
|
memset(&data->hdrinfo, 0, sizeof(JamHdrInfo));
|
|
read(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
|
|
|
|
if(not jamwide->smapihw and (data->fhjhw != -1)) {
|
|
lseek(data->fhjhw, 0, SEEK_SET);
|
|
read(data->fhjhw, &data->highwater, sizeof(int32_t));
|
|
}
|
|
else
|
|
data->highwater = -1;
|
|
|
|
// Is the signature invalid?
|
|
if(memcmp(data->hdrinfo.signature, JAM_SIGNATURE, 4)) {
|
|
|
|
// Initialize header info
|
|
memcpy(data->hdrinfo.signature, JAM_SIGNATURE, 4);
|
|
time_t a = time(NULL);
|
|
struct tm *tp = ggmtime(&a);
|
|
tp->tm_isdst = -1;
|
|
time_t b = mktime(tp);
|
|
data->hdrinfo.datecreated = a + a - b;
|
|
data->hdrinfo.passwordcrc = 0xFFFFFFFFL;
|
|
data->hdrinfo.basemsgnum = 1;
|
|
|
|
// Write header info
|
|
lseekset(data->fhjhr, 0);
|
|
write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
|
|
}
|
|
|
|
// Adjust base msg number if necessary
|
|
if(data->hdrinfo.basemsgnum == 0)
|
|
data->hdrinfo.basemsgnum = 1;
|
|
|
|
// Seek to beginning of the .JLR
|
|
lseekset(data->fhjlr, 0);
|
|
|
|
// Search for the userid (not the usercrc?!)
|
|
data->lastpos = 0;
|
|
int founduser = false;
|
|
while(read(data->fhjlr, &data->lastrec, sizeof(JamLast)) == sizeof(JamLast)) {
|
|
if(data->lastrec.usercrc == wide->usercrc) {
|
|
founduser = true;
|
|
break;
|
|
}
|
|
data->lastpos++;
|
|
}
|
|
|
|
// If user was not found, init the lastread with our values
|
|
if(not founduser) {
|
|
data->lastrec.usercrc = wide->usercrc;
|
|
data->lastrec.userid = wide->userid;
|
|
data->lastrec.lastread = 0;
|
|
data->lastrec.highread = 0;
|
|
}
|
|
|
|
data->timesposted = 0;
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::raw_scan(int __keep_index, int __scanpm) {
|
|
|
|
GFTRK("JamRawScan");
|
|
|
|
// Open the msgbase if it wasn't already
|
|
int _was_open = isopen;
|
|
if(not _was_open) {
|
|
if(not __keep_index or __scanpm)
|
|
just_scanning = true;
|
|
if(ispacked()) {
|
|
const char* newpath = Unpack(path());
|
|
if(newpath == NULL)
|
|
packed(false);
|
|
set_real_path(newpath ? newpath : path());
|
|
}
|
|
isopen++;
|
|
data_open();
|
|
open_area();
|
|
just_scanning = false;
|
|
}
|
|
|
|
// Get some sizes
|
|
int32_t _jdxlen = filelength(data->fhjdx);
|
|
uint _jdxsize = (uint)_jdxlen;
|
|
uint _jdxtotal = _jdxsize / sizeof(JamIndex);
|
|
|
|
// (Re)Allocate message index
|
|
if(__keep_index)
|
|
Msgn->Resize(_jdxtotal);
|
|
|
|
// Allocate buffer to hold .JDX data
|
|
JamIndex* _jdxbuf = (JamIndex*)throw_malloc(_jdxsize+1);
|
|
|
|
// Read the entire .JDX file into memory
|
|
lseekset(data->fhjdx, 0);
|
|
read(data->fhjdx, _jdxbuf, _jdxsize);
|
|
|
|
// Variables for the loop
|
|
uint _active = 0;
|
|
uint _firstmsgno = 0;
|
|
uint _lastmsgno = 0;
|
|
uint _lastreadfound = 0;
|
|
uint _msgno = data->hdrinfo.basemsgnum;
|
|
uint _total = data->hdrinfo.basemsgnum + _jdxtotal;
|
|
uint _lastread = data->lastrec.lastread;
|
|
uint _lastread_reln = 0;
|
|
uint32_t* _msgndxptr = Msgn->tag;
|
|
JamIndex* _jdxptr = _jdxbuf;
|
|
|
|
// Fill message index
|
|
while(_msgno < _total) {
|
|
if(_jdxptr->hdroffset != 0xFFFFFFFFL) {
|
|
_active++;
|
|
if(not _firstmsgno)
|
|
_firstmsgno = _msgno;
|
|
if(__keep_index)
|
|
*_msgndxptr++ = _msgno;
|
|
if((_msgno >= _lastread) and (_lastread_reln == 0)) {
|
|
_lastreadfound = _msgno;
|
|
_lastread_reln = (uint)(_active - (_msgno != _lastread ? 1 : 0));
|
|
}
|
|
_lastmsgno = _msgno;
|
|
}
|
|
_jdxptr++;
|
|
_msgno++;
|
|
}
|
|
|
|
// If the exact lastread was not found
|
|
if(_active and (_lastreadfound != _lastread)) {
|
|
|
|
// Higher than highest or lower than lowest?
|
|
if(_lastread > _lastmsgno)
|
|
_lastread_reln = _active;
|
|
else if(_lastread < _firstmsgno)
|
|
_lastread_reln = 0;
|
|
}
|
|
|
|
// Update area data
|
|
Msgn->SetCount(_active);
|
|
lastread = _lastread_reln;
|
|
lastreadentry = _lastreadfound;
|
|
|
|
// Scan for personal mail
|
|
if(__scanpm) {
|
|
INam uname;
|
|
int umax = (WidePersonalmail & PM_ALLNAMES) ? WideUsernames : 1;
|
|
dword* ucrc = (dword*)throw_calloc(umax, sizeof(dword));
|
|
for(int uc=0; uc<umax; uc++) {
|
|
jamstrlwr(strcpy(uname, WideUsername[uc]));
|
|
ucrc[uc] = strCrc32(uname, NO, CRC32_MASK_CCITT);
|
|
}
|
|
PMrk->ResetAll();
|
|
uint n = lastread + 1;
|
|
uint cnt = Msgn->Count();
|
|
int gotpm = false;
|
|
while(n <= cnt) {
|
|
JamIndex* idx = _jdxbuf + (uint)(Msgn->at(n-1) - data->hdrinfo.basemsgnum);
|
|
for(int u=0; u<umax; u++) {
|
|
if(idx->usercrc == ucrc[u]) {
|
|
gotpm = true;
|
|
break;
|
|
}
|
|
}
|
|
if(gotpm) {
|
|
JamHdr hdr;
|
|
lseekset(data->fhjhr, idx->hdroffset);
|
|
read(data->fhjhr, &hdr, sizeof(JamHdr));
|
|
if(not (hdr.attribute & JAMATTR_READ)) {
|
|
if(not (hdr.attribute & JAMATTR_DELETED)) {
|
|
PMrk->Append(hdr.messagenumber);
|
|
}
|
|
}
|
|
gotpm = false;
|
|
}
|
|
n++;
|
|
}
|
|
throw_free(ucrc);
|
|
}
|
|
|
|
if(WideDebug) {
|
|
WideLog->printf("- %s: t:%u, l:%u, fm:%u, hm:%u, lr:%u, u:%u, pm:%i",
|
|
echoid(),
|
|
Msgn->Count(),
|
|
lastread,
|
|
_firstmsgno,
|
|
_lastmsgno,
|
|
_lastread,
|
|
data->lastpos,
|
|
__scanpm ? (int)PMrk->Count() : -1
|
|
);
|
|
}
|
|
|
|
// Free the .JDX buffer
|
|
throw_free(_jdxbuf);
|
|
|
|
// Close the msgbase again if we opened it in here
|
|
if(not _was_open) {
|
|
raw_close();
|
|
data_close();
|
|
if(ispacked()) {
|
|
CleanUnpacked(real_path());
|
|
}
|
|
isopen--;
|
|
}
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::scan() {
|
|
|
|
GFTRK("JamArea::scan");
|
|
|
|
raw_scan(true);
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::scan_area() {
|
|
|
|
GFTRK("JamArea::scan_area");
|
|
|
|
raw_scan(false);
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
void JamArea::scan_area_pm() {
|
|
|
|
GFTRK("JamArea::scan_area_pm");
|
|
|
|
raw_scan(true, true);
|
|
Msgn->Reset();
|
|
|
|
GFTRK(NULL);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------
|