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 //  Copyright (C) 1999-2000 Alex. S. Aganichev
7 //  ------------------------------------------------------------------
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Library General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Library General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Library General Public
19 //  License along with this program; if not, write to the Free
20 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 //  MA 02111-1307, USA
22 //  ------------------------------------------------------------------
23 //  $Id: gmohuds4.cpp,v 1.10 2011/12/17 21:46:02 stas_degteff Exp $
24 //  ------------------------------------------------------------------
25 //  Hudson / Goldbase msgbase handling
26 //  ------------------------------------------------------------------
27 
28 
29 //  ------------------------------------------------------------------
30 
31 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
update_netecho(const char * __name,msgn_t __hdridx,int __delete)32 void _HudsWide<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::update_netecho(const char* __name, msgn_t __hdridx, int __delete)
33 {
34   GFTRK("HudsUpdateNetEcho");
35 
36   Path name;
37   strcpy(name, AddPath(syspath, __name));
38 
39   gfile _fh;
40   test_open(_fh, name, O_CREAT);
41 
42   // Get size of the file
43   uint _total = (uint)(_fh.FileLength()/sizeof(msgn_t));
44 
45   // Allocate memory for the scanning index
46   msgn_t* _scanidx = (msgn_t*)throw_calloc(_total+5, sizeof(msgn_t));
47 
48   // Read the scanning index
49   _fh.Read(_scanidx, _total*sizeof(msgn_t));
50 
51   // Close the file
52   _fh.Close();
53 
54   // Search for the specified header index
55   uint _pos = 0;
56   uint _closest = 0;
57   while(_pos < _total) {
58     if(_scanidx[_pos] <= __hdridx)
59       _closest = _pos;
60     if(_scanidx[_pos] == __hdridx)
61       break;
62     _pos++;
63   }
64 
65   // Delete or add the header index
66   if(__delete) {
67     if(_total and (_scanidx[_closest] == __hdridx)) {
68       if(_closest != _total) {
69         memmove(_scanidx+_closest, _scanidx+_closest+1, (_total-_closest+1)*sizeof(msgn_t));
70       }
71       --_total;
72     }
73   }
74   else {
75     if(_total) {
76       if(_scanidx[_closest] != __hdridx) {
77         if(_scanidx[_closest] < __hdridx)
78           _closest++;
79         if(_closest != _total)
80           memmove(_scanidx+_closest+1, _scanidx+_closest, (_total-_closest)*sizeof(msgn_t));
81         ++_total;
82       }
83     }
84     else
85       ++_total;
86     _scanidx[_closest++] = __hdridx;
87   }
88 
89   // Write the changed scanning file from scratch
90   if (_total)
91   {
92     test_open(_fh, __name, O_CREAT|O_TRUNC);
93     _fh.Write(_scanidx, _total*sizeof(msgn_t));
94     _fh.Close();
95   }
96   else {
97     // If the last header index was removed, delete the file
98     remove(__name);
99   }
100 
101   // Free the memory
102   throw_free(_scanidx);
103 
104   GFTRK(0);
105 }
106 
107 
108 //  ------------------------------------------------------------------
109 
110 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
save_message(int __mode,gmsg * __msg,HudsHdr & __hdr)111 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::save_message(int __mode, gmsg* __msg, HudsHdr& __hdr) {
112 
113   // Lock msgbase before doing anything
114   int _was_locked = wide->islocked;
115   if(not _was_locked)
116     lock();
117 
118   // Find header index
119   msgn_t _hdridx;
120   if (__mode & GMSG_NEW)
121   {
122     __msg->msgno = wide->msginfo.high + 1;
123     _hdridx = (msgn_t)(wide->fhhdr.FileLength()/sizeof(HudsHdr));
124   }
125   else {
126     _hdridx = get_hdr_idx(__msg, __FILE__, __LINE__);
127   }
128 
129   __hdr.board = (board_t)board();
130   __hdr.msgno = (msgn_t)__msg->msgno;
131   __hdr.replyto = (msgn_t)__msg->link.to();
132   __hdr.reply1st = (msgn_t)__msg->link.first();
133 
134   struct tm _tmp; ggmtime(&_tmp, &__msg->written);
135   strc2p(strftimei(__hdr.date, 9, "%m-%d-%y", &_tmp));
136   strc2p(strftimei(__hdr.time, 6, "%H:%M", &_tmp));
137 
138   strc2p(strxcpy(__hdr.to, __msg->to, sizeof(__hdr.to)));
139   strc2p(strxcpy(__hdr.by, __msg->by, sizeof(__hdr.by)));
140   strc2p(strxcpy(__hdr.re, __msg->re, sizeof(__hdr.re)));
141 
142   __hdr.origzone = (byte)__msg->oorig.zone;
143   __hdr.orignet  = __msg->oorig.net;
144   __hdr.orignode = __msg->oorig.node;
145 
146   __hdr.destzone = (byte)__msg->odest.zone;
147   __hdr.destnet  = __msg->odest.net;
148   __hdr.destnode = __msg->odest.node;
149 
150   __hdr.cost      = (word)__msg->cost;
151   __hdr.timesread = (word)__msg->timesread;
152 
153   // Transfer attributes
154   __hdr.msgattr = __hdr.netattr = 0;
155   __hdr.msgattr |= (byte)(__msg->attr.del() ? HUDS_DELETED   : 0);
156   __hdr.msgattr |= (byte)(__msg->attr.pvt() ? HUDS_PVT       : 0);
157   __hdr.msgattr |= (byte)(__msg->attr.rcv() ? HUDS_RECEIVED  : 0);
158   __hdr.msgattr |= (byte)(__msg->attr.loc() ? HUDS_LOCAL     : 0);
159   __hdr.msgattr |= (byte)(__msg->attr.grp() ? HUDS_GROUPMSG  : 0);
160   __hdr.netattr |= (byte)(__msg->attr.k_s() ? HUDS_KILLSENT  : 0);
161   __hdr.netattr |= (byte)(__msg->attr.snt() ? HUDS_SENT      : 0);
162   __hdr.netattr |= (byte)(__msg->attr.att() ? HUDS_ATTACH    : 0);
163   __hdr.netattr |= (byte)(__msg->attr.cra() ? HUDS_CRASH     : 0);
164   __hdr.netattr |= (byte)(__msg->attr.rrq() ? HUDS_RETRECREQ : 0);
165   __hdr.netattr |= (byte)(__msg->attr.arq() ? HUDS_AUDITREQ  : 0);
166   __hdr.netattr |= (byte)(__msg->attr.rrc() ? HUDS_RETREC    : 0);
167   __hdr.netattr |= (byte)(__msg->attr.frq() ? HUDS_FREQ      : 0);
168   if(isnet())
169     __hdr.msgattr |= HUDS_NETMSG;
170   if(__msg->attr.uns()) {
171     if(isnet())
172       __hdr.msgattr |= HUDS_NETTRANS;
173     else if(isecho())
174       __hdr.msgattr |= HUDS_ECHOTRANS;
175   }
176 
177   if(__mode & GMSG_DELETE)
178     __hdr.msgattr |= HUDS_DELETED;
179 
180   __hdr.startrec = (msgn_t)__msg->txtstart;
181   __hdr.numrecs = (word)__msg->txtlength;
182 
183   // Write to MSGTXT.BBS/DAT
184   if(__mode & GMSG_TXT) {
185 
186     // If the msg is new or the text is too large to fit
187     uint _txtlen = strlen(__msg->txt)+1;
188     if((__mode & GMSG_NEW) or (_txtlen > __msg->txtlength*255L))
189       __hdr.startrec = (msgn_t)(wide->fhtxt.FileLength()/256L);
190 
191     // Calculate the number of text records to write
192     register uint _fullrecs = _txtlen / 255;
193     register byte _extrarec = (byte)(_txtlen % 255);
194     __hdr.numrecs = (word)(_fullrecs + (_extrarec ? 1 : 0));
195 
196     // Seek to the text write position
197     wide->fhtxt.LseekSet(__hdr.startrec*256L);
198 
199     // Write the message text
200     register uint _count = 0;
201     register char* _txt = __msg->txt;
202     char _txtbuf[256];
203     char* _txtptr = _txtbuf + 1;
204     *_txtbuf = 255;
205     while (_count < _fullrecs)
206     {
207       memcpy(_txtptr, _txt, 255);
208       wide->fhtxt.Write(_txtbuf, 256);
209       _txt += 255;
210       _count++;
211     }
212     if (_extrarec)
213     {
214       *_txtbuf = _extrarec;
215       memset(_txtptr, 0, 255);
216       memcpy(_txtptr, _txt, _extrarec);
217       wide->fhtxt.Write(_txtbuf, 256);
218     }
219   }
220 
221   // Write to MSGHDR.BBS/DAT
222   wide->fhhdr.LseekSet(_hdridx*sizeof(HudsHdr));
223   wide->fhhdr.Write(&__hdr, sizeof(HudsHdr));
224 
225   // Write to MSGIDX.BBS/DAT
226   if(__mode & GMSG_NEW) {
227     wide->msgidxsize += sizeof(HudsIdx);
228     wide->msgidxptr = (HudsIdx*)throw_realloc(wide->msgidxptr, wide->msgidxsize+sizeof(HudsIdx));
229   }
230   HudsIdx* _idxp = wide->msgidxptr + (uint)_hdridx;
231   _idxp->board = __hdr.board;
232   _idxp->msgno = (msgn_t)((__mode & GMSG_DELETE) ? (__HUDSON ? HUDS_DELETEDMSGNO : GOLD_DELETEDMSGNO) : __hdr.msgno);
233   wide->fhidx.LseekSet(_hdridx*sizeof(HudsIdx));
234   wide->fhidx.Write(_idxp, sizeof(HudsIdx));
235 
236   // Write to MSGTOIDX.BBS/DAT
237   wide->fhtoi.LseekSet(_hdridx*sizeof(HudsToIdx));
238   if (__mode & GMSG_DELETE)
239     wide->fhtoi.Write("\xB* Deleted *\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(HudsToIdx));
240   else if(__hdr.msgattr & HUDS_RECEIVED)
241     wide->fhtoi.Write("\xC* Received *\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(HudsToIdx));
242   else
243     wide->fhtoi.Write(__hdr.to, sizeof(HudsToIdx));
244 
245   // Write to MSGINFO.BBS/DAT
246   if(__mode & GMSG_DELETE) {
247     wide->msginfo.total--;
248     wide->msginfo.active[__hdr.board-1]--;
249     if(__hdr.msgno == wide->msginfo.low) {
250       register uint _count = 0;
251       register msgn_t _total = (msgn_t)(wide->msgidxsize/sizeof(HudsIdx));
252       register HudsIdx* _msgidx_ptr = wide->msgidxptr;
253       while((_count++) < _total) {
254         if(_msgidx_ptr->msgno != (__HUDSON ? HUDS_DELETEDMSGNO : GOLD_DELETEDMSGNO)) {
255           wide->msginfo.low = _msgidx_ptr->msgno;
256           break;
257         }
258         _msgidx_ptr++;
259       }
260     }
261     if(__hdr.msgno == wide->msginfo.high) {
262       register uint _count = (uint)(wide->msgidxsize/sizeof(HudsIdx));
263       register HudsIdx* _msgidx_ptr = wide->msgidxptr + (_count-1);
264       while(_count--) {
265         if(_msgidx_ptr->msgno != (__HUDSON ? HUDS_DELETEDMSGNO : GOLD_DELETEDMSGNO)) {
266           wide->msginfo.high = _msgidx_ptr->msgno;
267           break;
268         }
269         _msgidx_ptr--;
270       }
271     }
272   }
273   else if(__mode & GMSG_NEW) {
274     wide->msginfo.total++;
275     wide->msginfo.active[__hdr.board-1]++;
276     if(__hdr.msgno < wide->msginfo.low)
277       wide->msginfo.low = __hdr.msgno;
278     if(__hdr.msgno > wide->msginfo.high)
279       wide->msginfo.high = __hdr.msgno;
280   }
281   wide->fhinf.LseekSet(0);
282   wide->fhinf.Write(&wide->msginfo, sizeof(HudsInfo));
283 
284   // Update scanning files
285   if((__hdr.msgattr & HUDS_NETTRANS) or (__mode & GMSG_DELETE))
286     wide->update_netecho(__HUDSON ? "netmail" HUDS_EXT : "netmail" GOLD_EXT, _hdridx, __hdr.msgattr & HUDS_DELETED);
287   if((__hdr.msgattr & HUDS_ECHOTRANS) or (__mode & GMSG_DELETE))
288     wide->update_netecho(__HUDSON ? "echomail" HUDS_EXT : "echomail" GOLD_EXT, _hdridx, __hdr.msgattr & HUDS_DELETED);
289 
290   if(__mode & GMSG_NEW) {
291 
292     // Count our msgs
293     wide->timesposted++;
294 
295     // Add new msgno to index
296     Msgn->Append(__msg->msgno);
297   }
298 
299   // Unlock msgbase after use
300   if(not _was_locked)
301     unlock();
302 
303   GFTRK(0);
304 }
305 
306 
307 //  ------------------------------------------------------------------
308 
309 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
save_hdr(int __mode,gmsg * __msg)310 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::save_hdr(int __mode, gmsg* __msg) {
311 
312   GFTRK("HudsSaveHdr");
313 
314   HudsHdr _hdr;
315   save_message(__mode|GMSG_HDR, __msg, _hdr);
316 }
317 
318 
319 //  ------------------------------------------------------------------
320 
321 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
save_msg(int __mode,gmsg * __msg)322 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::save_msg(int __mode, gmsg* __msg) {
323 
324   GFTRK("HudsSaveMsg");
325 
326   HudsHdr _hdr;
327   save_message(__mode|GMSG_HDRTXT, __msg, _hdr);
328 }
329 
330 
331 //  ------------------------------------------------------------------
332 
333 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
del_msg(gmsg * __msg)334 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::del_msg(gmsg* __msg) {
335 
336   GFTRK("HudsDelMsg");
337 
338   HudsHdr _hdr;
339   save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
340 }
341 
342 
343 //  ------------------------------------------------------------------
344 
345 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
new_msgno(gmsg * __msg)346 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::new_msgno(gmsg* __msg) {
347 
348   GFTRK("HudsNewMsgno");
349 
350   __msg->msgno = wide->msginfo.high + 1;
351 
352   GFTRK(0);
353 }
354 
355 
356 //  ------------------------------------------------------------------
357 
358 template <class msgn_t, class rec_t, class attr_t, class board_t, class last_t, bool __HUDSON>
update_timesread(gmsg * msg)359 void _HudsArea<msgn_t, rec_t, attr_t, board_t, last_t, __HUDSON>::update_timesread(gmsg* msg) {
360 
361   GFTRK("HudsArea::update_timesread");
362 
363   lock();
364 
365   msgn_t hdridx = get_hdr_idx(msg, __FILE__, __LINE__);
366   wide->fhhdr.LseekSet(hdridx*sizeof(HudsHdr));
367 
368   HudsHdr hdr;
369   wide->fhhdr.Read(&hdr, sizeof(HudsHdr));
370 
371   hdr.timesread = (word)msg->timesread;
372 
373   wide->fhhdr.LseekSet(hdridx*sizeof(HudsHdr));
374   wide->fhhdr.Write(&hdr, sizeof(HudsHdr));
375 
376   unlock();
377 
378   GFTRK(0);
379 }
380 
381 
382 //  ------------------------------------------------------------------
383 
384