1 // This may look like C code, but it is really -*- C++ -*-
2
3 // ------------------------------------------------------------------
4 // The Goldware Library
5 // Copyright (C) 1990-1999 Odinn Sorensen
6 // ------------------------------------------------------------------
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public
18 // License along with this program; if not, write to the Free
19 // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 // MA 02111-1307, USA
21 // ------------------------------------------------------------------
22 // $Id: gmojamm2.cpp,v 1.12 2006/05/14 11:45:05 ssianky Exp $
23 // ------------------------------------------------------------------
24 // JAM msgbase implementation, scanning.
25 // ------------------------------------------------------------------
26
27 #include <cerrno>
28 #include <gdbgerr.h>
29 #include <gmemdbg.h>
30 #include <gdbgtrk.h>
31 #include <gstrall.h>
32 #include <gcrcall.h>
33 #include <gmojamm.h>
34
35
36 // ------------------------------------------------------------------
37
data_open()38 void JamArea::data_open() {
39
40 wide = jamwide;
41 data = jamdata + (jamdatano++);
42 data->fhjhr = data->fhjdt = data->fhjdx = data->fhjlr = data->fhjhw = -1;
43 data->islocked = false;
44 data->timesposted = 0;
45 data->lastpos = 0;
46 }
47
48
49 // ------------------------------------------------------------------
50
data_close()51 void JamArea::data_close() {
52
53 jamdatano--;
54 }
55
56
57 // ------------------------------------------------------------------
58
test_open(const char * file)59 int JamArea::test_open(const char* file) {
60
61 GFTRK("JamArea::test_open");
62
63 int fh;
64 long tries = 0;
65
66 do {
67
68 fh = ::sopen(file, O_RDWR|O_CREAT|O_BINARY, WideSharemode, S_STDRW);
69 if(fh == -1) {
70
71 // Tell the world
72 if((errno != EACCES) or (PopupLocked(++tries, false, file) == false)) {
73 WideLog->ErrOpen();
74 raw_close();
75 WideLog->printf("! A JAM msgbase file could not be opened.");
76 WideLog->printf(": %s.", file);
77 WideLog->ErrOSInfo();
78 OpenErrorExit();
79 }
80 }
81 } while(fh == -1);
82
83 // Remove the popup window
84 if(tries)
85 PopupLocked(0, 0, NULL);
86
87 GFTRK(0);
88
89 return fh;
90 }
91
92
93 // ------------------------------------------------------------------
94
raw_open()95 void JamArea::raw_open() {
96
97 GFTRK("JamArea::raw_open");
98
99 Path file;
100 sprintf(file, "%s.jhr", real_path()); data->fhjhr = test_open(file);
101 sprintf(file, "%s.jdx", real_path()); data->fhjdx = test_open(file);
102 sprintf(file, "%s.jlr", real_path()); data->fhjlr = test_open(file);
103 if(not just_scanning) {
104 sprintf(file, "%s.jdt", real_path()); data->fhjdt = test_open(file);
105 if(not jamwide->smapihw) {
106 sprintf(file, "%s.cmhw", real_path()); data->fhjhw = ::sopen(file, O_RDWR|O_BINARY, WideSharemode, S_STDRW);
107 }
108 }
109
110 GFTRK(0);
111 }
112
113
114 // ------------------------------------------------------------------
115
raw_close()116 void JamArea::raw_close() {
117
118 GFTRK("JamArea::raw_close");
119
120 if(data->fhjlr != -1) { ::close(data->fhjlr); data->fhjlr = -1; }
121 if(data->fhjdx != -1) { ::close(data->fhjdx); data->fhjdx = -1; }
122 if(data->fhjdt != -1) { ::close(data->fhjdt); data->fhjdt = -1; }
123 if(data->fhjhr != -1) { ::close(data->fhjhr); data->fhjhr = -1; }
124 if(data->fhjhw != -1) { ::close(data->fhjhw); data->fhjhw = -1; }
125
126 GFTRK(0);
127 }
128
129
130 // ------------------------------------------------------------------
131
open_area()132 void JamArea::open_area() {
133
134 GFTRK("JamArea::open_area");
135
136 // Open the msgbase files
137 raw_open();
138
139 // Read the header info
140 memset(&data->hdrinfo, 0, sizeof(JamHdrInfo));
141 read(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
142
143 if(not jamwide->smapihw and (data->fhjhw != -1)) {
144 lseek(data->fhjhw, 0, SEEK_SET);
145 read(data->fhjhw, &data->highwater, sizeof(int32_t));
146 }
147 else
148 data->highwater = -1;
149
150 // Is the signature invalid?
151 if (memcmp(data->hdrinfo.signature, JAM_SIGNATURE, 4))
152 {
153 // Initialize header info
154 memcpy(data->hdrinfo.signature, JAM_SIGNATURE, 4);
155 time32_t a = gtime(NULL);
156 struct tm tp; ggmtime(&tp, &a);
157 tp.tm_isdst = -1;
158 time32_t b = gmktime(&tp);
159 data->hdrinfo.datecreated = a + a - b;
160 data->hdrinfo.passwordcrc = 0xFFFFFFFFL;
161 data->hdrinfo.basemsgnum = 1;
162
163 // Write header info
164 lseekset(data->fhjhr, 0);
165 write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
166 }
167
168 // Adjust base msg number if necessary
169 if(data->hdrinfo.basemsgnum == 0)
170 data->hdrinfo.basemsgnum = 1;
171
172 // Seek to beginning of the .JLR
173 lseekset(data->fhjlr, 0);
174
175 // Search for the userid (not the usercrc?!)
176 data->lastpos = 0;
177 int founduser = false;
178 while(read(data->fhjlr, &data->lastrec, sizeof(JamLast)) == sizeof(JamLast)) {
179 if(data->lastrec.usercrc == wide->usercrc) {
180 founduser = true;
181 break;
182 }
183 data->lastpos++;
184 }
185
186 // If user was not found, init the lastread with our values
187 if(not founduser) {
188 data->lastrec.usercrc = wide->usercrc;
189 data->lastrec.userid = wide->userid;
190 data->lastrec.lastread = 0;
191 data->lastrec.highread = 0;
192 }
193
194 data->timesposted = 0;
195
196 GFTRK(0);
197 }
198
199
200 // ------------------------------------------------------------------
201
raw_scan(int __keep_index,int __scanpm)202 void JamArea::raw_scan(int __keep_index, int __scanpm) {
203
204 GFTRK("JamRawScan");
205
206 // Open the msgbase if it wasn't already
207 int _was_open = isopen;
208 if(not _was_open) {
209 if(not __keep_index or __scanpm)
210 just_scanning = true;
211 if(ispacked()) {
212 const char* newpath = Unpack(path());
213 if(newpath == NULL)
214 packed(false);
215 set_real_path(newpath ? newpath : path());
216 }
217 isopen++;
218 data_open();
219 open_area();
220 just_scanning = false;
221 }
222
223 // Get some sizes
224 int32_t _jdxlen = filelength(data->fhjdx);
225 uint _jdxsize = (uint)_jdxlen;
226 uint _jdxtotal = _jdxsize / sizeof(JamIndex);
227
228 // (Re)Allocate message index
229 if(__keep_index)
230 Msgn->Resize(_jdxtotal);
231
232 // Allocate buffer to hold .JDX data
233 JamIndex* _jdxbuf = (JamIndex*)throw_malloc(_jdxsize+1);
234
235 // Read the entire .JDX file into memory
236 lseekset(data->fhjdx, 0);
237 read(data->fhjdx, _jdxbuf, _jdxsize);
238
239 // Variables for the loop
240 uint _active = 0;
241 uint _firstmsgno = 0;
242 uint _lastmsgno = 0;
243 uint _lastreadfound = 0;
244 uint _msgno = data->hdrinfo.basemsgnum;
245 uint _total = data->hdrinfo.basemsgnum + _jdxtotal;
246 uint _lastread = data->lastrec.lastread;
247 uint _lastread_reln = 0;
248 uint32_t* _msgndxptr = Msgn->tag;
249 JamIndex* _jdxptr = _jdxbuf;
250
251 // Fill message index
252 while(_msgno < _total) {
253 if(_jdxptr->hdroffset != 0xFFFFFFFFL) {
254 _active++;
255 if(not _firstmsgno)
256 _firstmsgno = _msgno;
257 if(__keep_index)
258 *_msgndxptr++ = _msgno;
259 if((_msgno >= _lastread) and (_lastread_reln == 0)) {
260 _lastreadfound = _msgno;
261 _lastread_reln = (uint)(_active - (_msgno != _lastread ? 1 : 0));
262 }
263 _lastmsgno = _msgno;
264 }
265 _jdxptr++;
266 _msgno++;
267 }
268
269 // If the exact lastread was not found
270 if(_active and (_lastreadfound != _lastread)) {
271
272 // Higher than highest or lower than lowest?
273 if(_lastread > _lastmsgno)
274 _lastread_reln = _active;
275 else if(_lastread < _firstmsgno)
276 _lastread_reln = 0;
277 }
278
279 // Update area data
280 Msgn->SetCount(_active);
281 lastread = _lastread_reln;
282 lastreadentry = _lastreadfound;
283
284 // Scan for personal mail
285 if(__scanpm) {
286 INam uname;
287 int umax = (WidePersonalmail & PM_ALLNAMES) ? WideUsernames : 1;
288 dword* ucrc = (dword*)throw_calloc(umax, sizeof(dword));
289 for(int uc=0; uc<umax; uc++) {
290 jamstrlwr(strcpy(uname, WideUsername[uc]));
291 ucrc[uc] = strCrc32(uname, NO, CRC32_MASK_CCITT);
292 }
293 PMrk->ResetAll();
294 uint n = lastread + 1;
295 uint cnt = Msgn->Count();
296 int gotpm = false;
297 while(n <= cnt) {
298 JamIndex* idx = _jdxbuf + (uint)(Msgn->at(n-1) - data->hdrinfo.basemsgnum);
299 for(int u=0; u<umax; u++) {
300 if(idx->usercrc == ucrc[u]) {
301 gotpm = true;
302 break;
303 }
304 }
305 if(gotpm) {
306 JamHdr hdr;
307 lseekset(data->fhjhr, idx->hdroffset);
308 read(data->fhjhr, &hdr, sizeof(JamHdr));
309 if(not (hdr.attribute & JAMATTR_READ)) {
310 if(not (hdr.attribute & JAMATTR_DELETED)) {
311 PMrk->Append(hdr.messagenumber);
312 }
313 }
314 gotpm = false;
315 }
316 n++;
317 }
318 throw_free(ucrc);
319 }
320
321 if(WideDebug) {
322 WideLog->printf("- %s: t:%u, l:%u, fm:%u, hm:%u, lr:%u, u:%u, pm:%i",
323 echoid(),
324 Msgn->Count(),
325 lastread,
326 _firstmsgno,
327 _lastmsgno,
328 _lastread,
329 data->lastpos,
330 __scanpm ? (int)PMrk->Count() : -1
331 );
332 }
333
334 // Free the .JDX buffer
335 throw_free(_jdxbuf);
336
337 // Close the msgbase again if we opened it in here
338 if(not _was_open) {
339 raw_close();
340 data_close();
341 if(ispacked()) {
342 CleanUnpacked(real_path());
343 }
344 isopen--;
345 }
346
347 GFTRK(0);
348 }
349
350
351 // ------------------------------------------------------------------
352
scan()353 void JamArea::scan() {
354
355 GFTRK("JamArea::scan");
356
357 raw_scan(true);
358
359 GFTRK(0);
360 }
361
362
363 // ------------------------------------------------------------------
364
scan_area()365 void JamArea::scan_area() {
366
367 GFTRK("JamArea::scan_area");
368
369 raw_scan(false);
370
371 GFTRK(0);
372 }
373
374
375 // ------------------------------------------------------------------
376
scan_area_pm()377 void JamArea::scan_area_pm() {
378
379 GFTRK("JamArea::scan_area_pm");
380
381 raw_scan(true, true);
382 Msgn->Reset();
383
384 GFTRK(0);
385 }
386
387
388 // ------------------------------------------------------------------
389