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: gmojamm4.cpp,v 1.12 2006/05/14 11:45:05 ssianky Exp $
23 // ------------------------------------------------------------------
24 // JAM msgbase implementation, save/delete.
25 // ------------------------------------------------------------------
26
27 #include <gmemdbg.h>
28 #include <gdbgtrk.h>
29 #include <gdbgerr.h>
30 #include <gcrcall.h>
31 #include <gstrall.h>
32 #include <gtxtpara.h>
33 #include <gutlmisc.h>
34 #include <gmojamm.h>
35
36
37 // ------------------------------------------------------------------
38
lock()39 void JamArea::lock() {
40
41 GFTRK("JamArea::lock");
42
43 if(not data->islocked and WideCanLock) {
44
45 long _tries = 0;
46
47 // Try to get the lock
48 while(::lock(data->fhjhr, 0, 1) == -1) {
49
50 // Tell the world
51 if(PopupLocked(++_tries, true, real_path()) == false) {
52 WideLog->ErrLock();
53 raw_close();
54 WideLog->printf("! A JAM msgbase file could not be locked.");
55 WideLog->printf(": %s.jhr.", real_path());
56 WideLog->ErrOSInfo();
57 LockErrorExit();
58 }
59 }
60
61 // Remove the popup window
62 if(_tries)
63 PopupLocked(0, 0, NULL);
64
65 data->islocked = true;
66 }
67
68 // Load fresh copy of the header info
69 lseekset(data->fhjhr, 0);
70 read(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
71
72 if(not jamwide->smapihw) {
73 if(data->fhjhw == -1) {
74 Path file;
75 sprintf(file, "%s.cmhw", real_path()); data->fhjhw = ::sopen(file, O_RDWR|O_BINARY, WideSharemode, S_STDRW);
76 }
77 if(data->fhjhw != -1) {
78 lseek(data->fhjhw, 0, SEEK_SET);
79 read(data->fhjhw, &data->highwater, sizeof(int32_t));
80 }
81 else
82 data->highwater = -1;
83 }
84 else
85 data->highwater = -1;
86
87 GFTRK(0);
88 }
89
90
91 // ------------------------------------------------------------------
92
unlock()93 void JamArea::unlock() {
94
95 GFTRK("JamArea::unlock");
96
97 if(data->islocked) {
98 ::unlock(data->fhjhr, 0, 1);
99 data->islocked = false;
100 }
101
102 GFTRK(0);
103 }
104
105
106 // ------------------------------------------------------------------
107
add_subfield(JamHdr & __hdr,byte * & __subfield,word __loid,word __hiid,char * __data,uint32_t __maxlen)108 void JamArea::add_subfield(JamHdr& __hdr, byte*& __subfield, word __loid, word __hiid, char* __data, uint32_t __maxlen) {
109
110 uint32_t _datlen = strlen(__data);
111 __subfield = (byte*)throw_realloc(__subfield, (uint)__hdr.subfieldlen+sizeof(JamSubFieldHdr)+_datlen);
112 JamSubField* _subfieldptr = (JamSubField*)(__subfield + (uint)__hdr.subfieldlen);
113 _subfieldptr->loid = __loid;
114 _subfieldptr->hiid = __hiid;
115 _subfieldptr->datlen = MinV(_datlen, __maxlen);
116 memcpy(_subfieldptr->buffer, __data, _subfieldptr->datlen);
117 __hdr.subfieldlen += sizeof(JamSubFieldHdr) + _subfieldptr->datlen;
118 }
119
120
121 // ------------------------------------------------------------------
122
save_message(int __mode,gmsg * __msg,JamHdr & __hdr)123 void JamArea::save_message(int __mode, gmsg* __msg, JamHdr& __hdr) {
124
125 int _was_locked = data->islocked;
126 if(not _was_locked)
127 lock();
128
129 // Reset header
130 memset(&__hdr, 0, sizeof(JamHdr));
131
132 // Init paragraph class
133 GParagraph _para;
134 if(WideDispsoftcr)
135 _para.softcr = SOFTCR;
136
137 // Set default msg text offset and length
138 __hdr.offset = __msg->txtstart;
139 __hdr.txtlen = __msg->txtlength;
140
141 // Get message text size
142 char* _txtcpy = NULL;
143 if(__msg->txt and (__mode & GMSG_TXT)) {
144
145 // Work on a copy of the original msg text
146 _txtcpy = throw_strdup(__msg->txt);
147
148 // Convert message text to a paragraph list
149 _para.ConvertText(_txtcpy, strlen(_txtcpy));
150
151 // Mark control lines and calculate pure message text size
152 __hdr.txtlen = _para.CheckCtrlLines();
153 }
154
155 // Determine where to write the message text
156 if((__mode & GMSG_NEW) or (__hdr.txtlen > __msg->txtlength))
157 __hdr.offset = filelength(data->fhjdt);
158
159 byte* _subfield = NULL;
160 char _buf[1024];
161 __hdr.subfieldlen = __msg->jam.subfieldlen;
162
163 if(__mode & GMSG_TXT) {
164
165 // Build the subfields
166 __hdr.subfieldlen = 0;
167
168 // Process addressing kludges
169 int _line = 0;
170 GParaData* _pdptr = _para.paraidx;
171 while(_line < _para.lines) {
172 if(_pdptr->control > CTRL_KLUDGE) {
173 word fmpt, topt;
174 char buf1[201], buf2[201];
175 switch(_pdptr->control) {
176 case CTRL_INTL:
177 fmpt = __msg->orig.point;
178 topt = __msg->dest.point;
179 sscanf(_pdptr->text+6, "%s %s", buf1, buf2);
180 __msg->dest.set(buf1);
181 __msg->orig.set(buf2);
182 __msg->orig.point = fmpt;
183 __msg->dest.point = topt;
184 break;
185 case CTRL_FMPT:
186 __msg->orig.point = atow(_pdptr->text+6);
187 break;
188 case CTRL_TOPT:
189 __msg->dest.point = atow(_pdptr->text+6);
190 break;
191 case CTRL_MSGID:
192 __msg->msgid.reset(_pdptr->text+8, __msg->odom);
193 break;
194 }
195 }
196 _pdptr++;
197 _line++;
198 }
199
200 if(*__msg->by)
201 add_subfield(__hdr, _subfield, JAMSUB_SENDERNAME, 0, __msg->by, JAMSUB_SENDERNAME_LEN);
202
203 if(__msg->orig.net) {
204 __msg->orig.make_string(_buf, __msg->odom);
205 add_subfield(__hdr, _subfield, JAMSUB_OADDRESS, 0, _buf, JAMSUB_OADDRESS_LEN);
206 }
207
208 if(*__msg->to)
209 add_subfield(__hdr, _subfield, JAMSUB_RECEIVERNAME, 0, __msg->to, JAMSUB_RECEIVERNAME_LEN);
210
211 if(__msg->dest.net) {
212 __msg->dest.make_string(_buf, __msg->ddom);
213 add_subfield(__hdr, _subfield, JAMSUB_DADDRESS, 0, _buf, JAMSUB_DADDRESS_LEN);
214 }
215
216 if(*__msg->re)
217 add_subfield(__hdr, _subfield, JAMSUB_SUBJECT, 0, __msg->re, JAMSUB_SUBJECT_LEN);
218
219 // Convert kludges
220 _line = 0;
221 _pdptr = _para.paraidx;
222 while(_line < _para.lines) {
223 if(_pdptr->control > CTRL_KLUDGE) {
224 uint _offset = 0;
225 word _loid = 0;
226 uint32_t _maxlen = 0;
227 switch(_pdptr->control) {
228 case CTRL_INTL:
229 case CTRL_FMPT:
230 case CTRL_TOPT:
231 // Strip these. Data is stored in the address subfields
232 break;
233 case CTRL_MSGID:
234 _loid = JAMSUB_MSGID;
235 _maxlen = JAMSUB_MSGID_LEN;
236 _offset = 8;
237 strxcpy(__msg->msgids, _pdptr->text+_offset, sizeof(__msg->msgids));
238 break;
239 case CTRL_REPLY:
240 _loid = JAMSUB_REPLYID;
241 _maxlen = JAMSUB_REPLYID_LEN;
242 _offset = 8;
243 strxcpy(__msg->replys, _pdptr->text+_offset, sizeof(__msg->replys));
244 break;
245 case CTRL_PID:
246 _loid = JAMSUB_PID;
247 _maxlen = JAMSUB_PID_LEN;
248 _offset = 6;
249 break;
250 case CTRL_VIA:
251 _loid = JAMSUB_TRACE;
252 _maxlen = JAMSUB_TRACE_LEN;
253 _offset = 5;
254 break;
255 case CTRL_SEENBY:
256 _loid = JAMSUB_SEENBY2D;
257 _maxlen = JAMSUB_SEENBY2D_LEN;
258 _offset = 9;
259 break;
260 case CTRL_SEENBY1:
261 _loid = JAMSUB_SEENBY2D;
262 _maxlen = JAMSUB_SEENBY2D_LEN;
263 _offset = 10;
264 break;
265 case CTRL_PATH:
266 _loid = JAMSUB_PATH2D;
267 _maxlen = JAMSUB_PATH2D_LEN;
268 _offset = 7;
269 break;
270 case CTRL_FLAGS:
271 _loid = JAMSUB_FLAGS;
272 _maxlen = JAMSUB_FLAGS_LEN;
273 _offset = 7;
274 break;
275 default:
276 _loid = JAMSUB_FTSKLUDGE;
277 _maxlen = JAMSUB_FTSKLUDGE_LEN;
278 _offset = 1;
279 }
280 if(_offset)
281 add_subfield(__hdr, _subfield, _loid, 0, _pdptr->text+_offset, _maxlen);
282 }
283 _pdptr++;
284 _line++;
285 }
286 }
287
288 JamIndex _idx;
289 bool was_deleted = false;
290 if(__mode & GMSG_NEW) {
291 __msg->msgno = data->hdrinfo.basemsgnum + (filelength(data->fhjdx)/sizeof(JamIndex));
292 __hdr.messagenumber = __msg->msgno;
293 _idx.hdroffset = filelength(data->fhjhr);
294 }
295 else {
296 __hdr.messagenumber = __msg->msgno;
297 lseekset(data->fhjdx, __hdr.messagenumber-data->hdrinfo.basemsgnum, sizeof(JamIndex));
298 read(data->fhjdx, &_idx, sizeof(JamIndex));
299 if(_idx.hdroffset != 0xFFFFFFFFL) {
300 lseekset(data->fhjhr, _idx.hdroffset);
301 JamHdr oldhdr;
302 read(data->fhjhr, &oldhdr, sizeof(JamHdr));
303 was_deleted = make_bool(oldhdr.attribute & JAMATTR_DELETED);
304 if(oldhdr.subfieldlen != __hdr.subfieldlen) {
305 oldhdr.attribute |= JAMATTR_DELETED;
306 oldhdr.txtlen = 0;
307 lseekset(data->fhjhr, _idx.hdroffset);
308 write(data->fhjhr, &oldhdr, sizeof(JamHdr));
309 _idx.hdroffset = filelength(data->fhjhr);
310 }
311 }
312 }
313
314 if(_idx.hdroffset != 0xFFFFFFFFL) {
315
316 memcpy(__hdr.signature, JAM_SIGNATURE, 4);
317 __hdr.revision = JAM_REVISION;
318
319 __hdr.replyto = __msg->link.to();
320 __hdr.reply1st = __msg->link.first();
321 __hdr.replynext = __msg->link.next();
322
323 __hdr.cost = __msg->cost;
324 __hdr.timesread = __msg->timesread;
325 __hdr.passwordcrc = 0xFFFFFFFFL;
326
327 __hdr.msgidcrc = strCrc32(jamstrlwr(strcpy(_buf, __msg->msgids)), NO, CRC32_MASK_CCITT);
328 __hdr.replycrc = strCrc32(jamstrlwr(strcpy(_buf, __msg->replys)), NO, CRC32_MASK_CCITT);
329 _idx.usercrc = strCrc32(jamstrlwr(strcpy(_buf, __msg->to)), NO, CRC32_MASK_CCITT);
330
331 __hdr.datewritten = __msg->written;
332 __hdr.datereceived = __msg->received;
333 __hdr.dateprocessed = __msg->arrived;
334
335 __hdr.attribute |= __msg->attr.loc() ? JAMATTR_LOCAL : 0;
336 __hdr.attribute |= __msg->attr.trs() ? JAMATTR_INTRANSIT : 0;
337 __hdr.attribute |= __msg->attr.pvt() ? JAMATTR_PRIVATE : 0;
338 __hdr.attribute |= __msg->attr.rcv() ? JAMATTR_READ : 0;
339 __hdr.attribute |= __msg->attr.snt() ? JAMATTR_SENT : 0;
340 __hdr.attribute |= __msg->attr.k_s() ? JAMATTR_KILLSENT : 0;
341 __hdr.attribute |= __msg->attr.a_s() ? JAMATTR_ARCHIVESENT : 0;
342 __hdr.attribute |= __msg->attr.hld() ? JAMATTR_HOLD : 0;
343 __hdr.attribute |= __msg->attr.cra() ? JAMATTR_CRASH : 0;
344 __hdr.attribute |= __msg->attr.imm() ? JAMATTR_IMMEDIATE : 0;
345 __hdr.attribute |= __msg->attr.dir() ? JAMATTR_DIRECT : 0;
346 __hdr.attribute |= __msg->attr.zon() ? JAMATTR_GATE : 0;
347 __hdr.attribute |= __msg->attr.frq() ? JAMATTR_FILEREQUEST : 0;
348 __hdr.attribute |= __msg->attr.att() ? JAMATTR_FILEATTACH : 0;
349 __hdr.attribute |= __msg->attr.tfs() ? JAMATTR_TRUNCFILE : 0;
350 __hdr.attribute |= __msg->attr.kfs() ? JAMATTR_KILLFILE : 0;
351 __hdr.attribute |= __msg->attr.rrq() ? JAMATTR_RECEIPTREQ : 0;
352 __hdr.attribute |= __msg->attr.cfm() ? JAMATTR_CONFIRMREQ : 0;
353 __hdr.attribute |= __msg->attr.orp() ? JAMATTR_ORPHAN : 0;
354 __hdr.attribute |= __msg->attr.lok() ? JAMATTR_LOCKED : 0;
355 __hdr.attribute |= __msg->attr.del() ? JAMATTR_DELETED : 0;
356
357 if(isnet())
358 __hdr.attribute |= JAMATTR_TYPENET;
359 else if(isecho())
360 __hdr.attribute |= JAMATTR_TYPEECHO;
361 else
362 __hdr.attribute |= JAMATTR_TYPELOCAL;
363
364 lseekset(data->fhjhr, _idx.hdroffset);
365 write(data->fhjhr, &__hdr, sizeof(JamHdr));
366
367 // Only write subfields if the msg body is written
368 if(__mode & GMSG_TXT)
369 write(data->fhjhr, _subfield, (uint)__hdr.subfieldlen);
370
371 // Delete msg if requested
372 if(__mode & GMSG_DELETE) {
373 if(not was_deleted)
374 data->hdrinfo.activemsgs--;
375 __hdr.attribute |= JAMATTR_DELETED;
376 _idx.usercrc = 0xFFFFFFFFL;
377 if(wide->harddelete)
378 _idx.hdroffset = 0xFFFFFFFFL;
379 }
380
381 // Write msg index
382 lseekset(data->fhjdx, __hdr.messagenumber-data->hdrinfo.basemsgnum, sizeof(JamIndex));
383 write(data->fhjdx, &_idx, sizeof(JamIndex));
384
385 // Free subfield buffer
386 throw_release(_subfield);
387
388 // Update the header info
389 if((__mode & GMSG_NEW) or (was_deleted and not __msg->attr.del()))
390 data->hdrinfo.activemsgs++;
391 data->hdrinfo.modcounter++;
392 lseekset(data->fhjhr, 0);
393 write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
394
395 // If message text is used
396 if(__mode & GMSG_TXT) {
397
398 char* _txt = (char*)throw_malloc((uint)(__hdr.txtlen+256));
399
400 // Copy text paragraphs, excluding kludges
401 int _line = 0;
402 char* _tptr = _txt;
403 GParaData* _pdptr = _para.paraidx;
404 while(_line < _para.lines) {
405 if(_pdptr->control < CTRL_KLUDGE) {
406 memcpy(_tptr, _pdptr->text, _pdptr->length);
407 _tptr += _pdptr->length;
408 *_tptr++ = CR;
409 }
410 _pdptr++;
411 _line++;
412 }
413 *_tptr = NUL;
414
415 // Seek to start position of the message text
416 lseekset(data->fhjdt, __hdr.offset);
417
418 // Write the message text
419 write(data->fhjdt, _txt, (uint)__hdr.txtlen);
420
421 // Release the memory we have used
422 throw_free(_txtcpy);
423 throw_free(_txt);
424 }
425
426 // Update internals if new
427 if(__mode & GMSG_NEW) {
428
429 // Count our msgs
430 data->timesposted++;
431
432 // Update internal array
433 Msgn->Append(__msg->msgno);
434 }
435
436 // Adjust the highwatermark if required
437 if(jamwide->smapihw and __msg->attr.uns()) {
438 if(data->hdrinfo.highwatermark >= __msg->msgno)
439 data->hdrinfo.highwatermark = __msg->msgno - 1;
440 }
441 else if((data->highwater != -1) and (data->fhjhw != -1)) {
442 if(data->highwater >= __msg->msgno) {
443 data->highwater = __msg->msgno - 1;
444 lseek(data->fhjhw, 0, SEEK_SET);
445 write(data->fhjhw, &data->highwater, sizeof(int32_t));
446 }
447 }
448 }
449 else {
450 scan();
451 }
452
453 if(not _was_locked) {
454 lseekset(data->fhjhr, 0);
455 write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
456 unlock();
457 }
458
459 GFTRK(0);
460 }
461
462
463 // ------------------------------------------------------------------
464
save_hdr(int __mode,gmsg * __msg)465 void JamArea::save_hdr(int __mode, gmsg* __msg) {
466
467 GFTRK("JamArea::save_hdr");
468
469 JamHdr _hdr;
470 save_message(__mode | GMSG_HDR, __msg, _hdr);
471 }
472
473
474 // ------------------------------------------------------------------
475
save_msg(int __mode,gmsg * __msg)476 void JamArea::save_msg(int __mode, gmsg* __msg) {
477
478 GFTRK("JamArea::save_msg");
479
480 JamHdr _hdr;
481 save_message(__mode | GMSG_HDRTXT, __msg, _hdr);
482 }
483
484
485 // ------------------------------------------------------------------
486
del_msg(gmsg * __msg)487 void JamArea::del_msg(gmsg* __msg) {
488
489 GFTRK("JamArea::del_msg");
490
491 JamHdr _hdr;
492 save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
493 }
494
495
496 // ------------------------------------------------------------------
497
new_msgno(gmsg * __msg)498 void JamArea::new_msgno(gmsg* __msg) {
499
500 GFTRK("JamArea::new_msgno");
501
502 __msg->msgno = data->hdrinfo.basemsgnum + (filelength(data->fhjdx)/sizeof(JamIndex));
503
504 GFTRK(0);
505 }
506
507
508 // ------------------------------------------------------------------
509
update_timesread(gmsg * msg)510 void JamArea::update_timesread(gmsg* msg) {
511
512 GFTRK("JamArea::update_timesread");
513
514 lock();
515
516 lseekset(data->fhjdx, msg->msgno-data->hdrinfo.basemsgnum, sizeof(JamIndex));
517
518 JamIndex idx;
519 read(data->fhjdx, &idx, sizeof(JamIndex));
520
521 JamHdr hdr;
522 lseekset(data->fhjhr, idx.hdroffset);
523 read(data->fhjhr, &hdr, sizeof(JamHdr));
524
525 hdr.timesread = msg->timesread;
526
527 lseekset(data->fhjhr, idx.hdroffset);
528 write(data->fhjhr, &hdr, sizeof(JamHdr));
529
530 data->hdrinfo.modcounter++;
531 lseekset(data->fhjhr, 0);
532 write(data->fhjhr, &data->hdrinfo, sizeof(JamHdrInfo));
533
534 unlock();
535
536 GFTRK(0);
537 }
538
539
540 // ------------------------------------------------------------------
541
542