/////////////////////////////////////////////////////////////////////////////
//
//   TLCWOR.CPP
//
//   Copyright (c) 1997  Galacticomm, Inc.        All Rights Reserved
//
//   Worldlink Teleconference Extension
//   Client Implementation
//                                               - Phil Henning 7/7/97
//
/////////////////////////////////////////////////////////////////////////////

#include "gcomm.h"
#include "majorbbs.h"
#include "tlcwor.h"
#include "tlcwfda.h"
#include "worlnk.h"
#include "worldlnk.h"
#include "wortlc.h"
#include "tlcdyncm.h"
#include "tlcdcmd.h"

#define FILREV "$Revision: 55 $"

#define WLTSMBCACHE   10

typedef struct wlusrflgdsk {
     CHAR userid[UIDSIZ];
     SHORT flags;
} WLUSRFLGDSK, *LPWLUSRFLGDSK;

typedef struct wlusrflg {
     SHORT flags;
} WLUSRFLG, *LPWLUSRFLG;


SHORT
doWorldCmd(
LPCMDPARAM param);

CMDSTRUCT worldCommand={
     "WORLD",
     "/W",
     TRUE,
     FALSE,
     NULL,
     NULL,
     doWorldCmd
};

const SHORT BOARD_NOTIFY      =0x0001;
const SHORT WLUSR_LOGON       =0x0002;
const SHORT WLUSR_LOGOFF      =0x0004;
const SHORT BOARD_LOGON_MSG   =0x0008;

const SHORT WLCHAN_NOSUCH     =-1;

SHORT dftflags;

VOID wortlcRemoveWLUsers(const CHAR* channel);
LPCHANINFO wortlcFindChannel(SHORT chn);
VOID wortlcCreateChan(LPWORCHN chaninf);
VOID wortlcRemoveChannel(const CHAR* channel);
VOID wortlcRemoveWLNodeUsers(CHAR* node);
VOID wortlcListBoards(VOID);
VOID wortlcListOnBoard(const CHAR* board);
GBOOL wortlclon(VOID);
VOID wortlcend(VOID);
VOID UpdateWLUsrProfile(LPWLUSRFLGDSK user);
GBOOL ToggleFlagSHORT(SHORT* flag,SHORT flagbit);
VOID wortlcInfoOnBoard(const CHAR* board);
VOID wortlcGetUserMods(const CHAR* board);
VOID NotifyHub(GBOOL logon);
VOID csWorConnect(VOID);
SHORT wortlcChannelToNum(const CHAR* channel);


INT wortlcGlobalFunctions(VOID);
VOID wortlcGlobalHelp(VOID);
INT (*oldGlobals)(VOID);
VOID (*oldGlobalHelp)(VOID);
VOID (*oldadd)(const CHAR*);
VOID (*oldrem)(const CHAR*);
VOID (*oldinv)(const WORUSER* pwu, GBOOL isInvis);
GBOOL (*oldvrfy)(const CHAR* user);
GBOOL (*oldison)(const CHAR* user);
VOID (*oldent)(const CHAR*);
VOID (*oldext)(const CHAR*);
GBOOL (*olddelhook)(const CHAR*);


VOID UsrAdd(const CHAR* userid);
VOID UsrRemove(const CHAR* userid);
VOID InvToggle(const WORUSER* pwu, GBOOL isInvis);
GBOOL worPalVrfy(const CHAR* user);
GBOOL worPalIson(const CHAR* user);
VOID wlent(const CHAR* uid);
VOID wlext(const CHAR* uid);
GBOOL wlusrdelhook(const CHAR* uid);


HMCVFILE wortlcmsg;
DFAFILE* dfaWlusr;
CHAR* tlcworbuf;
GBOOL wlchndft;

CHAR* primaryList;
CHAR* secondaryList;

CHAR* primaryRating;
CHAR* secondaryRating;

LPWLUSRFLG wlusr;
CSmb* pSmbUsers;

struct module wltlcmod={
     "",
     wortlclon,
     NULL,
     dfsthn,
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
     wortlcend
};

WORMODULE wortlcmod={
     WORAPID,
     WORAPNM,
     worTlcConnect,
     worTlcDisconnect,
     worNodeConnect,
     worNodeDisconnect,
     worCmdHdl,
     worSqCmdHdl
};

INT iWorTrans;

MARKSOURCE(tlcwor);

VOID EXPORT
init__galtlcw()
{
     INT rating;

     worInitialize();
     init__galtele();
     iWorTrans=tlcTransRegister("WorldLink",&transWor);
     hook_connect(csWorConnect);
     worRegisterModule(&wortlcmod);
     oldGlobals=worGlobalHDL;
     worGlobalHDL=wortlcGlobalFunctions;

     oldGlobalHelp=worGlobalHelpHDL;
     worGlobalHelpHDL=wortlcGlobalHelp;

     wortlcmsg=opnmsg("WORTLC.MCV");
     dfaWlusr=dfaOpen("WORTUSR.DAT",sizeof(WLUSRFLGDSK),NULL);
     stzcpy(wltlcmod.descrp,gmdnam("GALTLCW.MDF"),MNMSIZ);
     wlusr=static_cast<LPWLUSRFLG>(alczer(sizeof(WLUSRFLG)*nterms));
     register_module(&wltlcmod);
     /* set hooks */
     oldadd=worUsrAddHook;
     worUsrAddHook=UsrAdd;
     oldrem=worUsrRemHook;
     worUsrRemHook=UsrRemove;
     oldinv=worUserInvis;
     worUserInvis=InvToggle;
     oldvrfy=palvrfyhook;
     palvrfyhook=worPalVrfy;
     oldison=palisonhook;
     palisonhook=worPalIson;
     oldent=tlcenter;
     tlcenter=wlent;
     oldext=tlcexit;
     tlcexit=wlext;
     if (ynopt(DOBNOT)) {
          dftflags|=BOARD_NOTIFY;
     }
     if (ynopt(DOULON)) {
          dftflags|=WLUSR_LOGON;
     }
     if (ynopt(DOULOF)) {
          dftflags|=WLUSR_LOGOFF;
     }
     if (ynopt(DOBLOGN)) {
          dftflags|=BOARD_LOGON_MSG;
     }
     olddelhook=worPreUsrDelHook;
     worPreUsrDelHook=wlusrdelhook;
     primaryList=stgopt(WORALST);
     secondaryList=stgopt(WORALST2);
     rating=tokopt(ACTRATE,"UNRESTRICTED","ADULT","YOUTH","CHILD",NULL);
     if (rating == -1) {
        catastro("Invalid Action List Rating");
     }
     primaryRating=worRatings[rating-1];
     rating=tokopt(ACTRATE2,"UNRESTRICTED","ADULT","YOUTH","CHILD",NULL);
     if (rating == -1) {
        catastro("Invalid Action List Rating");
     }
     secondaryRating=worRatings[rating-1];
     tlcworbuf=static_cast<CHAR*>(alczer(WBUFSZ));
     pSmbUsers = new CSmb(sizeof(JINFSTR),smbUserSmbKey,WLTSMBCACHE);
     wlchndft=ynopt(USEWLCH);
     tlcCommandRegister(&worldCommand);
}

