/*   wgsrptu.C
 *
 *   Dumps user account information to delimited text file
 *   for import into external databases.
 *
 *   Command line:
 *       WGSRPTU [-Dx]
 *   -D is an optional delimeter character. Default is comma
 */

#define FILREV "$Revision: 1.0 $"
#define VERS "1.1"

#include "gcomm.h"
#include "majorbbs.h"
#include "gcspsrv.h"
#include "excphand.h"
#include "wgsuext.h"
#define NMQSTS        10           // max number of additional sign-up questions
#define ANSSIZ        80           // answer size

void procUserDat(void);
GBOOL dumpAcct(struct usracc *ap);
VOID outitem(CHAR *stg);
VOID ReadUext(void);
VOID ReadSup(void);
CHAR *SQLFixup(CHAR *stg);
CHAR * StrReplace(char *Str, char *OldStr, char *NewStr);
VOID shostx(VOID);

                                     /* command line parameter help message */
static CHAR parhlp[]="\nSyntax:  WGSRPTU [-Dx] [?]\n";

CHAR delim=',';
CHAR outfile[]="userlist.txt";
DFAFILE *accbb;                    /* Btrieve data block ptr for "keys" file    */
DFAFILE *genbb;                    /* generic user data file btrieve file p*/
DFAFILE *dfaUserExt;               /* user account extension database */
struct usracc uacct;               /* user account structure               */
struct uaccext uaccext;       // User account extension buffer
struct supbuf {
    CHAR userid[UIDSIZ];     // User-ID
    CHAR modnam[MNMSIZ];     // Module Name ("WGSSUP - AddlQues")
    CHAR answer[NMQSTS][ANSSIZ]; // answers to questions
} supbuf;

// ASCII file stuff
FILE *outfp;
long reccnt=0;
long wreccnt=0;

// Stuff for Keys
static VOID dspkey(CHAR *keyr,INT ring);
static INT getkey(CHAR *uid);
CHAR *keytmp;                      /* buffer for loading in the key data   */
DFAFILE *bfp,                      /* btrieve file pointer                 */
        *bfp2,                     /* btrieve file pointer                 */
        *keybb;                    /* user keys btrieve file ptr           */

INT
main(
INT argc,
CHAR *argv[])
{
TRY
     INT i;
     (VOID)argc;
#ifdef GCWINNT
//  Let's let them run while system is up
//     if (!canRunUtil()) {
//          MessageBox(NULL,"\nUnable to proceed, another Worldgroup process is active.",
//                    argv[0],MB_ICONSTOP|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
//          return(1);
//     }
#else
     (VOID)argv;
#endif // GCWINNT

     initvid(); // Because Gcomm uses their own printf() fuction, need initvid() or GPs on first printf
     printf("WSGRPTU. User Account Database Export Utility.  Version %s\n",VERS);
     ansion(0);
     for (i=1 ; i < argc ; i++) {
          if (*argv[i] == '-') {
               switch (toupper(argv[i][1])) {
               case 'D':
                    delim=argv[i][2];
                    break;
               default:
                    shostx();
               }
          }
          else {
               shostx();
          }
     }

  // open output
     if ((outfp=fopen(outfile,"w")) == NULL) {
         printf("CANNOT OPEN OUTPUT FILE %s\n",outfile);
         exit(1);
     }
     printf("Creating output file %s\n",outfile);

  // Main Loop
     reccnt=0;
     wreccnt=0;
     procUserDat();

  // cleanup
     printf("%s read. %s written.  \n", spr("%ld",reccnt), spr("%ld",wreccnt));
     printf("\ndone.\n");
     fclose(outfp);

     //MessageBox(NULL,"\nProgram complete.",argv[0],MB_ICONINFORMATION|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
     return(0);

EXCEPT
#ifdef GCWINNT
     return(1);
#endif // GCWINNT
}

