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