// 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 #include #include #include #include #include #include // ------------------------------------------------------------------ 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); time32_t a = gtime(NULL); struct tm *tp = ggmtime(&a); tp->tm_isdst = -1; time32_t b = gmktime(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; ucResetAll(); 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; uusercrc == 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); } // ------------------------------------------------------------------