1 /*
2 ** Adapted for MSGAPI by Fedor Lizunkov 2:5020/960@FidoNet
3 */
4
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <errno.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <time.h>
14 #include <fcntl.h>
15
16 #include <huskylib/compiler.h>
17
18 #ifdef HAS_IO_H
19 #include <io.h>
20 #endif
21
22 #ifdef HAS_SHARE_H
23 #include <share.h>
24 #endif
25
26 #ifdef HAS_MALLOC_H
27 #include <malloc.h>
28 #endif
29
30 #ifdef HAS_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #ifdef HAS_STRINGS_H
35 #include <strings.h>
36 #endif
37
38 #define MSGAPI_HANDLERS
39
40 #include <huskylib/huskylib.h>
41
42 /* Swith for build DLL */
43 #define DLLEXPORT
44 #include <huskylib/huskyext.h>
45 #include <huskylib/strext.h>
46
47 #include "msgapi.h"
48 #include "api_jam.h"
49 #include "api_jamp.h"
50 #include "apidebug.h"
51
52 #define Jmd ((JAMBASE *)(jm->apidata))
53 #define MsghJm ((JAMBASE *)(((struct _msgh *)msgh)->sq->apidata))
54
55 #ifdef __TURBOC__
56 #pragma warn -pia*
57 #pragma warn -ucp
58 #pragma warn -sig
59 #endif
60
61 #define NOTH 3
62
63 static JAMBASE *jbOpen = NULL;
64
65 /* Free's up a SubField-Chain */
66
freejamsubfield(JAMSUBFIELD2LIST * subfield)67 static void freejamsubfield(JAMSUBFIELD2LIST *subfield)
68 {
69 if (subfield) pfree(subfield);
70 }
71
JamOpenArea(byte * name,word mode,word type)72 MSGA *MSGAPI JamOpenArea(byte * name, word mode, word type)
73 {
74 MSGA *jm=NULL;
75 unsigned long len;
76
77 if( !name || !*name )
78 {
79 msgapierr = MERR_BADNAME;
80 return NULL;
81 }
82
83 jm = palloc(sizeof(MSGA));
84 if (jm == NULL)
85 {
86 msgapierr = MERR_NOMEM;
87 return NULL;
88 }
89
90 memset(jm, '\0', sizeof(MSGA));
91
92 jm->id = MSGAPI_ID;
93
94 if (type & MSGTYPE_ECHO)
95 {
96 jm->isecho = TRUE;
97 }
98
99 if (type & MSGTYPE_NOTH) jm->isecho = NOTH;
100
101 jm->api = (struct _apifuncs *)palloc(sizeof(struct _apifuncs));
102 if (jm->api == NULL) {
103 msgapierr = MERR_NOMEM;
104 pfree(jm);
105 return NULL;
106 }
107
108 memset(jm->api, '\0', sizeof(struct _apifuncs));
109
110 jm->apidata = (void*)palloc(sizeof(JAMBASE));
111
112 if (jm->apidata == NULL) {
113 msgapierr = MERR_NOMEM;
114 pfree(jm->api);
115 pfree(jm);
116 return NULL;
117 }
118
119 memset((byte *) jm->apidata, '\0', sizeof(JAMBASE));
120
121 jm->len = sizeof(MSGA);
122
123 jm->num_msg = 0;
124 jm->high_msg = 0;
125 jm->high_water = (dword) -1;
126
127 if (!Jam_OpenBase(jm, &mode, name)) {
128 pfree(jm->api);
129 pfree(jm->apidata);
130 pfree(jm);
131 msgapierr = MERR_BADF;
132 return NULL;
133 }
134
135 /* fix for corrupted areas */
136 lseek(Jmd->IdxHandle, 0, SEEK_END);
137 len = tell(Jmd->IdxHandle);
138 if (Jmd->HdrInfo.ActiveMsgs > len/IDX_SIZE) {
139 Jmd->HdrInfo.ActiveMsgs = len/IDX_SIZE;
140 Jmd->modified = 1;
141 }
142 lseek(Jmd->IdxHandle, 0, SEEK_SET);
143
144 /* If ActiveMsgs is not correct, it will be updated on first OpenMessage */
145 /* Jam_ActiveMsgs() is not needed for toss, just append new msgs */
146 /* But if ActiveMsgs==0 read returns immediately without Jam_ActiveMsgs() */
147 /* For prevent losing messages in this case do Jam_ActiveMsgs here */
148 if (Jmd->HdrInfo.ActiveMsgs == 0 && len > 0)
149 Jam_ActiveMsgs(jm);
150
151 jm->high_water = Jmd->HdrInfo.highwater;
152 /* jm->high_msg = Jam_HighMsg(Jmd); */
153 jm->high_msg = jm->num_msg = Jmd->HdrInfo.ActiveMsgs;
154
155 jm->type = MSGTYPE_JAM;
156
157 jm->sz_xmsg = sizeof(XMSG);
158 *jm->api = jm_funcs;
159
160 msgapierr = 0;
161 return jm;
162 }
163
JamCloseArea(MSGA * jm)164 static sword _XPENTRY JamCloseArea(MSGA * jm)
165 {
166 dword i;
167 JAMBASE *jbptr = jbOpen;
168
169 if (InvalidMh(jm))
170 {
171 return -1;
172 }
173
174 if (Jmd->msgs_open) {
175 msgapierr = MERR_EOPEN;
176 return -1;
177 }
178
179 if (jbptr != Jmd)
180 while((jbptr) && ((JAMBASE *)jbptr->jbNext) && ((JAMBASE *)jbptr->jbNext != Jmd))
181 jbptr = (JAMBASE *)jbptr->jbNext;
182
183 if (Jmd->modified || Jmd->HdrInfo.highwater != jm->high_water) {
184 Jmd->HdrInfo.highwater = jm->high_water;
185 Jmd->HdrInfo.ModCounter++;
186 Jam_WriteHdrInfo(Jmd);
187 }
188
189 if (jm->locked) JamUnlock(jm);
190
191 Jam_CloseFile(Jmd);
192
193 pfree(Jmd->BaseName);
194 if (Jmd->actmsg) {
195 for (i=0; i<Jmd->HdrInfo.ActiveMsgs; i++)
196 freejamsubfield(Jmd->actmsg[i].subfield);
197 pfree(Jmd->actmsg);
198 }
199
200 if (jbOpen != Jmd)
201 jbptr->jbNext = Jmd->jbNext;
202 else
203 jbOpen = jbOpen->jbNext;
204
205 pfree(jm->api);
206 pfree(jm->apidata);
207 jm->id = 0L;
208 memset(jm, 0, sizeof(MSGA));
209 pfree(jm);
210
211 return 0;
212 }
213
JamCloseOpenAreas()214 int JamCloseOpenAreas()
215 {
216 void *broken, **current = &broken; /* JAMBASE* and JAMBASE** */
217 *current = NULL;
218
219 while(jbOpen)
220 if(-1 == JamCloseArea(jbOpen->jm))
221 { /* avoid infinite loop possibility in case of error in JamCloseArea */
222 /* not closed bases are stored in the broken list */
223 printf("SMAPI ERROR: can't close '%s' properly!\n", jbOpen->BaseName); /* at least we must say something */
224 *current = jbOpen;
225 current = &jbOpen->jbNext;
226 jbOpen = jbOpen->jbNext;
227 *current = NULL;
228 }
229
230 /* TODO: implement 'forced close' mode to do as much cleanup work as possible */
231
232 jbOpen = (JAMBASE *)broken;
233
234 /*
235 do something tricky with it
236
237 JamForceCloseArea();
238 */
239 if(jbOpen) /* If we still have unclosed areas then return -1
240 in hope that somebody (most likely somebody in heaven)
241 will do something with it */
242 return -1;
243 if(broken) /* If we had problems with closing areas but have closed
244 them anyway then return -2. Really, does anybody expect we will
245 just suffer here in silence? NO, WE WON'T! =) */
246 return -2;
247
248 return 0;
249 }
250
JamOpenMsg(MSGA * jm,word mode,dword msgnum)251 static MSGH *_XPENTRY JamOpenMsg(MSGA * jm, word mode, dword msgnum)
252 {
253 struct _msgh *msgh;
254
255 if (InvalidMh(jm)) {
256 return NULL;
257 }
258
259 if (mode == MOPEN_CREATE) {
260 if ((sdword) msgnum < 0 || msgnum > jm->num_msg) {
261 msgapierr = MERR_NOENT;
262 return NULL;
263 }
264
265 if (msgnum != 0) {
266 msgh = Jam_OpenMsg(jm, mode, msgnum);
267
268 if (msgh == NULL) {
269 msgapierr = MERR_NOENT;
270 return NULL;
271 }
272 } else {
273 msgh = palloc(sizeof(struct _msgh));
274 if (msgh == NULL) {
275 msgapierr = MERR_NOMEM;
276 return NULL;
277 }
278
279 memset(msgh, '\0', sizeof(struct _msgh));
280
281 msgh->sq = jm;
282 msgh->bytes_written = 0L;
283 msgh->cur_pos = 0L;
284 msgh->msgnum = msgnum;
285 msgh->Hdr.TxtLen = 0;
286
287 } /* endif */
288
289 }
290 else if (msgnum == 0) {
291 msgapierr = MERR_NOENT;
292 return NULL;
293 } else {
294 msgh = Jam_OpenMsg(jm, mode, msgnum);
295 if (msgh == NULL) {
296 msgapierr = MERR_NOENT;
297 return NULL;
298 }
299 }
300
301 msgh->mode = mode;
302 msgh->id = MSGH_ID;
303
304 MsghJm->msgs_open++;
305
306 return (MSGH *) msgh;
307 }
308
JamCloseMsg(MSGH * msgh)309 static sword _XPENTRY JamCloseMsg(MSGH * msgh)
310 {
311 if (InvalidMsgh(msgh))
312 {
313 return -1;
314 }
315
316
317 MsghJm->msgs_open--;
318
319 /* Fill the message out to the length that the app said it would be */
320
321 msgh->id = 0L;
322 pfree(msgh->ctrl);
323 pfree(msgh->lctrl);
324 pfree(msgh->SubFieldPtr);
325 pfree(msgh);
326
327 return 0;
328 }
329
openfilejm(char * name,word mode,mode_t permissions)330 static int openfilejm(char *name, word mode, mode_t permissions)
331 {
332 return sopen(name, mode, SH_DENYNONE, permissions);
333 }
334
opencreatefilejm(char * name,word mode,mode_t permissions)335 static int opencreatefilejm(char *name, word mode, mode_t permissions)
336 {
337 int hF =sopen(name, mode, SH_DENYNONE, permissions);
338
339 if ((hF == -1) && (mode & O_CREAT) && (errno == ENOENT) )
340 {
341 char* slash = strrchr(name, PATH_DELIM);
342 if (slash) {
343 *slash = '\0';
344 _createDirectoryTree(name);
345 *slash = PATH_DELIM;
346 }
347 hF=sopen(name, mode, SH_DENYNONE, permissions);
348 }
349 return hF;
350 }
351
Jam_OpenTxtFile(JAMBASE * jambase)352 static int Jam_OpenTxtFile(JAMBASE *jambase)
353 {
354 char *txt;
355
356 if (!jambase || !jambase->BaseName) {
357 msgapierr = MERR_BADA;
358 return 0;
359 }
360
361 txt = (char *) palloc(strlen((char*)(jambase->BaseName))+5);
362 if (!txt) {
363 msgapierr = MERR_NOMEM;
364 return 0;
365 }
366 strcpy(txt, (char*)(jambase->BaseName));
367 strcat(txt, EXT_TXTFILE);
368 if (jambase->mode == MSGAREA_CREATE)
369 jambase->TxtHandle = openfilejm(txt, fop_wpb, jambase->permissions);
370 else
371 jambase->TxtHandle = openfilejm(txt, fop_rpb, jambase->permissions);
372 if ((jambase->TxtHandle == -1) && (jambase->mode == MSGAREA_CRIFNEC)) {
373 jambase->mode = MSGAREA_CREATE;
374 jambase->TxtHandle = opencreatefilejm(txt, fop_cpb, jambase->permissions);
375 }
376 pfree(txt);
377 if (jambase->TxtHandle == -1) {
378 Jam_CloseFile(jambase);
379 msgapierr = MERR_NOENT;
380 return 0;
381 }
382 return 1;
383 }
384
JamReadMsg(MSGH * msgh,XMSG * msg,dword offset,dword bytes,byte * text,dword clen,byte * ctxt)385 static dword _XPENTRY JamReadMsg(MSGH * msgh, XMSG * msg, dword offset, dword bytes, byte * text, dword clen, byte * ctxt)
386 {
387 JAMSUBFIELD2ptr SubField;
388 dword SubPos, bytesread;
389 struct tm *s_time;
390 SCOMBO *scombo;
391 unsigned char *ftsdate;
392
393 if (InvalidMsgh(msgh))
394 {
395 return (dword)-1L;
396 }
397
398 if (msgh->Hdr.Attribute & JMSG_DELETED) {
399 return (dword)-1L;
400 } /* endif */
401
402 if (msg) {
403 /* make msg */
404
405 msg->attr = Jam_JamAttrToMsg(msgh);
406
407 memset(msg->from, '\0', XMSG_FROM_SIZE);
408 memset(msg->to, '\0', XMSG_TO_SIZE);
409 memset(msg->subj, '\0', XMSG_SUBJ_SIZE);
410 memset(&(msg->orig), 0, sizeof(msg->orig));
411 memset(&(msg->dest), 0, sizeof(msg->dest));
412
413 /* get "from name" line */
414 SubPos = 0;
415 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_SENDERNAME);
416 if (SubField != NULL) {
417 strncpy((char*)(msg->from), (char*)(SubField->Buffer), min(SubField->DatLen, sizeof(msg->from)-1));
418 } /* endif */
419
420 /* get "to name" line */
421 SubPos = 0;
422 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_RECVRNAME);
423 if (SubField != NULL) {
424 strncpy((char*)(msg->to), (char*)(SubField->Buffer), min(SubField->DatLen, sizeof(msg->to)-1));
425 } /* endif */
426
427 /* get "subj" line */
428 SubPos = 0;
429 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_SUBJECT);
430 if (SubField != NULL) {
431 strncpy((char*)(msg->subj), (char*)(SubField->Buffer), min(SubField->DatLen, sizeof(msg->subj)-1));
432 } /* endif */
433
434 /* try to fetch orig/dest addresses even for echomail */
435 /* if (!msgh->sq->isecho) { */
436 /* get "orig address" line */
437 SubPos = 0;
438 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_OADDRESS);
439 if (SubField != NULL) {
440 parseFtnAddrS((char*)SubField->Buffer, &(msg->orig), SubField->DatLen);
441 } /* endif */
442
443 /* get "dest address" line */
444 SubPos = 0;
445 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_DADDRESS);
446 if (SubField != NULL) {
447 parseFtnAddrS((char*)SubField->Buffer, &(msg->dest), SubField->DatLen);
448 } /* endif */
449 /* } else { */
450 /* get "orig address" from MSGID */
451 SubPos = 0;
452 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_MSGID);
453 if (SubField != NULL)
454 if (!(msg->orig.zone || msg->orig.net || msg->orig.node))
455 parseFtnAddrS((char*)SubField->Buffer, &(msg->dest), SubField->DatLen);
456 /* } */ /* endif */
457
458 {
459 const time_t c_time = msgh->Hdr.DateWritten;
460 s_time = gmtime(&c_time);
461 }
462 scombo = (SCOMBO*)(&(msg->date_written));
463 scombo = TmDate_to_DosDate(s_time, scombo);
464 /* ftsdate = msg->__ftsc_date; */
465 ftsdate = (unsigned char *)sc_time(scombo, (char *)(msg->__ftsc_date));
466
467 if (msgh->Hdr.DateProcessed) {
468 const time_t c_time = msgh->Hdr.DateProcessed;
469 s_time = gmtime(&c_time);
470 scombo = (SCOMBO*)(&(msg->date_arrived));
471 scombo = TmDate_to_DosDate(s_time, scombo);
472 }
473 else
474 ((SCOMBO*)(&(msg->date_arrived)))->ldate = 0;
475
476 msg->replyto = msgh->Hdr.ReplyTo;
477 msg->xmreply1st = msgh->Hdr.Reply1st;
478 msg->replies[1] = 0;
479 msg->xmreplynext = msgh->Hdr.ReplyNext;
480 msg->xmtimesread = msgh->Hdr.TimesRead;
481 msg->xmcost = msgh->Hdr.Cost;
482
483 } /* endif */
484
485 bytesread = 0;
486
487 if (bytes > 0 && text) {
488
489 /* read text message */
490
491 if (offset > (msgh->Hdr.TxtLen+msgh->lclen)) offset = msgh->Hdr.TxtLen+msgh->lclen;
492
493 msgh->cur_pos = offset;
494
495 if (offset >= msgh->Hdr.TxtLen) {
496 offset -= msgh->Hdr.TxtLen;
497 if (bytes > msgh->lclen) bytes = msgh->lclen;
498 if (offset < msgh->lclen) {
499 if (offset < bytes)
500 bytesread = bytes-offset;
501 else
502 bytesread = 0;
503 strncpy((char*)text, (char*)(msgh->lctrl+offset), bytesread);
504 } else {
505 } /* endif */
506 msgh->cur_pos += bytesread;
507 } else {
508 if (MsghJm->TxtHandle == 0) Jam_OpenTxtFile(MsghJm);
509 lseek(MsghJm->TxtHandle, msgh->Hdr.TxtOffset+offset, SEEK_SET);
510 if (bytes > msgh->Hdr.TxtLen-offset) {
511 bytesread = farread(MsghJm->TxtHandle, text, msgh->Hdr.TxtLen-offset);
512 bytes -= (msgh->Hdr.TxtLen-offset);
513 if (offset < bytes)
514 bytes -= offset;
515 else bytes = 0;
516 if (bytes > msgh->lclen) bytes = msgh->lclen;
517 strncpy((char*)(text+bytesread), (char*)(msgh->lctrl), bytes);
518 bytesread += bytes;
519 } else {
520 bytesread = farread(MsghJm->TxtHandle, text, bytes);
521 } /* endif */
522 msgh->cur_pos += bytesread;
523 } /* endif */
524 text[bytesread] = '\0';
525 }
526
527 if (clen && ctxt) {
528 /* read first kludges */
529 if (clen > msgh->clen) clen = msgh->clen;
530 strncpy((char*)(ctxt), (char*)(msgh->ctrl), clen);
531 ctxt[clen] = '\0';
532 }
533
534
535 msgapierr = MERR_NONE;
536 return bytesread;
537 }
538
JamWriteMsg(MSGH * msgh,word append,XMSG * msg,byte * text,dword textlen,dword totlen,dword clen,byte * ctxt)539 static sword _XPENTRY JamWriteMsg(MSGH * msgh, word append, XMSG * msg,
540 byte * text, dword textlen, dword totlen, dword clen, byte * ctxt)
541 {
542 /* not supported append if JAM !!!
543 the reason is that we need to know ALL of the text before we can set up
544 the JAM headers.
545 */
546
547 JAMHDR jamhdrNew;
548 JAMIDXREC jamidxNew;
549 JAMSUBFIELD2LISTptr subfieldNew;
550 XMSG msg_old;
551 MSGA *jm;
552 dword x = 0;
553
554 char ch = 0;
555 unsigned char *onlytext=NULL;
556 int didlock = FALSE;
557 sword rc = 0;
558
559 assert(append == 0);
560
561 if (InvalidMsgh(msgh)) {
562 return -1L;
563 }
564
565 if (msgh->mode != MOPEN_CREATE && msgh->mode != MOPEN_WRITE && msgh->mode != MOPEN_RW)
566 return -1L;
567
568 jm = msgh->sq;
569 Jmd->modified = 1;
570
571 memset(&jamidxNew, '\0', sizeof(JAMIDXREC));
572 memset(&jamhdrNew, '\0', sizeof(JAMHDR));
573
574 if (!ctxt)
575 clen = 0L;
576
577 if (!text)
578 textlen = 0L;
579
580 if (textlen == 0L)
581 text = NULL;
582
583 if (clen == 0L)
584 ctxt = NULL;
585
586 if (msgh->mode != MOPEN_CREATE)
587 {
588 if (clen) clen = 0;
589 if (ctxt) ctxt = NULL;
590 }
591
592 if (clen && ctxt)
593 {
594 x = strlen((char*)ctxt);
595 if (clen < x) clen = x+1;
596 }
597
598 subfieldNew = NULL;
599 if (msg)
600 ConvertXmsgToJamHdr(msgh, msg, &jamhdrNew, &subfieldNew);
601 else
602 if (msgh->mode != MOPEN_CREATE)
603 {
604 JamReadMsg(msgh, &msg_old, 0, 0, NULL, 0, NULL);
605 ConvertXmsgToJamHdr(msgh, &msg_old, &jamhdrNew, &subfieldNew);
606 }
607
608 if (!jm->locked) {
609 didlock = Jam_Lock(jm, 1);
610 if (didlock == 0) {
611 freejamsubfield(subfieldNew);
612 msgapierr = MERR_SHARE;
613 return -1;
614 }
615 }
616
617 jamhdrNew.ReplyCRC = jamhdrNew.MsgIdCRC = 0xFFFFFFFFUL;
618
619 if (clen && ctxt)
620 ConvertCtrlToSubf(&jamhdrNew, &subfieldNew, clen, ctxt);
621
622 if (textlen && text)
623 onlytext = DelimText(&jamhdrNew, &subfieldNew, text, textlen);
624 else
625 if (msgh->mode != MOPEN_CREATE)
626 {
627 DelimText(&jamhdrNew, &subfieldNew, msgh->lctrl, msgh->lclen);
628 jamhdrNew.TxtOffset = msgh->Hdr.TxtOffset;
629 jamhdrNew.TxtLen = msgh->Hdr.TxtLen;
630 }
631
632 if (onlytext==NULL) {
633 onlytext = calloc(1,1);
634 if (!onlytext) {
635 freejamsubfield(subfieldNew);
636 msgapierr = MERR_NOMEM;
637 return -1;
638 }
639 }
640
641 if (msgh->mode == MOPEN_CREATE)
642 {
643 /* no logic if msg not present */
644 if (msg)
645 {
646 if (Jmd->TxtHandle == 0) Jam_OpenTxtFile(Jmd);
647 if (msgh->msgnum == 0)
648 {
649 /* new message in end of position */
650 lseek(Jmd->IdxHandle, 0, SEEK_END);
651 lseek(Jmd->HdrHandle, 0, SEEK_END);
652 lseek(Jmd->TxtHandle, 0, SEEK_END);
653 jamhdrNew.MsgNum = Jmd->HdrInfo.BaseMsgNum+(tell(Jmd->IdxHandle)/IDX_SIZE);
654 msgh->seek_idx = tell(Jmd->IdxHandle);
655 msgh->seek_hdr = jamidxNew.HdrOffset = tell(Jmd->HdrHandle);
656 jamidxNew.UserCRC = Jam_Crc32(msg->to, strlen((char*)(msg->to)));
657 jamhdrNew.TxtOffset = tell(Jmd->TxtHandle);
658 jamhdrNew.TxtLen = strlen((char*)onlytext);
659 msgh->bytes_written = (dword) farwrite(Jmd->TxtHandle, onlytext, jamhdrNew.TxtLen);
660 if (msgh->bytes_written != jamhdrNew.TxtLen)
661 {
662 setfsize(Jmd->TxtHandle, jamhdrNew.TxtOffset);
663 freejamsubfield(subfieldNew);
664 msgapierr = MERR_NODS;
665 return -1;
666 }
667 msgh->cur_pos = tell(Jmd->TxtHandle);
668 if (!write_hdr(Jmd->HdrHandle, &jamhdrNew))
669 {
670 setfsize(Jmd->HdrHandle, msgh->seek_hdr);
671 setfsize(Jmd->TxtHandle, jamhdrNew.TxtOffset);
672 freejamsubfield(subfieldNew);
673 free(onlytext); onlytext=NULL;
674 msgapierr = MERR_NODS;
675 return -1;
676 }
677 if (!write_subfield(Jmd->HdrHandle, &subfieldNew, jamhdrNew.SubfieldLen))
678 {
679 setfsize(Jmd->HdrHandle, msgh->seek_hdr);
680 setfsize(Jmd->TxtHandle, jamhdrNew.TxtOffset);
681 freejamsubfield(subfieldNew);
682 free(onlytext);
683 msgapierr = MERR_NODS;
684 return -1;
685 }
686 if (!write_idx(Jmd->IdxHandle, &jamidxNew))
687 {
688 setfsize(Jmd->IdxHandle, msgh->seek_idx);
689 setfsize(Jmd->HdrHandle, msgh->seek_hdr);
690 setfsize(Jmd->TxtHandle, jamhdrNew.TxtOffset);
691 freejamsubfield(subfieldNew);
692 free(onlytext);
693 msgapierr = MERR_NODS;
694 return -1;
695 }
696 Jmd->HdrInfo.ActiveMsgs++;
697 #ifdef HARD_WRITE_HDR
698 Jmd->HdrInfo.ModCounter++;
699 if (Jam_WriteHdrInfo(Jmd))
700 {
701 setfsize(Jmd->HdrHandle, msgh->seek_hdr);
702 setfsize(Jmd->IdxHandle, msgh->seek_idx);
703 setfsize(Jmd->TxtHandle, jamhdrNew.TxtOffset);
704 freejamsubfield(subfieldNew);
705 free(onlytext);
706 msgapierr = MERR_NODS;
707 return -1;
708 }
709 #endif
710 jm->high_msg++;
711 if (Jmd->actmsg_read) {
712 Jmd->actmsg = (JAMACTMSGptr)farrealloc(Jmd->actmsg, sizeof(JAMACTMSG)*(jm->num_msg+1));
713 if(!Jmd->actmsg) {
714 freejamsubfield(subfieldNew);
715 free(onlytext);
716 msgapierr = MERR_NOMEM;
717 return -1;
718 }
719 Jmd->actmsg[jm->num_msg].IdxOffset = msgh->seek_idx;
720 Jmd->actmsg[jm->num_msg].TrueMsg = msgh->seek_hdr;
721 Jmd->actmsg[jm->num_msg].UserCRC = jamidxNew.UserCRC;
722 memcpy(&(Jmd->actmsg[jm->num_msg].hdr), &jamhdrNew, sizeof(jamhdrNew));
723 if (Jmd->actmsg_read == 1)
724 Jmd->actmsg[jm->num_msg].subfield = subfieldNew;
725 else { /* not incore subfields */
726 Jmd->actmsg[jm->num_msg].subfield = NULL;
727 freejamsubfield(subfieldNew);
728 }
729 } else
730 freejamsubfield(subfieldNew);
731 jm->num_msg++;
732 }
733 else
734 {
735 /* new message instead of old message position */
736 msgh->Hdr.TxtLen = 0;
737 msgh->Hdr.Attribute |= JMSG_DELETED;
738 lseek(Jmd->HdrHandle, 0, SEEK_END);
739 jamidxNew.HdrOffset = tell(Jmd->HdrHandle);
740 jamhdrNew.MsgNum = msgh->Hdr.MsgNum;
741 jamidxNew.UserCRC = Jam_Crc32(msg->to, strlen((char*)(msg->to)));
742 lseek(Jmd->TxtHandle, 0, SEEK_END);
743 jamhdrNew.TxtOffset = tell(Jmd->TxtHandle);
744 jamhdrNew.TxtLen = strlen((char*)onlytext);
745 msgh->bytes_written = (dword) farwrite(Jmd->TxtHandle, onlytext, jamhdrNew.TxtLen);
746 msgh->cur_pos = tell(Jmd->TxtHandle);
747 lseek(Jmd->TxtHandle, jamhdrNew.TxtOffset+totlen-1, SEEK_SET);
748 farwrite(Jmd->TxtHandle, &ch, 1);
749 write_hdr(Jmd->HdrHandle, &jamhdrNew);
750 write_subfield(Jmd->HdrHandle, &subfieldNew, jamhdrNew.SubfieldLen);
751 lseek(Jmd->IdxHandle, msgh->seek_idx, SEEK_SET);
752 write_idx(Jmd->IdxHandle, &jamidxNew);
753 lseek(Jmd->HdrHandle, msgh->seek_hdr, SEEK_SET);
754 write_hdr(Jmd->HdrHandle, &(msgh->Hdr));
755 msgh->seek_hdr = jamidxNew.HdrOffset;
756 #ifdef HARD_WRITE_HDR
757 Jmd->HdrInfo.ModCounter++;
758 Jam_WriteHdrInfo(Jmd);
759 #endif
760 /* info from new message to msgh srtuct */
761 if (Jmd->actmsg_read) {
762 Jmd->actmsg[msgh->msgnum - 1].TrueMsg = msgh->seek_hdr;
763 Jmd->actmsg[msgh->msgnum - 1].UserCRC = jamidxNew.UserCRC;
764 memcpy(&(Jmd->actmsg[msgh->msgnum-1].hdr), &jamhdrNew, sizeof(jamhdrNew));
765 if (Jmd->actmsg_read == 1)
766 Jmd->actmsg[msgh->msgnum - 1].subfield = subfieldNew;
767 else { /* subfields not incore */
768 Jmd->actmsg[msgh->msgnum - 1].subfield = NULL;
769 freejamsubfield(subfieldNew);
770 }
771 } else
772 freejamsubfield(subfieldNew);
773 } /* endif */
774 } /* endif */
775 }
776 else
777 {
778 /* change text and SEEN_BY, PATH, VIA kludges posible only (message != create)*/
779 ConvertCtrlToSubf(&jamhdrNew, &subfieldNew, msgh->clen, msgh->ctrl);
780
781 if (msg)
782 jamidxNew.UserCRC = Jam_Crc32(msg->to, strlen((char*)(msg->to)));
783 else
784 jamidxNew.UserCRC = msgh->Idx.UserCRC;
785
786 if (text && textlen) {
787 if (Jmd->TxtHandle == 0) Jam_OpenTxtFile(Jmd);
788 lseek(Jmd->TxtHandle, 0, SEEK_END);
789 jamhdrNew.TxtOffset = tell(Jmd->TxtHandle);
790 jamhdrNew.TxtLen = strlen((char*)onlytext);
791 farwrite(Jmd->TxtHandle, onlytext, jamhdrNew.TxtLen);
792 } /* endif */
793
794 if (jamhdrNew.SubfieldLen > msgh->Hdr.SubfieldLen)
795 {
796 msgh->Hdr.TxtLen = 0;
797 msgh->Hdr.Attribute |= JMSG_DELETED;
798 lseek(Jmd->HdrHandle, msgh->seek_hdr, SEEK_SET);
799 write_hdr(Jmd->HdrHandle, &(msgh->Hdr));
800 lseek(Jmd->HdrHandle, 0, SEEK_END);
801 msgh->seek_hdr = tell(Jmd->HdrHandle);
802 }
803
804 jamhdrNew.MsgNum = msgh->Hdr.MsgNum;
805 jamidxNew.HdrOffset = msgh->seek_hdr;
806
807 lseek(Jmd->HdrHandle, msgh->seek_hdr, SEEK_SET);
808 write_hdr(Jmd->HdrHandle, &jamhdrNew);
809 write_subfield(Jmd->HdrHandle, &subfieldNew, jamhdrNew.SubfieldLen);
810
811 if (Jmd->actmsg_read &&
812 Jmd->actmsg[msgh->msgnum - 1].TrueMsg == msgh->seek_hdr &&
813 Jmd->actmsg[msgh->msgnum - 1].UserCRC == jamidxNew.UserCRC) {
814 /* no index update needed */ ;
815 } else {
816 lseek(Jmd->IdxHandle, msgh->seek_idx, SEEK_SET);
817 write_idx(Jmd->IdxHandle, &jamidxNew);
818 }
819
820 #ifdef HARD_WRITE_HDR
821 Jmd->HdrInfo.ModCounter++;
822 Jam_WriteHdrInfo(Jmd);
823 #endif
824 memmove(&(msgh->Idx), &(jamidxNew), sizeof(JAMIDXREC));
825 memmove(&(msgh->Hdr), &(jamhdrNew), sizeof(JAMHDR));
826 freejamsubfield(msgh->SubFieldPtr);
827 msgh->SubFieldPtr = subfieldNew;
828 pfree(msgh->ctrl);
829 pfree(msgh->lctrl);
830 DecodeSubf(msgh);
831 if (Jmd->actmsg_read) {
832 Jmd->actmsg[msgh->msgnum - 1].TrueMsg = msgh->seek_hdr;
833 Jmd->actmsg[msgh->msgnum - 1].UserCRC = jamidxNew.UserCRC;
834 memcpy(&(Jmd->actmsg[msgh->msgnum - 1].hdr), &jamhdrNew, sizeof(jamhdrNew));
835 freejamsubfield(Jmd->actmsg[msgh->msgnum - 1].subfield);
836 if (Jmd->actmsg_read == 1)
837 copy_subfield(&(Jmd->actmsg[msgh->msgnum - 1].subfield), subfieldNew);
838 else
839 Jmd->actmsg[msgh->msgnum - 1].subfield = NULL;
840 }
841
842 } /* endif */
843 if (didlock) {
844 Jam_Unlock(jm);
845 } /* endif */
846
847 pfree(onlytext);
848
849 return rc;
850 }
851
852
JamKillMsg(MSGA * jm,dword msgnum)853 static sword _XPENTRY JamKillMsg(MSGA * jm, dword msgnum)
854 {
855 JAMIDXREC jamidx;
856 JAMHDR jamhdr;
857
858 if (InvalidMh(jm)) {
859 return -1;
860 }
861
862 if (jm->locked) return -1L;
863
864 if (msgnum == 0 || msgnum > jm->num_msg) {
865 msgapierr = MERR_NOENT;
866 return -1L;
867 } /* endif */
868
869 if (!Jam_PosHdrMsg(jm, msgnum, &jamidx, &jamhdr)) {
870 msgapierr = MERR_BADF;
871 return -1L;
872 } /* endif */
873
874 if (JamLock(jm) == -1) return -1L;
875
876 lseek(Jmd->HdrHandle, jamidx.HdrOffset, SEEK_SET);
877 /*lseek(Jmd->IdxHandle, (IDX_SIZE)*(msgnum - 1), SEEK_SET);*/
878 lseek(Jmd->IdxHandle, Jmd->actmsg[msgnum - 1].IdxOffset, SEEK_SET); /* can be buggy! */
879
880 Jmd->modified = 1;
881 Jmd->HdrInfo.ActiveMsgs--;
882 jamhdr.TxtLen = 0;
883 jamhdr.Attribute |= JMSG_DELETED;
884 jamidx.UserCRC = 0xFFFFFFFFL;
885 jamidx.HdrOffset = 0xFFFFFFFFL;
886 /*
887 lseek(Jmd->HdrHandle, -(HDR_SIZE), SEEK_CUR);
888 lseek(Jmd->IdxHandle, -(IDX_SIZE), SEEK_CUR);
889 */
890 write_idx(Jmd->IdxHandle, &jamidx);
891 write_hdr(Jmd->HdrHandle, &jamhdr);
892 #ifdef HARD_WRITE_HDR
893 Jmd->HdrInfo.ModCounter++;
894 Jam_WriteHdrInfo(Jmd);
895 #endif
896
897 if (Jmd->actmsg_read) {
898 dword i;
899 for (i=0; i<Jmd->HdrInfo.ActiveMsgs; i++)
900 freejamsubfield(Jmd->actmsg[i].subfield);
901 pfree(Jmd->actmsg);
902 Jmd->actmsg_read = 0;
903 Jmd->actmsg = NULL;
904 }
905
906 Jam_ActiveMsgs(jm);
907 jm->num_msg = Jmd->HdrInfo.ActiveMsgs;
908
909 JamUnlock(jm);
910 return 0;
911 }
912
JamLock(MSGA * jm)913 static sword _XPENTRY JamLock(MSGA * jm)
914 {
915 if (InvalidMh(jm)) {
916 return -1;
917 }
918
919 /* Don't do anything if already locked */
920
921 if (jm->locked) {
922 return 0;
923 }
924
925 if (!Jam_Lock(jm, 0))
926 return -1;
927
928 jm->locked = TRUE;
929
930 return 0;
931 }
932
JamUnlock(MSGA * jm)933 static sword _XPENTRY JamUnlock(MSGA * jm)
934 {
935 if (InvalidMh(jm)) {
936 return -1;
937 }
938
939 if (!jm->locked) {
940 return -1;
941 }
942
943 jm->locked = FALSE;
944
945 if (mi.haveshare) {
946 unlock(Jmd->HdrHandle, 0L, 1L);
947 }
948
949 return 0;
950 }
951
JamSetCurPos(MSGH * msgh,dword pos)952 static sword _XPENTRY JamSetCurPos(MSGH * msgh, dword pos)
953 {
954 if (InvalidMsgh(msgh))
955 return -1;
956
957 msgh->cur_pos = pos;
958 return 0;
959 }
960
JamGetCurPos(MSGH * msgh)961 static dword _XPENTRY JamGetCurPos(MSGH * msgh)
962 {
963 if (InvalidMsgh(msgh))
964 return (dword)-1;
965
966 return msgh->cur_pos;
967 }
968
JamMsgnToUid(MSGA * jm,dword msgnum)969 static UMSGID _XPENTRY JamMsgnToUid(MSGA * jm, dword msgnum)
970 {
971 if (InvalidMh(jm))
972 return (UMSGID) -1;
973
974 msgapierr = MERR_NONE;
975 if (msgnum > jm->num_msg) return (UMSGID) -1;
976 if (msgnum <= 0) return (UMSGID) 0;
977 if (!Jmd->actmsg_read) {
978 Jam_ActiveMsgs(jm);
979 if (msgnum > jm->num_msg) return (UMSGID) -1;
980 }
981 return (UMSGID) (Jmd->actmsg[msgnum - 1].IdxOffset / 8 + Jmd->HdrInfo.BaseMsgNum);
982 }
983
JamUidToMsgn(MSGA * jm,UMSGID umsgid,word type)984 static dword _XPENTRY JamUidToMsgn(MSGA * jm, UMSGID umsgid, word type)
985 {
986 dword msgnum, left, right, current;
987 UMSGID umsg;
988
989 if (InvalidMh(jm))
990 return (dword)-1L;
991
992 msgnum = umsgid - Jmd->HdrInfo.BaseMsgNum + 1;
993 if (msgnum <= 0)
994 return 0;
995 if (!Jmd->actmsg_read) Jam_ActiveMsgs(jm);
996 left = 1;
997 right = jm->num_msg;
998 while (left <= right)
999 {
1000 current = (right + left) / 2;
1001 umsg = JamMsgnToUid(jm, current);
1002 if (umsg == (UMSGID)-1)
1003 return 0;
1004 if (umsg < msgnum)
1005 left = current + 1;
1006 else if (umsg > msgnum){
1007 if( current > 0 ) right = current - 1;
1008 else right = 0;
1009 }else
1010 return current;
1011 }
1012 if (type == UID_EXACT) return 0;
1013 if (type == UID_PREV)
1014 return right;
1015 return (left > jm->num_msg) ? jm->num_msg : left;
1016 }
1017
JamGetHighWater(MSGA * jm)1018 static dword _XPENTRY JamGetHighWater(MSGA * jm)
1019 {
1020 if (InvalidMh(jm))
1021 return (dword)-1L;
1022
1023 return JamUidToMsgn(jm, jm->high_water, UID_PREV);
1024 }
1025
JamSetHighWater(MSGA * jm,dword hwm)1026 static sword _XPENTRY JamSetHighWater(MSGA * jm, dword hwm)
1027 {
1028 if (InvalidMh(jm))
1029 return -1L;
1030
1031 hwm = JamMsgnToUid(jm, hwm);
1032 if (hwm > jm->high_msg + Jmd->HdrInfo.BaseMsgNum) return -1L;
1033
1034 jm->high_water = hwm;
1035
1036 return 0;
1037 }
1038
JamGetTextLen(MSGH * msgh)1039 static dword _XPENTRY JamGetTextLen(MSGH * msgh)
1040 {
1041 if( InvalidMsgh(msgh) )
1042 return (dword)0L;
1043 return (msgh->Hdr.TxtLen+msgh->lclen);
1044 }
1045
JamGetCtrlLen(MSGH * msgh)1046 static dword _XPENTRY JamGetCtrlLen(MSGH * msgh)
1047 {
1048 if( InvalidMsgh(msgh) )
1049 return (dword)0L;
1050 return (msgh->clen);
1051 }
1052
1053
JamValidate(byte * name)1054 sword MSGAPI JamValidate(byte * name)
1055 {
1056 byte temp[PATHLEN];
1057
1058 if(!name || !*name) return FALSE;
1059
1060 sprintf((char *) temp, "%s%s", name, EXT_HDRFILE);
1061
1062 if (!fexist((char *) temp))
1063 return FALSE;
1064
1065 sprintf((char *) temp, "%s%s", name, EXT_TXTFILE);
1066
1067 if (!fexist((char *) temp))
1068 return FALSE;
1069
1070 sprintf((char *) temp, "%s%s", name, EXT_IDXFILE);
1071
1072 if (!fexist((char *) temp))
1073 return FALSE;
1074
1075 return TRUE;
1076 }
1077
Jam_CloseFile(JAMBASE * jambase)1078 void Jam_CloseFile(JAMBASE *jambase)
1079 {
1080 if(!jambase)
1081 { errno = EINVAL;
1082 msgapierr = MERR_BADA;
1083 return;
1084 }
1085
1086 if (jambase->HdrHandle != 0 && jambase->HdrHandle != -1) {
1087 close(jambase->HdrHandle);
1088 jambase->HdrHandle = 0;
1089 } /* endif */
1090
1091 if (jambase->TxtHandle != 0 && jambase->TxtHandle != -1) {
1092 close(jambase->TxtHandle);
1093 jambase->TxtHandle = 0;
1094 } /* endif */
1095
1096 if (jambase->IdxHandle != 0 && jambase->IdxHandle != -1) {
1097 close(jambase->IdxHandle);
1098 jambase->IdxHandle = 0;
1099 } /* endif */
1100
1101 if (jambase->LrdHandle != 0 && jambase->LrdHandle != -1) {
1102 close(jambase->LrdHandle);
1103 jambase->LrdHandle = 0;
1104 } /* endif */
1105 }
1106
1107 /* Return values:
1108 * 0 = error
1109 * 1 = success
1110 */
JamDeleteBase(char * name)1111 int JamDeleteBase(char *name)
1112 {
1113 char *fn=NULL;
1114 int rc = 1;
1115
1116 if( !name || !*name )
1117 { errno = EINVAL;
1118 msgapierr = MERR_BADNAME;
1119 return 0;
1120 }
1121
1122 fn = palloc( strlen(name)+5 );
1123 if( !fn )
1124 { errno = ENOMEM;
1125 msgapierr = MERR_NOMEM;
1126 return 0;
1127 }
1128
1129 sprintf(fn, "%s%s", name, EXT_HDRFILE);
1130 if (unlink(fn)) rc=0; /* error */
1131 sprintf(fn, "%s%s", name, EXT_TXTFILE);
1132 if (unlink(fn)) rc=0; /* error */
1133 sprintf(fn, "%s%s", name, EXT_IDXFILE);
1134 if (unlink(fn)) rc=0; /* error */
1135 sprintf(fn, "%s%s", name, EXT_LRDFILE);
1136 if (unlink(fn) && errno!=ENOENT) rc=0; /* error */
1137
1138 pfree(fn);
1139 return rc;
1140 }
1141
1142 /* Return values:
1143 * 0 = error
1144 * 1 = success
1145 */
Jam_OpenFile(JAMBASE * jambase,word * mode,mode_t permissions)1146 int Jam_OpenFile(JAMBASE *jambase, word *mode, mode_t permissions)
1147 {
1148 char *hdr=NULL, *idx=NULL, *txt=NULL, *lrd=NULL;
1149 int x;
1150
1151 if(!jambase || !mode)
1152 {
1153 msgapierr = MERR_BADA;
1154 return 0;
1155 }
1156
1157 x = strlen((char*)(jambase->BaseName))+5;
1158
1159 hdr = (char*) palloc(x);
1160 idx = (char*) palloc(x);
1161 txt = (char*) palloc(x);
1162 /* lrd = (char*) palloc(x);*/
1163
1164 if( !(hdr && idx && txt /*&& lrd*/) )
1165 {
1166 pfree(hdr);
1167 pfree(idx);
1168 pfree(txt);
1169 pfree(lrd);
1170 errno = ENOMEM;
1171 msgapierr = MERR_NOMEM;
1172 return 0;
1173 }
1174
1175 sprintf(hdr, "%s%s", jambase->BaseName, EXT_HDRFILE);
1176 sprintf(txt, "%s%s", jambase->BaseName, EXT_TXTFILE);
1177 sprintf(idx, "%s%s", jambase->BaseName, EXT_IDXFILE);
1178 /* sprintf(lrd, "%s%s", jambase->BaseName, EXT_LRDFILE);*/
1179
1180 if (*mode == MSGAREA_CREATE) {
1181 jambase->HdrHandle = opencreatefilejm(hdr, fop_wpb, permissions);
1182 jambase->TxtHandle = openfilejm(txt, fop_wpb, permissions);
1183 jambase->IdxHandle = openfilejm(idx, fop_wpb, permissions);
1184 /* jambase->LrdHandle = openfilejm(lrd, fop_wpb, permissions);
1185 */ jambase->LrdHandle = 0;
1186
1187 memset(&(jambase->HdrInfo), '\0', sizeof(JAMHDRINFO));
1188 strcpy((char*)(jambase->HdrInfo.Signature), HEADERSIGNATURE);
1189
1190 jambase->HdrInfo.DateCreated = time(NULL) + gettz();
1191 jambase->HdrInfo.ModCounter = 1;
1192 jambase->HdrInfo.PasswordCRC = 0xffffffffUL;
1193 jambase->HdrInfo.BaseMsgNum = 1;
1194
1195 write_hdrinfo(jambase->HdrHandle, &(jambase->HdrInfo));
1196
1197 } else {
1198 jambase->HdrHandle = openfilejm(hdr, fop_rpb, permissions);
1199 /* jambase->TxtHandle = openfilejm(txt, fop_rpb, permissions);
1200 */ jambase->TxtHandle = 0;
1201 jambase->IdxHandle = openfilejm(idx, fop_rpb, permissions);
1202 /* jambase->LrdHandle = openfilejm(lrd, fop_rpb, permissions);
1203 */ jambase->LrdHandle = 0;
1204 } /* endif */
1205
1206 if (jambase->HdrHandle == -1 || jambase->TxtHandle == -1 || jambase->IdxHandle == -1) {
1207 if (*mode != MSGAREA_CRIFNEC) {
1208 Jam_CloseFile(jambase);
1209 pfree(hdr);
1210 pfree(txt);
1211 pfree(idx);
1212 pfree(lrd);
1213 msgapierr = MERR_NOENT;
1214 return 0;
1215 }
1216 *mode = MSGAREA_CREATE;
1217 jambase->HdrHandle = opencreatefilejm(hdr, fop_cpb, permissions);
1218 jambase->TxtHandle = openfilejm(txt, fop_cpb, permissions);
1219 jambase->IdxHandle = openfilejm(idx, fop_cpb, permissions);
1220 /* jambase->LrdHandle = openfilejm(lrd, fop_cpb, permissions);
1221 */ jambase->LrdHandle = 0;
1222
1223 if (jambase->HdrHandle == -1 || jambase->TxtHandle == -1 || jambase->IdxHandle == -1) {
1224 Jam_CloseFile(jambase);
1225 pfree(hdr);
1226 pfree(txt);
1227 pfree(idx);
1228 pfree(lrd);
1229 msgapierr = MERR_NOENT;
1230 return 0;
1231 } /* endif */
1232
1233
1234 memset(&(jambase->HdrInfo), '\0', sizeof(JAMHDRINFO));
1235 strcpy((char*)(jambase->HdrInfo.Signature), HEADERSIGNATURE);
1236 jambase->HdrInfo.DateCreated = time(NULL) + gettz();
1237 jambase->HdrInfo.ModCounter = 1;
1238 jambase->HdrInfo.PasswordCRC = 0xffffffffUL;
1239 jambase->HdrInfo.BaseMsgNum = 1;
1240
1241 write_hdrinfo(jambase->HdrHandle, &(jambase->HdrInfo));
1242
1243 } /* endif */
1244
1245 pfree(hdr);
1246 pfree(txt);
1247 pfree(idx);
1248 pfree(lrd);
1249
1250 jambase->mode = *mode;
1251 jambase->permissions = permissions;
1252 jambase->modified = 0;
1253
1254 return 1;
1255 }
1256
1257 /* Return values:
1258 * 0 = error
1259 * 1 = success
1260 */
Jam_OpenBase(MSGA * jm,word * mode,unsigned char * basename)1261 static sword MSGAPI Jam_OpenBase(MSGA *jm, word *mode, unsigned char *basename)
1262 {
1263 if( InvalidMh(jm) || !mode)
1264 {
1265 msgapierr = MERR_BADA;
1266 return 0;
1267 }
1268 if( !basename || !*basename )
1269 {
1270 msgapierr = MERR_BADNAME;
1271 return 0;
1272 }
1273
1274 Jmd->BaseName = (unsigned char*)palloc(strlen((char*)basename)+1);
1275 if( !Jmd->BaseName ) {
1276 errno = ENOMEM;
1277 msgapierr = MERR_NOMEM;
1278 return 0;
1279 }
1280 strcpy((char*)(Jmd->BaseName), (char*)basename);
1281
1282 if (!Jam_OpenFile(Jmd, mode, FILEMODE(jm->isecho))) {
1283 /* Jam_OpenFile() set MSGAPIERR */
1284 pfree(Jmd->BaseName);
1285 return 0;
1286 } /* endif */
1287
1288 Jmd->jm = jm;
1289
1290 Jmd->jbNext = jbOpen;
1291 jbOpen = Jmd;
1292
1293 lseek(Jmd->HdrHandle, 0, SEEK_SET);
1294 read_hdrinfo(Jmd->HdrHandle, &(Jmd->HdrInfo));
1295
1296 return 1;
1297 }
1298
1299 /* Return values:
1300 * 0 = error
1301 * 1 = success
1302 */
Jam_OpenMsg(MSGA * jm,word mode,dword msgnum)1303 static MSGH *Jam_OpenMsg(MSGA * jm, word mode, dword msgnum)
1304 {
1305 struct _msgh *msgh;
1306 /* JAMIDXREC idx; */
1307 /* JAMHDR hdr; */
1308
1309 unused(mode);
1310
1311 if( InvalidMh(jm) )
1312 return NULL;
1313
1314 if (msgnum == MSGNUM_CUR) {
1315 msgnum = jm->cur_msg;
1316 } else if (msgnum == MSGNUM_NEXT) {
1317 msgnum = jm->cur_msg+1;
1318 if (msgnum > jm->num_msg) {
1319 msgapierr = MERR_NOENT;
1320 return NULL;
1321 } /* endif */
1322 jm->cur_msg = msgnum;
1323 } else if (msgnum == MSGNUM_PREV) {
1324 msgnum = jm->cur_msg-1;
1325 if (msgnum == 0) {
1326 msgapierr = MERR_NOENT;
1327 return NULL;
1328 } /* endif */
1329 jm->cur_msg = msgnum;
1330 } else {
1331 if (msgnum > jm->num_msg) {
1332 msgapierr = MERR_NOENT;
1333 return NULL;
1334 } /* endif */
1335 }
1336
1337 msgh = palloc(sizeof(struct _msgh));
1338 if (msgh == NULL) {
1339 msgapierr = MERR_NOMEM;
1340 return NULL;
1341 }
1342
1343 memset(msgh, '\0', sizeof(struct _msgh));
1344
1345 msgh->sq = jm;
1346 msgh->msgnum = msgnum;
1347
1348 msgh->mode = mode;
1349 msgh->id = MSGH_ID;
1350
1351 /* msgh->Idx.HdrOffset = 0xffffffff; */
1352 /* msgh->Idx.UserCRC = 0xffffffff; */
1353
1354 if (!Jmd->actmsg_read) {
1355 Jam_ActiveMsgs(jm);
1356 if (msgnum > jm->num_msg) {
1357 msgapierr = MERR_NOENT;
1358 return NULL;
1359 }
1360 }
1361
1362 if (Jmd->actmsg) {
1363 msgh->seek_idx = Jmd->actmsg[msgnum-1].IdxOffset;
1364 msgh->Idx.HdrOffset = Jmd->actmsg[msgnum-1].TrueMsg;
1365 msgh->Idx.UserCRC = Jmd->actmsg[msgnum-1].UserCRC;
1366 if (msgh->Idx.HdrOffset != 0xffffffffUL) {
1367 msgh->seek_hdr = msgh->Idx.HdrOffset;
1368 memcpy(&(msgh->Hdr), &(Jmd->actmsg[msgnum-1].hdr), sizeof(msgh->Hdr));
1369 if (sstricmp((char*)&msgh->Hdr, "JAM") != 0) {
1370 pfree(msgh);
1371 return NULL;
1372 } else {
1373 } /* endif */
1374 if (mode == MOPEN_CREATE) return (MSGH *)msgh;
1375
1376 msgh->SubFieldPtr = 0;
1377
1378 if (Jmd->actmsg[msgnum-1].subfield)
1379 copy_subfield(&(msgh->SubFieldPtr), Jmd->actmsg[msgnum-1].subfield);
1380 else {
1381 lseek(Jmd->HdrHandle, Jmd->actmsg[msgnum-1].TrueMsg+HDR_SIZE, SEEK_SET);
1382 read_subfield(Jmd->HdrHandle, &(msgh->SubFieldPtr), &(Jmd->actmsg[msgnum-1].hdr.SubfieldLen));
1383 }
1384 DecodeSubf(msgh);
1385 return (MSGH *) msgh;
1386 }
1387 }
1388
1389 pfree(msgh);
1390 return NULL;
1391 }
1392
Jam_GetSubField(MSGH * msgh,dword * SubPos,word what)1393 JAMSUBFIELD2ptr Jam_GetSubField( MSGH *msgh, dword *SubPos, word what)
1394 {
1395 JAMSUBFIELD2ptr SubField;
1396 JAMSUBFIELD2LISTptr SubFieldList;
1397 dword i;
1398
1399 if( InvalidMsgh(msgh) )
1400 {
1401 msgapierr = MERR_BADA;
1402 return 0;
1403 }
1404
1405 SubFieldList = msgh->SubFieldPtr;
1406 SubField = msgh->SubFieldPtr->subfield;
1407 for (i=*SubPos; i<SubFieldList->subfieldCount; i++, SubField++) {
1408 if (SubField->LoID == what) {
1409 *SubPos = i;
1410 return SubField;
1411 }
1412 }
1413
1414 return NULL;
1415 }
1416
Jam_GetKludge(MSGA * jm,dword msgnum,word what)1417 char *Jam_GetKludge(MSGA *jm, dword msgnum, word what)
1418 {
1419 JAMSUBFIELD2LISTptr subf;
1420 JAMSUBFIELD2ptr subfptr;
1421 dword i;
1422 char *res;
1423
1424 if( InvalidMh(jm) )
1425 return NULL;
1426
1427 if (msgnum == MSGNUM_CUR) {
1428 msgnum = jm->cur_msg;
1429 } else if (msgnum == MSGNUM_NEXT) {
1430 msgnum = jm->cur_msg+1;
1431 if (msgnum > jm->num_msg) {
1432 msgapierr = MERR_NOENT;
1433 return NULL;
1434 } /* endif */
1435 jm->cur_msg = msgnum;
1436 } else if (msgnum == MSGNUM_PREV) {
1437 msgnum = jm->cur_msg-1;
1438 if (msgnum == 0) {
1439 msgapierr = MERR_NOENT;
1440 return NULL;
1441 } /* endif */
1442 jm->cur_msg = msgnum;
1443 } else {
1444 if (msgnum > jm->num_msg) {
1445 msgapierr = MERR_NOENT;
1446 return NULL;
1447 } /* endif */
1448 }
1449
1450 if (!Jmd->actmsg_read) {
1451 Jam_ActiveMsgs(jm);
1452 if (msgnum > jm->num_msg) {
1453 msgapierr = MERR_NOENT;
1454 return NULL;
1455 }
1456 }
1457
1458 if (!Jmd->actmsg)
1459 return NULL;
1460 subf = Jmd->actmsg[msgnum-1].subfield;
1461 if (subf == NULL) {
1462 lseek(Jmd->HdrHandle, Jmd->actmsg[msgnum-1].TrueMsg+HDR_SIZE, SEEK_SET);
1463 read_subfield(Jmd->HdrHandle, &subf, &(Jmd->actmsg[msgnum-1].hdr.SubfieldLen));
1464 }
1465 for (i=0, subfptr = subf->subfield; i<subf->subfieldCount; i++, subfptr++)
1466 if (subfptr->LoID == what) {
1467 res = palloc(subfptr->DatLen + 1);
1468 if (res == NULL) {
1469 if (Jmd->actmsg[msgnum-1].subfield == NULL) pfree(subf);
1470 msgapierr = MERR_NOMEM;
1471 return NULL;
1472 }
1473 memcpy(res, subfptr->Buffer, subfptr->DatLen);
1474 res[subfptr->DatLen] = '\0';
1475 if (Jmd->actmsg[msgnum-1].subfield == NULL) pfree(subf);
1476 return res;
1477 }
1478
1479 if (Jmd->actmsg[msgnum-1].subfield == NULL) pfree(subf);
1480 return NULL;
1481 }
1482
Jam_GetHdr(MSGA * jm,dword msgnum)1483 JAMHDR *Jam_GetHdr(MSGA *jm, dword msgnum)
1484 {
1485 if( InvalidMh(jm) )
1486 return NULL;
1487
1488 msgapierr = MERR_NONE;
1489 if (msgnum == MSGNUM_CUR) {
1490 msgnum = jm->cur_msg;
1491 } else if (msgnum == MSGNUM_NEXT) {
1492 msgnum = jm->cur_msg+1;
1493 if (msgnum > jm->num_msg) {
1494 msgapierr = MERR_NOENT;
1495 return NULL;
1496 } /* endif */
1497 jm->cur_msg = msgnum;
1498 } else if (msgnum == MSGNUM_PREV) {
1499 msgnum = jm->cur_msg-1;
1500 if (msgnum == 0) {
1501 msgapierr = MERR_NOENT;
1502 return NULL;
1503 } /* endif */
1504 jm->cur_msg = msgnum;
1505 } else {
1506 if (msgnum > jm->num_msg) {
1507 msgapierr = MERR_NOENT;
1508 return NULL;
1509 } /* endif */
1510 }
1511
1512 if (!Jmd->actmsg_read) {
1513 Jam_ActiveMsgs(jm);
1514 if (msgnum > jm->num_msg) {
1515 msgapierr = MERR_NOENT;
1516 return NULL;
1517 }
1518 }
1519
1520 if (!Jmd->actmsg)
1521 return NULL;
1522
1523 return &(Jmd->actmsg[msgnum-1].hdr);
1524 }
1525
Jam_WriteHdr(MSGA * jm,JAMHDR * jamhdr,dword msgnum)1526 void Jam_WriteHdr(MSGA *jm, JAMHDR *jamhdr, dword msgnum)
1527 {
1528 if( InvalidMh(jm) || !jamhdr )
1529 {
1530 msgapierr = MERR_BADA;
1531 return;
1532 }
1533 msgapierr = MERR_NONE;
1534
1535 if (!Jmd->actmsg_read) Jam_ActiveMsgs(jm);
1536
1537 if (!Jmd->actmsg)
1538 return;
1539
1540 memcpy(&(Jmd->actmsg[msgnum-1].hdr), jamhdr, sizeof(JAMHDR));
1541 lseek(Jmd->HdrHandle, Jmd->actmsg[msgnum-1].TrueMsg, SEEK_SET);
1542 write_hdr(Jmd->HdrHandle, jamhdr);
1543 }
1544
Jam_HighMsg(JAMBASEptr jambase)1545 dword Jam_HighMsg(JAMBASEptr jambase)
1546 {
1547 dword highmsg;
1548
1549 if( !jambase )
1550 {
1551 msgapierr = MERR_BADA;
1552 return 0;
1553 }
1554 msgapierr = MERR_NONE;
1555
1556 lseek(jambase->IdxHandle, 0, SEEK_END);
1557 highmsg = tell(jambase->IdxHandle);
1558 return (highmsg / IDX_SIZE);
1559 }
1560
Jam_ActiveMsgs(MSGA * jm)1561 void Jam_ActiveMsgs(MSGA *jm)
1562 {
1563 if( InvalidMh(jm) )
1564 {
1565 msgapierr = MERR_BADA;
1566 return;
1567 }
1568 msgapierr = MERR_NONE;
1569
1570 read_allidx(Jmd);
1571 jm->num_msg = Jmd->HdrInfo.ActiveMsgs;
1572 }
1573
Jam_PosHdrMsg(MSGA * jm,dword msgnum,JAMIDXREC * jamidx,JAMHDR * jamhdr)1574 dword Jam_PosHdrMsg(MSGA * jm, dword msgnum, JAMIDXREC *jamidx, JAMHDR *jamhdr)
1575 {
1576
1577 if( InvalidMh(jm) ) return 0;
1578 if( !jamidx )
1579 {
1580 msgapierr = MERR_BADA;
1581 return 0;
1582 }
1583 msgapierr = MERR_NONE;
1584
1585 if (!Jmd->actmsg_read) Jam_ActiveMsgs(jm);
1586
1587 jamidx->HdrOffset = Jmd->actmsg[msgnum-1].TrueMsg;
1588
1589 if (jamidx->HdrOffset == 0xffffffffUL) return 0;
1590
1591 if (lseek(Jmd->HdrHandle, jamidx->HdrOffset, SEEK_SET) == -1) return 0;
1592
1593 if (read_hdr(Jmd->HdrHandle, jamhdr) == 0) return 0;
1594
1595 if (jamhdr->Attribute & JMSG_DELETED) return 0;
1596
1597 return 1;
1598 }
1599
1600
Jam_Lock(MSGA * jm,int force)1601 static int near Jam_Lock(MSGA *jm, int force)
1602 {
1603 return !(mi.haveshare && ((force) ? waitlock(Jmd->HdrHandle, 0L, 1L)
1604 : lock(Jmd->HdrHandle, 0L, 1L) == -1));
1605 }
1606
Jam_Unlock(MSGA * jm)1607 static void near Jam_Unlock(MSGA * jm)
1608 {
1609 if (mi.haveshare)
1610 {
1611 unlock(Jmd->HdrHandle, 0L, 1L);
1612 }
1613 }
1614
Jam_WriteHdrInfo(JAMBASEptr jambase)1615 sword Jam_WriteHdrInfo(JAMBASEptr jambase)
1616 {
1617 if( !jambase )
1618 {
1619 msgapierr = MERR_BADA;
1620 return -1;
1621 }
1622
1623 msgapierr = MERR_NONE;
1624 if (lseek(jambase->HdrHandle, 0, SEEK_SET) == -1) return -1;
1625 if (write_hdrinfo(jambase->HdrHandle, &(jambase->HdrInfo)) == 0) return -1;
1626 jambase->modified = 0;
1627 return 0;
1628 }
1629
Jam_JamAttrToMsg(MSGH * msgh)1630 static dword Jam_JamAttrToMsg(MSGH *msgh)
1631 {
1632 dword attr = 0;
1633
1634 if( InvalidMsgh(msgh) )
1635 {
1636 msgapierr = MERR_BADA;
1637 return 0;
1638 }
1639
1640 if (msgh->Hdr.Attribute & JMSG_LOCAL) attr |= MSGLOCAL;
1641 if (msgh->Hdr.Attribute & JMSG_PRIVATE) attr |= MSGPRIVATE;
1642 if (msgh->Hdr.Attribute & JMSG_READ) attr |= MSGREAD;
1643 if (msgh->Hdr.Attribute & JMSG_SENT) attr |= MSGSENT;
1644 if (msgh->Hdr.Attribute & JMSG_KILLSENT) attr |= MSGKILL;
1645 if (msgh->Hdr.Attribute & JMSG_HOLD) attr |= MSGHOLD;
1646 if (msgh->Hdr.Attribute & JMSG_CRASH) attr |= MSGCRASH;
1647 if (msgh->Hdr.Attribute & JMSG_FILEREQUEST) attr |= MSGFRQ;
1648 if (msgh->Hdr.Attribute & JMSG_FILEATTACH) attr |= MSGFILE;
1649 if (msgh->Hdr.Attribute & JMSG_INTRANSIT) attr |= MSGFWD;
1650 if (msgh->Hdr.Attribute & JMSG_RECEIPTREQ) attr |= MSGRRQ;
1651 if (msgh->Hdr.Attribute & JMSG_ORPHAN) attr |= MSGORPHAN;
1652 if (msgh->Hdr.Attribute & JMSG_CONFIRMREQ) attr |= MSGCPT;
1653 if (msgh->Hdr.Attribute & JMSG_LOCKED) attr |= MSGLOCKED;
1654 if (msgh->Hdr.Attribute & JMSG_DIRECT) attr |= MSGXX2;
1655 if (msgh->Hdr.Attribute & JMSG_IMMEDIATE) attr |= MSGIMM;
1656 if (msgh->Hdr.Attribute2 & 0x00000800L) attr |= MSGREADTMR;
1657
1658 return attr;
1659 }
1660
Jam_MsgAttrToJam(XMSG * msg)1661 static dword Jam_MsgAttrToJam(XMSG *msg)
1662 {
1663 dword attr = 0;
1664
1665 if( InvalidMsg(msg) )
1666 return 0;
1667
1668 if (msg->attr & MSGLOCAL) attr |= JMSG_LOCAL;
1669 if (msg->attr & MSGPRIVATE) attr |= JMSG_PRIVATE;
1670 if (msg->attr & MSGREAD) attr |= JMSG_READ;
1671 if (msg->attr & MSGSENT) attr |= JMSG_SENT;
1672 if (msg->attr & MSGKILL) attr |= JMSG_KILLSENT;
1673 if (msg->attr & MSGHOLD) attr |= JMSG_HOLD;
1674 if (msg->attr & MSGCRASH) attr |= JMSG_CRASH;
1675 if (msg->attr & MSGFRQ) attr |= JMSG_FILEREQUEST;
1676 if (msg->attr & MSGFILE) attr |= JMSG_FILEATTACH;
1677 if (msg->attr & MSGFWD) attr |= JMSG_INTRANSIT;
1678 if (msg->attr & MSGRRQ) attr |= JMSG_RECEIPTREQ;
1679 if (msg->attr & MSGORPHAN) attr |= JMSG_ORPHAN;
1680 if (msg->attr & MSGCPT) attr |= JMSG_CONFIRMREQ;
1681 if (msg->attr & MSGLOCKED) attr |= JMSG_LOCKED;
1682 if (msg->attr & MSGXX2) attr |= JMSG_DIRECT;
1683 if (msg->attr & MSGIMM) attr |= JMSG_IMMEDIATE;
1684
1685 return attr;
1686 }
1687
Jam_MsgAttr2ToJam(XMSG * msg)1688 static dword Jam_MsgAttr2ToJam(XMSG *msg)
1689 {
1690 if (InvalidMsg(msg))
1691 return 0;
1692 if (msg->attr & MSGREADTMR) return 0x00000800L;
1693 return 0L;
1694 }
1695
1696
StrToSubfield(const unsigned char * str,dword lstr,dword * len,JAMSUBFIELD2ptr subf)1697 static int StrToSubfield(const unsigned char *str, dword lstr, dword *len, JAMSUBFIELD2ptr subf)
1698 {
1699 /* warning: str is read only and NOT nul-terminated! */
1700 const unsigned char *kludge;
1701 word subtypes;
1702
1703 if ( !str || !subf)
1704 { msgapierr = MERR_BADA;
1705 return 0;
1706 }
1707
1708 msgapierr = MERR_NONE;
1709 while (lstr > 0)
1710 if (str[lstr-1] == '\r')
1711 lstr--;
1712 else
1713 break;
1714
1715 kludge = str;
1716 subtypes = JAMSFLD_FTSKLUDGE;
1717
1718 switch (*str) {
1719 case 'F': if (lstr>5 && strncmp((char*)str, "FMPT ", 5) == 0)
1720 return 0;
1721 else if (lstr>6 && strncmp((char*)str, "FLAGS ", 6) == 0) {
1722 kludge = str+6;
1723 subtypes = JAMSFLD_FLAGS;
1724 }
1725 break;
1726 case 'I': if (lstr>4 && strncmp((char*)str, "INTL ", 4) == 0)
1727 return 0;
1728 break;
1729 case 'M': if (lstr>7 && strncmp((char*)str, "MSGID: ", 7) == 0) {
1730 kludge = str+7;
1731 subtypes = JAMSFLD_MSGID;
1732 }
1733 break;
1734 case 'P': if (lstr>6 && strncmp((char*)str, "PATH: ", 6) == 0) {
1735 kludge = str+6;
1736 subtypes = JAMSFLD_PATH2D;
1737 } else if (lstr>5 && strncmp((char*)str, "PID: ", 5) == 0) {
1738 kludge = str+5;
1739 subtypes = JAMSFLD_PID;
1740 }
1741 break;
1742 case 'R': if (lstr>7 && strncmp((char*)str, "REPLY: ", 7) == 0) {
1743 kludge = str+7;
1744 subtypes = JAMSFLD_REPLYID;
1745 }
1746 break;
1747 case 'S': if (lstr>9 && strncmp((char*)str, "SEEN-BY: ", 9) == 0) {
1748 kludge = str+9;
1749 subtypes = JAMSFLD_SEENBY2D;
1750 }
1751 break;
1752 case 'T': if (lstr>5 && strncmp((char*)str, "TOPT ", 5) == 0)
1753 return 0;
1754 else if (lstr>7 && strncmp((char *)str, "TZUTC: ", 7) == 0) {
1755 kludge = str+7;
1756 subtypes = JAMSFLD_TZUTCINFO;
1757 }
1758 break;
1759 case 'V': if (lstr>4 && strncmp((char*)str, "Via ", 4) == 0) {
1760 kludge = str+4;
1761 subtypes = JAMSFLD_TRACE;
1762 }
1763 break;
1764 default:
1765 break;
1766 }
1767 subf->LoID = subtypes;
1768 subf->HiID = 0;
1769 subf->DatLen = lstr-(kludge-str);
1770 memcpy(subf->Buffer, kludge, subf->DatLen);
1771 subf->Buffer[subf->DatLen] = '\0';
1772 if(len) *len = sizeof(JAMBINSUBFIELD)+subf->DatLen;
1773 return 1;
1774 }
1775
NETADDRtoSubf(NETADDR addr,dword * len,word opt,JAMSUBFIELD2ptr subf)1776 static int NETADDRtoSubf(NETADDR addr, dword *len, word opt, JAMSUBFIELD2ptr subf)
1777 {
1778 /* opt = 0 origaddr */
1779 /* opt = 1 destaddr */
1780
1781 if (!subf)
1782 { msgapierr = MERR_BADA;
1783 return 0;
1784 }
1785
1786 if (addr.zone==0 && addr.net==0 && addr.node==0 && addr.point==0)
1787 return 0;
1788 if (addr.point) {
1789 sprintf((char*)(subf->Buffer), "%d:%d/%d.%d", addr.zone, addr.net, addr.node, addr.point);
1790 } else {
1791 sprintf((char*)(subf->Buffer), "%d:%d/%d", addr.zone, addr.net, addr.node);
1792 } /* endif */
1793
1794 subf->DatLen = strlen((char*)(subf->Buffer));
1795 if(len){
1796 *len = subf->DatLen + sizeof(JAMBINSUBFIELD);
1797 }
1798 subf->LoID = opt ? JAMSFLD_DADDRESS : JAMSFLD_OADDRESS;
1799 subf->HiID = 0;
1800
1801 msgapierr = MERR_NONE;
1802 return 1;
1803 }
1804
FromToSubjTOSubf(word jamsfld,unsigned char * txt,dword * len,JAMSUBFIELD2ptr subf)1805 static int FromToSubjTOSubf(word jamsfld, unsigned char *txt, dword *len, JAMSUBFIELD2ptr subf)
1806 {
1807 if (!subf)
1808 { msgapierr = MERR_BADA;
1809 return 0;
1810 }
1811 subf->LoID = jamsfld;
1812 subf->HiID = 0;
1813 if(txt) memmove(subf->Buffer, txt, subf->DatLen = strlen((char*)txt));
1814 else{ subf->Buffer = NULL; subf->DatLen = 0; }
1815 if(len) *len = subf->DatLen + sizeof(JAMBINSUBFIELD);
1816
1817 return 1;
1818 }
1819
ConvertXmsgToJamHdr(MSGH * msgh,XMSG * msg,JAMHDRptr jamhdr,JAMSUBFIELD2LISTptr * subfield)1820 static void MSGAPI ConvertXmsgToJamHdr(MSGH *msgh, XMSG *msg, JAMHDRptr jamhdr, JAMSUBFIELD2LISTptr *subfield)
1821 {
1822 JAMSUBFIELD2ptr SubFieldCur;
1823 struct tm stm, *ptm;
1824 dword clen, sublen;
1825
1826 memset(jamhdr, '\0', sizeof(JAMHDR));
1827
1828 if( InvalidMsgh(msgh) || InvalidMsg(msg) )
1829 return;
1830
1831 clen = msgh->sq->isecho ? 3 : 5;
1832 sublen = sizeof(JAMSUBFIELD2LIST)+sizeof(JAMSUBFIELD2)*clen+37+37+73+
1833 (msgh->sq->isecho ? 0 : 30*2);
1834 *subfield = palloc(sublen);
1835 if (*subfield==NULL) {
1836 msgapierr = MERR_NOMEM;
1837 return;
1838 }
1839
1840 subfield[0]->arraySize = sublen;
1841 subfield[0]->subfieldCount = 0;
1842 subfield[0]->subfield[0].Buffer = (unsigned char *)&(subfield[0]->subfield[clen+1]);
1843
1844 jamhdr->Attribute = Jam_MsgAttrToJam(msg);
1845 jamhdr->Attribute2 = Jam_MsgAttr2ToJam(msg);
1846
1847 if (msgh->sq->isecho != NOTH) {
1848 if (msgh->sq->isecho) {
1849 jamhdr->Attribute |= JMSG_TYPEECHO;
1850 } else {
1851 jamhdr->Attribute |= JMSG_TYPENET;
1852 } /* endif */
1853 }
1854 strcpy((char*)(jamhdr->Signature), HEADERSIGNATURE);
1855 jamhdr->Revision = CURRENTREVLEV;
1856 if (((SCOMBO*)&(msg->date_arrived))->ldate) {
1857 /* save arrived date for sqpack */
1858 ptm = &stm;
1859 ptm = DosDate_to_TmDate((SCOMBO*)(&(msg->date_arrived)), ptm);
1860 jamhdr->DateProcessed = mktime(ptm) + gettz();
1861 }
1862 else
1863 jamhdr->DateProcessed = time(NULL) + gettz();
1864 ptm = &stm;
1865 ptm = DosDate_to_TmDate((SCOMBO*)(&(msg->date_written)), ptm);
1866 jamhdr->DateWritten = mktime(ptm) + gettz();
1867
1868 sublen = 0;
1869
1870 /* From Name */
1871
1872 SubFieldCur = subfield[0]->subfield;
1873 if (FromToSubjTOSubf(JAMSFLD_SENDERNAME, msg->from, &clen, SubFieldCur)) {
1874 SubFieldCur[1].Buffer = SubFieldCur->Buffer+SubFieldCur->DatLen+1;
1875 subfield[0]->subfieldCount++;
1876 SubFieldCur++;
1877 sublen += clen;
1878 } /* endif */
1879
1880 /* To Name */
1881
1882 if (FromToSubjTOSubf(JAMSFLD_RECVRNAME, msg->to, &clen, SubFieldCur)) {
1883 SubFieldCur[1].Buffer = SubFieldCur->Buffer+SubFieldCur->DatLen+1;
1884 subfield[0]->subfieldCount++;
1885 SubFieldCur++;
1886 sublen += clen;
1887 } /* endif */
1888
1889 /* Subject */
1890
1891 if (FromToSubjTOSubf(JAMSFLD_SUBJECT, msg->subj, &clen, SubFieldCur)) {
1892 SubFieldCur[1].Buffer = SubFieldCur->Buffer+SubFieldCur->DatLen+1;
1893 subfield[0]->subfieldCount++;
1894 SubFieldCur++;
1895 sublen += clen;
1896 } /* endif */
1897
1898 if (!msgh->sq->isecho) {
1899
1900 /* Orig Address */
1901
1902 if (NETADDRtoSubf(msg->orig, &clen, 0, SubFieldCur)) {
1903 SubFieldCur[1].Buffer = SubFieldCur->Buffer+SubFieldCur->DatLen+1;
1904 subfield[0]->subfieldCount++;
1905 SubFieldCur++;
1906 sublen += clen;
1907 } /* endif */
1908
1909 /* Dest Address */
1910
1911 if (NETADDRtoSubf(msg->dest, &clen, 1, SubFieldCur)) {
1912 SubFieldCur[1].Buffer = SubFieldCur->Buffer+SubFieldCur->DatLen+1;
1913 subfield[0]->subfieldCount++;
1914 SubFieldCur++;
1915 sublen += clen;
1916 } /* endif */
1917
1918 }
1919 assert(SubFieldCur->Buffer<=(byte *)*subfield+subfield[0]->arraySize);
1920 assert((byte *)(SubFieldCur+1)<=subfield[0]->subfield[0].Buffer);
1921
1922 jamhdr->SubfieldLen = sublen;
1923 jamhdr->PasswordCRC = 0xFFFFFFFFUL;
1924
1925 jamhdr->ReplyTo = msg->replyto;
1926 jamhdr->Reply1st = msg->xmreply1st;
1927 jamhdr->ReplyNext = msg->xmreplynext;
1928 jamhdr->TimesRead = msg->xmtimesread;
1929 jamhdr->Cost = msg->xmcost;
1930 msgapierr = MERR_NONE;
1931 }
1932
resize_subfields(JAMSUBFIELD2LISTptr * sflist,dword newcount,dword len)1933 static void resize_subfields(JAMSUBFIELD2LISTptr *sflist, dword newcount,
1934 dword len)
1935 {
1936 #define LASTFIELD(x) ((x)->subfield[(x)->subfieldCount-1])
1937 dword i;
1938 JAMSUBFIELD2LISTptr new_list, old_list;
1939 byte *new_buffer, *old_buffer;
1940 size_t new_buffer_size, old_buffer_size;
1941
1942 if( !sflist || !*sflist || len==0 )
1943 {
1944 msgapierr = MERR_BADA;
1945 return;
1946 }
1947
1948 old_list = *sflist;
1949 if(old_list->subfieldCount == 0)
1950 {
1951 old_buffer = (byte*)&(old_list->subfield[0]);
1952 old_buffer_size = 0;
1953 }
1954 else
1955 {
1956 old_buffer = old_list->subfield[0].Buffer;
1957 /* really used size */
1958 old_buffer_size = LASTFIELD(old_list).Buffer + LASTFIELD(old_list).DatLen - old_buffer;
1959 }
1960 /* Check consistency of source structure */
1961 assert(old_buffer + old_buffer_size <= (byte*)old_list+old_list->arraySize);
1962
1963 assert(newcount > old_list->subfieldCount); /* Code below relies on this */
1964
1965 new_list = palloc(len);
1966 if (!new_list) {
1967 msgapierr = MERR_NOMEM;
1968 return;
1969 }
1970
1971 new_list->arraySize = len;
1972 new_list->subfieldCount = old_list->subfieldCount;
1973
1974 new_buffer = (byte*)&(new_list->subfield[newcount]);
1975 new_buffer_size = new_list->arraySize - (new_buffer - (byte*)new_list);
1976
1977 assert(new_buffer_size >= old_buffer_size);
1978
1979 if (old_list->subfieldCount > 0)
1980 {
1981 /* copy array of JAMSUBFIELD2 */
1982 memcpy(new_list->subfield, old_list->subfield,
1983 new_list->subfieldCount * sizeof(JAMSUBFIELD2));
1984 /* fix pointers. note brackets: that's right, subtracting pointers
1985 * referring to two different objects gives UB */
1986 for (i = 0; i < old_list->subfieldCount; ++i)
1987 new_list->subfield[i].Buffer =
1988 new_buffer + (old_list->subfield[i].Buffer - old_buffer);
1989 /* copy data */
1990 memcpy(new_buffer, old_buffer, old_buffer_size);
1991 }
1992 /* Set up next subfield's buffer */
1993 new_list->subfield[new_list->subfieldCount].Buffer = new_buffer + old_buffer_size;
1994
1995 freejamsubfield(old_list);
1996 *sflist = new_list;
1997 msgapierr = MERR_NONE;
1998 #undef LASTFIELD
1999 }
2000
ConvertCtrlToSubf(JAMHDRptr jamhdr,JAMSUBFIELD2LISTptr * subfield,dword clen,unsigned char * ctxt)2001 static void MSGAPI ConvertCtrlToSubf(JAMHDRptr jamhdr, JAMSUBFIELD2LISTptr
2002 *subfield, dword clen, unsigned char *ctxt)
2003 {
2004 JAMSUBFIELD2ptr SubField;
2005 dword len, i;
2006 unsigned char *ptr;
2007
2008 if( !subfield || !ctxt || !jamhdr )
2009 {
2010 msgapierr = MERR_BADA;
2011 return;
2012 }
2013
2014 /* count new subfields */
2015 i = *ctxt ? 2 : 1;
2016 for (ptr=ctxt, len=0; len<clen; len++)
2017 if (*ptr++=='\001') i++;
2018 resize_subfields(subfield, subfield[0]->subfieldCount+i,
2019 subfield[0]->arraySize + clen + i + i*sizeof(JAMSUBFIELD2));
2020 SubField = &(subfield[0]->subfield[subfield[0]->subfieldCount]);
2021
2022 for (ptr=ctxt, len=0; len<=clen; len++, ptr++) {
2023 if (*ptr=='\0' || len==clen || *ptr=='\001') {
2024 if (*ctxt && *ctxt!='\001' &&
2025 StrToSubfield(ctxt, ptr-ctxt, &i, SubField)) {
2026 SubField[1].Buffer = SubField->Buffer+SubField->DatLen+1;
2027 jamhdr->SubfieldLen += i;
2028 subfield[0]->subfieldCount++;
2029 if (SubField->LoID==JAMSFLD_MSGID)
2030 jamhdr->MsgIdCRC=Jam_Crc32(SubField->Buffer, SubField->DatLen);
2031 else if (SubField->LoID==JAMSFLD_REPLYID)
2032 jamhdr->ReplyCRC=Jam_Crc32(SubField->Buffer, SubField->DatLen);
2033 SubField++;
2034 }
2035 if (*ptr=='\0' || len==clen)
2036 break;
2037 ctxt = ptr+1;
2038 }
2039 }
2040 assert(SubField->Buffer<=(byte *)*subfield+subfield[0]->arraySize);
2041 assert((byte *)(SubField+1)<=subfield[0]->subfield[0].Buffer);
2042 msgapierr = MERR_NONE;
2043 }
2044
DelimText(JAMHDRptr jamhdr,JAMSUBFIELD2LISTptr * subfield,unsigned char * text,size_t textlen)2045 unsigned char *DelimText(JAMHDRptr jamhdr, JAMSUBFIELD2LISTptr *subfield,
2046 unsigned char *text, size_t textlen)
2047 {
2048 JAMSUBFIELD2ptr SubField;
2049 dword clen, firstlen, i, len;
2050 unsigned char *onlytext, *first, *ptr, *curtext;
2051
2052 if( !subfield || !jamhdr )
2053 {
2054 msgapierr = MERR_BADA;
2055 return NULL;
2056 }
2057
2058 if (text && textlen)
2059 {
2060 if (text[textlen-1] != '\r')
2061 textlen++;
2062 onlytext = curtext = (unsigned char*)palloc(textlen + 1);
2063 if (!onlytext) {
2064 msgapierr = MERR_NOMEM;
2065 return NULL;
2066 }
2067 *onlytext = '\0';
2068
2069 /* count subfields */
2070 i = 1;
2071 len = 0;
2072 for (first = text; first<text+textlen; first = ptr+1) {
2073 ptr = (unsigned char *)strchr((char*)first, '\r');
2074 if (ptr==NULL) ptr=text+textlen;
2075 if (*first == '\001' || strncmp((char *)first, "SEEN-BY: ", 9) == 0) {
2076 if (*first == '\001') first++;
2077 i++;
2078 len += (ptr-first);
2079 }
2080 }
2081 resize_subfields(subfield, subfield[0]->subfieldCount+i,
2082 subfield[0]->arraySize + len + i + i*sizeof(JAMSUBFIELD2));
2083 SubField = &(subfield[0]->subfield[subfield[0]->subfieldCount]);
2084
2085 first = text;
2086 while (*first) {
2087 ptr = (unsigned char *)strchr((char *)first, '\r');
2088 if (ptr) *ptr = '\0';
2089 firstlen = ptr ? (dword)(ptr-first) : strlen((char *)first);
2090 if ((firstlen > 9 && strncmp((char *)first, "SEEN-BY: ", 9) == 0) ||
2091 *first == '\001') {
2092
2093 if (*first == '\001') {
2094 first++;
2095 firstlen--;
2096 }
2097
2098 if (StrToSubfield(first, firstlen, &clen, SubField)) {
2099 SubField[1].Buffer = SubField->Buffer+SubField->DatLen+1;
2100 jamhdr->SubfieldLen += clen;
2101 subfield[0]->subfieldCount++;
2102 if (SubField->LoID==JAMSFLD_MSGID)
2103 jamhdr->MsgIdCRC=Jam_Crc32(SubField->Buffer, SubField->DatLen);
2104 else if (SubField->LoID==JAMSFLD_REPLYID)
2105 jamhdr->ReplyCRC=Jam_Crc32(SubField->Buffer, SubField->DatLen);
2106 SubField++;
2107 }
2108 } else {
2109 assert((size_t)((curtext - onlytext) + firstlen + 1) <= textlen);
2110 strcpy((char *)curtext, (char *)first);
2111 curtext+=firstlen;
2112 *curtext++ = '\r';
2113 *curtext = '\0';
2114 } /* endif */
2115 if (ptr) {
2116 *ptr = '\r';
2117 first = ptr+1;
2118 } else {
2119 first += firstlen;
2120 } /* endif */
2121 } /* endwhile */
2122 assert(SubField->Buffer<=(byte *)*subfield+subfield[0]->arraySize);
2123 assert((byte *)(SubField+1)<=subfield[0]->subfield[0].Buffer);
2124 }
2125 else
2126 {
2127 onlytext = NULL;
2128 }
2129
2130 msgapierr = MERR_NONE;
2131 return onlytext;
2132 }
2133
addkludge(char ** line,char * kludge,char * ent,char * lf,dword len)2134 static void addkludge(char **line, char *kludge, char *ent, char *lf, dword len)
2135 {
2136 if( !line || !*line || !kludge || !ent || !lf )
2137 {
2138 msgapierr = MERR_BADA;
2139 return;
2140 }
2141
2142 strcpy(*line, kludge);
2143 *line += strlen(kludge);
2144 strncpy(*line, ent, len);
2145 (*line)[len]='\0';
2146 *line += strlen(*line);
2147 strcpy(*line, lf);
2148 *line += strlen(*line);
2149 }
2150
2151 /* WARNING: rewrites clen, ctrl, lclen, lctrl */
DecodeSubf(MSGH * msgh)2152 void DecodeSubf(MSGH *msgh)
2153 {
2154 dword SubPos;
2155 JAMSUBFIELD2ptr SubField;
2156 JAMSUBFIELD2LISTptr sfl;
2157 char *ptr, *pctrl, *plctrl, *fmpt, *topt;
2158 char orig[101], dest[101]; /* by JAM's spec DADDRESS and OADDRESS
2159 * subfield's DATLEN must not exceed 100 bytes.
2160 * 101 for last \0 */
2161 dword i;
2162
2163 if( InvalidMsgh(msgh) ) return;
2164
2165 msgh->ctrl = (unsigned char*)palloc(msgh->SubFieldPtr->arraySize+65);
2166 msgh->lctrl = (unsigned char*)palloc(msgh->SubFieldPtr->arraySize+65);
2167 if (!(msgh->ctrl && msgh->lctrl)) {
2168 pfree(msgh->ctrl);
2169 pfree(msgh->lctrl);
2170 msgapierr = MERR_NOMEM;
2171 return;
2172 }
2173
2174 *(msgh->ctrl)=*(msgh->lctrl)='\0';
2175 pctrl = (char *)(msgh->ctrl);
2176 plctrl = (char *)(msgh->lctrl);
2177 orig[0] = dest[0] = '\0';
2178
2179 if (!msgh->sq->isecho) {
2180 SubPos = 0;
2181 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_OADDRESS);
2182 if (SubField != NULL)
2183 {
2184 memcpy(orig, SubField->Buffer, min(SubField->DatLen, sizeof(orig)-1));
2185 orig[min(SubField->DatLen, sizeof(orig)-1)] = '\0';
2186 }
2187 SubPos = 0;
2188 SubField = Jam_GetSubField(msgh, &SubPos, JAMSFLD_DADDRESS);
2189 if (SubField != NULL)
2190 {
2191 memcpy(dest, SubField->Buffer, min(SubField->DatLen, sizeof(dest)-1));
2192 dest[min(SubField->DatLen, sizeof(dest)-1)] = '\0';
2193 }
2194 fmpt = topt = NULL;
2195 if (orig[0]) {
2196 ptr = strchr(orig, '@');
2197 if (ptr) *ptr = '\0';
2198 ptr = strchr(orig, '.');
2199 if (ptr) {
2200 *ptr++ = '\0';
2201 if (atoi(ptr) != 0) fmpt = ptr;
2202 }
2203 }
2204 if (dest[0]) {
2205 ptr = strchr(dest, '@');
2206 if (ptr) *ptr = '\0';
2207 ptr = strchr(dest, '.');
2208 if (ptr) {
2209 *ptr++ = '\0';
2210 if (atoi(ptr) != 0) topt = ptr;
2211 }
2212 }
2213 if (orig[0] && dest[0]) {
2214 strcpy(pctrl, "\001" "INTL "); pctrl+=strlen(pctrl);
2215 strcpy(pctrl, dest); pctrl+=strlen(pctrl);
2216 strcpy(pctrl, " "); pctrl++;
2217 strcpy(pctrl, orig); pctrl+=strlen(pctrl);
2218 }
2219 if (fmpt)
2220 addkludge(&pctrl, "\001" "FMPT ", "", fmpt, 0);
2221 if (topt)
2222 addkludge(&pctrl, "\001" "TOPT ", "", topt, 0);
2223 orig[0] = dest[0] = '\0';
2224 }
2225
2226 SubPos = 0;
2227
2228 sfl = msgh->SubFieldPtr;
2229
2230 SubField = &(sfl->subfield[0]);
2231 for (i=0; i<sfl->subfieldCount; i++, SubField++) {
2232
2233 if (SubField->LoID == JAMSFLD_MSGID)
2234 addkludge(&pctrl, "\001MSGID: ", (char *)(SubField->Buffer), "", SubField->DatLen);
2235 else if (SubField->LoID == JAMSFLD_REPLYID)
2236 addkludge(&pctrl, "\001REPLY: ", (char *)(SubField->Buffer), "", SubField->DatLen);
2237 else if (SubField->LoID == JAMSFLD_PID)
2238 addkludge(&pctrl, "\001PID: ", (char *)(SubField->Buffer), "", SubField->DatLen);
2239 else if (SubField->LoID == JAMSFLD_TRACE)
2240 addkludge(&plctrl, "\001Via ", (char *)(SubField->Buffer), "\r", SubField->DatLen);
2241 else if (SubField->LoID == JAMSFLD_FTSKLUDGE) {
2242 if (strncasecmp((char *)(SubField->Buffer), "Via", 3) == 0 ||
2243 strncasecmp((char *)(SubField->Buffer), "Recd", 4) == 0)
2244 addkludge(&plctrl, "\001", (char *)(SubField->Buffer), "\r", SubField->DatLen);
2245 else
2246 addkludge(&pctrl, "\001", (char *)(SubField->Buffer), "", SubField->DatLen);
2247 }
2248 else if (SubField->LoID == JAMSFLD_FLAGS)
2249 addkludge(&pctrl, "\001" "FLAGS ", (char *)(SubField->Buffer), "", SubField->DatLen);
2250 else if (SubField->LoID == JAMSFLD_PATH2D)
2251 addkludge(&plctrl, "\001PATH: ", (char *)(SubField->Buffer), "\r", SubField->DatLen);
2252 else if (SubField->LoID == JAMSFLD_SEENBY2D)
2253 addkludge(&plctrl, "SEEN-BY: ", (char *)(SubField->Buffer), "\r", SubField->DatLen);
2254 else if (SubField->LoID == JAMSFLD_TZUTCINFO)
2255 addkludge(&pctrl, "\001TZUTC: ", (char *)(SubField->Buffer), "", SubField->DatLen);
2256 } /* endwhile */
2257 msgh->clen = pctrl -(char *)msgh->ctrl;
2258 msgh->lclen = plctrl-(char *)msgh->lctrl;
2259 assert(msgh->clen <msgh->SubFieldPtr->arraySize+65);
2260 assert(msgh->lclen<msgh->SubFieldPtr->arraySize+65);
2261 msgh->ctrl = (unsigned char *)realloc(msgh->ctrl, msgh->clen + 1);
2262 msgh->lctrl = (unsigned char *)realloc(msgh->lctrl, msgh->lclen + 1);
2263 if (!(msgh->ctrl && msgh->lctrl)) {
2264 msgapierr = MERR_NOMEM;
2265 return;
2266 }
2267 msgapierr = MERR_NONE;
2268 }
2269
2270 /***********************************************************************
2271 **
2272 ** Crc32 lookup table
2273 **
2274 ***********************************************************************/
2275 static hINT32 crc32tab[256]= {
2276 0L, 1996959894L, -301047508L, -1727442502L, 124634137L,
2277 1886057615L, -379345611L, -1637575261L, 249268274L, 2044508324L,
2278 -522852066L, -1747789432L, 162941995L, 2125561021L, -407360249L,
2279 -1866523247L, 498536548L, 1789927666L, -205950648L, -2067906082L,
2280 450548861L, 1843258603L, -187386543L, -2083289657L, 325883990L,
2281 1684777152L, -43845254L, -1973040660L, 335633487L, 1661365465L,
2282 -99664541L, -1928851979L, 997073096L, 1281953886L, -715111964L,
2283 -1570279054L, 1006888145L, 1258607687L, -770865667L, -1526024853L,
2284 901097722L, 1119000684L, -608450090L, -1396901568L, 853044451L,
2285 1172266101L, -589951537L, -1412350631L, 651767980L, 1373503546L,
2286 -925412992L, -1076862698L, 565507253L, 1454621731L, -809855591L,
2287 -1195530993L, 671266974L, 1594198024L, -972236366L, -1324619484L,
2288 795835527L, 1483230225L, -1050600021L, -1234817731L, 1994146192L,
2289 31158534L, -1731059524L, -271249366L, 1907459465L, 112637215L,
2290 -1614814043L, -390540237L, 2013776290L, 251722036L, -1777751922L,
2291 -519137256L, 2137656763L, 141376813L, -1855689577L, -429695999L,
2292 1802195444L, 476864866L, -2056965928L, -228458418L, 1812370925L,
2293 453092731L, -2113342271L, -183516073L, 1706088902L, 314042704L,
2294 -1950435094L, -54949764L, 1658658271L, 366619977L, -1932296973L,
2295 -69972891L, 1303535960L, 984961486L, -1547960204L, -725929758L,
2296 1256170817L, 1037604311L, -1529756563L, -740887301L, 1131014506L,
2297 879679996L, -1385723834L, -631195440L, 1141124467L, 855842277L,
2298 -1442165665L, -586318647L, 1342533948L, 654459306L, -1106571248L,
2299 -921952122L, 1466479909L, 544179635L, -1184443383L, -832445281L,
2300 1591671054L, 702138776L, -1328506846L, -942167884L, 1504918807L,
2301 783551873L, -1212326853L, -1061524307L, -306674912L, -1698712650L,
2302 62317068L, 1957810842L, -355121351L, -1647151185L, 81470997L,
2303 1943803523L, -480048366L, -1805370492L, 225274430L, 2053790376L,
2304 -468791541L, -1828061283L, 167816743L, 2097651377L, -267414716L,
2305 -2029476910L, 503444072L, 1762050814L, -144550051L, -2140837941L,
2306 426522225L, 1852507879L, -19653770L, -1982649376L, 282753626L,
2307 1742555852L, -105259153L, -1900089351L, 397917763L, 1622183637L,
2308 -690576408L, -1580100738L, 953729732L, 1340076626L, -776247311L,
2309 -1497606297L, 1068828381L, 1219638859L, -670225446L, -1358292148L,
2310 906185462L, 1090812512L, -547295293L, -1469587627L, 829329135L,
2311 1181335161L, -882789492L, -1134132454L, 628085408L, 1382605366L,
2312 -871598187L, -1156888829L, 570562233L, 1426400815L, -977650754L,
2313 -1296233688L, 733239954L, 1555261956L, -1026031705L, -1244606671L,
2314 752459403L, 1541320221L, -1687895376L, -328994266L, 1969922972L,
2315 40735498L, -1677130071L, -351390145L, 1913087877L, 83908371L,
2316 -1782625662L, -491226604L, 2075208622L, 213261112L, -1831694693L,
2317 -438977011L, 2094854071L, 198958881L, -2032938284L, -237706686L,
2318 1759359992L, 534414190L, -2118248755L, -155638181L, 1873836001L,
2319 414664567L, -2012718362L, -15766928L, 1711684554L, 285281116L,
2320 -1889165569L, -127750551L, 1634467795L, 376229701L, -1609899400L,
2321 -686959890L, 1308918612L, 956543938L, -1486412191L, -799009033L,
2322 1231636301L, 1047427035L, -1362007478L, -640263460L, 1088359270L,
2323 936918000L, -1447252397L, -558129467L, 1202900863L, 817233897L,
2324 -1111625188L, -893730166L, 1404277552L, 615818150L, -1160759803L,
2325 -841546093L, 1423857449L, 601450431L, -1285129682L, -1000256840L,
2326 1567103746L, 711928724L, -1274298825L, -1022587231L, 1510334235L,
2327 755167117L
2328 };
2329
2330
2331 /***********************************************************************
2332 **
2333 ** JAM_Crc32 - Calculate CRC32 on a data block
2334 **
2335 ** Note: This function returns data, NOT a status code!
2336 **
2337 ***********************************************************************/
Jam_Crc32(unsigned char * buff,dword len)2338 dword Jam_Crc32(unsigned char* buff, dword len)
2339 {
2340 dword crc = 0xffffffffUL;
2341 unsigned char *ptr = buff;
2342
2343 if( buff )
2344 for (; len; len--, ptr++)
2345 crc=(crc >> 8) ^ crc32tab [(int) ((crc^tolower(*ptr)) & 0xffUL)];
2346 return crc;
2347 }
2348
2349
JamGetHash(HAREA mh,dword msgnum)2350 static dword _XPENTRY JamGetHash(HAREA mh, dword msgnum)
2351 {
2352 XMSG xmsg;
2353 HMSG msgh;
2354 dword rc = 0l;
2355
2356 msgh=JamOpenMsg(mh, MOPEN_READ, msgnum);
2357 if (msgh==NULL)
2358 return (dword) 0l;
2359
2360 if (JamReadMsg(msgh, &xmsg, 0L, 0L, NULL, 0L, NULL)!=(dword)-1)
2361 {
2362 rc = SquishHash(xmsg.to) | (xmsg.attr & MSGREAD) ? 0x80000000l : 0;
2363 }
2364
2365 JamCloseMsg(msgh);
2366
2367 msgapierr=MERR_NONE;
2368 return rc;
2369 }
2370
JamGetNextUid(HAREA ha)2371 static UMSGID _XPENTRY JamGetNextUid(HAREA ha)
2372 {
2373 if (InvalidMh(ha))
2374 return 0L;
2375
2376 if (!ha->locked)
2377 {
2378 msgapierr=MERR_NOLOCK;
2379 return 0L;
2380 }
2381
2382 msgapierr=MERR_NONE;
2383 return ha->high_msg+1;
2384 }
2385