void
procUserDat(void)       // Process user file
{
   INT i;
// Open files
   keytmp=alcmem(RINGSZ);
   dfaUserExt=dfaOpen(UACCEXTDAT,sizeof(struct uaccext),NULL);
   genbb=dfaOpen("wgsgen2.dat",GENSIZ,NULL);
   keybb=dfaOpen("wgskey2.dat",RINGSZ,NULL);
   accbb=dfaOpen("wgsusr2.dat",sizeof(struct usracc),NULL);

// header line
   outitem("userid");
   outitem("name");
   outitem("address 1");
   outitem("address 2");
   outitem("address 3");
   outitem("address 4");
   outitem("phone");
   outitem("e-mail");
   outitem("password");
   outitem("password hint");
   outitem("systyp");
   outitem("prefflags");
   outitem("ansiflags");
   outitem("Screen Width");
   outitem("Screen length");
   outitem("Screen FSE length");
   outitem("age");
   outitem("sex");
   outitem("creation date");
   outitem("lastuse date");
   outitem("perm class");
   outitem("current class");
   outitem("current class days left");
   outitem("forgive days");
   outitem("credits");
   outitem("total credits");
   outitem("total paid credits");
   outitem("birthday");
   outitem("keys");
   for (i=0; i < NMQSTS; i++)
      outitem(spr("Q%d",i));
   fprintf(outfp, "\"timestamp\"\n");

// Main Loop
   dfaSetBlk(accbb);
   if (dfaQueryLO(0)) {
      do {
         //printf("processing record %d\r", reccnt+1);
         dfaAbsRec( &uacct, 0);
         ReadUext();
         ReadSup();
         if  (dumpAcct(&uacct))
           ++wreccnt;
         ++reccnt;
      } while (dfaQueryNX());
   }

// Close files
   dfaClose( accbb );
   dfaClose(keybb);
}

VOID
ReadUext(void)
{
   dfaSetBlk(dfaUserExt);
   setmem(&uaccext,sizeof(struct uaccext),0);
   if (!dfaAcqEQ(&uaccext,uacct.userid,0)) {
      uaccext.alteml[0]=' ';
      uaccext.pwdhint[0]=' ';
   }
   dfaAcqEQ(&uaccext,uacct.userid,0);
   dfaRstBlk();
}

VOID
ReadSup(void)
{
   INT i;
   dfaSetBlk(genbb);
   setmem(&supbuf,sizeof(struct supbuf),0);
   stzcpy(supbuf.userid,uacct.userid,UIDSIZ);
   stzcpy(supbuf.modnam,"WGSSUP - AddlQues",MNMSIZ);
   if (!dfaAcqEQ(&supbuf,&supbuf,0)) {
      for (i=0; i < NMQSTS; i++)
         supbuf.answer[i][0]= ' ';
   }
   dfaRstBlk();
}

GBOOL
dumpAcct(
struct usracc *ap)
{
     static CHAR credat[sizeof("MM/DD/YYYY")+1];
     static CHAR usedat[sizeof("MM/DD/YYYY")+1];
     static CHAR birthd[sizeof("MM/DD/YYYY")+1];
     INT i;

// detail lines
   outitem(ap->userid);
   outitem(ap->usrnam);
   outitem(ap->usrad1);
   outitem(ap->usrad2);
   outitem(ap->usrad3);
   outitem(ap->usrad4);
   outitem(ap->usrpho);
   outitem(uaccext.alteml);
   outitem(ap->psword);
   outitem(uaccext.pwdhint);
   outitem(ltoa(ap->systyp));
   outitem(ltoa(ap->usrprf));
   outitem(ltoa(ap->ansifl));
   outitem(ltoa(ap->scnwid));
   outitem(ltoa(ap->scnbrk));
   outitem(ltoa(ap->scnfse));
   outitem(ltoa(ap->age));
   outitem((ap->sex=='M') ? "M" : "F");
   strcpy(credat,ncdatel(ap->credat));
   outitem(credat);
   strcpy(usedat,ncdatel(ap->usedat));
   outitem(usedat);
   outitem(ap->prmcls);
   outitem(ap->curcls);
   outitem(ltoa(ap->daystt));  //   outitem(ncdate(today()+ap->daystt));
   outitem(ltoa(ap->fgvdys));
   outitem(ltoa(ap->creds));
   outitem(ltoa(ap->totcreds));
   outitem(ltoa(ap->totpaid));
   strcpy(birthd,strBirthdate(ap->birthd));
   outitem((birthd[0]=='\0') ? "01/01/2000" : spr("%s",birthd));

// Dump keys for this user
   dspkey(ap->userid,0);

// Dump additional singup questions
   for (i=0; i < NMQSTS; i++)
       outitem(supbuf.answer[i]);
   fprintf(outfp, "\"%s-%s\"\n",ncdatel(today()),nctime(now()));

