/***************************************************************************
 *                                                                         *
 *   NNTPUTIL.C                                                            *
 *                                                                         *
 *   Copyright (c) 1995-1997 Galacticomm, Inc.  All rights reserved.       *
 *                                                                         *
 *   Utility functions related to NNTP.                                    *
 *                                                                         *
 *                               6/26/95 - Bert Love,                      *
 *                                         Ilya Minkin &                   *
 *                                         Charles Dunn                    *
 *                                                                         *
 ***************************************************************************/

#include <sys\timeb.h>
#include "gcomm.h"
#include "majorbbs.h"
#include "gme.h"
#include "tcpip.h"
#include "dns.h"
#include "alias.h"
#include "smtpexp.h"
#include "nntp.h"
#include "smnnhook.h"

#define FILREV "$Revision: 13 $"

static INT filegs(CHAR *bf,UINT len,FILE *fp);

GBOOL                              /*   returns: FALSE when done           */
uuencode(                          /* UUENCODE 'inf' into 'outf' (cycled)  */
FILE *inf,
FILE *outf)
{
     CHAR buf[LINSIZ];
     INT n;
     register INT i,j;
     register UINT c1,c2,c3,c4;
     UINT e1,e2,e3,e4;

     for (j=0 ; j < NUMLINS ; j++) {
          setmem(buf,sizeof(buf),0);
          n=filegs(buf,45,inf);
          fputc(ENC(n),outf);
          for (i=0 ; i < n ; i+=3) {
               c1=buf[i] >> 2;
               c2=((buf[i] << 4) & 060) | ((buf[i+1] >> 4) & 017);
               c3=((buf[i+1] << 2) & 074) | ((buf[i+2] >> 6) & 03);
               c4=((buf[i+2]) & 077);
               if ((e1=ENC(c1)) == ' ') {
                    e1='`';
               }
               if ((e2=ENC(c2)) == ' ') {
                    e2='`';
               }
               if ((e3=ENC(c3)) == ' ') {
                    e3='`';
               }
               if ((e4=ENC(c4)) == ' ') {
                    e4='`';
               }
               fputc(e1,outf);
               fputc(e2,outf);
               fputc(e3,outf);
               fputc(e4,outf);
          }
          if (n <= 0) {
               fprintf(outf,"`\r\nend\r\n");
               return(FALSE);
          }
          else {
               fprintf(outf,"\r\n");
          }
     }
     return(TRUE);
}

static INT
filegs(                            /* Get 'len' chars from 'fp'            */
CHAR *bf,
UINT len,
FILE *fp)
{
     register INT ic;
     register UINT i;

     for (i=0 ; i < len ; i++) {
          ic=fgetc(fp);
          if (ic == EOF) {
               return(i);
          }
          *bf++=ic;
     }
     return(len);
}

VOID
cvtFrom(                           /* convert From addr to internet format */
CHAR *dst,                         /*   destination buffer (must be MAXADR)*/
const CHAR *src)                   /*   source buffer                      */
{
     stlcpy(dst,src,MAXADR);
     if (!xltGME2Int(dst)) {
          stlcpy(dst,(*alsofusr)((CHAR *)src),MAXADR);
          stlcat(dst,"@",MAXADR);
          stlcat(dst,smtpHost(),MAXADR);
     }
}

GBOOL
curHost(                           /* is name one of our host's aliases?   */
const CHAR *name)
{
     return(sameas(name,domain) || sameas(name,hstdom));
}

GBOOL
nntval(                            /* is this a valid Usenet address?      */
const CHAR *addr)                  /*   address to check                   */
{
     return(strchr(addr,'@') == NULL && strchr(addr,'!') == NULL
         && strchr(addr,' ') == NULL && strchr(addr,'.') != NULL);
}

VOID
add2db(                            /* adds new record to database          */
const struct message *msg,         /*   GME format message header          */
const CHAR *idstr)                 /*   rfc822 format message ID           */
{
     struct cmpkey ckey;
     struct midinf midinf;
     USHORT tim,cof;

     if (msg->forum == EMLID) {
          return;
     }
     dfaSetBlk(midbb);
     ckey.forum=msg->forum;
     ckey.msgidx=LASTI;
     if (!dfaAcqLT(&midinf,&ckey,FIDKEY) || midinf.forum != msg->forum) {
          midinf.msgidx=0L;
     }
     ++midinf.msgidx;
     midinf.midcrc=crc32(idstr,strlen(idstr));
     midinf.forum=msg->forum;
     midinf.globid=msg->gmid;
     midinf.thrid=msg->thrid;
     tim=msg->crtime;
     cof=cofdat(msg->crdate);
     midinf.timadd=315532800L           /* 00:00 1/1/70 to 00:00 1/1/80    */
                  +cof*86400L           /* 00:00 1/1/80 to 00:00 msg day   */
                  +dthour(tim)*3600L    /*  \                              */
                  +dtmin(tim)*60L       /*   > compute time since          */
                  +dtsec(tim);          /*  /  00:00 on msg day            */
     stzcpy(midinf.midstr,idstr,MIDSIZ);
     if (dfaAcqEQ(NULL,&midinf.globid,MSGKEY)) {
          dfaUpdate(&midinf);
     }
     else {
          dfaInsert(&midinf);
     }
     dfaRstBlk();
}

const CHAR *
getref(                            /* get reference to message             */
const struct message *msg)
{
     CHAR *retval=NULL;
     static struct midinf mid;

     dfaSetBlk(midbb);
     if (msg->rplto.sysid != 0L && msg->rplto.msgid != 0L) {
          if (dfaAcqEQ(&mid,&msg->rplto,MSGKEY)) {
               retval=mid.midstr;
          }
     }
     dfaRstBlk();
     return(retval);
}

/*
 *   Hook Management Functions
 */

GBOOL                              /*   returns TRUE if hook set           */
nntpHook(                          /* set a NNTP function hook             */
INT hooktype,                      /*   type of hook to set                */
voidfunc hookfunc,                 /*   hook function pointer              */
SHORT hookpri)                     /*   priority (0=normal >0=high <0=low) */
{
     return(HookAdd(hooktype,hookfunc,hookpri));
}

GBOOL                              /*   returns TRUE to halt processing    */
hookHandleExp(                     /* handle exported message              */
INT * pRet,                        /*   GME status code                    */
struct message * pMsg,             /*   header of message to send off      */
CHAR const ** pTo,                 /*   to field                           */
CHAR const ** pAtt,                /*   path+file name of attachment       */
CHAR ** pText,                     /*   message text buffer                */
size_t TextBufSize)                /*   current text buffer size           */
{
     INT i;
     smtphook_export hook;
     GBOOL stopped;

     i=NOIDX;
     stopped=FALSE;
     while ((i=HookNext(SMTPHOOK_EXPORT,i)) != NOIDX && !stopped) {
          hook=(smtphook_export)(HookArr[i].hookfunc);
          *pRet=GMEAGAIN;
          stopped=(*hook)(pRet,pMsg,pTo,pAtt,pText,TextBufSize);
     }
     return(stopped && *pRet != GMEAGAIN);
}