GBOOL
wortlclon(VOID)
{
     WLUSRFLGDSK user;

     dfaSetBlk(dfaWlusr);
     if (!dfaAcqEQ(&user,usaptr->userid,0)) {
          memset(&user,0,sizeof(WLUSRFLGDSK));
          stlcpy(user.userid,usaptr->userid,UIDSIZ);
          user.flags=dftflags;
          dfaInsert(&user);
     }
     wlusr[usrnum].flags=user.flags;
     dfaRstBlk();
     if (!(usrptr->flags&WSGCSU)) {
          NotifyHub(TRUE);
          if (wlusr[usrnum].flags&BOARD_LOGON_MSG) {
               wortlcListBoards();
          }
     }
     return(0);
}

VOID
csWorConnect(VOID)
{
     NotifyHub(TRUE);
}

VOID
NotifyHub(
GBOOL logon)
{
     JINFSTR jinfo;
     WORUSER wu;

     if (worConnected()) {
          memset(&jinfo,0,sizeof(JINFSTR));
          jinfo.Nodenumber=worNodeNUM;
          jinfo.chn=-1;
          if (worGetUserInfo(&wu,usaptr->userid)) {
               jinfo.unum=wu.UserNumber;
               jinfo.tlcunum=tlcUserFindID(usaptr->userid);
               worSendFDA(WORAPID,logon ? WORCMD_ADDUSER : WORCMD_REMOVEUSER,
                          sizeof(JINFSTR),&jinfo,jinfoFDA);
          }
     }
}

VOID
wortlcend(VOID)
{
     clsmsg(wortlcmsg);
     dfaClose(dfaWlusr);
}

WORCONNECT
worTlcConnect()
{
     JINFSTR jinfo;
     LPUSRSTRUCT pUser;
     WORUSER wu;

     // Get lists of channels
     worSend(WORAPID,WORCMD_GETCHAN,0,NULL);
     // Get list of users and their channels
     worSend(WORAPID,WORCMD_GETUSERS,0,NULL);
     jinfo.chn=-1;
     jinfo.Nodenumber=worNodeNUM;

     pUser=tlcUserGetFirst();
     while (pUser != NULL) {
          if (pUser->m_iUsrnum == -1) {
               if (worGetUserInfo(&wu,pUser->m_pszName)) {
                    jinfo.unum=wu.UserNumber;
                    jinfo.tlcunum=tlcUserFindID(pUser->m_pszName);
                    worSendFDA(WORAPID,WORCMD_ADDUSER,sizeof(JINFSTR),&jinfo,jinfoFDA);
               }
          }
          pUser=tlcUserGetNext();
     }
     for (int i=0 ; i < nterms ; i++) {
          if (usroff(i)->usrcls == ACTUSR) {
               if (worGetUserInfo(&wu,uacoff(i)->userid)) {
                    jinfo.unum=wu.UserNumber;
                    jinfo.tlcunum=tlcUserFindID(uacoff(i)->userid);
                    worSendFDA(WORAPID,WORCMD_ADDUSER,sizeof(JINFSTR),&jinfo,jinfoFDA);
               }
          }
     }
     if (wlchndft) {
          tlcSetDefaultChannel(worDomain());
     }
}

WORDISCONNECT
worTlcDisconnect()
{
     LPCHANINFO pChannel;
     CHAR chan[CHAN_MAX_SIZE];

     setmbk(msgTlc);
     pChannel=tlcChannelGetFirst();
     while (pChannel != NULL) {
          stlcpy(chan,pChannel->m_strName,CHAN_MAX_SIZE);
          if ((pChannel->m_type)&CHAN_TYPE_WL_PUBLIC) {
               wortlcRemoveWLUsers(pChannel->m_strName);
               tlcChannelMoveAllUsers(pChannel->m_strName
                  ,tlcGetDefaultChannel(),CHAN_SWITCH_NODE_LOGOFF,NKICKO2);
               pChannel=tlcChannelGetInfo(chan);
               wortlcRemoveChannel(pChannel->m_strName);
          }
          pChannel=tlcChannelGetGT(chan);
     }
     while (pSmbUsers->GetLow(0) != NULL) {
          pSmbUsers->Delete();
     }
     rstmbk();
     if (wlchndft) {
          tlcSetDefaultChannel("");
     }
}

WORNODECONNECT
worNodeConnect(
const WORNODE* node)
{
     if (worNodeSquelched(node->ID)) {
          return;
     }
     setmbk(wortlcmsg);
     for (int i=0 ; i < nterms ; i++) {
          othusp=usroff(i);
          if (onsysn(uacoff(i)->userid,1) && othusp->usrcls == ACTUSR
              && !(othusp->flags&ISGCSU)
              && wlusr[othusn].flags&BOARD_NOTIFY
              && !(othusp->flags&NOINJO)
              && worRatingHaskeyUseridBynum(uacoff(i)->userid,node->Rating)) {
               prfmlt(NODCON4,node->ID,
                    ((*(node->Name)) == '\0') ? " " : spr("%s",node->Name));
               injoth();
          }
     }
     rstmbk();

}

WORNODEDISCONNECT
worNodeDisconnect(
const WORNODE* node)
{
     VOID* ptr;

     if (worNodeSquelched(node->ID)) {
          return;
     }
     setmbk(wortlcmsg);
     for (int i=0 ; i < nterms ; i++) {
          othusp=usroff(i);
          if (onsysn(uacoff(i)->userid,1) && othusp->usrcls == ACTUSR
              && !(othusp->flags&ISGCSU)
              && wlusr[othusn].flags&BOARD_NOTIFY
              && !(othusp->flags&NOINJO)
              && worRatingHaskeyUseridBynum(uacoff(i)->userid,node->Rating)) {
               prfmlt(NODDIS4,node->ID,
                    ((*(node->Name)) == '\0') ? " " : spr("%s",node->Name));
               injoth();
          }
     }
     rstmbk();
     while ((ptr=pSmbUsers->GetEqual(&node->Number,1)) != NULL) {
          LPJINFSTR jinfo=(LPJINFSTR)ptr;
          RemoveInviteNUM(jinfo->tlcunum,jinfo->Nodenumber);
          pSmbUsers->Delete();
     }
}

