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