home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / MSG1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-13  |  12.9 KB  |  487 lines

  1. #line 1 "MSG1.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. /***********************************************************************/
  6. /* Functions that do i/o with messages (posts/mail/auto) or their data */
  7. /***********************************************************************/
  8.  
  9. #include "sbbs.h"
  10.  
  11. #define LZH 1
  12.  
  13. void lfputs(char HUGE16 *buf, FILE *fp)
  14. {
  15. while(*buf) {
  16.     fputc(*buf,fp);
  17.     buf++; }
  18. }
  19.  
  20. /****************************************************************************/
  21. /* Loads an SMB message from the open msg base the fastest way possible     */
  22. /* first by offset, and if that's the wrong message, then by number.        */
  23. /* Returns 1 if the message was loaded and left locked, otherwise            */
  24. /****************************************************************************/
  25. int loadmsg(smbmsg_t *msg, ulong number)
  26. {
  27.     char str[128];
  28.     int i;
  29.  
  30. if(msg->idx.offset) {                /* Load by offset if specified */
  31.  
  32.     if((i=smb_lockmsghdr(&smb,msg))!=0) {
  33.         errormsg(WHERE,ERR_LOCK,smb.file,i);
  34.         return(0); }
  35.  
  36.     i=smb_getmsghdr(&smb,msg);
  37.     if(!i && msg->hdr.number==number)
  38.         return(1);
  39.  
  40.     /* Wrong offset  */
  41.  
  42.     if(!i) {
  43.         smb_freemsgmem(msg);
  44.         msg->total_hfields=0; }
  45.  
  46.     smb_unlockmsghdr(&smb,msg); }
  47.  
  48. msg->hdr.number=number;
  49. if((i=smb_getmsgidx(&smb,msg))!=0)                 /* Message is deleted */
  50.     return(0);
  51. if((i=smb_lockmsghdr(&smb,msg))!=0) {
  52.     errormsg(WHERE,ERR_LOCK,smb.file,i);
  53.     return(0); }
  54. if((i=smb_getmsghdr(&smb,msg))!=0) {
  55.     sprintf(str,"(%06lX) #%lu/%lu %s",msg->idx.offset,msg->idx.number
  56.         ,number,smb.file);
  57.     smb_unlockmsghdr(&smb,msg);
  58.     errormsg(WHERE,ERR_READ,str,i);
  59.     return(0); }
  60. return(msg->total_hfields);
  61. }
  62.  
  63. /****************************************************************************/
  64. /* Displays a text file to the screen, reading/display a block at time        */
  65. /****************************************************************************/
  66. void putmsg_fp(FILE *fp, long length, int mode)
  67. {
  68.     uchar *buf,tmpatr;
  69.     int i,j,b=8192,orgcon=console;
  70.     long l;
  71.  
  72. tmpatr=curatr;    /* was lclatr(-1) */
  73. if((buf=MALLOC(b+1))==NULL) {
  74.     errormsg(WHERE,ERR_ALLOC,nulstr,b+1L);
  75.     return; }
  76. for(l=0;l<length;l+=b) {
  77.     if(l+b>length)
  78.         b=length-l;
  79.     i=j=fread(buf,1,b,fp);
  80.     if(!j) break;                        /* No bytes read */
  81.     if(l+i<length)                        /* Not last block */
  82.         while(i && buf[i-1]!=LF) i--;    /* Search for last LF */
  83.     if(!i) i=j;                         /* None found */
  84.     buf[i]=0;
  85.     if(i<j)
  86.         fseek(fp,(long)-(j-i),SEEK_CUR);
  87.     b=i;
  88.     if(putmsg(buf,mode|P_SAVEATR))
  89.         break; }
  90. if(!(mode&P_SAVEATR)) {
  91.     console=orgcon;
  92.     attr(tmpatr); }
  93. FREE(buf);
  94. }
  95.  
  96. void show_msgattr(ushort attr)
  97. {
  98.  
  99. bprintf(text[MsgAttr]
  100.     ,attr&MSG_PRIVATE    ? "Private  "   :nulstr
  101.     ,attr&MSG_READ        ? "Read  "      :nulstr
  102.     ,attr&MSG_DELETE    ? "Deleted  "   :nulstr
  103.     ,attr&MSG_KILLREAD    ? "Kill  "      :nulstr
  104.     ,attr&MSG_ANONYMOUS ? "Anonymous  " :nulstr
  105.     ,attr&MSG_LOCKED    ? "Locked  "    :nulstr
  106.     ,attr&MSG_PERMANENT ? "Permanent  " :nulstr
  107.     ,attr&MSG_MODERATED ? "Moderated  " :nulstr
  108.     ,attr&MSG_VALIDATED ? "Validated  " :nulstr
  109.     );
  110. }
  111.  
  112. /****************************************************************************/
  113. /* Displays a message header to the screen                                  */
  114. /****************************************************************************/
  115. void show_msghdr(smbmsg_t msg)
  116. {
  117.     char    *sender=NULL;
  118.     int     i;
  119.  
  120. attr(LIGHTGRAY);
  121. if(useron.misc&CLRSCRN)
  122.     outchar(FF);
  123. else
  124.     CRLF;
  125. bprintf(text[MsgSubj],msg.subj);
  126. if(msg.hdr.attr)
  127.     show_msgattr(msg.hdr.attr);
  128.  
  129. bprintf(text[MsgTo],msg.to);
  130. if(msg.to_ext)
  131.     bprintf(text[MsgToExt],msg.to_ext);
  132. if(msg.to_net.addr)
  133.     bprintf(text[MsgToNet],msg.to_net.type==NET_FIDO
  134.         ? faddrtoa(*(faddr_t *)msg.to_net.addr) : msg.to_net.addr);
  135. if(!(msg.hdr.attr&MSG_ANONYMOUS) || SYSOP) {
  136.     bprintf(text[MsgFrom],msg.from);
  137.     if(msg.from_ext)
  138.         bprintf(text[MsgFromExt],msg.from_ext);
  139.     if(msg.from_net.addr)
  140.         bprintf(text[MsgFromNet],msg.from_net.type==NET_FIDO
  141.             ? faddrtoa(*(faddr_t *)msg.from_net.addr)
  142.                 : msg.from_net.addr); }
  143. bprintf(text[MsgDate]
  144.     ,timestr((time_t *)&msg.hdr.when_written.time)
  145.     ,zonestr(msg.hdr.when_written.zone));
  146.  
  147. CRLF;
  148.  
  149. for(i=0;i<msg.total_hfields;i++) {
  150.     if(msg.hfield[i].type==SENDER)
  151.         sender=msg.hfield_dat[i];
  152.     if(msg.hfield[i].type==FORWARDED && sender)
  153.         bprintf(text[ForwardedFrom],sender
  154.             ,timestr((time_t *)msg.hfield_dat[i])); }
  155.  
  156. /* Debug stuff
  157. if(SYSOP) {
  158.     bprintf("\1n\1c\r\nAux  : \1h%08lX",msg.hdr.auxattr);
  159.     bprintf("\1n\1c\r\nNum  : \1h%lu",msg.hdr.number); }
  160. */
  161.  
  162. CRLF;
  163. }
  164.  
  165. #if !LZH
  166.  
  167. /****************************************************************************/
  168. /* Displays message header and text (if not deleted)                        */
  169. /****************************************************************************/
  170. void show_msg(smbmsg_t msg, int mode)
  171. {
  172.     ushort xlat;
  173.     int i;
  174.  
  175. show_msghdr(msg);
  176. for(i=0;i<msg.hdr.total_dfields;i++)
  177.     switch(msg.dfield[i].type) {
  178.         case TEXT_BODY:
  179.         case TEXT_TAIL:
  180.             fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
  181.                 ,SEEK_SET);
  182.             fread(&xlat,2,1,smb.sdt_fp);
  183.             if(xlat!=XLAT_NONE)         /* no translations supported */
  184.                 continue;
  185.             putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode);
  186.             CRLF;
  187.             break; }
  188. }
  189.  
  190. #else
  191.  
  192. /****************************************************************************/
  193. /* Displays message header and text (if not deleted)                        */
  194. /****************************************************************************/
  195. void show_msg(smbmsg_t msg, int mode)
  196. {
  197.     char *inbuf,*lzhbuf;
  198.     ushort xlat;
  199.     int i,lzh;
  200.     long lzhlen,length;
  201.  
  202. show_msghdr(msg);
  203. for(i=0;i<msg.hdr.total_dfields;i++)
  204.     switch(msg.dfield[i].type) {
  205.         case TEXT_BODY:
  206.         case TEXT_TAIL:
  207.             fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
  208.                 ,SEEK_SET);
  209.             fread(&xlat,2,1,smb.sdt_fp);
  210.             lzh=0;
  211.             if(xlat==XLAT_LZH) {
  212.                 lzh=1;
  213.                 fread(&xlat,2,1,smb.sdt_fp); }
  214.             if(xlat!=XLAT_NONE)         /* no translations supported */
  215.                 continue;
  216.             if(lzh) {
  217.                 length=msg.dfield[i].length-4;
  218.                 if((inbuf=MALLOC(length))==NULL) {
  219.                     errormsg(WHERE,ERR_ALLOC,nulstr,length);
  220.                     continue; }
  221.                 fread(inbuf,length,1,smb.sdt_fp);
  222.                 lzhlen=*(long *)inbuf;
  223. /**
  224.                 if(SYSOP)
  225.                 bprintf("Decoding %lu bytes of LZH into %lu bytes of text "
  226.                     "(%d%% compression)"
  227.                     ,length,lzhlen
  228.                     ,(int)(((float)(lzhlen-length)/lzhlen)*100.0));
  229. **/
  230.                 if((lzhbuf=MALLOC(lzhlen+2L))==NULL) {
  231.                     FREE(inbuf);
  232.                     errormsg(WHERE,ERR_ALLOC,nulstr,lzhlen+2L);
  233.                     continue; }
  234.                 lzh_decode(inbuf,length,lzhbuf);
  235.                 lzhbuf[lzhlen]=0;
  236. //                  CRLF;
  237.                 putmsg(lzhbuf,P_NOATCODES);
  238.                 FREE(lzhbuf);
  239.                 FREE(inbuf); }
  240.             else
  241.                 putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode);
  242.             CRLF;
  243.             break; }
  244. }
  245.  
  246. #endif
  247.  
  248. void quotemsg(smbmsg_t msg, int tails)
  249. {
  250.     char    str[256];
  251.  
  252. sprintf(str,"%sQUOTES.TXT",node_dir);
  253. remove(str);
  254. msgtotxt(msg,str,0,tails);
  255. }
  256.  
  257.  
  258. /****************************************************************************/
  259. /* Writes message header and text data to a text file                        */
  260. /****************************************************************************/
  261. void msgtotxt(smbmsg_t msg, char *str, int header, int tails)
  262. {
  263.     uchar    HUGE16 *buf;
  264.     ushort    xlat;
  265.     int     i,j,x;
  266.     ulong    l;
  267.     FILE    *out;
  268.  
  269. if((out=fnopen(&i,str,O_WRONLY|O_CREAT|O_APPEND))==NULL) {
  270.     errormsg(WHERE,ERR_OPEN,str,0);
  271.     return; }
  272. if(header) {
  273.     fprintf(out,"\r\n");
  274.     fprintf(out,"Subj : %s\r\n",msg.subj);
  275.     fprintf(out,"To   : %s",msg.to);
  276.     if(msg.to_ext)
  277.         fprintf(out," #%s",msg.to_ext);
  278.     if(msg.to_net.addr)
  279.         fprintf(out," (%s)",msg.to_net.type==NET_FIDO
  280.             ? faddrtoa(*(faddr_t *)msg.to_net.addr) : msg.to_net.addr);
  281.     fprintf(out,"\r\nFrom : %s",msg.from);
  282.     if(msg.from_ext && !(msg.hdr.attr&MSG_ANONYMOUS))
  283.         fprintf(out," #%s",msg.from_ext);
  284.     if(msg.from_net.addr)
  285.         fprintf(out," (%s)",msg.from_net.type==NET_FIDO
  286.             ? faddrtoa(*(faddr_t *)msg.from_net.addr)
  287.                 : msg.from_net.addr);
  288.     fprintf(out,"\r\nDate : %.24s %s"
  289.         ,timestr((time_t *)&msg.hdr.when_written.time)
  290.         ,zonestr(msg.hdr.when_written.zone));
  291.     fprintf(out,"\r\n\r\n"); }
  292.  
  293. buf=smb_getmsgtxt(&smb,&msg,tails);
  294. if(buf) {
  295.     lfputs(buf,out);
  296.     LFREE(buf); }
  297. else if(smb_getmsgdatlen(&msg)>2)
  298.     errormsg(WHERE,ERR_ALLOC,smb.file,smb_getmsgdatlen(&msg));
  299. fclose(out);
  300. }
  301.  
  302.  
  303. /****************************************************************************/
  304. /* Returns total number of posts in a sub-board                             */
  305. /****************************************************************************/
  306. ulong getposts(uint subnum)
  307. {
  308.     char str[128];
  309.     ulong l;
  310.  
  311. sprintf(str,"%s%s.SID",sub[subnum]->data_dir,sub[subnum]->code);
  312. l=flength(str);
  313. if((long)l==-1)
  314.     return(0);
  315. return(l/sizeof(idxrec_t));
  316. }
  317.  
  318. /****************************************************************************/
  319. /* Returns message number posted at or after time                            */
  320. /****************************************************************************/
  321. ulong getmsgnum(uint subnum, time_t t)
  322. {
  323.     int     i;
  324.     ulong    l,total,bot,top;
  325.     smbmsg_t msg;
  326.  
  327. if(!t)
  328.     return(0);
  329.  
  330. sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
  331. smb.retry_time=smb_retry_time;
  332. if((i=smb_open(&smb))!=0) {
  333.     errormsg(WHERE,ERR_OPEN,smb.file,i);
  334.     return(0); }
  335.  
  336. total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
  337.  
  338. if(!total) {           /* Empty base */
  339.     smb_close(&smb);
  340.     return(0); }
  341.  
  342. if((i=smb_locksmbhdr(&smb))!=0) {
  343.     smb_close(&smb);
  344.     errormsg(WHERE,ERR_LOCK,smb.file,i);
  345.     return(0); }
  346.  
  347. if((i=smb_getlastidx(&smb,&msg.idx))!=0) {
  348.     smb_close(&smb);
  349.     errormsg(WHERE,ERR_READ,smb.file,i);
  350.     return(0); }
  351.  
  352. if(msg.idx.time<=t) {
  353.     smb_close(&smb);
  354.     return(msg.idx.number); }
  355.  
  356. bot=0;
  357. top=total;
  358. l=total/2; /* Start at middle index */
  359. clearerr(smb.sid_fp);
  360. while(1) {
  361.     fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET);
  362.     if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
  363.         break;
  364.     if(bot==top-1)
  365.         break;
  366.     if(msg.idx.time>t) {
  367.         top=l;
  368.         l=bot+((top-bot)/2);
  369.         continue; }
  370.     if(msg.idx.time<t) {
  371.         bot=l;
  372.         l=top-((top-bot)/2);
  373.         continue; }
  374.     break; }
  375. smb_close(&smb);
  376. return(msg.idx.number);
  377. }
  378.  
  379. /****************************************************************************/
  380. /* Returns the time of the message number pointed to by 'ptr'               */
  381. /****************************************************************************/
  382. time_t getmsgtime(uint subnum, ulong ptr)
  383. {
  384.     char    str[128];
  385.     int     i;
  386.     long    l;
  387.     smbmsg_t msg;
  388.     idxrec_t lastidx;
  389.  
  390. sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
  391. smb.retry_time=smb_retry_time;
  392. if((i=smb_open(&smb))!=0) {
  393.     errormsg(WHERE,ERR_OPEN,smb.file,i);
  394.     return(0); }
  395. if(!filelength(fileno(smb.sid_fp))) {            /* Empty base */
  396.     smb_close(&smb);
  397.     return(0); }
  398. msg.offset=0;
  399. msg.hdr.number=0;
  400. if(smb_getmsgidx(&smb,&msg)) {                /* Get first message index */
  401.     smb_close(&smb);
  402.     return(0); }
  403. if(!ptr || msg.idx.number>=ptr) {            /* ptr is before first message */
  404.     smb_close(&smb);
  405.     return(msg.idx.time); }                 /* so return time of first msg */
  406.  
  407. if(smb_getlastidx(&smb,&lastidx)) {              /* Get last message index */
  408.     smb_close(&smb);
  409.     return(0); }
  410. if(lastidx.number<ptr) {                    /* ptr is after last message */
  411.     smb_close(&smb);
  412.     return(lastidx.time); }                 /* so return time of last msg */
  413.  
  414. msg.idx.time=0;
  415. msg.hdr.number=ptr;
  416. if(!smb_getmsgidx(&smb,&msg)) {
  417.     smb_close(&smb);
  418.     return(msg.idx.time); }
  419.  
  420. if(ptr-msg.idx.number < lastidx.number-ptr) {
  421.     msg.offset=0;
  422.     msg.idx.number=0;
  423.     while(msg.idx.number<ptr) {
  424.         msg.hdr.number=0;
  425.         if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr)
  426.             break;
  427.         msg.offset++; }
  428.     smb_close(&smb);
  429.     return(msg.idx.time); }
  430.  
  431. ptr--;
  432. while(ptr) {
  433.     msg.hdr.number=ptr;
  434.     if(!smb_getmsgidx(&smb,&msg))
  435.         break;
  436.     ptr--; }
  437. smb_close(&smb);
  438. return(msg.idx.time);
  439. }
  440.  
  441.  
  442. /****************************************************************************/
  443. /* Returns the total number of msgs in the sub-board and sets 'ptr' to the  */
  444. /* number of the last message in the sub (0) if no messages.                */
  445. /****************************************************************************/
  446. ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
  447. {
  448.     char        str[256];
  449.     int         i;
  450.     ulong        total;
  451.     idxrec_t    idx;
  452.  
  453. if(ptr)
  454.     (*ptr)=0;
  455. if(t)
  456.     (*t)=0;
  457. if(subnum>=total_subs)
  458.     return(0);
  459.  
  460. sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
  461. smb.retry_time=smb_retry_time;
  462. if((i=smb_open(&smb))!=0) {
  463.     errormsg(WHERE,ERR_OPEN,smb.file,i);
  464.     return(0); }
  465.  
  466. if(!filelength(fileno(smb.sid_fp))) {            /* Empty base */
  467.     smb_close(&smb);
  468.     return(0); }
  469. if((i=smb_locksmbhdr(&smb))!=0) {
  470.     smb_close(&smb);
  471.     errormsg(WHERE,ERR_LOCK,smb.file,i);
  472.     return(0); }
  473. if((i=smb_getlastidx(&smb,&idx))!=0) {
  474.     smb_close(&smb);
  475.     errormsg(WHERE,ERR_READ,smb.file,i);
  476.     return(0); }
  477. total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
  478. smb_unlocksmbhdr(&smb);
  479. smb_close(&smb);
  480. if(ptr)
  481.     (*ptr)=idx.number;
  482. if(t)
  483.     (*t)=idx.time;
  484. return(total);
  485. }
  486.  
  487.