WORCOMMANDHANDLER
worCmdHdl(
SHORT cmdnum,
UINT length,
VOID* value)
{
     LPCHANINFO pChan;
     LPUSRSTRUCT pUser;
     LPUSRSTRUCT pToUser;
     SHORT chn;
     LPSPEAKINF spkinf;
     LPACTIONINF actioninf;
     LPJINFSTR jinfo;
     WORUSER wu;
     LPWORCHAT wchat;
     struct usracc* uaptr;
     CHAR useridfrom[TLCUIDSIZ];
     CHAR usrinfo[MNMSIZ+UIDSIZ+1];
     CHAR *amp, *mod, *user;

     INT i;
     WORNODE node;

     setmbk(msgTlc);
     (VOID)length;
     switch (cmdnum) {
     case WORCMD_CREATE_CHANNEL:
          worConvertFDA(worchnFDA);
          if (!worNodeSquelched(static_cast<LPWORCHN>(value)->worID)) {
               wortlcCreateChan(static_cast<LPWORCHN>(value));
          }
          break;
     case WORCMD_DELETE_CHANNEL:
          chn=*(static_cast<SHORT*>(value));
          if ((pChan=wortlcFindChannel(chn)) != NULL) {
               wortlcRemoveWLUsers(pChan->m_strName);
               tlcChannelMoveAllUsers(pChan->m_strName,tlcGetDefaultChannel()
                                     ,CHAN_SWITCH_NODE_LOGOFF,NKICKO2);
               wortlcRemoveChannel(pChan->m_strName);
          }
          break;
     case WORCMD_ACTION:
          worConvertFDA(actioninfFDA);
          actioninf=(LPACTIONINF)value;
          pChan=wortlcFindChannel(actioninf->chn);
          if (pChan != NULL) {
               if (actioninf->from == SYSUIDN) {
                    stzcpy(useridfrom,SYSUID,TLCUIDSIZ);
               }
               else {
                    stzcpy(useridfrom,worNumberToAlias(actioninf->from),TLCUIDSIZ);
               }
               if (*useridfrom != '\0') {
#ifdef DEBUG2
                    shocst("RECEIVED WORCMD_ACTION","From: %s",useridfrom);
#endif
                   WorChWLAction(actioninf,pChan->m_strName);
               }
          }
          break;
     case WORCMD_PUBLIC_SEND:
          worConvertFDA(speakinfFDA);
          spkinf=static_cast<LPSPEAKINF>(value);
          pChan=wortlcFindChannel(spkinf->chn);
          if (pChan != NULL) {
               if (spkinf->unumFrom == SYSUIDN) {
                    stzcpy(useridfrom,SYSUID,TLCUIDSIZ);
               }
               else {
                    stzcpy(useridfrom,worNumberToAlias(spkinf->unumFrom),TLCUIDSIZ);
               }
               if (*useridfrom != '\0') {
                    WorChWLRecv(pChan->m_strName,useridfrom,
                         worNumberToUserid(spkinf->unumTo),spkinf->msg,
                         spkinf->type,spkinf->iMsgNum,spkinf->ptr1,
                         spkinf->ptr2,spkinf->ptr3);
               }
          }
          break;
     case WORCMD_CHAT_NOTIFY:
          worConvertFDA(worchatFDA);
          wchat=static_cast<LPWORCHAT>(value);
          pUser=tlcUserGetInfo(worNumberToAlias(wchat->unumFrom));
          pToUser=tlcUserGetInfo(worNumberToUserid(wchat->unumTo));
          if (pToUser == NULL) {
               LONG tmp;
               tmp=wchat->unumFrom;
               wchat->unumFrom=wchat->unumTo;
               wchat->unumTo=tmp;
               wchat->error=cmdnum;
               worSendFDA(WORAPID,WORCMD_CHAT_NOTINTELE,sizeof(WORCHAT)
                         ,&wchat,worchatFDA);

          }
          else if (pUser != NULL) {
               SHORT code;
               if (sameas(tlcUserGetChatUser(pToUser->m_pszName)
                         ,pUser->m_pszName)) {
                    if (pUser->m_fFlags&USR_INCHAN) {
                         // check if user is still able to go into chat
                         if (pToUser->m_iUsrnum >= 0) {
                              aachat[pToUser->m_iUsrnum].chatch=pUser->m_iUsrnum;
                         }
                         tlcUserSetChatUser(pUser->m_pszName,pToUser->m_pszName);
                         tlcUserChatBegin(pUser->m_pszName,CHAT_ACCEPTED);
                         tlcUserChatBegin(pToUser->m_pszName,CHAT_START);
                    }
                    else {
                         LONG tmp;
                         tmp=wchat->unumFrom;
                         wchat->unumFrom=wchat->unumTo;
                         wchat->unumTo=tmp;
                         wchat->error=CMD_CHAT_BUSY;
                         worSendFDA(WORAPID,WORCMD_CHAT_NOTAVAIL,sizeof(WORCHAT)
                                   ,&wchat,worchatFDA);
                    }
                    break;
               }
               else if (pToUser->m_fFlags&USR_CHATTING) {
                    code=CMD_CHAT_ALREADY;
               }
               else if (tlcUserCheckForget(pToUser->m_pszName,pUser->m_pszName)) {
                    code=CMD_CHAT_FGT;
               }
               else if (pagesetUid(pToUser->m_pszName) == PAGE_OFF) {
                    code=CMD_CHAT_NOCHAT;
               }
               else if (pageIgnoredRou(pToUser->m_pszName,pUser->m_pszName)) {
                    code=CMD_CHAT_NOCHATU;
               }
               else if (!(pToUser->m_fFlags&USR_INCHAN)) {
                    code=CMD_CHAT_CANTCHAT;
               }
               else {
                    stlcpy((CHAR*)tlcwrk,pUser->m_pszName,TLCUIDSIZ);
                    if (tlcUserSetContext(pUser->m_pszName) != NULL) {
                         tlcTransCmdResult(tlcTransUserIs(pToUser->m_pszName)
                                          ,pToUser
                                          ,CMD_CHAT
                                          ,TRUE
                                          ,CMD_CHAT_NOTIFY);
                    }
                    break;
               }
               LONG tmp;
               tmp=wchat->unumFrom;
               wchat->unumFrom=wchat->unumTo;
               wchat->unumTo=tmp;
               wchat->error=code;
               worSendFDA(WORAPID,WORCMD_CHAT_NOTIFYERROR,sizeof(WORCHAT)
                         ,&wchat,worchatFDA);
          }
          break;
     case WORCMD_CHAT_NOTIFYERROR:
          worConvertFDA(worchatFDA);
          wchat=static_cast<LPWORCHAT>(value);
          pUser=tlcUserGetInfo(worNumberToAlias(wchat->unumFrom));
          if (pUser != NULL) {
               pToUser=tlcUserGetInfo(worNumberToUserid(wchat->unumTo));
               if (pToUser != NULL) {
                    stlcpy((CHAR*)tlcwrk,pUser->m_pszName,TLCUIDSIZ);
                    tlcUserSetContext(pUser->m_pszName);
                    tlcTransCmdResult(tlcTransUserIs(pToUser->m_pszName)
                                     ,pToUser
                                     ,CMD_CHAT
                                     ,FALSE
                                     ,wchat->error);
               }
          }
          break;
     case WORCMD_CHAT_NOTINTELE:
          worConvertFDA(worchatFDA);
          wchat=static_cast<LPWORCHAT>(value);
          pToUser=tlcUserGetInfo(worNumberToUserid(wchat->unumTo));
          if (pToUser != NULL) {
               INT savusn=usrnum;
               stlcpy((CHAR*)tlcwrk,tlcUserGetChatUser(pToUser->m_pszName),TLCUIDSIZ);
               tlcUserSetChatUser(pToUser->m_pszName,"");
               if (pToUser->m_iUsrnum >= 0) {
                    curusr(pToUser->m_iUsrnum);
               }
               else {
                    clingo=0;
               }
               setmbk(wortlcmsg);
               prfmsg(NOTINTL,tlcwrk);
               tlcUserSendText(pToUser->m_pszName,(CHAR*)tlcwrk,NULL,NULL
                              ,RECV_TYPE_PRFBUF,0,NULL,NULL,NULL);
               rstmbk();
               clrprf();
               curusr(savusn);
          }
          break;
     case WORCMD_CHAT_ACCEPT:
          worConvertFDA(worchatFDA);
          wchat=static_cast<LPWORCHAT>(value);
          pUser=tlcUserGetInfo(worNumberToAlias(wchat->unumFrom));
          pToUser=tlcUserGetInfo(worNumberToUserid(wchat->unumTo));
          if (pToUser == NULL || pUser == NULL
           || !sameas(tlcUserGetChatUser(pToUser->m_pszName)
                     ,pUser->m_pszName)) {
               LONG tmp;
               tmp=wchat->unumFrom;
               wchat->unumFrom=wchat->unumTo;
               wchat->unumTo=tmp;
               wchat->error=cmdnum;
               worSendFDA(WORAPID,WORCMD_CHAT_DONE,sizeof(WORCHAT)
                         ,&wchat,worchatFDA);
          }
          else {
               if (pToUser->m_iUsrnum >= 0) {
                    aachat[pToUser->m_iUsrnum].chatch=pUser->m_iUsrnum;
               }
               tlcUserSetChatUser(pUser->m_pszName,pToUser->m_pszName);
               tlcUserChatBegin(pToUser->m_pszName,CHAT_START);
          }
          break;
     case WORCMD_CHAT_DONE:
          worConvertFDA(worchatFDA);
          wchat=static_cast<LPWORCHAT>(value);
          pToUser=tlcUserGetInfo(worNumberToUserid(wchat->unumTo));
          if (pToUser != NULL) {
               tlcUserSetChatUser(pToUser->m_pszName,"");
               ExitChat(wchat->error == CMD_CHAT_HANGUP,pToUser->m_pszName
                       ,FALSE);
          }
          break;
     case WORCMD_CHAT_NOTAVAIL:
          worConvertFDA(worchatFDA);
          wchat=static_cast<LPWORCHAT>(value);
          pToUser=tlcUserGetInfo(worNumberToUserid(wchat->unumTo));
          if (pToUser != NULL) {
               tlcTransCmdResult(tlcTransUserIs(pToUser->m_pszName)
                               ,pToUser,CMD_CHAT,FALSE,CMD_CHAT_BUSY);
          }
          break;
     case WORCMD_PRIVATE_SEND:
          worConvertFDA(speakinfFDA);
          spkinf=static_cast<LPSPEAKINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(spkinf->unumTo));
          if (pUser != NULL) {
               if (spkinf->unumFrom == SYSUIDN) {
                    stzcpy(useridfrom,SYSUID,TLCUIDSIZ);
               }
               else {
                    stzcpy(useridfrom,worNumberToAlias(spkinf->unumFrom),TLCUIDSIZ);
               }
               if (*useridfrom != '\0') {
                    tlcUserSendText(pUser->m_pszName,useridfrom,NULL,spkinf->msg,
                               spkinf->type,spkinf->iMsgNum,
                               spkinf->ptr1,spkinf->ptr2,spkinf->ptr3);
               }
          }
          break;
     case WORCMD_ACTION_NOACS:
          // no access
#ifdef DEBUG2
          shocst("RECEIVED NOACS MSG","");
#endif
          worConvertFDA(actioninfFDA);
          actioninf=static_cast<LPACTIONINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->from));
          pToUser=tlcUserGetInfo(worNumberToUserid(actioninf->to));
          if (pUser != NULL) {
              setmbk(msgTlc);
              tlcUserSendText(pUser->m_pszName,
                              ((pToUser == NULL)
                              ? "Unknown" : pToUser->m_pszName),
                              NULL,actioninf->name,0,
                              CNTSEE3,NULL,NULL,NULL);
              rstmbk();
          }
          break;
     case WORCMD_ACTION_NOUSR:
#ifdef DEBUG2
          shocst("RECEIVED NOUSR MSG","");
#endif
          worConvertFDA(actioninfFDA);
          actioninf=static_cast<LPACTIONINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->from));
          if (pUser != NULL) {
              setmbk(msgTlc);
              tlcUserSendText(pUser->m_pszName,SYSUID,NULL,NULL,0
                             ,WHSNHR3,NULL,NULL,NULL);

              rstmbk();
          }
          break;
     case WORCMD_ACTION_IGNORE:
#ifdef DEBUG2
          shocst("RECEIVED IGNORE MSG","");
#endif
          worConvertFDA(actioninfFDA);
          actioninf=static_cast<LPACTIONINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->from));
          stlcpy(useridfrom,pUser->m_pszName,TLCUIDSIZ);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->to));
          if (pUser != NULL) {
              setmbk(msgTlc);
              tlcUserSendText(pUser->m_pszName,useridfrom,NULL,NULL
                             ,0,IGNORN3,NULL,NULL,NULL);

              rstmbk();
          }
          break;
     case WORCMD_ACTION_FORGET:
#ifdef DEBUG2
          shocst("RECEIVED FORGET MSG","");
#endif
          worConvertFDA(actioninfFDA);
          actioninf=static_cast<LPACTIONINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->from));
          stlcpy(useridfrom,pUser->m_pszName,TLCUIDSIZ);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->to));
          if (pUser != NULL) {
              setmbk(msgTlc);
              tlcUserSendText(pUser->m_pszName,useridfrom,NULL,NULL
                             ,0,FORGTN2,NULL,NULL,NULL);

              rstmbk();
          }
          break;
     case WORCMD_ACTION_REQUEST:
          worConvertFDA(actioninfFDA);
          actioninf=static_cast<LPACTIONINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->to));
          pChan=wortlcFindChannel(actioninf->chn);

          if (pUser != NULL && pChan != NULL) {
               if (actioninf->from == SYSUIDN) {
                    stzcpy(useridfrom,SYSUID,TLCUIDSIZ);
               }
               else {
                    stzcpy(useridfrom,worNumberToAlias(actioninf->from),TLCUIDSIZ);
               }
               if (*useridfrom != '\0') {
#ifdef DEBUG2
                    shocst("ACTION ACS REQ","From: %s",useridfrom);
#endif
                    switch (
                        WorChWLActionUser(actioninf,pUser->m_pszName,
                                          pChan->m_strName,FALSE)) {
                    case ACTION_NOACS:
#ifdef DEBUG2
                        shocst("ACTION ACS RESP","NOACS");
#endif
                        worSendFDA(WORAPID,WORCMD_ACTION_NOACS,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                        break;
                    case ACTION_NOUSR:
#ifdef DEBUG2
                        shocst("ACTION ACS RESP","NOUSR");
#endif
                        worSendFDA(WORAPID,WORCMD_ACTION_NOUSR,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                        break;
                    case ACTION_IGNORE:
#ifdef DEBUG2
                        shocst("ACTION ACS RESP","IGNORE");
#endif
                        worSendFDA(WORAPID,WORCMD_ACTION_IGNORE,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                        break;
                    case ACTION_FORGET:
#ifdef DEBUG2
                        shocst("ACTION ACS RESP","FORGET");
#endif
                        worSendFDA(WORAPID,WORCMD_ACTION_FORGET,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                        break;

                    case 0:
                    default:
                        // success
#ifdef DEBUG2
                        shocst("ACTION ACS RESP","SENDING ACTION TO ALL");
#endif
                        worSendFDA(WORAPID,WORCMD_ACTION,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                    }
               }
          }
          break;
     case WORCMD_PRIVATE_ACTION:
          worConvertFDA(actioninfFDA);
          actioninf=static_cast<LPACTIONINF>(value);
          pUser=tlcUserGetInfo(worNumberToUserid(actioninf->to));
          pChan=wortlcFindChannel(actioninf->chn);
          if (pUser != NULL && pChan != NULL) {
               if (actioninf->from == SYSUIDN) {
                    stzcpy(useridfrom,SYSUID,TLCUIDSIZ);
               }
               else {
                    stzcpy(useridfrom,worNumberToAlias(actioninf->from),TLCUIDSIZ);
               }
               if (*useridfrom != '\0') {
                    switch (WorChWLActionUser(actioninf,pUser->m_pszName,
                                           pChan->m_strName,TRUE)) {
                    case ACTION_NOACS:
                        worSendFDA(WORAPID,WORCMD_ACTION_NOACS,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                        break;
                    case ACTION_NOUSR:
                        worSendFDA(WORAPID,WORCMD_ACTION_NOUSR,
                                   fldoff(actioninf,extra)
                                    +strlen(((LPACTIONINF)value)->extra),
                                   value,actioninfFDA);
                        break;
                    case 0:
                    default:
                        break;
                    }
               }
          }
          break;
     case WORCMD_USER_JOIN:
     case WORCMD_USER_REJOIN:
          worConvertFDA(jinfoFDA);
          jinfo=static_cast<LPJINFSTR>(value);
          if (worGetUserInfoByNumber(&wu,jinfo->unum)
           && !(wu.Flags&(WLUSER_INVIS|WLUSER_SQUELCHED))) {
               stlcpy(useridfrom,worUserToAlias(&wu),TLCUIDSIZ);
               if ((pChan=wortlcFindChannel(jinfo->chn)) != NULL) {
                    WorChAddNetworkUser(pChan->m_strName,useridfrom);
               }
          }
          break;
     case WORCMD_USER_UNJOIN:
          worConvertFDA(jinfoFDA);
          jinfo=static_cast<LPJINFSTR>(value);
          if (worGetUserInfoByNumber(&wu,jinfo->unum)) {
               stlcpy(useridfrom,worUserToAlias(&wu),TLCUIDSIZ);
               if ((pChan=wortlcFindChannel(jinfo->chn)) != NULL) {
                    WorChRemoveNetworkUser(pChan->m_strName,useridfrom);
               }
          }
          break;
     case WORCMD_REMOVE_NODE_USERS:
          amp=static_cast<CHAR*>(value);
          wortlcRemoveWLNodeUsers(amp);
          break;
     case WORCMD_USERMODS:
          memset(tlcworbuf,0,WBUFSZ);
          strcat(tlcworbuf,itemidx(static_cast<CHAR*>(value),0));   // usrnum
          strcat(tlcworbuf,"\t");
          strcat(tlcworbuf,itemidx(static_cast<CHAR*>(value),1));   // originating board
          strcat(tlcworbuf,"\t");
          strcat(tlcworbuf,spr("%hd",worNodeNUM));     // this board
          for (i=0; i < nterms ; i++) {
               if (usroff(i)->usrcls >= BBSPRV) {
                    uaptr=uacoff(i);
                    if (worGetUserInfo(&wu,uaptr->userid)) {
                         sprintf(usrinfo,"\t%ld\t%s",wu.UserNumber
                                ,module[usroff(i)->state]->descrp);
                         strcat(tlcworbuf,usrinfo);
                    }
               }
          }
          pUser=tlcTransGetFirstUser(iAHTrans,NULL);
          while (pUser != NULL) {
               if (worGetUserInfo(&wu,pUser->m_pszName)) {
                    sprintf(usrinfo,"\t%ld\t%s",wu.UserNumber
                     ,module[GetTeleState()]->descrp);
                    strcat(tlcworbuf,usrinfo);
               }
               pUser=tlcTransGetNextUser(iAHTrans,NULL);
          }
          worSend(WORAPID,WORCMD_USERMODS_REPLY,STGLEN,tlcworbuf);
          break;
     case WORCMD_USERMODS_REPLY:
          setmbk(wortlcmsg);
          if (onsysn(uacoff(atoi(itemidx(static_cast<CHAR*>(value),0)))->userid,1)) {
               worNodeInfoBynum(&node,(USHORT)atoi(itemidx(static_cast<CHAR*>(value),2)));
               prfmlt(WLMODHE3,node.ID,node.Name);
               if (itemcnt(static_cast<CHAR*>(value)) < 4) {
                    prfmlt(WLUSNOU2);
               }
               else {
                    INT index=3;
                    CHAR userid[UIDSIZ];
                    do {
                         user=itemidx(static_cast<CHAR*>(value),index);
                         stlcpy(userid,
                                worUseridUnmake(worNumberToAlias((ULONG)atol(user))),
                                UIDSIZ);
                         mod=itemidx(static_cast<CHAR*>(value),index+1);
                         if (*userid != '\0') {
                              prfmlt(WLMODLI2,userid,mod);
                         }
                         index=index+2;
                    } while (index < itemcnt(static_cast<CHAR*>(value)));
               }
               if (!(othusp->flags&NOINJO)) {
                    injoth();
               }
          }
          rstmbk();
          break;
     case WORCMD_USERMODS_NOTELE:
          setmbk(wortlcmsg);
          if (onsysn(uacoff(atoi(itemidx(static_cast<CHAR*>(value),0)))->userid,1)) {
               worNodeInfo(&node,itemidx(static_cast<CHAR*>(value),2));
               if (!(othusp->flags&NOINJO)) {
                   prfmlt(WLNOTEL2,node.ID,node.Name);
                   injoth();
               }
          }
          rstmbk();
          break;
     case WORCMD_INVISTOGGLE:
          LPUSRSTRUCT pUser;
          stlcpy(useridfrom,worNumberToAlias(atoi(itemidx(static_cast<CHAR*>(value),0))),TLCUIDSIZ);
          if (*useridfrom != '\0') {
               if ((pUser=tlcUserGetInfo(useridfrom)) != NULL) {
                    if (atoi(itemidx(static_cast<CHAR*>(value),1))) {
                         pUser->m_fFlags|=USR_INVISB;
                    }
                    else {
                         pUser->m_fFlags&=~USR_INVISB;
                    }
               }
          }
          break;
     case WORCMD_ADDUSER:
          worConvertFDA(jinfoFDA);
          jinfo=static_cast<LPJINFSTR>(value);
          pSmbUsers->Insert(jinfo);
          break;
     case WORCMD_REMOVEUSER:
          worConvertFDA(jinfoFDA);
          jinfo=static_cast<LPJINFSTR>(value);
          if (pSmbUsers->GetEqual(&jinfo->unum,0) != NULL) {
               pSmbUsers->Delete();
          }
          break;
     case WORCMD_USER_UNLISTED:
          worConvertFDA(jinfoFDA);
          jinfo=static_cast<LPJINFSTR>(value);
          if (worGetUserInfoByNumber(&wu,jinfo->unum)
           && !(wu.Flags&(WLUSER_INVIS|WLUSER_SQUELCHED))) {
               stlcpy(useridfrom,worUserToAlias(&wu),TLCUIDSIZ);
               LPUSRSTRUCT pUser=tlcUserGetInfo(useridfrom);
               if (pUser != NULL) {
                    if (jinfo->chn) {
                         pUser->m_fFlags|=USR_UNLIST;
                    }
                    else {
                         pUser->m_fFlags&=~USR_UNLIST;
                    }
                    tlcPublicSendAllChannels(pUser->m_pszName,pUser->m_pszName
                                            ,NULL,RECV_TYPE_LISTCHG,0);
               }
          }
          break;
     }
     rstmbk();
     tlcOutputFinished();
}

WORSQUELCHHANDLER
worSqCmdHdl(
SHORT cmdnum,
UINT length,
VOID* value)
{
     (VOID)cmdnum;
     (VOID)length;
     (VOID)value;

}

VOID
wortlcRemoveWLUsers(
const CHAR* channel)
{
     LPUSRSTRUCT pUser;
     CHAR userid[TLCUIDSIZ];

     pUser=tlcChannelGetFirstUser(channel);

     while (pUser != NULL) {
          stlcpy(userid,pUser->m_pszName,TLCUIDSIZ);
          if (tlcTransUserIs(pUser->m_pszName) == iWorTrans) {
               WorChRemoveNetworkUser(channel,userid);
               pUser=tlcChannelGetUserGT(channel,userid);
          }
          else {
               pUser=tlcChannelGetUserGT(channel,userid);
          }
     }
}

VOID
wortlcRemoveWLNodeUsers(
CHAR* node)
{
     LPUSRSTRUCT pUser;
     CHAR userid[TLCUIDSIZ];

     pUser=tlcUserGetFirst();
     while (pUser != NULL) {
          stlcpy(userid,pUser->m_pszName,TLCUIDSIZ);
          if (tlcTransUserIs(pUser->m_pszName) == iWorTrans) {
               if (samend(pUser->m_pszName,node)) {
                    WorChRemoveNetworkUser(pUser->m_pszChannel,pUser->m_pszName);
               }
          }
          pUser=tlcUserGetGT(userid);
     }
}


LPCHANINFO
wortlcFindChannel(
SHORT chn)
{
     LPCHANINFO pChan;
     pChan=tlcChannelGetFirst();
     do {
          if (pChan->m_type&CHAN_TYPE_WL_PUBLIC) {
               SHORT num;
               num=(static_cast<LPWORCHANCUSTOM>(pChan->m_pCustom))->num;
               if (num == chn) {
                    return(pChan);
               }
          }
     } while ((pChan=tlcChannelGetNext()) != NULL);
     return(NULL);
}

VOID
wortlcCreateChan(
LPWORCHN chaninf)
{
     LPWORCHANCUSTOM cu;
     CHANINFO channel;

     if (chaninf->chnName[0] == '\0') {
          return;
     }
     cu=new WORCHANCUSTOM;
     cu->num=chaninf->chn;
     stlcpy(cu->pszNode,chaninf->worID,WBOASIZ);
     cu->rating=chaninf->rating;
     memset(&channel,0,sizeof(CHANINFO));
     stlcpy(channel.m_strName,chaninf->chnName,CHAN_MAX_SIZE);
     stlcpy(channel.m_strTopic,chaninf->topic,CHAN_MAX_TOPIC_SIZE);
     stlcpy(channel.m_actList1,primaryList,LISTSIZ);
     stlcpy(channel.m_actList2,secondaryList,LISTSIZ);
     channel.m_pCustom=cu;
     setmbk(msgTlc);
     channel.m_iCrConsumptionRate=numopt(TELCCR,-32767,32767);
     rstmbk();
     channel.m_type|=(CHAN_TYPE_WL_PUBLIC|CHAN_TYPE_NOEDIT);
     setmbk(msgTlc);

     if (tlcChannelCreateCustom(&channel,&worChannel) != CHAN_CREATE_OK) {
          delete cu;
     }
}

VOID
wortlcRemoveChannel(
const CHAR* channel)
{
     LPCHANINFO pInfo;

     pInfo=tlcChannelGetInfo(channel);
     LPWORCHANCUSTOM pCu;

     pCu=static_cast<LPWORCHANCUSTOM>(pInfo->m_pCustom);
     delete pCu;
     tlcChannelRemove(channel);
}

INT
wortlcGlobalFunctions(VOID)
{
     GBOOL flg;

     setmbk(wortlcmsg);
     if (sameas(margv[0]+1,"U")) {
          if (margc == 1) {
               wortlcListBoards();
          }
          else {
               wortlcGetUserMods(margv[1]);
          }
     }
     else if (sameas(margv[0]+1,"G")) {
          if (margc == 1) {
               setmbk(wormsg);
               prfmsg(GRID);
               outprf(usrnum);
               rstmbk();
          }
          else {
               wortlcListOnBoard(margv[1]);
          }
     }
     else if (margc == 1 && sameas(margv[0]+1,"L")) {
          WLUSRFLGDSK user;
          flg=ToggleFlagSHORT(&wlusr[usrnum].flags,BOARD_NOTIFY);
          stzcpy(user.userid,usaptr->userid,UIDSIZ);
          user.flags=wlusr[usrnum].flags;
          UpdateWLUsrProfile(&user);
          prfmsg(BLNKSET,(flg ? "" : "no longer "));
          outprf(usrnum);
     }
     else if (margc == 1 && sameas(margv[0]+1,"LON")) {
          WLUSRFLGDSK user;
          flg=ToggleFlagSHORT(&wlusr[usrnum].flags,WLUSR_LOGON);
          stzcpy(user.userid,usaptr->userid,UIDSIZ);
          user.flags=wlusr[usrnum].flags;
          UpdateWLUsrProfile(&user);
          prfmsg(BLONSET,(flg ? "" : "no longer "));
          outprf(usrnum);
     }
     else if (margc == 1 && sameas(margv[0]+1,"LOF")) {
          WLUSRFLGDSK user;
          flg=ToggleFlagSHORT(&wlusr[usrnum].flags,WLUSR_LOGOFF);
          stzcpy(user.userid,usaptr->userid,UIDSIZ);
          user.flags=wlusr[usrnum].flags;
          UpdateWLUsrProfile(&user);
          prfmsg(BLOFSET,(flg ? "" : "no longer "));
          outprf(usrnum);
     }
     else if (margc == 1 && sameas(margv[0]+1,"B")) {
          WLUSRFLGDSK user;
          flg=ToggleFlagSHORT(&wlusr[usrnum].flags,BOARD_LOGON_MSG);
          stzcpy(user.userid,usaptr->userid,UIDSIZ);
          user.flags=wlusr[usrnum].flags;
          UpdateWLUsrProfile(&user);
          prfmsg(BLOGSET,(flg ? "" : "no longer "));
          outprf(usrnum);
     }
     else if (sameas(margv[0]+1,"I")) {
          if (margc > 1) {
               wortlcInfoOnBoard(margv[1]);
          }
          else {
               prfmsg(NEEDBRD);
               outprf(usrnum);
          }
     }
     else {
          return(oldGlobals());
     }
     rstmbk();
     return(1);
}

VOID
UsrAdd(
const CHAR* userid)
{
     WORUSER usr;

     if (worGetUserInfo(&usr,userid)
      && !(usr.Flags&WLUSER_INVIS)) {
          setmbk(wortlcmsg);
          for (int i=0 ; i < nterms ; i++) {
               othusp=usroff(i);
               if (onsysn(uacoff(i)->userid,1) && othusp->usrcls == ACTUSR
                    && !(othusp->flags&ISGCSU)
                    && wlusr[othusn].flags&WLUSR_LOGON
                    && !(othusp->flags&NOINJO)) {
                    if (worLocalUser(userid)) {
                         prfmlt(WLUSLON2,userid,
                                   spr("%s Age %d",
                                   usr.Flags&WLUSER_MALE ? "Male" : "Female",
                                   usr.Age),
                                   worUsers());
                         injoth();
                    }
                    else if (worConnected()
                      && !(usr.Flags&(WLUSER_SQUELCHED|WLUSER_INVIS))) {
                         prfmlt(WLUSLON2,worUserToAlias(&usr),
                                   spr("%s Age %d",
                                   usr.Flags&WLUSER_MALE ? "Male" : "Female",
                                   usr.Age),
                                   worUsers());
                         injoth();
                    }
               }
          }
          rstmbk();
     }
     oldadd(userid);
}

VOID
UsrRemove(
const CHAR* userid)
{
     WORUSER usr;

     setmbk(wortlcmsg);
     if (worGetUserInfo(&usr,userid)
          && !(usr.Flags&WLUSER_INVIS)) {
          for (int i=0 ; i < nterms ; i++) {
               othusp=usroff(i);
               if (onsysn(uacoff(i)->userid,1) && othusp->usrcls == ACTUSR
                    && !(othusp->flags&ISGCSU)
                    && wlusr[othusn].flags&WLUSR_LOGOFF
                    && !(othusp->flags&NOINJO)) {
                    if (worLocalUser(userid)) {
                         prfmlt(WLUSLOF2,userid,worUsers());
                         injoth();
                    }
                    else if (worConnected()
                     && !(usr.Flags&WLUSER_SQUELCHED)) {
                         prfmlt(WLUSLOF2,worUserToAlias(&usr),worUsers());
                         injoth();
                    }

               }
          }
     }
     rstmbk();
     if (onsysn(userid,1)) {
          LPUSRSTRUCT pUser=tlcUserGetInfo(userid);
          if (pUser != NULL) {
              LPCHANINFO pChan=tlcChannelGetInfo(pUser->m_pszChannel);
              if (pChan->m_type&CHAN_TYPE_WL_PUBLIC) {
                    WorChRemoveUser(pChan->m_strName,pUser,LEAVE_LOGOFF);
              }
          }
     }
     NotifyHub(FALSE);
     oldrem(userid);
}

GBOOL
ToggleFlagSHORT(
SHORT* flag,
SHORT flagbit)
{
     if ((*flag)&flagbit) {
          (*flag)&=~flagbit;
          return(FALSE);
     }
     (*flag)|=flagbit;
     return(TRUE);
}

VOID
UpdateWLUsrProfile(
LPWLUSRFLGDSK user)
{

     ASSERT(user != NULL);
     ASSERT(user->userid != NULL);

     dfaSetBlk(dfaWlusr);
     if (dfaAcqEQ(NULL,user->userid,0)) {
          dfaUpdate(user);
     }
     else {
          dfaInsert(user);
     }
     dfaRstBlk();
}

VOID
wortlcListOnBoard(
const CHAR* board)
{
     WORUSER user;
     WORNODE node;

     if (!worConnected()) {
          setmbk(wormsg);
          prfmsg(NTCONN);
          outprf(usrnum);
          rstmbk();
          return;
     }
     setmbk(wortlcmsg);
     if (worNodeLinked(board) && !worNodeSquelched(board)) {
          worNodeInfo(&node,board);
     }
     else {
          switch (worNodeFind(&node,board)) {
          case 0:
               prfmsg(WLINVB3,board);
               outprf(usrnum);
               rstmbk();
               return;
          case 1:
               break;
          default:
               prfmsg(WLNAMB,board);
               outprf(usrnum);
               rstmbk();
               return;
          }
     }
     if (worRatingHaskeyBynum(node.Rating)) {
          prfmsg(WLUSHE3,node.ID);
          if (!sameas(node.ID,worDomain())) {
               if (worUserFirstNode(&user,node.ID)) {
                    do {
                         if (!(user.Flags&WLUSER_INVIS)) {
                              outprf(usrnum);
                              clrprf();
                              prfmsg(WLUSLI3,user.Alias,
                                (user.Flags&WLUSER_MALE ? "M" : "F" ),
                                user.Age);
                         }
                    } while (worUserNextNode(&user));
                    prfmsg(WLUSFT2,worUsersNode(node.ID));
               }
               else {
                    prfmsg(WLUSNOU2);
               }
          }
          else {
               if (worUserFirstLocal(&user)) {
                    do {
                         if (!(user.Flags&WLUSER_INVIS)) {
                              outprf(usrnum);
                              clrprf();
                              prfmsg(WLUSLI3,user.Userid,
                                (user.Flags&WLUSER_MALE ? "M" : "F" ),
                                user.Age);
                         }
                    } while (worUserNextLocal(&user));
                    prfmsg(WLUSFT2,worUsersLocal());
               }
               else {
                    prfmsg(WLUSNOU2);
               }
          }
          rstmbk();
          outprf(usrnum);
     }
     else {
          prfmsg(WLINVB3,board);
          outprf(usrnum);
          rstmbk();
     }
}

VOID
wortlcInfoOnBoard(
const CHAR* board)
{
     WORNODE node;

     if (!worConnected()) {
          setmbk(wormsg);
          prfmsg(NTCONN);
          outprf(usrnum);
          rstmbk();
          return;
     }
     if (margc == 1) {
          prfmsg(NEEDBRD);
          outprf(usrnum);
          return;
     }
     if (worNodeLinked(board) && !worNodeSquelched(board)) {
          worNodeInfo(&node,board);
     }
     else {
          switch (worNodeFind(&node,board)) {
          case 0:
               prfmsg(WLINVB3,board);
               outprf(usrnum);
               rstmbk();
               return;
          case 1:
               break;
          default:
               prfmsg(WLNAMB,board);
               outprf(usrnum);
               rstmbk();
               return;
          }
     }
     prfmsg(WLNINF2,node.ID,node.Name,node.Phone,node.City,
              node.Sysop,node.Blurb,node.ipaddr,node.webaddr);
     outprf(usrnum);
     rstmbk();
}

VOID
wortlcListBoards(VOID)
{
     WORNODE node;
     ULONG uiUsers;
     INT cnt=0;

     setmbk(wortlcmsg);
     if (worConnected()) {
          prfmsg(WLBDHE4);
          outprf(usrnum);
          worNodeFirst(&node);
          do {
               if (!worNodeSquelched(node.ID)
                && worRatingHaskeyBynum(node.Rating)) {
                    cnt++;
                    if (node.Number == worNodeNUM) {
                         uiUsers=worUsersLocal();
                    }
                    else {
                         uiUsers=worUsersNode(node.ID);
                    }
                    prfmsg(WLBDLI4,node.ID,node.City,uiUsers);
                    outprf(usrnum);
               }
          } while (worNodeNext(&node));
          prfmsg(WLBDFT5,worUsersWorld()+worUsersLocal(),cnt,worGlobal);
     }
     else {
          setmbk(wormsg);
          prfmsg(NTCONN);
          rstmbk();
     }
     rstmbk();
     outprf(usrnum);
}

VOID
wortlcGetUserMods(
const CHAR* board)
{
     WORNODE node;

     if (!worConnected()) {
          setmbk(wormsg);
          prfmsg(NTCONN);
          outprf(usrnum);
          rstmbk();
          return;
     }
     if (worNodeLinked(board) && !worNodeSquelched(board)) {
          worNodeInfo(&node,board);
     }
     else {
          setmbk(wortlcmsg);
          switch (worNodeFind(&node,board)) {
          case 0:
               prfmsg(WLINVB3,board);
               outprf(usrnum);
               rstmbk();
               return;
          case 1:
               break;
          default:
               prfmsg(WLNAMB,board);
               outprf(usrnum);
               rstmbk();
               return;
          }
          rstmbk();
     }
     if (worRatingHaskeyBynum(node.Rating)) {
          worSend(WORAPID,WORCMD_USERMODS,
           STGLEN,spr("%d\t%hd\t%s",usrnum,worNodeNUM,node.ID));
     }
     else {
          setmbk(wortlcmsg);
          prfmsg(WLINVB3,board);
          outprf(usrnum);
          rstmbk();
     }
}


VOID
InvToggle(
const WORUSER *pwu,
GBOOL isInvis)
{
     const CHAR* uid=worUserToUserid(pwu);

     if (worLocalUser(uid) && !isInvis) {
          LPUSRSTRUCT pUser=tlcUserGetInfo(uid);
          if (pUser != NULL) {
               SHORT chn=wortlcChannelToNum(pUser->m_pszChannel);
               if (chn != WLCHAN_NOSUCH) {
                    JINFSTR jinfo;
                    memset(&jinfo,0,sizeof(JINFSTR));
                    jinfo.unum=pwu->UserNumber;
                    jinfo.tlcunum=tlcUserFindID(uid);
                    jinfo.chn=chn;
                    worSendFDA(WORAPID,WORCMD_USER_REJOIN,sizeof(JINFSTR),&jinfo,jinfoFDA);
               }
          }
     }
     else if (worWorldUser(uid) && isInvis) {
          const CHAR* Alias=worUserToAlias(pwu);
          LPUSRSTRUCT pUser=tlcUserGetInfo(Alias);
          if (pUser != NULL) {
               SHORT chn=wortlcChannelToNum(pUser->m_pszChannel);
               if (chn != WLCHAN_NOSUCH) {
                    WorChRemoveNetworkUser(pUser->m_pszChannel,Alias);
               }
          }
     }
     oldinv(pwu,isInvis);
}

SHORT
wortlcChannelToNum(
const CHAR* channel)
{
     LPCHANINFO pChan=tlcChannelGetInfo(channel);

     if (pChan != NULL) {
          if (pChan->m_type&CHAN_TYPE_WL_PUBLIC) {
               SHORT num;
               num=(static_cast<LPWORCHANCUSTOM>(pChan->m_pCustom))->num;
               return(num);
          }
     }
     return(WLCHAN_NOSUCH);
}


GBOOL
worPalVrfy(
const CHAR* user)
{
     if (worLocalUser(user)) {
          return(oldvrfy(user));
     }
     return(TRUE);
}


GBOOL
worPalIson(
const CHAR* user)
{
     if (worLocalUser(user)) {
          return(oldison(user));
     }
     if (worAliasToNumber(user) != WLUSER_NOT_FOUND) {
          return(TRUE);
     }
     return(FALSE);
}


VOID
wlent(
const CHAR* uid)
{
     JINFSTR jinfo;
     WORUSER wu;

     if (!onsysn(uid,1)) {
          worUserAssignNum(uid);
          jinfo.Nodenumber=worNodeNUM;
          jinfo.chn=-1;
          if (worGetUserInfo(&wu,uid)) {
               jinfo.unum=wu.UserNumber;
               if ((jinfo.tlcunum=tlcUserFindID(uid)) == 0) {
                    jinfo.tlcunum=tlcUserCreateUniqueID(uid);
               }
               worSendFDA(WORAPID,WORCMD_ADDUSER,sizeof(JINFSTR),&jinfo,jinfoFDA);
          }
     }
     oldent(uid);
}

VOID
wlext(
const CHAR* uid)
{
     JINFSTR jinfo;
     WORUSER wu;

     if (!onsysn(uid,1)) {
          jinfo.Nodenumber=worNodeNUM;
          jinfo.chn=-1;
          if (worGetUserInfo(&wu,uid)) {
               jinfo.unum=wu.UserNumber;
               jinfo.tlcunum=tlcUserFindID(uid);
               worSendFDA(WORAPID,WORCMD_REMOVEUSER,sizeof(JINFSTR),&jinfo,jinfoFDA);
               worUserDeleteNum(uid);
          }
     }
     oldext(uid);
}

GBOOL
wlusrdelhook(
const CHAR* uid)
{
     if (tlcUserGetInfo(uid) != NULL) {
          // ok they are in tele
          if (onsysn(uid,1)) {
               // they are on the system
               if (tlcTransUserIs(uid) == iAHTrans) {
                    // they are in tele from web
                    return(FALSE);
               }
               else {
                    return(TRUE);
               }
          }
          else {
               // not on system
               return(FALSE);
          }
     }
     return(olddelhook(uid));
}

VOID
wortlcGlobalHelp(VOID)
{
     setmbk(wortlcmsg);
     prfmsg(WLTHLP);
     outprf(usrnum);
     clrprf();
     prf("");
     rstmbk();
}

SHORT
doWorldCmd(
LPCMDPARAM param)
{
     stzcpy(input,param->m_pszCmdParam,tinpsz);
     parsin();
     if (margc != 0) {
          return(0);
     }
     if (worConnected()) {
          param->m_pszCmdParam=worDomain();
          return(tlcCommandIssue("JOIN",param));
     }
     setmbk(wormsg);
     prfmsg(NTCONN);
     rstmbk();
     tlcTransOutput(tlcTransUserIs(param->m_pUser->m_pszName),param->m_pUser);
     return(1);
}