   return(TRUE);
}

VOID
outitem(CHAR *stg)
{
   fprintf(outfp, "\"%s\"%c",SQLFixup(stg),delim);
}

static
VOID
dspkey(                            /* display a rough list of keys in list */
CHAR *keyr,                             /* keyring name to display (or UID)*/
INT ring)                               /* is it a keyring? (0 or 1)       */
{
     CHAR *ptr,keyring[UIDSIZ];

     if (ring) {
          keyring[0]=RINGID;
          strcpy(keyring+1,keyr);
     }
     else {
          strcpy(keyring,keyr);
     }
     if (!getkey(keyring)) {
          outitem(" "); // no keys
          return;
     }
     ptr=&keytmp[KLSTOF];
     if (*ptr == '\0') {
          outitem(" "); // no keys
          return;
     }
     outitem(ptr);
}

static
INT
getkey(                            /* get a list of keys from BTRIEVE      */
CHAR *uid)                              /* user-id or keyring name to get  */
{
     INT acq;
     dfaSetBlk(keybb);
     acq=dfaAcqEQ(keytmp,uid,0);
     dfaRstBlk();
     return(acq);
}

CHAR *
SQLFixup(CHAR *stg)
// Certain character will screw up sql, so replace. (single quote, double quote, pipe)
{
   CHAR *s;
#pragma warn -pia
   s=stg; while (s=StrReplace(s,"\'",","));  // note drop single quotes
   s=stg; while (s=StrReplace(s,"\"",",")); // note drop double quotes
   s=stg; while (s=StrReplace(s,"|","\\"));
#pragma warn +pia
   return(stg);
}

CHAR *   // Returns pointer to first location behind where NewStr was inserted
         // or NULL if OldStr was not found. This is useful for multiple replacements.
         // Eventually put this in \gcommlib
StrReplace(char *Str, char *OldStr, char *NewStr)
/*
 * StrReplace: Replace OldStr by NewStr in string Str.
 *
 * Str should have enough allocated space for the replacement, no check
 * is made for this. Str and OldStr/NewStr should not overlap.
 * The empty string ("") is found at the beginning of every string.
 *
 * Returns: pointer to first location behind where NewStr was inserted
 * or NULL if OldStr was not found.
 * This is useful for multiple replacements.
 * (be careful not to replace the empty string this way !)
 */
{
      int OldLen, NewLen;
      char *p, *q;

#pragma warn -pia
      if(!(p = strstr(Str, OldStr)))
#pragma warn +pia           
            return p;
      OldLen = strlen(OldStr);
      NewLen = strlen(NewStr);
      memmove(q = p+NewLen, p+OldLen, strlen(p+OldLen)+1);
      memcpy(p, NewStr, NewLen);
      return q;
}

GBOOL                              /*   returns TRUE if modified           */
fixBirthdate(                      /* fix date from MM/DD/YY to YYYYMMDD   */
CHAR *strDate)                     /*   birth date string (must be DATSIZ) */
{
     INT m,d,y;

     ASSERT(strDate != NULL);
     if (!alldgs(strDate)
      && sscanf(strDate,"%d/%d/%d",&m,&d,&y) == 3) {
          y+=1900;
          sDateEncode(y,m,d,strDate,DATSIZ);
          return(TRUE);
     }
     return(FALSE);
}

const CHAR *                       /*   returns pointer to static buffer   */
strBirthdate(                      /* format birthdate into "MM/DD/YYYY"   */
const CHAR *strDate)               /*   birth date string                  */
{
     INT y,m,d;
     static CHAR retBuf[LDATSIZ];

     ASSERT(strDate != NULL);
     fixBirthdate(stlcpy(retBuf,strDate,DATSIZ));
     sDateDecode(retBuf,&y,&m,&d);
     if (y < 0 || m < 0 || d < 0) {
          return("");
     }
     return(prnDate(y,m,d,retBuf,LDATSIZ,PRND_MDYY,'/'));
}


VOID
shostx(VOID)                         /* help message for bungling operators */
{
     printf(parhlp);
     clsvid();
     exit(1);
}

