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: gmojamm3.cpp,v 1.12 2010/03/24 07:29:21 stas_degteff Exp $
23 // ------------------------------------------------------------------
24 // JAM msgbase implementation, load.
25 // ------------------------------------------------------------------
26
27
28 // ------------------------------------------------------------------
29
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <gmemdbg.h>
33 #include <gdbgtrk.h>
34 #include <gstrall.h>
35
36 #include "gmojamm.h"
37
38
39 // ------------------------------------------------------------------
40
load_message(int __mode,gmsg * __msg,JamHdr & __hdr)41 int JamArea::load_message(int __mode, gmsg* __msg, JamHdr& __hdr) {
42 ssize_t rwresult=0;
43
44 // Read index record for msg
45 JamIndex _idx;
46 memset(&_idx, 0, sizeof(JamIndex));
47 lseekset(data->fhjdx, __msg->msgno-data->hdrinfo.basemsgnum, sizeof(JamIndex));
48 rwresult = read(data->fhjdx, &_idx, sizeof(JamIndex));
49 if( rwresult!=sizeof(JamIndex) ) {
50 if( rwresult<0 )
51 WideLog->printf("! JamArea::load_message: index file read error \"%s\"", strerror(errno));
52 if( rwresult>=0 )
53 WideLog->printf("! JamArea::load_message: can't read index data");
54 WideLog->printf(": Info: Your msgbase is corrupted.");
55 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
56 GFTRK(0);
57 return false;
58 }
59
60 if(_idx.hdroffset == 0xFFFFFFFFL) {
61 GFTRK(0);
62 return false;
63 }
64
65 // Read message header
66 memset(&__hdr, 0, sizeof(JamHdr));
67 lseekset(data->fhjhr, _idx.hdroffset);
68 rwresult = read(data->fhjhr, &__hdr, sizeof(JamHdr));
69 if( rwresult!=sizeof(JamHdr) ) {
70 if( rwresult<0 )
71 WideLog->printf("! JamArea::load_message: data file read error \"%s\"", strerror(errno));
72 if( rwresult>=0 )
73 WideLog->printf("! JamArea::load_message: can't read header");
74 WideLog->printf(": Info: Your msgbase is corrupted.");
75 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
76 GFTRK(0);
77 return false;
78 }
79
80 if(strncmp(__hdr.signature, "JAM", 4) != 0) {
81 WideLog->printf("! Invalid signature found in %s (msgno %d).", path(), __msg->msgno);
82 WideLog->printf(": Info: Your msgbase is corrupted.");
83 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
84
85 GFTRK(0);
86 return false;
87 }
88
89 __msg->link.to_set(__hdr.replyto);
90 __msg->link.first_set(__hdr.reply1st);
91 __msg->link.next_set(__hdr.replynext);
92
93 __msg->cost = (uint)__hdr.cost;
94 __msg->timesread = (uint)__hdr.timesread;
95
96 __msg->written = __hdr.datewritten;
97 __msg->arrived = __hdr.dateprocessed;
98 __msg->received = __hdr.datereceived;
99
100 __msg->attr.loc(__hdr.attribute & JAMATTR_LOCAL);
101 __msg->attr.trs(__hdr.attribute & JAMATTR_INTRANSIT);
102 __msg->attr.pvt(__hdr.attribute & JAMATTR_PRIVATE);
103 __msg->attr.rcv(__hdr.attribute & JAMATTR_READ);
104 __msg->attr.snt(__hdr.attribute & JAMATTR_SENT);
105 __msg->attr.k_s(__hdr.attribute & JAMATTR_KILLSENT);
106 __msg->attr.a_s(__hdr.attribute & JAMATTR_ARCHIVESENT);
107 __msg->attr.hld(__hdr.attribute & JAMATTR_HOLD);
108 __msg->attr.cra(__hdr.attribute & JAMATTR_CRASH);
109 __msg->attr.imm(__hdr.attribute & JAMATTR_IMMEDIATE);
110 __msg->attr.dir(__hdr.attribute & JAMATTR_DIRECT);
111 __msg->attr.zon(__hdr.attribute & JAMATTR_GATE);
112 __msg->attr.frq(__hdr.attribute & JAMATTR_FILEREQUEST);
113 __msg->attr.att(__hdr.attribute & JAMATTR_FILEATTACH);
114 __msg->attr.tfs(__hdr.attribute & JAMATTR_TRUNCFILE);
115 __msg->attr.kfs(__hdr.attribute & JAMATTR_KILLFILE);
116 __msg->attr.rrq(__hdr.attribute & JAMATTR_RECEIPTREQ);
117 __msg->attr.cfm(__hdr.attribute & JAMATTR_CONFIRMREQ);
118 __msg->attr.orp(__hdr.attribute & JAMATTR_ORPHAN);
119 __msg->attr.lok(__hdr.attribute & JAMATTR_LOCKED);
120 __msg->attr.del(__hdr.attribute & JAMATTR_DELETED);
121
122 if(isnet() or isecho())
123 __msg->attr.uns(__msg->attr.loc() and not __msg->attr.snt());
124 else
125 __msg->attr.uns0();
126
127 __msg->txtstart = __hdr.offset;
128 __msg->txtlength = __hdr.txtlen;
129
130 // Allocate space for the subfields
131 __msg->jam.subfieldlen = __hdr.subfieldlen;
132 byte* _subfield = (byte*)throw_malloc((uint)(__hdr.subfieldlen+1));
133
134 // Allocate space for kludge versions of the subfields
135 char* _kludges = (char*)throw_malloc((uint)(__hdr.subfieldlen*2)+1);
136 *_kludges = NUL;
137
138 // Allocate space for seenby/paths
139 char* _kludges2 = (char*)throw_malloc((uint)(__hdr.subfieldlen*2)+1);
140 *_kludges2 = NUL;
141
142 // Read the subfields
143 rwresult = read(data->fhjhr, _subfield, (uint)__hdr.subfieldlen);
144 if( rwresult!=(ssize_t)__hdr.subfieldlen ) {
145 if( rwresult<0 )
146 WideLog->printf("! JamArea::load_message: data file read error \"%s\"", strerror(errno));
147 if( rwresult>=0 )
148 WideLog->printf("! JamArea::load_message: can't read Jam subfield");
149 WideLog->printf(": Info: Your msgbase is corrupted.");
150 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
151 throw_free(_subfield);
152 throw_free(_kludges);
153 throw_free(_kludges2);
154 GFTRK(0);
155 return false;
156 }
157
158 // Pointer to the subfields
159 JamSubField* _subfieldptr = (JamSubField*)_subfield;
160
161 // Process the subfields
162 int _got_oaddr = false;
163 int _got_daddr = false;
164 uint _subfieldpos = 0;
165
166 while(_subfieldpos < __hdr.subfieldlen) {
167
168 _subfieldpos += sizeof(JamSubFieldHdr);
169 uint _datlen = (uint)_subfieldptr->datlen;
170
171 if(_subfieldpos > __hdr.subfieldlen)
172 break;
173
174 if((_subfieldpos + _datlen) > __hdr.subfieldlen)
175 _datlen = (uint)(__hdr.subfieldlen - _subfieldpos);
176
177 char* _buf = _subfieldptr->buffer;
178 char _bufendchar = _buf[_datlen];
179 _buf[_datlen] = NUL;
180
181 char* _ptr;
182
183 switch(_subfieldptr->loid) {
184
185 case JAMSUB_OADDRESS:
186 if(not _got_oaddr) {
187 _got_oaddr = true;
188 __msg->oorig.set(_buf, __msg->odom);
189 __msg->orig = __msg->oorig;
190 if(_got_daddr) {
191 add_intl_topt_fmpt:
192 if(isnet()) {
193 sprintf(_kludges+strlen(_kludges), "\001INTL %u:%u/%u %u:%u/%u\r",
194 __msg->dest.zone, __msg->dest.net, __msg->dest.node,
195 __msg->orig.zone, __msg->orig.net, __msg->orig.node
196 );
197 if(__msg->dest.point)
198 sprintf(_kludges+strlen(_kludges), "\001TOPT %u\r", __msg->dest.point);
199 if(__msg->orig.point)
200 sprintf(_kludges+strlen(_kludges), "\001FMPT %u\r", __msg->orig.point);
201 }
202 }
203 }
204 break;
205
206 case JAMSUB_DADDRESS:
207 if(not _got_daddr) {
208 _got_daddr = true;
209 __msg->odest.set(_buf, __msg->ddom);
210 __msg->dest = __msg->odest;
211 if(_got_oaddr)
212 goto add_intl_topt_fmpt;
213 }
214 break;
215
216 case JAMSUB_SENDERNAME:
217 strxcpy(__msg->by, _buf, sizeof(__msg->by));
218 break;
219
220 case JAMSUB_RECEIVERNAME:
221 strxcpy(__msg->to, _buf, sizeof(__msg->by));
222 break;
223
224 case JAMSUB_MSGID:
225 sprintf(_kludges+strlen(_kludges), "\001MSGID: %s\r", _buf);
226 strxcpy(__msg->msgids, _buf, sizeof(__msg->msgids));
227 __msg->msgid.reset_fast();
228 if(atoi(__msg->msgids)) {
229 __msg->msgid.set(__msg->msgids, __msg->odom);
230 if(__msg->msgid.net and (__msg->orig.net == 0))
231 __msg->orig = __msg->msgid;
232 }
233 break;
234
235 case JAMSUB_REPLYID:
236 sprintf(_kludges+strlen(_kludges), "\001REPLY: %s\r", _buf);
237 strxcpy(__msg->replys, _buf, sizeof(__msg->replys));
238 break;
239
240 case JAMSUB_SUBJECT:
241 strxcpy(__msg->re, _buf, sizeof(__msg->re));
242 break;
243
244 case JAMSUB_PID:
245 sprintf(_kludges+strlen(_kludges), "\001PID: %s\r", _buf);
246 strxcpy(__msg->pid, _buf, sizeof(__msg->pid));
247 break;
248
249 case JAMSUB_TRACE:
250 sprintf(_kludges2+strlen(_kludges2), "\001Via %s\r", _buf);
251 // Not processed
252 break;
253
254 case JAMSUB_ENCLOSEDFILE:
255 sprintf(_kludges+strlen(_kludges), "\001ENCLFILE: %s\r", _buf);
256 // Not processed
257 break;
258
259 case JAMSUB_ENCLOSEDFILEWALIAS:
260 sprintf(_kludges+strlen(_kludges), "\001ENCLFILEWALIAS: %s\r", _buf);
261 // Not processed
262 break;
263
264 case JAMSUB_ENCLOSEDFREQ:
265 sprintf(_kludges+strlen(_kludges), "\001ENCLFREQ: %s\r", _buf);
266 // Not processed
267 break;
268
269 case JAMSUB_ENCLOSEDFILEWCARD:
270 sprintf(_kludges+strlen(_kludges), "\001ENCLFILEWCARD: %s\r", _buf);
271 // Not processed
272 break;
273
274 case JAMSUB_ENCLOSEDINDIRECFILE:
275 sprintf(_kludges+strlen(_kludges), "\001ENCLINDIRFILE: %s\r", _buf);
276 // Not processed
277 break;
278
279 case JAMSUB_EMBINDAT:
280 // Not processed
281 break;
282
283 case JAMSUB_FTSKLUDGE:
284 {
285 char *_kludgesx;
286 if(strneql(_buf, "Via ", 4) or strneql(_buf, "Recd", 4) or strneql(_buf, "Forwarded", 9))
287 _kludgesx = _kludges2;
288 else
289 _kludgesx = _kludges;
290 sprintf(_kludgesx+strlen(_kludgesx), "\001%s\r", _buf);
291 }
292 // Not processed
293 break;
294
295 case JAMSUB_SEENBY2D:
296 _ptr = _buf;
297 while(strlen(_ptr) > 70) {
298 char* _tmp = _ptr;
299 _ptr += 70;
300 while(*_ptr != ' ')
301 _ptr--;
302 *_ptr++ = NUL;
303 sprintf(_kludges2+strlen(_kludges2), "SEEN-BY: %s\r", _tmp);
304 }
305 sprintf(_kludges2+strlen(_kludges2), "SEEN-BY: %s\r", _ptr);
306 // Not processed
307 break;
308
309 // 1 2 3 4 5 6 7 8
310 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
311 // SEEN-BY: 123/456 123/456 123/456 123/456 123/456 123/456 123/456 123/456 23/456 123/456
312 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
313 // 1 2 3 4 5 6 7 8
314
315 case JAMSUB_PATH2D:
316 _ptr = _buf;
317 while(strlen(_ptr) > 72) {
318 char* _tmp = _ptr;
319 _ptr += 72;
320 while(*_ptr != ' ')
321 _ptr--;
322 *_ptr++ = NUL;
323 sprintf(_kludges2+strlen(_kludges2), "\001PATH: %s\r", _tmp);
324 }
325 sprintf(_kludges2+strlen(_kludges2), "\001PATH: %s\r", _ptr);
326 // Not processed
327 break;
328
329 case JAMSUB_FLAGS:
330 sprintf(_kludges+strlen(_kludges), "\001FLAGS %s\r", _buf);
331 GetAttribstr(&__msg->attr, _buf);
332 break;
333
334 case JAMSUB_TZUTCINFO:
335 sprintf(_kludges+strlen(_kludges), "\001TZUTC: %s\r", _buf);
336 // Not processed
337 break;
338 }
339
340 _buf[_datlen] = _bufendchar;
341
342 _subfieldpos += _datlen;
343 _subfieldptr = (JamSubField*)(_subfield + _subfieldpos);
344 }
345
346 // Free subfield buffer
347 throw_free(_subfield);
348
349 // Get reply numbers in chain
350 if (wide->lookreplies and __msg->link.first())
351 {
352 int r = 0;
353 uint32_t m = __msg->link.first();
354 while (m)
355 {
356 JamHdr _rhdr;
357 memset(&_rhdr, 0, sizeof(JamHdr));
358 lseekset(data->fhjdx, m-data->hdrinfo.basemsgnum, sizeof(JamIndex));
359 read(data->fhjdx, &_idx, sizeof(JamIndex));
360 lseekset(data->fhjhr, _idx.hdroffset);
361 read(data->fhjhr, &_rhdr, sizeof(JamHdr));
362 m = _rhdr.replynext;
363 if (m) __msg->link.list_set(r++, m);
364 }
365 }
366
367 // If message text is used
368 if(__mode & GMSG_TXT) {
369
370 // Get size of kludges
371 uint _kludgelen1 = strlen(_kludges);
372 uint _kludgelen2 = strlen(_kludges2);
373 uint _kludgelen = _kludgelen1 + _kludgelen2;
374 uint32_t _msgsize = __hdr.txtlen;
375
376 // Allocate memory for the message text
377 __msg->txt = (char*)throw_realloc(_kludges, (uint)(_msgsize+_kludgelen+256));
378
379 // Read the message text
380 lseekset(data->fhjdt, __hdr.offset);
381 rwresult = read(data->fhjdt, __msg->txt+_kludgelen1, (uint)_msgsize);
382 if( rwresult!=(ssize_t)_msgsize ) {
383 if( rwresult<0 )
384 WideLog->printf("! JamArea::load_message: data file read error \"%s\"", strerror(errno));
385 if( rwresult>=0 )
386 WideLog->printf("! JamArea::load_message: can't read Jam msgtext");
387 WideLog->printf(": Info: Your msgbase is corrupted.");
388 WideLog->printf("+ Advice: Run a msgbase index rebuild/recover utility.");
389 throw_free(_subfield);
390 throw_free(_kludges);
391 throw_free(_kludges2);
392 GFTRK(0);
393 return false;
394 }
395
396 // Is there a CR at the end?
397 {
398 char* ptr = __msg->txt+_kludgelen1+_msgsize-1;
399 if(*ptr != '\r') {
400 if(*ptr) {
401 ptr++;
402 _msgsize++;
403 }
404 *ptr = '\r';
405 }
406 }
407
408 memcpy(__msg->txt+_kludgelen1+(uint)_msgsize, _kludges2, _kludgelen2);
409 __msg->txt[(uint)_msgsize+_kludgelen] = NUL;
410 }
411 else {
412
413 // Free kludge buffer
414 throw_free(_kludges);
415 }
416
417 throw_free(_kludges2);
418
419 GFTRK(0);
420
421 return true;
422 }
423
424
425 // ------------------------------------------------------------------
426
load_hdr(gmsg * __msg)427 int JamArea::load_hdr(gmsg* __msg) {
428
429 if( __msg == NULL )
430 {
431 WideLog->printf("! JamArea::load_hdr() is called with NULL pointer." );
432 return false;
433 }
434 GFTRK("JamArea::load_hdr");
435
436 JamHdr _hdr;
437 return load_message(GMSG_HDR, __msg, _hdr);
438 }
439
440
441 // ------------------------------------------------------------------
442
load_msg(gmsg * __msg)443 int JamArea::load_msg(gmsg* __msg) {
444
445 if( __msg == NULL )
446 {
447 WideLog->printf("! JamArea::load_msg() is called with NULL pointer." );
448 return false;
449 }
450 GFTRK("JamArea::load_msg");
451
452 JamHdr _hdr;
453 return load_message(GMSG_HDRTXT, __msg, _hdr);
454 }
455
456
457 // ------------------------------------------------------------------
458