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