From 5cd97f3f7095dd25ae2621b0aa6b59a802e23684 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 10 Nov 2022 17:00:08 +0000 Subject: [PATCH 01/47] 1) remove loglevel in zmodem code (use main log level) 2) update session bytes upload/downloaded to handle >4gb 3) better handling of telnet iac codes during file transfers 4) allow settings to control password lengths and strengths, password expiry 5) add PBKDF2 encryption of user passwords 6) Improve caching of download directory contents 7) Improve cps calculations to handle faster transfers 8) add second page of options to account editor 9) add force password reset, account lockout and number of password failures to account editor screen 10) setting a password now requires the user to enter the password twice for verification --- axenums.e | 2 + axobjects.e | 12 +- express.e | 1522 ++++++++++++++++++++++++++++++++++----------------- makefile | 17 +- sha256.e | 353 ++++++++++++ zmodem.e | 7 +- 6 files changed, 1391 insertions(+), 522 deletions(-) create mode 100644 sha256.e diff --git a/axenums.e b/axenums.e index 1832eb3..25de8f3 100644 --- a/axenums.e +++ b/axenums.e @@ -44,3 +44,5 @@ EXPORT ENUM SUBTYPE_ANYCMD=-1, SUBTYPE_CONFCMD=0, SUBTYPE_NODECMD=1, SUBTYPE_CMD -> User Keys Flags /* show new user message */ /* show all users only once */ EXPORT ENUM USER_NEWMSG=1,USER_TOCONF1=2, USER_ONETIME_MSG=4,USER_SCRNCLR=8,USER_DONATED=16,USER_ED_FULLSCREEN=32,USER_ED_PROMPT=64,USER_BGFILECHECK=128 + +EXPORT ENUM PWD_LEGACY=0, PWD_PBKDF2_5=1, PWD_PBKDF2_50=2, PWD_PBKDF2_100=3,PWD_PBKDF2_1000=4,PWD_PBKDF2_10000=5 \ No newline at end of file diff --git a/axobjects.e b/axobjects.e index d04fa97..90c5b6b 100644 --- a/axobjects.e +++ b/axobjects.e @@ -87,10 +87,14 @@ EXPORT OBJECT userMisc uploadBytesBCD[8]:ARRAY OF CHAR eMail[50]:ARRAY OF CHAR lastDlCPS:LONG - unused[142]:ARRAY OF CHAR - ->unknown[28]:ARRAY OF CHAR - ->nodeFlags[32]:ARRAY OF LONG - ->confFlags2[10]:ARRAY OF LONG + pwdHash[32]:ARRAY OF CHAR + salt[8]:ARRAY OF CHAR + pwdType:CHAR + forcePwdReset:CHAR + accountLocked:CHAR + invalidAttempts:CHAR + pwdLastUpdated:LONG + unused[94]:ARRAY OF CHAR ENDOBJECT EXPORT OBJECT tempAccess diff --git a/express.e b/express.e index 0d74eeb..e493fc0 100644 --- a/express.e +++ b/express.e @@ -26,7 +26,7 @@ MODULE 'intuition/screens','intuition/intuition','intuition/gadgetclass','exec/p 'libraries/asyncio' MODULE '*axcommon','*axconsts','*axenums','*axobjects','*miscfuncs','*stringlist','*ftpd','*httpd','*errors','*mailssl','*zmodem', - '*xymodem','*hydra','*bcd','*pwdhash','*tooltypes','*expversion' + '*xymodem','*hydra','*bcd','*pwdhash','*sha256','*tooltypes','*expversion' DEF masterMsg:acpMessage DEF resmp: PTR TO mp @@ -42,7 +42,7 @@ DEF singleNode=0: PTR TO singlePort DEF masterNode=0: PTR TO multiPort DEF debug=FALSE DEF consoleDebugLevel=LOG_NONE -DEF debugLogLevel=LOG_NONE +DEF debugLogLevel=LOG_ERROR DEF inputLogging=FALSE DEF inac=FALSE @@ -150,8 +150,8 @@ DEF tTCPS=0 ->DEF tTTM=0 DEF ulTTTM=0 DEF dlTTTM=0 -DEF dTBT=0 -DEF uTBT=0 +DEF dTBT[8]:ARRAY OF CHAR +DEF uTBT[8]:ARRAY OF CHAR DEF beenUDd=0 DEF lcFileXfr=0 DEF recFileNames:PTR TO stringlist @@ -279,7 +279,8 @@ DEF doorSilent=FALSE DEF cancelTransferOffHook=FALSE DEF aeGoodFile=0 -DEF sysopdl,numFiles,fsize,dtfsize +DEF sysopdl,numFiles,fsize +DEF dtfsize[8]:ARRAY OF CHAR DEF zModemInfo: zModem DEF chatSerFlag=0,chatConFlag=0 @@ -356,7 +357,8 @@ DEF includeDeact=FALSE DEF bgChecking=FALSE -DEF ftptime=0 +DEF ftptime1=0 +DEF ftptime2=0 DEF nativeTelnet=FALSE DEF nativeFtp=FALSE @@ -366,7 +368,10 @@ DEF offHookFlag=TRUE DEF lastIAC=FALSE DEF lastIAC2=FALSE +DEF iaccmd=0 DEF nawsMode=0 +DEF willsent=FALSE +DEF dosent=FALSE DEF nodeStart=0 @@ -383,7 +388,7 @@ DEF zmodemRxBuffer=0 DEF zModemRxBufferSize=65536 DEF bufferedBytes=0 DEF bufferReadOffset=0 -->DEF lastCarrierCheck=0 +DEF lastCarrierCheck=0 DEF cmdShortcuts=FALSE DEF shortcuts:PTR TO stringlist @@ -902,6 +907,125 @@ PROC resetSystem() ENDIF ENDPROC +PROC checkPasswordStrength(newPass:PTR TO CHAR) + DEF min,act,lower=0,upper=0,num=0,sym=0,i + min:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_LENGTH') + IF min>0 + IF StrLen(newPass)0 + act:=0 + IF min>4 THEN min:=4 + FOR i:=0 TO StrLen(newPass)-1 + IF (newPass[i]>=48) AND (newPass[i]<=57) + num:=1 + ELSEIF (newPass[i]>=65) AND (newPass[i]<=90) + upper:=1 + ELSEIF (newPass[i]>=97) AND (newPass[i]<=122) + lower:=1 + ELSE + sym:=1 + ENDIF + ENDFOR + act:=lower+upper+num+sym + IF act=0 + IF userMisc.invalidAttempts>=maxAttempts + userMisc.accountLocked:=TRUE + userMisc.invalidAttempts:=0 + ENDIF + ENDIF + ELSE + userMisc.invalidAttempts:=0 + ENDIF + +ENDPROC res + + PROC acceptIncomingConnection(sock,ftp) DEF ni:PTR TO nodeInfo DEF socket @@ -1054,8 +1178,8 @@ PROC checkDoorMsg(mode) ->calculate the new password hash StrCopy(tempstring,servermsg.string) IF StrLen(tempstring)>0 - UpperStr(tempstring) - loggedOnUser.pwdHash:=calcPasswordHash(tempstring) + setNewPassword(loggedOnUser,loggedOnUserMisc,tempstring) + loggedOnUserMisc.pwdLastUpdated:=getSystemTime() ENDIF ENDIF CASE DT_LOCATION @@ -1368,11 +1492,12 @@ PROC checkDoorMsg(mode) inac:=FALSE ENDPROC returnval -PROC getPass2(prompt: PTR TO CHAR,password:PTR TO CHAR,pwdhash:LONG, max:LONG,outstr=NIL:PTR TO CHAR) +PROC getPass2(prompt: PTR TO CHAR,password:PTR TO CHAR,userPwd, max:LONG,outstr=NIL:PTR TO CHAR) DEF c,i,j DEF pass[200]:STRING DEF tempstr[255]:STRING + DEF passType i:=1 IF (password<>NIL) @@ -1427,13 +1552,39 @@ PROC getPass2(prompt: PTR TO CHAR,password:PTR TO CHAR,pwdhash:LONG, max:LONG,ou aePuts('\b\n') RETURN RESULT_SUCCESS ENDIF - ELSE - UpperStr(pass) - IF calcPasswordHash(pass)=pwdhash + ELSEIF userPwd + IF checkUserPassword(loggedOnUser,loggedOnUserMisc,pass) + IF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','LEGACY') + passType:=PWD_LEGACY + ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_5') + passType:=PWD_PBKDF2_5 + ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_50') + passType:=PWD_PBKDF2_50 + ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_100') + passType:=PWD_PBKDF2_100 + ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_1000') + passType:=PWD_PBKDF2_1000 + ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_10000') + passType:=PWD_PBKDF2_10000 + ELSE + passType:=PWD_PBKDF2_100 + ENDIF + + IF loggedOnUserMisc.pwdType<>passType + setNewPassword(loggedOnUser,loggedOnUserMisc,pass) + ENDIF + + IF checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'STRICT_PASSWORD_POLICY') + IF checkPasswordStrength(pass)<>TRUE THEN loggedOnUserMisc.forcePwdReset:=TRUE + ENDIF purgeLine() aePuts('\b\n') RETURN RESULT_SUCCESS ENDIF + ELSE + purgeLine() + aePuts('\b\n') + RETURN RESULT_SUCCESS ENDIF ENDIF aePuts('\b\n') @@ -3309,8 +3460,8 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n ->calculate the new password hash StrCopy(tempstring,msg.string) IF StrLen(tempstring)>0 - UpperStr(tempstring) - loggedOnUser.pwdHash:=calcPasswordHash(tempstring) + setNewPassword(loggedOnUser,loggedOnUserMisc,tempstring) + loggedOnUserMisc.pwdLastUpdated:=getSystemTime() ENDIF ENDIF CASE DT_LOCATION @@ -3512,8 +3663,8 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n CASE BB_LOCAL AstrCopy(msg.string,cmds.bbsLoc,200) CASE ZMODEMSEND - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=NIL dlTTTM:=NIL tTEFF:=NIL @@ -3522,8 +3673,8 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n ch:=downloadFile(tempstring) IF((logonType>=LOGON_TYPE_REMOTE) AND (checkCarrier()=FALSE)) THEN msg.data:=-2 ELSE msg.data:=ch CASE BATCHZMODEMSEND - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=NIL dlTTTM:=NIL tTEFF:=NIL @@ -3531,8 +3682,8 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n ch:=downloadFile(msg.filler1) IF((logonType>=LOGON_TYPE_REMOTE) AND (checkCarrier()=FALSE)) THEN msg.data:=-2 ELSE msg.data:=ch CASE ZMODEMRECEIVE - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=NIL dlTTTM:=NIL tTEFF:=NIL @@ -3788,8 +3939,8 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n ioFlags[IOFLAG_SER_OUT]:=msg.data CASE AXNET_SEND - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=0 dlTTTM:=0 tTEFF:=0 @@ -3802,8 +3953,8 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n ENDIF ENDIF CASE AXNET_RECEIVE - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=0 dlTTTM:=0 tTEFF:=0 @@ -3831,8 +3982,12 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n IF checkConfAccess(msg.data+1) THEN msg.data:=1 ELSE msg.data:=0 ENDIF CASE PASSWORD_HASH - formatUnsignedLong(calcPasswordHash(msg.string),tempstring) - AstrCopy(msg.string,tempstring,20) + IF loggedOnUserMisc.pwdType=PWD_LEGACY + formatUnsignedLong(calcPasswordHash(msg.string),tempstring) + ELSE + StrCopy(tempstring,loggedOnUserMisc.pwdHash,32) + ENDIF + AstrCopy(msg.string,tempstring,40) CASE GET_GNSFLAG msg.data:=IF(nonStopDisplayFlag) THEN 1 ELSE 0 CASE DISPLAY_FILE @@ -9105,7 +9260,7 @@ PROC doorLog(type, str:PTR TO CHAR) formatLongDateTime(getSystemTime(),str1) IF StrLen(str)>0 - StringF(string,'[\s[25]] \s - \d - \s[10]',str1,name,type,str) + StringF(string,'[\s[25]] \s - \d - \s',str1,name,type,str) ELSE StringF(string,'[\s[25]] \s - \d - Exiting',str1,name,type) ENDIF @@ -9416,8 +9571,8 @@ PROC checkAttachedFile(msgnumb,flag) StrCopy(tempStr,'') - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=NIL ulTTTM:=0 tTEFF:=NIL @@ -11013,13 +11168,13 @@ PROC chooseComputer() ENDFOR aePuts('\b\n') -jLoop5: +jLoop6: aePuts('Choose computer type: ') stat:=lineInput('','',3,INPUT_TIMEOUT,tempStr) IF(stat<0) THEN RETURN stat IF(StrLen(tempStr)=0) THEN RETURN RESULT_SUCCESS stat:=Val(tempStr) - IF((stat <= 0) OR (stat > computerTypes.count())) THEN JUMP jLoop5 + IF((stat <= 0) OR (stat > computerTypes.count())) THEN JUMP jLoop6 loggedOnUser.secBulletin:=stat-1 @@ -12354,7 +12509,7 @@ PROC checkFIBForFileSize(fullPath:PTR TO CHAR, checkConfNum, fBlock:PTR TO filei IF(dp=NIL) IF tfsizeList<>NIL THEN tfsizeList.setItem(checkConfNum-1,tfsizeList.item(checkConfNum-1)+fsize) - dtfsize:=dtfsize+fsize + addBCD(dtfsize,fsize) ENDIF ENDPROC dp @@ -12365,14 +12520,14 @@ PROC checkForFileSize(checkFilename:PTR TO CHAR, checkConfNum, tfsizeList:PTR TO DEF path[255]:STRING,str[255]:STRING,tempstr[100]:STRING,tempstr2[100]:STRING DEF fname1[255]:STRING,fname2[255]:STRING DEF final[255]:STRING - DEF ft,dp + DEF ft=0,dp DEF fBlock: PTR TO fileinfoblock - DEF fLock=0 + DEF fLock=0,fLock2,res DEF drivenum DEF ramDir[255]:STRING DEF patternBuf,patBufLen - DEF debugcount + DEF debugcount,xit IF checkConfNum=-1 THEN checkConfNum:=currentConf @@ -12388,7 +12543,7 @@ PROC checkForFileSize(checkFilename:PTR TO CHAR, checkConfNum, tfsizeList:PTR TO IF StriCmp(fname1,fname2) StringF(tempstr,' File (\s) not found.\b\n',fname1) IF (ftpConn=FALSE) THEN aePuts(tempstr) - RETURN RESULT_FAILURE + RETURN RESULT_NOT_FOUND ENDIF ENDIF @@ -12397,7 +12552,7 @@ PROC checkForFileSize(checkFilename:PTR TO CHAR, checkConfNum, tfsizeList:PTR TO IF StriCmp(fname1,fname2) StringF(tempstr,' File (\s) not found.\b\n',fname1) IF ftpConn=FALSE THEN aePuts(tempstr) - RETURN RESULT_FAILURE + RETURN RESULT_NOT_FOUND ENDIF ENDIF @@ -12462,6 +12617,7 @@ jumpIn: IF MatchPatternNoCase(patternBuf,ramDir) THEN fLock:=Lock(final,ACCESS_READ) ENDWHILE Close(ft) + ft:=0 ELSE fLock:=Lock(final,ACCESS_READ) ENDIF @@ -12480,6 +12636,10 @@ jumpIn: IF(doflag) IF fLock=NIL + StringF(ramDir,'RAM:DirCaches/Conf\dDir\d',checkConfNum,drivenum-1) + IF fileExists(ramDir) + ft:=Open(ramDir,MODE_OLDFILE) + ENDIF IF((fLock:=Lock(final,ACCESS_READ))=0) FreeDosObject(DOS_FIB,fBlock) StringF(str,'Error, Path \s missing, adjust paths file..',path) @@ -12500,32 +12660,58 @@ jumpIn: IF(wflag=0) THEN JUMP gotit debugcount:=0 - WHILE (ExNext(fLock,fBlock)) /* my change.. prior to this we had a blank file name */ - debugcount++ - IF(fBlock.direntrytype<0) + WHILE TRUE + IF(ft=0) + xit:=ExNext(fLock,fBlock)=0 + ELSE + xit:=(Fgets(ft,tempstr,255)=0) + ENDIF + EXIT xit + + debugcount++ + IF ft ORELSE (fBlock.direntrytype<0) gotit: - StrCopy(tempstr,fBlock.filename) + IF ft + IF tempstr[StrLen(tempstr)-1]=10 THEN SetStr(tempstr,StrLen(tempstr)-1) + ELSE + StrCopy(tempstr,fBlock.filename) + ENDIF UpperStr(tempstr) stat:=MatchPatternNoCase(patternBuf,tempstr) + res:=TRUE IF((stat<>0) OR sysopdl) fflag:=1 IF(sysopdl) StrCopy(final,checkFilename) ELSE - StrCopy(final,path) - StrAdd(final,fBlock.filename) + IF ft<>0 + StringF(final,'\s\s',path,tempstr) + fLock2:=Lock(final,ACCESS_READ) + IF fLock2 + Examine(fLock2,fBlock) + UnLock(fLock2) + ELSE + res:=FALSE + ENDIF + ELSE + StringF(final,'\s\s',path,fBlock.filename) + ENDIF ENDIF - IF (dp:=checkFIBForFileSize(final, checkConfNum, fBlock,tfsizeList,freeDFlagList,cfn, z))=-1 - FreeDosObject(DOS_FIB,fBlock) - UnLock(fLock) - RETURN 11 + IF res + IF (dp:=checkFIBForFileSize(final, checkConfNum, fBlock,tfsizeList,freeDFlagList,cfn, z))=-1 + FreeDosObject(DOS_FIB,fBlock) + UnLock(fLock) + IF ft<>0 THEN Close(ft) + RETURN 11 + ENDIF ENDIF IF(wflag=0) FreeDosObject(DOS_FIB,fBlock) UnLock(fLock) + IF ft<>0 THEN Close(ft) IF(dp<>NIL) THEN RETURN RESULT_FAILURE ELSE RETURN RESULT_SUCCESS ENDIF ENDIF @@ -12537,6 +12723,7 @@ gotit: IF(stat<0) FreeDosObject(DOS_FIB,fBlock) UnLock(fLock) + IF ft<>0 THEN Close(ft) RETURN RESULT_NO_CARRIER ENDIF SELECT stat @@ -12545,21 +12732,26 @@ gotit: IF(stat<0) FreeDosObject(DOS_FIB,fBlock) UnLock(fLock) + IF ft<>0 THEN Close(ft) RETURN RESULT_NO_CARRIER ENDIF CASE 3 /* ^C */ aePuts('**Break\b\n') FreeDosObject(DOS_FIB,fBlock) UnLock(fLock) + IF ft<>0 THEN Close(ft) RETURN 10 ENDSELECT ENDIF ENDIF ENDWHILE UnLock(fLock) + IF ft<>0 THEN Close(ft) + ft:=0 fLock:=0 IF(z=1) THEN JUMP outst ENDIF +nxt: StringF(tempstr,'DLPATH.\d',drivenum++) UNTIL pstat=0 @@ -12575,7 +12767,7 @@ outst: StringF(str,' File (\s) not found.\b\n',checkFilename) aePuts(str) ENDIF - RETURN RESULT_FAILURE + RETURN RESULT_NOT_FOUND ENDIF IF(dp<>NIL) THEN RETURN RESULT_FAILURE @@ -13382,7 +13574,7 @@ PROC xprfopen() MOVE.L A0,fn MOVE.L A1,am - loadA4() + loadA4({tasksA4}) IF StriCmp(am,'r') filemode:=MODE_OLDFILE @@ -13476,7 +13668,7 @@ PROC xprfclose() -> A0 MOVE.L A0,fp - loadA4() + loadA4({tasksA4}) StringF(tempstr,'xprfclose \d',fp) debugLog(LOG_DEBUG,tempstr) @@ -13491,7 +13683,7 @@ PROC xprfclose() ENDIF ENDIF IF zModemInfo.needUpdateDownloadStats - zmdownloadcompleted(zModemInfo.filesize) + zmdownloadcompleted(zModemInfo.filesize,zModemInfo.filesize-zModemInfo.resumePos) zModemInfo.needUpdateDownloadStats:=FALSE ENDIF @@ -13507,7 +13699,7 @@ PROC xprchkabort() DEF winmsg:PTR TO intuimessage,res ->DEF tempstr[255]:STRING - loadA4() + loadA4({tasksA4}) res:=0 IF windowZmodem<>NIL @@ -13542,7 +13734,7 @@ PROC xprfread() MOVE.L D1,bcount MOVE.L A1,fp - loadA4() + loadA4({tasksA4}) ->StringF(tempstr,'xprfread: \d bytes',bsize*bcount) ->debugLog(LOG_DEBUG,tempstr) @@ -13576,7 +13768,7 @@ PROC xprfwrite() MOVE.L D1,bcount MOVE.L A1,fp - loadA4() + loadA4({tasksA4}) ->StringF(tempstr,'xprfwrite: \d bytes',Mul(bsize,bcount)) ->debugLog(LOG_DEBUG,tempstr) @@ -13610,7 +13802,7 @@ PROC xprsread() MOVE.L D0,bsize MOVE.L D1,timeout - loadA4() + loadA4({tasksA4}) StringF(tempstr,'xprsread: \d bytes \d timeout',bsize,timeout) debugLog(LOG_DEBUG,tempstr) @@ -13881,7 +14073,7 @@ PROC xprswrite() MOVE.L A0,buf MOVE.L D0,bsize - loadA4() + loadA4({tasksA4}) StringF(tempstr,'xprswrite: \d bytes',bsize) debugLog(LOG_DEBUG,tempstr) @@ -13908,7 +14100,7 @@ PROC xprfseek() MOVE.L D0,offset MOVE.L D1,origin - loadA4() + loadA4({tasksA4}) StringF(tempstr,'xprfseek: \d offset',offset) debugLog(LOG_DEBUG,tempstr) @@ -13940,7 +14132,7 @@ PROC xprsflushAsm() ENDPROC D0 PROC xprsflush() - loadA4() + loadA4({tasksA4}) debugLog(LOG_DEBUG,'xprsflush') ENDPROC FALSE @@ -13959,7 +14151,7 @@ PROC xprupdate() MOVE.L A0,xpru - loadA4() + loadA4({tasksA4}) IF(xpru.xpru_updatemask AND XPRU_ERRORMSG)<>0 AstrCopy(zModemInfo.zStat,xpru.xpru_errormsg,60) @@ -14057,7 +14249,7 @@ PROC xprsetserial() MOVE.L D0,newstatus - loadA4() + loadA4({tasksA4}) StringF(tempstr,'xprsetserial \d',newstatus) debugLog(LOG_DEBUG,tempstr) @@ -14081,7 +14273,7 @@ PROC xprfinfo() MOVE.L A0,fn MOVE.L D0,fitype - loadA4() + loadA4({tasksA4}) StringF(tempstr,'xprsfinfo - fitype \d \s',fitype,fn) debugLog(LOG_DEBUG,tempstr) @@ -14126,7 +14318,7 @@ ENDPROC D0 PROC xprunlink() DEF fn MOVE.L A0,fn - loadA4() + loadA4({tasksA4}) ENDPROC xprunlink2(fn) PROC xprunlink2(fn) @@ -14162,7 +14354,7 @@ PROC xprffirst() DEF buffer:PTR TO CHAR MOVE.L A0,buffer - loadA4() + loadA4({tasksA4}) ENDPROC xprffirst2(buffer) PROC xprffirst2(buffer) @@ -14186,7 +14378,7 @@ PROC xprfnext() MOVE.L A0,buffer - loadA4() + loadA4({tasksA4}) ENDPROC xprfnext2(buffer) @@ -14409,7 +14601,7 @@ PROC updateZDisplay() ENDIF ELSE IF zModemInfo.currentOperation=ZMODEM_DOWNLOAD - StringF(tempstr,'[Node \d] Send Window (\d/\d)',node,zModemInfo.currentDL,zModemInfo.total) + StringF(tempstr,'[Node \d] Send Window (\d/\d)',node,zModemInfo.currentDL,zModemInfo.totalDL) AstrCopy(zModemInfo.titleBar,tempstr) ELSE StringF(tempstr,'[Node \d] Receive Window (\d/??)',node,zModemInfo.currentUL) @@ -14551,7 +14743,7 @@ PROC downloadFile(str: PTR TO CHAR,forceZmodem=FALSE) ENDFOR ENDIF - res:=downloadFiles(templist,0,FALSE,forceZmodem) + res:=downloadFiles(templist,NIL,FALSE,forceZmodem) clearFlagItems(templist) END templist @@ -14633,17 +14825,20 @@ PROC ftpUploadFileStart(fileName:PTR TO CHAR,resumefrom) zModemInfo.filesize:=0 zModemInfo.resumePos:=resumefrom zModemInfo.transPos:=0 - ftptime:=getSystemTime() + ftptime1,ftptime2:=getSystemTime() updateZDisplay() ENDPROC PROC ftpUploadFileEnd(fileName:PTR TO CHAR,success) DEF i DEF str[255]:STRING + DEF t1,t2 IF ftpConn THEN ulTTTM:=0 - ulTTTM:=ulTTTM+getSystemTime()-ftptime + t1,t2:=getSystemTime() + + ulTTTM:=ulTTTM+Mul(t1-ftptime1,50)+t2-ftptime2 setEnvStat(ENV_UPLOADING) IF ftpConn @@ -14651,7 +14846,8 @@ PROC ftpUploadFileEnd(fileName:PTR TO CHAR,success) StringF(str,'\tUploading \s \d bytes',fileName,zModemInfo.transPos) callersLog(str) - StringF(str,'\t 1 file(s), \dk bytes, \d minute(s). \d second(s), \d cps, N/A % efficiency.',Shr(zModemInfo.transPos,10),Div(ulTTTM,60),Mod(ulTTTM,60),tTCPS) + ulTTTM:=Div(ulTTTM,50) + StringF(str,'\t 1 file(s), \dk bytes, \d minute(s). \d second(s), \d cps, N/A % efficiency.',Shr(zModemInfo.transPos-zModemInfo.resumePos,10),Div(ulTTTM,60),Mod(ulTTTM,60),tTCPS) callersLog(str) ELSE callersLog('\tUpload Failed..') @@ -14665,14 +14861,13 @@ PROC ftpUploadFileEnd(fileName:PTR TO CHAR,success) ENDIF ENDPROC -PROC ftpDownloadFileStart(fileName:PTR TO CHAR,filelen) +PROC ftpDownloadFileStart(fileName:PTR TO CHAR,filelen,resume) DEF fileItem:PTR TO flagFileItem DEF item:PTR TO flagFileItem DEF fn:PTR TO CHAR DEF i - ftptime:=getSystemTime() - + ftptime1,ftptime2:=getSystemTime() fileItem:=NIL fn:=FilePart(fileName) @@ -14692,7 +14887,7 @@ PROC ftpDownloadFileStart(fileName:PTR TO CHAR,filelen) ENDIF zModemInfo.filesize:=filelen - zModemInfo.resumePos:=0 + zModemInfo.resumePos:=resume zModemInfo.transPos:=0 tTEFF:=0 tTCPS:=0 @@ -14708,10 +14903,13 @@ PROC ftpDownloadFileEnd(fileName:PTR TO CHAR, result) DEF fn:PTR TO CHAR DEF tempStr[255]:STRING DEF i + DEF t1,t2 IF ftpConn THEN dlTTTM:=0 - dlTTTM:=dlTTTM+getSystemTime()-ftptime + t1,t2:=getSystemTime() + + dlTTTM:=dlTTTM+Mul(t1-ftptime1,50)+t2-ftptime2 fileItem:=NIL fn:=FilePart(fileName) @@ -14724,11 +14922,12 @@ PROC ftpDownloadFileEnd(fileName:PTR TO CHAR, result) IF fileItem=NIL THEN RETURN - IF (result) THEN updateDownloadStats(fileItem,zModemInfo.filesize) + IF (result) THEN updateDownloadStats(fileItem,zModemInfo.filesize,zModemInfo.filesize-zModemInfo.resumePos) IF ftpConn + dlTTTM:=Div(dlTTTM,50) IF result - StringF(tempStr,'\t 1 file(s), \dk bytes, \d minutes \d seconds \d cps, N/A % efficiency.',Shr(zModemInfo.filesize,10) AND $003fffff,Div(dlTTTM,60),Mod(dlTTTM,60),tTCPS) + StringF(tempStr,'\t 1 file(s), \dk bytes, \d minutes \d seconds \d cps, N/A % efficiency.',Shr(zModemInfo.filesize-zModemInfo.resumePos,10) AND $003fffff,Div(dlTTTM,60),Mod(dlTTTM,60),tTCPS) callersLog(tempStr) udLog(tempStr) ELSE @@ -14959,9 +15158,7 @@ ENDPROC res<>0 PROC ftpAuth(userName:PTR TO CHAR,password:PTR TO CHAR) IF StriCmp(userName,loggedOnUser.name,31)=FALSE THEN RETURN FALSE - UpperStr(password) - IF calcPasswordHash(password)<>loggedOnUser.pwdHash THEN RETURN FALSE -ENDPROC TRUE +ENDPROC checkUserPassword(loggedOnUser,loggedOnUserMisc,password) PROC ftpFindFile(filename:PTR TO CHAR,outFullFilename:PTR TO CHAR) DEF fileList:PTR TO stdlist @@ -14977,41 +15174,43 @@ PROC ftpFindFile(filename:PTR TO CHAR,outFullFilename:PTR TO CHAR) END fileList ENDPROC -PROC updateDownloadStats(fileItem:PTR TO flagFileItem,fsize) +PROC updateDownloadStats(fileItem:PTR TO flagFileItem,fsize,sentsize) DEF cb:PTR TO confBase dlFileCount++ - dTBT:=addWO(dTBT,fsize) + addBCD(dTBT,sentsize) IF sopt.toggles[TOGGLES_CREDITBYKB] fsize:=Shr(fsize,10) AND $003fffff ENDIF - IF(checkSecurity(ACS_CONFERENCE_ACCOUNTING)) - saveMsgPointers(currentConf,currentMsgBase) + IF sentsize + IF(checkSecurity(ACS_CONFERENCE_ACCOUNTING)) + saveMsgPointers(currentConf,currentMsgBase) - IF(freeDownloads=FALSE) - IF creditAccountTrackDownloads(loggedOnUser) - cb:=confBases.item(getConfIndex(fileItem.confNum,1)) + IF(freeDownloads=FALSE) + IF creditAccountTrackDownloads(loggedOnUser) + cb:=confBases.item(getConfIndex(fileItem.confNum,1)) - addBCD(cb.downloadBytesBCD,fsize) - cb.bytesDownload:=convertFromBCD(cb.downloadBytesBCD) - cb.downloads:=cb.downloads+1 + addBCD(cb.downloadBytesBCD,fsize) + cb.bytesDownload:=convertFromBCD(cb.downloadBytesBCD) + cb.downloads:=cb.downloads+1 + ENDIF ENDIF - ENDIF - loadMsgPointers(currentConf,currentMsgBase) - ELSE - IF(freeDownloads=FALSE) - IF creditAccountTrackDownloads(loggedOnUser) + loadMsgPointers(currentConf,currentMsgBase) + ELSE + IF(freeDownloads=FALSE) + IF creditAccountTrackDownloads(loggedOnUser) - addBCD(loggedOnUserMisc.downloadBytesBCD,fsize) - loggedOnUser.bytesDownload:=convertFromBCD(loggedOnUserMisc.downloadBytesBCD) - loggedOnUser.downloads:=loggedOnUser.downloads+1 + addBCD(loggedOnUserMisc.downloadBytesBCD,fsize) + loggedOnUser.bytesDownload:=convertFromBCD(loggedOnUserMisc.downloadBytesBCD) + loggedOnUser.downloads:=loggedOnUser.downloads+1 + ENDIF ENDIF ENDIF + loggedOnUser.dailyBytesDld:=loggedOnUser.dailyBytesDld+fsize + IF bytesADL<>$7fffffff THEN bytesADL:=bytesADL-fsize ENDIF - loggedOnUser.dailyBytesDld:=loggedOnUser.dailyBytesDld+fsize - IF bytesADL<>$7fffffff THEN bytesADL:=bytesADL-fsize ENDPROC PROC ftpUpload(uploadFolder:PTR TO CHAR,ftpPorts,ftpDataPorts) @@ -15117,13 +15316,13 @@ PROC ftpDownload(fileList: PTR TO stdlist, updateDownloadStats,ftpPorts,ftpDataP ENDPROC ->this returns 0 = fail, 1 = success unlike most of the routines -PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, forceZmodem=FALSE) +PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize:PTR TO CHAR, updateDownloadStats, forceZmodem=FALSE) DEF tempstr[255]:STRING DEF tempstr2[255]:STRING DEF debugstr[255]:STRING DEF xprio: PTR TO xprIO DEF result - DEF time1,time2 + DEF time1,time2,ticks1,ticks2 DEF oldshared DEF ftpPorts:PTR TO LONG,ftpDataPorts:PTR TO LONG,httpPorts:PTR TO LONG DEF zm=NIL: PTR TO zmodem_t @@ -15139,6 +15338,7 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, DEF internalName[10]:STRING DEF path[255]:STRING DEF txwindow,rxwindow + DEF tmpBCD[8]:ARRAY OF CHAR DEF protocol[255]:STRING @@ -15210,7 +15410,7 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, zModemInfo.shouldUpdateDownloadStats:=updateDownloadStats zModemInfo.needUpdateDownloadStats:=FALSE - zModemInfo.currentDL:=0;zModemInfo.total:=fileList.count();zModemInfo.transPos:=0;zModemInfo.filesize:=0;zModemInfo.errorCount:=0;zModemInfo.errorPos:=0; zModemInfo.resumePos:=0 + zModemInfo.currentDL:=0;zModemInfo.totalDL:=fileList.count();zModemInfo.transPos:=0;zModemInfo.filesize:=0;zModemInfo.errorCount:=0;zModemInfo.errorPos:=0; zModemInfo.resumePos:=0 AstrCopy(zModemInfo.zStat,'') AstrCopy(zModemInfo.fileName,'') AstrCopy(zModemInfo.lastTime,'') @@ -15372,7 +15572,7 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, hyd.hyd_flush:={zmflush} hyd.hyd_isconnected:={zmisconnected} hyd.hyd_iscancelled:=NIL - hyd.hyd_logmessage:={zmlputs} + hyd.hyd_logmessage:={debugLog} hyd.hyd_getkey:={hydgetkey} hyd.hyd_sysidle:={hydsysidle} hyd.hyd_chatwrite:={hydchatwrite} @@ -15380,10 +15580,10 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, ELSEIF xmodemFlag OR ymodemFlag xym:=NEW xym - xym.log_level:=ZM_LOG_DEBUG + binaryRaw:=(telnetSocket>=0) xymodem_init(xym, 0, - {zmlputs}, + {debugLog}, {zmprogress}, IF telnetSocket>=0 THEN {zmrecvbyteTelnet} ELSE {zmrecvbyteSerial}, {zmisconnected}, @@ -15404,13 +15604,12 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, {zmnextfile}, 2048,0,binaryRaw,65536) xym.total_files:=fileList.count() - xym.total_bytes:=estimatedSize + IF estimatedSize THEN CopyMem(estimatedSize,xym.total_bytes,8) ELSE convertToBCD(0,xym.total_bytes) ELSE zm:=NEW zm - zm.log_level:=ZM_LOG_DEBUG binaryRaw:=(telnetSocket>=0) zmodem_init(zm, 0, - {zmlputs}, + {debugLog}, {zmprogress}, IF telnetSocket>=0 THEN {zmrecvbyteTelnet} ELSE {zmrecvbyteSerial}, {zmisconnected}, @@ -15431,12 +15630,19 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, {zmnextfile}, maxBlkSize,0,binaryRaw,65536) zm.total_files:=fileList.count() - zm.total_bytes:=estimatedSize + IF estimatedSize THEN CopyMem(estimatedSize,zm.total_bytes,8) ELSE convertToBCD(0,zm.total_bytes) ENDIF ENDIF asynciobase:=OpenLibrary('asyncio.library',0) + IF telnetSocket>=0 + willsent:=0 + dosent:=0 + iac(telnetSocket,253,0) ->do binary + iac(telnetSocket,251,0) ->will binary + ENDIF + IF ext StringF(debugstr,'xpr setup options = \s',tempstr) debugLog(LOG_DEBUG,debugstr) @@ -15465,10 +15671,10 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, IF ext xprio.xpr_filename:=NIL - time1:=getSystemTime() + time1,ticks1:=getSystemTime() result:=XprotocolSend(xprio) - time2:=getSystemTime() - dlTTTM:=time2-time1; + time2,ticks2:=getSystemTime() + dlTTTM:=Mul(time2-time1,50)+ticks2-ticks1; IF zModemInfo.transPos<>zModemInfo.filesize THEN result:=FALSE ELSE IF hydraFlag @@ -15484,14 +15690,20 @@ PROC downloadFiles(fileList: PTR TO stdlist, estimatedSize, updateDownloadStats, result:=zmodem_send_files(zm, NIL,{dlTimeTaken}) ENDIF dlTTTM:=dlTimeTaken + ENDIF - IF dlTTTM - tTCPS:=Mul(Div(dTBT,dlTTTM),50) - ELSE - tTCPS:=Mul(dTBT,50) - ENDIF - dlTTTM:=Div(dlTTTM,50) - tTEFF:=calcEfficiency(tTCPS,onlineBaud) + IF dlTTTM + CopyMem(dTBT,tmpBCD,8) + mulBCD(tmpBCD,50) + tTCPS:=divBCD(tmpBCD,dlTTTM) + ELSE + tTCPS:=convertFromBCD(dTBT) + ENDIF + tTEFF:=calcEfficiency(tTCPS,onlineBaud) + + IF telnetSocket>=0 + iac(telnetSocket,254,0) ->dont binary + iac(telnetSocket,252,0) ->wont binary ENDIF IF ext @@ -15551,7 +15763,7 @@ PROC checklist(lfnames: PTR TO stdlist, sizeList:PTR TO stdlist, freeDFlagList:P item:=lfnames.item(i) IF(StrLen(item.fileName)>0) status:=checkForFileSize(item.fileName,item.confNum,sizeList,freeDFlagList,clrfinal,0) - IF((status=11) OR (status=10)) THEN RETURN RESULT_SUCCESS + IF((status=RESULT_SIGNALLED) OR (status=RESULT_PRIVATE)) THEN RETURN RESULT_SUCCESS ENDIF ENDFOR ENDPROC RESULT_SUCCESS @@ -15788,7 +16000,7 @@ PROC hydsysidle() tv.secs:=1 tv.micro:=0 setSingleFDS(fds,telnetSocket) - WaitSelect(telnetSocket+1,fds,fds,0,tv,consig) + WaitSelect(telnetSocket+1,fds,fds,0,tv,{consig}) ELSE /*openTimer() setTimer(1,0) @@ -15977,21 +16189,6 @@ PROC hydstatus(hyd:PTR TO hydra_t,xmit) ENDIF ENDPROC/*hydra_status()*/ -PROC zmlputs(level, str:PTR TO CHAR) - SELECT level - CASE ZM_LOG_DEBUG - debugLog(LOG_DEBUG,str) - CASE ZM_LOG_INFO - debugLog(LOG_DEBUG,str) - CASE ZM_LOG_NOTICE - debugLog(LOG_DEBUG,str) - CASE ZM_LOG_WARNING - debugLog(LOG_WARN,str) - CASE ZM_LOG_ERR - debugLog(LOG_ERROR,str) - ENDSELECT -ENDPROC - PROC zmprogress(pos,cnt,filesize,s1,s2,errors,startpos,filename:PTR TO CHAR,newfile,blocksize) DEF t1,t2,t,td,n DEF h,m,s @@ -16066,7 +16263,7 @@ PROC zmrecvbyteTelnet(timeout) DEF r DEF tv:timeval ->DEF sysTime - + MOVE.L bufferReadOffset,A0 MOVE.L bufferedBytes,A1 MOVE.L zmodemRxBuffer,A2 @@ -16098,22 +16295,41 @@ testiac: BRA recret test1: - CMP.B #250,D0 - BCC.S test2 - - MOVEQ.L #2,D2 - MOVE.L D2,lastIAC - BRA repbuff - -test2: MOVEQ.L #2,D2 MOVE.L D2,lastIAC + MOVE.L D0,iaccmd BRA repbuff testiac2: CMP.B #2,D2 - BNE.S testiac3 + BNE testiac3 + + TST.B D0 + BNE notbin + + CMP.L #251,iaccmd + BNE.S notwill + TST.L dosent + BNE.S notwill + MOVEM.L D0-D7/A0-A6,-(A7) + iac(telnetSocket,253,0) ->if will binary then do binary + dosent:=1 + MOVEM.L (A7)+,D0-D7/A0-A6 + +notwill: + CMP.L #253,iaccmd + BNE.S notdo + + TST.L willsent + BNE.S notdo + MOVEM.L D0-D7/A0-A6,-(A7) + iac(telnetSocket,251,0) ->if do binary then will binary + willsent:=1 + MOVEM.L (A7)+,D0-D7/A0-A6 + +notdo: +notbin: CLR.L D2 MOVE.L D2,lastIAC BRA repbuff @@ -16128,8 +16344,8 @@ testiac3: buffempty: res:=1 - bufferReadOffset:=0 - bufferedBytes:=0 + bufferReadOffset:=0 + bufferedBytes:=0 IF timeout tv.secs:=timeout @@ -16144,8 +16360,8 @@ buffempty: IF (r:=Recv(telnetSocket,zmodemRxBuffer,zModemRxBufferSize,0))<>-1 bufferedBytes:=bufferedBytes+r ENDIF - ENDIF - + ENDIF + IF r<=0 IF (checkCarrier()=FALSE) THEN RETURN -1 ENDIF @@ -16171,11 +16387,27 @@ redo1: RETURN res ELSEIF (res>=250) AND (res<255) lastIAC:=2 + iac1:=res ELSE WriteF('unknown IAC \d\b\n',res) lastIAC:=2 ENDIF ELSEIF lastIAC=2 + IF res=0 + IF iac1=251 + //will + iacr[0]:=255 + iacr[1]:=253 + iacr[2]:=0 + serPuts(iacr,3,TRUE,TRUE) + ELSEIF iac1=253 + //do + iacr[0]:=255 + iacr[1]:=251 + iacr[2]:=0 + serPuts(iacr,3,TRUE,TRUE) + ENDIF + ENDIF lastIAC:=0 ELSEIF res=255 lastIAC:=1 @@ -16199,6 +16431,8 @@ redo1: n:=(zModemRxBufferSize-bufferedBytes) UNTIL (r=-1) OR (n=0) + sysTime:=getSystemTime() + IF ((lastCarrierCheck+5)NIL - uTBT:=addWO(uTBT,filesize) + addBCD(uTBT,filesize) recFileNames.add(FilePart(fname)) ulFileCount++ doBgCheck() @@ -16366,11 +16600,11 @@ PROC zmfclose(fh) ENDIF ENDPROC -PROC zmdownloadcompleted(fsize) +PROC zmdownloadcompleted(fsize,sentsize) DEF fileItem:PTR TO flagFileItem fileItem:=zModemInfo.fileList.item(zModemInfo.currentDL) removeFlagFromList(FilePart(fileItem.fileName),fileItem.confNum) - updateDownloadStats(fileItem,fsize) + updateDownloadStats(fileItem,fsize,sentsize) ENDPROC PROC zmfseek(fh,offset,origin) @@ -16424,7 +16658,7 @@ PROC createBackgroundFileCheckThread() proc:=CreateNewProc(tags) END tags[countTags(tags)] IF proc<>NIL - saveA4thread(proc.task) + saveA4(proc.task,{threadtasksA4}) ELSE transfering:=FALSE bgChecking:=FALSE @@ -16446,8 +16680,9 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE DEF tempstr[255]:STRING,tempstr2[255]:STRING,debugstr[255]:STRING DEF result DEF xprio=NIL: PTR TO xprIO - DEF time1,time2 + DEF time1,time2,ticks1,ticks2 DEF oldshared,bgport + DEF internalName[10]:STRING DEF msg:PTR TO jhMessage,tags=NIL:PTR TO LONG DEF ftpPorts:PTR TO LONG,ftpDataPorts:PTR TO LONG,httpPorts:PTR TO LONG DEF protocol[255]:STRING @@ -16462,12 +16697,14 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE DEF ulTimeTaken DEF ext=TRUE DEF txwindow,rxwindow + DEF tmpBCD[8]:ARRAY OF CHAR statWinType:=0 ObtainSemaphore(bgData) bgData.checkedCount:=0 - bgData.checkedBytes:=0 + convertToBCD(0,bgData.checkedBytes) + ReleaseSemaphore(bgData) IF (forceZmodem) OR (loggedOnUser=NIL) @@ -16476,34 +16713,42 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE StrCopy(protocol,(xprLib.item(loggedOnUser.xferProtocol))) ENDIF + IF(StriCmp(protocol,'INTERNAL')) + StrCopy(internalName,'ZModem') + ext:=FALSE + ENDIF + IF(StriCmp(protocol,'HYDRA')) StrCopy(protocol,'INTERNAL') hydraFlag:=TRUE statWinType:=1 + StrCopy(internalName,'Hydra') ext:=FALSE ENDIF IF(StriCmp(protocol,'INTERNALXM')) StrCopy(protocol,'INTERNAL') xmodemFlag:=TRUE + StrCopy(internalName,'XModem') ext:=FALSE ENDIF IF(StriCmp(protocol,'INTERNALYM')) StrCopy(protocol,'INTERNAL') ymodemFlag:=TRUE + StrCopy(internalName,'YModem') ext:=FALSE ENDIF IF(StriCmp(protocol,'INTERNAL8K')) StrCopy(protocol,'INTERNAL') maxBlkSize:=8192 + StrCopy(internalName,'ZModem') ext:=FALSE ENDIF - IF(StriCmp(protocol,'INTERNAL')) THEN ext:=FALSE - IF (StriCmp(protocol,'XPRZM')) + StrCopy(internalName,'ZModem') StrCopy(protocol,'INTERNAL') ext:=TRUE ENDIF @@ -16549,8 +16794,8 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE wantzwin:=FALSE checkOffhookFlag() receivePlayPen(TRUE) - IF (uTBT>0) AND (ulTTTM>0) - tTEFF:=calcEfficiency(Div(uTBT,ulTTTM),onlineBaud) + IF (ulTTTM>0) + tTEFF:=calcEfficiency(divBCD(uTBT,ulTTTM),onlineBaud) ELSE tTEFF:=0 ENDIF @@ -16578,8 +16823,8 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE wantzwin:=FALSE checkOffhookFlag() receivePlayPen(TRUE) - IF (uTBT>0) AND (ulTTTM>0) - tTEFF:=calcEfficiency(Div(uTBT,ulTTTM),onlineBaud) + IF (ulTTTM>0) + tTEFF:=calcEfficiency(divBCD(uTBT,ulTTTM),onlineBaud) ELSE tTEFF:=0 ENDIF @@ -16659,7 +16904,7 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE hyd.hyd_flush:={zmflush} hyd.hyd_isconnected:={zmisconnected} hyd.hyd_iscancelled:=NIL - hyd.hyd_logmessage:={zmlputs} + hyd.hyd_logmessage:={debugLog} hyd.hyd_getkey:={hydgetkey} hyd.hyd_sysidle:={hydsysidle} hyd.hyd_chatwrite:={hydchatwrite} @@ -16667,10 +16912,9 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE ELSEIF xmodemFlag OR ymodemFlag xym:=NEW xym - xym.log_level:=ZM_LOG_DEBUG binaryRaw:=(telnetSocket>=0) xymodem_init(xym, 0, - {zmlputs}, + {debugLog}, {zmprogress}, IF telnetSocket>=0 THEN {zmrecvbyteTelnet} ELSE {zmrecvbyteSerial}, {zmisconnected}, @@ -16692,10 +16936,9 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE 2048,0,binaryRaw,0) ELSE zm:=NEW zm - zm.log_level:=ZM_LOG_DEBUG binaryRaw:=(telnetSocket>=0) zmodem_init(zm, 0, - {zmlputs}, + {debugLog}, {zmprogress}, IF telnetSocket>=0 THEN {zmrecvbyteTelnet} ELSE {zmrecvbyteSerial}, {zmisconnected}, @@ -16720,6 +16963,13 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE asynciobase:=OpenLibrary('asyncio.library',0) + IF telnetSocket>=0 + willsent:=0 + dosent:=0 + iac(telnetSocket,253,0) ->do binary + iac(telnetSocket,251,0) ->will binary + ENDIF + IF ext StrCopy(tempstr,'') IF(StriCmp(protocol,'INTERNAL')) @@ -16758,10 +17008,10 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE ENDIF IF ext - time1:=getSystemTime() + time1,ticks1:=getSystemTime() result:=XprotocolReceive(xprio) - time2:=getSystemTime() - ulTTTM:=Mul(time2-time1,50) + time2,ticks2:=getSystemTime() + ulTTTM:=Mul(time2-time1,50)+ticks2-ticks1; ELSE IF hydraFlag result:=hydra_do_transfer(hyd,file,NIL,NIL,NIL,{ulTimeTaken}) @@ -16773,13 +17023,19 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE ulTTTM:=ulTimeTaken ENDIF IF ulTTTM - tTCPS:=Mul(Div(uTBT,ulTTTM),50) + CopyMem(uTBT,tmpBCD,8) + mulBCD(tmpBCD,50) + tTCPS:=divBCD(tmpBCD,ulTTTM) ELSE - tTCPS:=Mul(uTBT,50) + tTCPS:=convertFromBCD(uTBT) ENDIF tTEFF:=calcEfficiency(tTCPS,onlineBaud) - ulTTTM:=Div(ulTTTM,50) + IF telnetSocket>=0 + iac(telnetSocket,254,0) ->dont binary + iac(telnetSocket,252,0) ->wont binary + ENDIF + IF ext XprotocolCleanup(xprio) ELSE @@ -16799,7 +17055,7 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE IF msg msg.command:=BG_EXIT msg.msg.length:=SIZEOF jhMessage - + msg.msg.ln.type:=NT_FREEMSG ->signal background checking to finish PutMsg(bgport,msg) @@ -16823,7 +17079,11 @@ PROC fileUpload(file,forceZmodem=FALSE) HANDLE Delay(50) - aePuts(protocol) + IF(StriCmp(protocol,'INTERNAL')) + aePuts(internalName) + ELSE + aePuts(xprTitle.item(loggedOnUser.xferProtocol)) + ENDIF IF(result) THEN aePuts(' upload successful\b\n') ELSE aePuts(' upload unsuccessful\b\n') IF tags<>NIL THEN END tags @@ -17493,7 +17753,7 @@ PROC receivePlayPen(log) ObtainSemaphore(bgData) ulFileCount:=bgData.checkedCount - uTBT:=bgData.checkedBytes + CopyMem(bgData.checkedBytes,uTBT,8) ReleaseSemaphore(bgData) recFileNames.clear() @@ -17541,7 +17801,7 @@ PROC receivePlayPen(log) s++ ENDWHILE ulFileCount++ - uTBT:=addWO(uTBT,fib.size) + addBCD(uTBT,fib.size) IF log StringF(tempstr,'\tUploading \s[12] \d bytes',fib.filename, fib.size) udLog(tempstr) @@ -17947,6 +18207,7 @@ PROC doBgCheck() IF msg msg.command:=BG_CHECKFILE AstrCopy(msg.string,FilePart(zModemInfo.fileName),200) + msg.msg.ln.type:=NT_FREEMSG msg.msg.length:=SIZEOF jhMessage ->signal background checking to check the file @@ -17962,7 +18223,7 @@ PROC backgroundFileCheckThread() DEF exit=FALSE DEF msgcmd,type - loadA4thread() + loadA4({threadtasksA4}) bgCheckPort:=createPort(bgCheckPortName,0) IF bgCheckPort @@ -18015,6 +18276,8 @@ PROC checkFileExternal(temp: PTR TO CHAR, checkFile: PTR TO CHAR) stat:=RESULT_SUCCESS +debugLog(LOG_ERROR,'debug10d1') + IF readToolType(TOOLTYPE_FCHECK,temp,'CHECKER',s) StrCopy(options,s) ELSE @@ -18038,32 +18301,41 @@ PROC checkFileExternal(temp: PTR TO CHAR, checkFile: PTR TO CHAR) pri:=0 ENDIF ->(RTS) +debugLog(LOG_ERROR,'debug10d2') StrAdd(options,' ') StrAdd(options,checkFile) StringF(fileName,'\sOutPut_Of_Test',nodeWorkDir) IF((fi:=Open(fileName,MODE_NEWFILE)))<>0 filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,fi,NP_STACKSIZE,stack,NP_PRIORITY,pri,TAG_DONE]:LONG +debugLog(LOG_ERROR,'debug10d3') SystemTagList(options,filetags) +debugLog(LOG_ERROR,'debug10d4') END filetags[countTags(filetags)] Close(fi) +debugLog(LOG_ERROR,'debug10d5') IF bgChecking=FALSE THEN displayOutPutofTest() +debugLog(LOG_ERROR,'debug10d6') IF(readToolType(TOOLTYPE_FCHECK,temp,'SCRIPT',s)) StrAdd(s,' ') IF(fi:=Open('NIL:',MODE_NEWFILE))<>0 filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,fi,NP_STACKSIZE,stack,NP_PRIORITY,pri,TAG_DONE]:LONG +debugLog(LOG_ERROR,'debug10d7') StringF(options,'\s \s \s \d',s,checkFile,FilePart(checkFile),node) SystemTagList(options,filetags) +debugLog(LOG_ERROR,'debug10d8') END filetags[countTags(filetags)] Close(fi) ENDIF ENDIF +debugLog(LOG_ERROR,'debug10d9') StringF(options,'\sOutPut_Of_Test',nodeWorkDir) i:=1 StringF(fileName,'ERROR.\d',i) i++ +debugLog(LOG_ERROR,'debug10d10') WHILE(readToolType(TOOLTYPE_FCHECK,temp,fileName,s)) fi1:=Open(options,MODE_OLDFILE) WHILE((ReadStr(fi1,image)<>-1)) OR (StrLen(image)>0) @@ -18078,11 +18350,15 @@ PROC checkFileExternal(temp: PTR TO CHAR, checkFile: PTR TO CHAR) StringF(fileName,'ERROR.\d',i) i++ ENDWHILE +debugLog(LOG_ERROR,'debug10d11') SetProtection(options,FIBF_OTR_DELETE) DeleteFile(options) +debugLog(LOG_ERROR,'debug10d12') ELSE +debugLog(LOG_ERROR,'debug10d13') RETURN 0,stat ENDIF +debugLog(LOG_ERROR,'debug10d14') ENDPROC 1,stat PROC testFile(str: PTR TO CHAR, path: PTR TO CHAR) @@ -18118,7 +18394,9 @@ PROC testFile(str: PTR TO CHAR, path: PTR TO CHAR) aePuts('\b\n') StrAdd(temp4,temp) +debugLog(LOG_ERROR,'debug10d') r,stat:=checkFileExternal(temp2,temp4) +debugLog(LOG_ERROR,'debug10e') RETURN stat ENDIF ENDIF @@ -18238,6 +18516,7 @@ PROC sysopUpload() DEF tempstr2[255]:STRING DEF destpath[255]:STRING DEF string[255]:STRING + DEF tmpBCD[8]:ARRAY OF CHAR DEF str[255]:STRING DEF stat,cnt DEF spacehi,spacelo,space2hi,space2lo @@ -18280,8 +18559,8 @@ PROC sysopUpload() ulFileCount:=0 skipdFiles.clear() - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) dlTTTM:=0 ulTTTM:=0 tTEFF:=0 @@ -18295,7 +18574,12 @@ PROC sysopUpload() sysopUploading:=FALSE aePuts('\b\n\b\nFile Uploading Complete...\b\n') - StringF(string,' \d file(s), \dk bytes, \d minute(s). \d second(s), \d cps, \d% efficiency.',ulFileCount,Shr(uTBT,10) AND $003fffff,Div(ulTTTM,60),Mod(ulTTTM,60),tTCPS,tTEFF) + CopyMem(uTBT,tmpBCD,8) + divBCD1024(tmpBCD) + formatBCD(tmpBCD,tempstr) + + ulTTTM:=Div(ulTTTM,50) + StringF(string,' \d file(s), \sk bytes, \d minute(s). \d second(s), \d cps, \d% efficiency.',ulFileCount,tempstr,Div(ulTTTM,60),Mod(ulTTTM,60),tTCPS,tTEFF) aePuts(string) aePuts('\b\n\b\n') @@ -18393,12 +18677,13 @@ PROC uploadaFile(uLFType,cmd,attach,alreadyUploaded=FALSE) -> JOE DEF odate[20]:STRING,fcomment[256]:STRING DEF ray[256]:STRING,ray2[256]:STRING,string[256]:STRING DEF buff[255]:STRING + DEF tmpBCD[8]:ARRAY OF CHAR DEF tempstr[255]:STRING,tempstr2[255]:STRING,tempstr3[255]:STRING DEF uaf,f DEF foundDupe=0 DEF mstat /* check for carrier. trying to stop upload guru from parcial upload */ DEF fsstr[11]:STRING - DEF tempsize,bgCnt,bgBytes + DEF tempsize,bgCnt DEF dizSysCmd[255]:STRING DEF exitLoop @@ -18476,8 +18761,8 @@ PROC uploadaFile(uLFType,cmd,attach,alreadyUploaded=FALSE) -> JOE /* uploading to another device?? */ IF(StrLen(sopt.ramPen)>0) THEN StrCopy(path,sopt.ramPen) ELSE StringF(path,'\sNode\d/Playpen/',cmds.bbsLoc,node) - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=0 dlTTTM:=0 tTEFF:=0 @@ -18497,15 +18782,19 @@ PROC uploadaFile(uLFType,cmd,attach,alreadyUploaded=FALSE) -> JOE pcps:=NIL ObtainSemaphore(bgData) bgCnt:=bgData.checkedCount - bgBytes:=bgData.checkedBytes ReleaseSemaphore(bgData) - IF(ulFileCount<>0) OR (bgBytes<>0) + IF(ulFileCount<>0) OR (bgCnt<>0) peff:=tTEFF pcps:=tTCPS ENDIF - StringF(string,' \d file(s), \dk bytes, \d minute(s). \d second(s), \d cps, \d% efficiency.',ulFileCount,Shr(uTBT,10) AND $003fffff,Div(ulTTTM,60),Mod(ulTTTM,60),pcps,peff) + CopyMem(uTBT,tmpBCD,8) + divBCD1024(tmpBCD) + formatBCD(tmpBCD,tempstr) + + ulTTTM:=Div(ulTTTM,50) + StringF(string,' \d file(s), \sk bytes, \d minute(s). \d second(s), \d cps, \d% efficiency.',ulFileCount,tempstr,Div(ulTTTM,60),Mod(ulTTTM,60),pcps,peff) aePuts(string) IF (pcps > loggedOnUserKeys.upCPS2) @@ -18589,6 +18878,7 @@ PROC uploadaFile(uLFType,cmd,attach,alreadyUploaded=FALSE) -> JOE /* loop thru uploaded (ing) list of files & move to where they belong*/ /* this gets the list of files uploaded */ + FOR x:=0 TO recFileNames.count()-1 StrCopy(str,recFileNames.item(x)) IF(cmds.acLvl[LVL_CAPITOLS_in_FILE]=1) THEN UpperStr(str) @@ -18793,6 +19083,7 @@ cNext: status2:=testFile(str,path) IF((status2=RESULT_NOT_ALLOWED) OR (status2=RESULT_SUCCESS)) THEN aePuts('\b\nTested Ok...') ENDIF + status:=checkForFile(str) IF(moveToLCFILES) @@ -18894,6 +19185,7 @@ move_It: /* gets here if lostcarrier, and file is complete but not when file StringF(fmtstr,'\l\s[13] \s \s \s\n',str,fsstr,odate,fcomment) ENDIF + IF(StrLen(str) < 13) /* for big file name on lost carrier */ IF(checksym) fmtstr[13]:=checksym @@ -18961,7 +19253,7 @@ eit: cleanItUp() /* we get here after lcfile but gugued*/ - tempsize:=uTBT + tempsize:=convertFromBCD(uTBT) IF sopt.toggles[TOGGLES_CREDITBYKB] tempsize:=Shr(tempsize,10) AND $003fffff ENDIF @@ -19108,7 +19400,7 @@ PROC doBackgroundCheck(fname:PTR TO CHAR) ObtainSemaphore(bgData) bgData.checkedCount:=bgData.checkedCount+1 - bgData.checkedBytes:=bgData.checkedBytes+fsize + addBCD(bgData.checkedBytes,fsize) ReleaseSemaphore(bgData) sysopULStats(hold) @@ -19382,7 +19674,7 @@ PROC downloadAFile(cmdcode: PTR TO CHAR, params) HANDLE DEF tsec,min,secs,i,x,status,mystat,proto DEF peff,pcps ->DEF tempsize,tbad - DEF badBCD[8]:ARRAY OF CHAR + DEF tmpBCD[8]:ARRAY OF CHAR DEF bcdStr[20]:STRING DEF tempStr[255]:STRING DEF tempStr2[255]:STRING @@ -19415,7 +19707,7 @@ PROC downloadAFile(cmdcode: PTR TO CHAR, params) HANDLE estDlCPS:=Div(onlineBaud,10) ENDIF - dtfsize:=0 + convertToBCD(0,dtfsize) displayULStats(loggedOnUser,loggedOnUserMisc) /* Show User stats.. Num Dnloads, uploads */ @@ -19431,18 +19723,18 @@ PROC downloadAFile(cmdcode: PTR TO CHAR, params) HANDLE ENDIF IF(loggedOnUser.secBoard<2) - convertToBCD(0,badBCD) + convertToBCD(0,tmpBCD) FOR i:=1 TO loggedOnUser.secLibrary - addBCD2(badBCD,loggedOnUserMisc.uploadBytesBCD) + addBCD2(tmpBCD,loggedOnUserMisc.uploadBytesBCD) ENDFOR - subBCD2(badBCD,loggedOnUserMisc.downloadBytesBCD) - IF badBCD[0]>=$50 + subBCD2(tmpBCD,loggedOnUserMisc.downloadBytesBCD) + IF tmpBCD[0]>=$50 ->result was negative StrCopy(bcdStr,'0') cnt:=0 ELSE - formatBCD(badBCD,bcdStr) - cnt:=convertFromBCD(badBCD) + formatBCD(tmpBCD,bcdStr) + cnt:=convertFromBCD(tmpBCD) ->bad needs to be used in a signed comparison, so don't allow values >7fffffff IF cnt<0 THEN cnt:=$7fffffff @@ -19604,7 +19896,7 @@ arestart: ENDIF status:=checkForFileSize(tempStr,currentConf,tfsizes,freeDFlags,finalList,0) - IF((status=RESULT_FAILURE) OR (status=11) OR (status=10)) + IF((status=RESULT_FAILURE) OR (status=RESULT_SIGNALLED) OR (status=RESULT_PRIVATE)) Throw(ERR_EXCEPT,RESULT_SUCCESS) ENDIF ENDLOOP @@ -19633,10 +19925,12 @@ astart: ENDIF aePuts(tempStr) - tsec:=Div(dtfsize,estDlCPS) - min:=tsec/60 - secs:=tsec-(min*60) - StringF(tempStr,' \d files, \dk bytes, \d mins \d secs\b\n',numFiles,Shr(dtfsize,10) AND $003fffff,min,secs) + tsec:=divBCD(dtfsize,estDlCPS) + min:=Div(tsec,60) + secs:=tsec-(Mul(min,60)) + CopyMem(dtfsize,tmpBCD,8) + divBCD1024(tmpBCD) + StringF(tempStr,' \d files, \dk bytes, \d mins \d secs\b\n',numFiles,convertFromBCD(tmpBCD),min,secs) aePuts(tempStr) IF(min>(Div(timeLimit,60))) AND (checkSecurity(ACS_OVERRIDE_TIMELIMIT)=FALSE) @@ -19667,8 +19961,8 @@ breakd: IF (mystat<>13) THEN aePuts('Goodbye!\b\n\b\n') ELSE aePuts('\b\n\b\n') - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) ulTTTM:=0 dlTTTM:=0 tTEFF:=0 @@ -19692,15 +19986,18 @@ breakd: ->peff:=Div(tTEFF,onlineNFiles) ->pcps:=Div(tTCPS,onlineNFiles) peff:=tTEFF - pcps:=tTCPS + pcps:=tTCPS + loggedOnUserMisc.lastDlCPS:=pcps ENDIF ->// (RTS) added dnload cps rate Fri Mar 27 13:13:29 1992 - StringF(string,' \d files, \dk bytes, \d minutes \d seconds \d cps, \d% efficiency at \d',dlFileCount,Shr(dTBT,10) AND $003fffff,Div(dlTTTM,60),Mod(dlTTTM,60),pcps,peff,onlineBaud) + CopyMem(dTBT,tmpBCD,8) + divBCD1024(tmpBCD) + formatBCD(tmpBCD,tempStr) + dlTTTM:=Div(dlTTTM,50) + StringF(string,' \d files, \sk bytes, \d minutes \d seconds \d cps, \d% efficiency at \d',dlFileCount,tempStr,Div(dlTTTM,60),Mod(dlTTTM,60),pcps,peff,onlineBaud) aePuts(string) aePuts('\b\n\b\n') - loggedOnUserMisc.lastDlCPS:=pcps - /* is this baud higher then max cps up ? */ IF(pcps > loggedOnUserKeys.dnCPS2) loggedOnUserKeys.dnCPS2:=pcps @@ -19722,17 +20019,19 @@ breakd: udLog('\tDownload Failed..') ENDIF - IF (uTBT>0) + IF (ulFileCount>0) ->hydra uploads ObtainSemaphore(bgData) bgData.checkedCount:=0 - bgData.checkedBytes:=0 + convertToBCD(0,bgData.checkedBytes) ReleaseSemaphore(bgData) IF ulTTTM - tTCPS:=Div(uTBT,ulTTTM) + CopyMem(uTBT,tmpBCD,8) + mulBCD(tmpBCD,50) + tTCPS:=divBCD(tmpBCD,ulTTTM) ELSE - tTCPS:=uTBT + tTCPS:=convertFromBCD(uTBT) ENDIF tTEFF:=calcEfficiency(tTCPS,onlineBaud) @@ -20673,9 +20972,9 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: aePuts('No-Save\b\n') flag:=1 CASE " " - ->page:=Eor(page,1) - ->sendCLS() - ->displayAccount(which,page,hoozer,hoozer2,hoozer3,f6) + page:=Eor(page,1) + sendCLS() + displayAccount(which,page,hoozer,hoozer2,hoozer3,f6) CASE "+" IF(onlineEdit=FALSE) which:=which+1 @@ -20694,6 +20993,28 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: loadAccount(which,hoozer,hoozer2,hoozer3) displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) ENDIF + CASE "~" /* SAVE */ + aePuts('Save\b\n') + hoozer.newUser:=0 + displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) + IF(hoozer.slotNumber=0) + hoozer2.number:=0 + stat:=saveAccount(hoozer,hoozer2,hoozer3,which,1) /* 1 = FORCE SAVE */ + + IF(stat<>RESULT_SUCCESS) THEN aePuts('Can''t Save account\b\n') + ELSE + hoozer2.number:=hoozer.slotNumber + /* save using Slot_number */ + stat:=saveAccount(hoozer,hoozer2,hoozer3,0,0) /* Not forced */ + IF(stat<>RESULT_SUCCESS) THEN aePuts('Can''t Save account\b\n') + ENDIF + + IF logonType>=LOGON_TYPE_REMOTE + StringF(tempStr,'\tREMOTE Account Maintenance on Account \d',hoozer.slotNumber) + ELSE + StringF(tempStr,'\tLOCAL Account Maintenance on Account \d',hoozer.slotNumber) + ENDIF + callersLog(tempStr) CASE "!" /* Credit Maintenance */ creditMaintenance(which,hoozer,hoozer2,hoozer3,f6) displayAccount(which,page,hoozer,hoozer2,hoozer3,f6) @@ -20756,59 +21077,53 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: deleteConfAccess(stat) displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) flag:=0 - CASE "~" /* SAVE */ - aePuts('Save\b\n') - hoozer.newUser:=0 - displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) - IF(hoozer.slotNumber=0) - hoozer2.number:=0 - stat:=saveAccount(hoozer,hoozer2,hoozer3,which,1) /* 1 = FORCE SAVE */ - - IF(stat<>RESULT_SUCCESS) THEN aePuts('Can''t Save account\b\n') - ELSE - hoozer2.number:=hoozer.slotNumber - /* save using Slot_number */ - stat:=saveAccount(hoozer,hoozer2,hoozer3,0,0) /* Not forced */ - IF(stat<>RESULT_SUCCESS) THEN aePuts('Can''t Save account\b\n') - ENDIF - - IF logonType>=LOGON_TYPE_REMOTE - StringF(tempStr,'\tREMOTE Account Maintenance on Account \d',hoozer.slotNumber) - ELSE - StringF(tempStr,'\tLOCAL Account Maintenance on Account \d',hoozer.slotNumber) - ENDIF - callersLog(tempStr) - CASE "9" /* RE-ACTIVATE */ aePuts('Re-Activate\b\n') hoozer.slotNumber:=which flag:=0 - CASE "A" /* NAME */ - aePuts('') - StrCopy(tempStr,hoozer.name) - lineInput('',tempStr,30,INPUT_TIMEOUT,tempStr) - AstrCopy(hoozer.name,tempStr,31) - UpperStr(tempStr) - AstrCopy(hoozer2.userName,tempStr,31) - flag:=0 - CASE "B" /* Real Name */ - aePuts('') - StrCopy(tempStr,hoozer3.realName) - lineInput('',tempStr,25,INPUT_TIMEOUT,tempStr) - AstrCopy(hoozer3.realName,tempStr,26) - flag:=0 - CASE "C" /* Location */ - aePuts('') - StrCopy(tempStr,hoozer.location) - lineInput('',tempStr,29,INPUT_TIMEOUT,tempStr) - AstrCopy(hoozer.location,tempStr,30) - flag:=0 - CASE "D" /* PASS */ - IF((logonType>=LOGON_TYPE_REMOTE) AND (f6=FALSE)) - IF(loggedOnUser.slotNumber=1) - aePuts('') + ENDSELECT - StrCopy(tempStr,'') + IF (page=0) + SELECT command + CASE "A" /* NAME */ + aePuts('') + StrCopy(tempStr,hoozer.name) + lineInput('',tempStr,30,INPUT_TIMEOUT,tempStr) + AstrCopy(hoozer.name,tempStr,31) + UpperStr(tempStr) + AstrCopy(hoozer2.userName,tempStr,31) + flag:=0 + CASE "B" /* Real Name */ + aePuts('') + StrCopy(tempStr,hoozer3.realName) + lineInput('',tempStr,25,INPUT_TIMEOUT,tempStr) + AstrCopy(hoozer3.realName,tempStr,26) + flag:=0 + CASE "C" /* Location */ + aePuts('') + StrCopy(tempStr,hoozer.location) + lineInput('',tempStr,29,INPUT_TIMEOUT,tempStr) + AstrCopy(hoozer.location,tempStr,30) + flag:=0 + CASE "D" /* PASS */ + IF((logonType>=LOGON_TYPE_REMOTE) AND (f6=FALSE)) + IF(loggedOnUser.slotNumber=1) + aePuts('') + + StrCopy(tempStr,'') + StrAdd(tempStr,' ') + FOR i:=1 TO 9 + StrAddChar(tempStr,8) + ENDFOR + aePuts(tempStr) + lineInput('','',50,INPUT_TIMEOUT,tempStr) + IF StrLen(tempStr)>0 + setNewPassword(hoozer,hoozer3,tempStr) + hoozer3.pwdLastUpdated:=getSystemTime() + ENDIF + ENDIF + ELSE + StrCopy(tempStr,'') StrAdd(tempStr,' ') FOR i:=1 TO 9 StrAddChar(tempStr,8) @@ -20816,176 +21131,189 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: aePuts(tempStr) lineInput('','',50,INPUT_TIMEOUT,tempStr) IF StrLen(tempStr)>0 - UpperStr(tempStr) - hoozer.pwdHash:=calcPasswordHash(tempStr) + setNewPassword(hoozer,hoozer3,tempStr) + hoozer3.pwdLastUpdated:=getSystemTime() ENDIF ENDIF - ELSE - StrCopy(tempStr,'') - StrAdd(tempStr,' ') - FOR i:=1 TO 9 - StrAddChar(tempStr,8) - ENDFOR - aePuts(tempStr) - lineInput('','',50,INPUT_TIMEOUT,tempStr) - IF StrLen(tempStr)>0 - UpperStr(tempStr) - hoozer.pwdHash:=calcPasswordHash(tempStr) - ENDIF - ENDIF - flag:=0 - CASE "E" /* Phone number */ - aePuts('') - StrCopy(tempStr,hoozer.phoneNumber) - lineInput('',tempStr,12,INPUT_TIMEOUT,tempStr) - AstrCopy(hoozer.phoneNumber,tempStr,13) - flag:=0 - CASE "F" /* conference access */ - aePuts('') - StrCopy(tempStr,hoozer.conferenceAccess) - lineInput('',tempStr,9,INPUT_TIMEOUT,tempStr) - AstrCopy(hoozer.conferenceAccess,tempStr,10) - flag:=0 - CASE "G" /* RATIO */ - aePuts('') - hoozer.secLibrary:=numberInput(hoozer.secLibrary) - flag:=0 - CASE "H" /* SEC_Level */ - IF((logonType>=LOGON_TYPE_REMOTE) AND (f6=FALSE)) - IF(loggedOnUser.slotNumber=1) + flag:=0 + CASE "E" /* Phone number */ + aePuts('') + StrCopy(tempStr,hoozer.phoneNumber) + lineInput('',tempStr,12,INPUT_TIMEOUT,tempStr) + AstrCopy(hoozer.phoneNumber,tempStr,13) + flag:=0 + CASE "F" /* conference access */ + aePuts('') + StrCopy(tempStr,hoozer.conferenceAccess) + lineInput('',tempStr,9,INPUT_TIMEOUT,tempStr) + AstrCopy(hoozer.conferenceAccess,tempStr,10) + flag:=0 + CASE "G" /* RATIO */ + aePuts('') + hoozer.secLibrary:=numberInput(hoozer.secLibrary) + flag:=0 + CASE "H" /* SEC_Level */ + IF((logonType>=LOGON_TYPE_REMOTE) AND (f6=FALSE)) + IF(loggedOnUser.slotNumber=1) + aePuts('') + hoozer.secStatus:=numberInput(hoozer.secStatus) + ENDIF + ELSE aePuts('') hoozer.secStatus:=numberInput(hoozer.secStatus) ENDIF - ELSE - aePuts('') - hoozer.secStatus:=numberInput(hoozer.secStatus) - ENDIF - flag:=0 - CASE "I" /* Ratio Type */ - aePuts('') - hoozer.secBoard:=numberInput(hoozer.secBoard) - IF((hoozer.secBoard<0) OR (hoozer.secBoard > 2)) - sendBELL() - hoozer.secBoard:=0 - ENDIF - StringF(tempStr,'I> Ratio Type ....: \l\d[5]',hoozer.secBoard) - aePuts(tempStr) - IF(hoozer.secBoard=0) THEN aePuts(' <-Byte)') - IF(hoozer.secBoard=1) THEN aePuts(' <-B/F) ') - IF(hoozer.secBoard=2) THEN aePuts(' <-File)') - flag:=0 - CASE "J" /* conference ReJoin */ - aePuts('') - value1,value2:=rJoinInput(hoozer.confRJoin, hoozer.msgBaseRJoin) - hoozer.confRJoin:=value1 - hoozer.msgBaseRJoin:=value2 - flag:=0 - CASE "K" /* UPLOADS */ - aePuts('') - hoozer.uploads:=numberInput(hoozer.uploads) - flag:=0 - CASE "L" /* MESSAGES_POSTED */ - aePuts('') - hoozer.messagesPosted:=numberInput(hoozer.messagesPosted) - flag:=0 - CASE "M" /* DOWNLOADS */ - aePuts('') - hoozer.downloads:=numberInput(hoozer.downloads) - flag:=0 - CASE "N" /* New user ?? */ - aePuts(' ') - command:=yesNo(0) - IF(command) THEN hoozer.newUser:=1 ELSE hoozer.newUser:=0 - flag:=0 - CASE "#" - aePuts('') - hoozer.timesCalled:=numberInput(hoozer.timesCalled) - flag:=0 - CASE "%" - aePuts('') - hoozer2.timesOnToday:=numberInput(getTodaysCalls(hoozer,hoozer2)) - flag:=0 - CASE "O" /* Bytes Uploaded */ - aePuts('') - - bcdNumberInput(hoozer3.uploadBytesBCD) - hoozer.bytesUpload:=convertFromBCD(hoozer3.uploadBytesBCD) + flag:=0 + CASE "I" /* Ratio Type */ + aePuts('') + hoozer.secBoard:=numberInput(hoozer.secBoard) + IF((hoozer.secBoard<0) OR (hoozer.secBoard > 2)) + sendBELL() + hoozer.secBoard:=0 + ENDIF + StringF(tempStr,'I> Ratio Type ....: \l\d[5]',hoozer.secBoard) + aePuts(tempStr) + IF(hoozer.secBoard=0) THEN aePuts(' <-Byte)') + IF(hoozer.secBoard=1) THEN aePuts(' <-B/F) ') + IF(hoozer.secBoard=2) THEN aePuts(' <-File)') + flag:=0 + CASE "J" /* conference ReJoin */ + aePuts('') + value1,value2:=rJoinInput(hoozer.confRJoin, hoozer.msgBaseRJoin) + hoozer.confRJoin:=value1 + hoozer.msgBaseRJoin:=value2 + flag:=0 + CASE "K" /* UPLOADS */ + aePuts('') + hoozer.uploads:=numberInput(hoozer.uploads) + flag:=0 + CASE "L" /* MESSAGES_POSTED */ + aePuts('') + hoozer.messagesPosted:=numberInput(hoozer.messagesPosted) + flag:=0 + CASE "M" /* DOWNLOADS */ + aePuts('') + hoozer.downloads:=numberInput(hoozer.downloads) + flag:=0 + CASE "N" /* New user ?? */ + aePuts(' ') + command:=yesNo(0) + IF(command) THEN hoozer.newUser:=1 ELSE hoozer.newUser:=0 + flag:=0 + CASE "#" + aePuts('') + hoozer.timesCalled:=numberInput(hoozer.timesCalled) + flag:=0 + CASE "%" + aePuts('') + hoozer2.timesOnToday:=numberInput(getTodaysCalls(hoozer,hoozer2)) + flag:=0 + CASE "O" /* Bytes Uploaded */ + aePuts('') + + bcdNumberInput(hoozer3.uploadBytesBCD) + hoozer.bytesUpload:=convertFromBCD(hoozer3.uploadBytesBCD) - flag:=0 - CASE "P" /* Bytes Downloaded */ - aePuts('') - bcdNumberInput(hoozer3.downloadBytesBCD) - hoozer.bytesDownload:=convertFromBCD(hoozer3.downloadBytesBCD) - flag:=0 - CASE "Q" /* Daily Bytes Limit */ - aePuts(' ') - IF hoozer.todaysBytesLimit<>0 - temp:=hoozer.todaysBytesLimit-hoozer.dailyBytesLimit - ELSE - temp:=0 - ENDIF - hoozer.dailyBytesLimit:=longNumberInput(hoozer.dailyBytesLimit) - hoozer.todaysBytesLimit:=hoozer.dailyBytesLimit - IF hoozer.todaysBytesLimit<>0 THEN hoozer.todaysBytesLimit:=hoozer.todaysBytesLimit+temp - flag:=0 - CASE "R" /* Time_Total */ - aePuts('') - hoozer.timeTotal:=Mul(numberInput(Div(hoozer.timeTotal,60)),60) - IF(hoozer.timeTotal0 + temp:=hoozer.todaysBytesLimit-hoozer.dailyBytesLimit + ELSE + temp:=0 + ENDIF + hoozer.dailyBytesLimit:=longNumberInput(hoozer.dailyBytesLimit) + hoozer.todaysBytesLimit:=hoozer.dailyBytesLimit + IF hoozer.todaysBytesLimit<>0 THEN hoozer.todaysBytesLimit:=hoozer.todaysBytesLimit+temp + flag:=0 + CASE "R" /* Time_Total */ + aePuts('') + hoozer.timeTotal:=Mul(numberInput(Div(hoozer.timeTotal,60)),60) + IF(hoozer.timeTotal65535 THEN hoozer2.oldUpCPS:=65535 ELSE hoozer2.oldUpCPS:=hoozer2.upCPS2 - flag:=0; - CASE "T" /* zero dncps rate */ - aePuts('') - hoozer2.dnCPS2:=longNumberInput(hoozer2.dnCPS2) - IF hoozer2.dnCPS2>65535 THEN hoozer2.oldDnCPS:=65535 ELSE hoozer2.oldDnCPS:=hoozer2.dnCPS2 - flag:=0 - CASE "U" /* Time_Limit */ - aePuts('') - hoozer.timeLimit:=Mul(numberInput(Div(hoozer.timeLimit,60)),60) - IF(hoozer.timeTotal65535 THEN hoozer2.oldUpCPS:=65535 ELSE hoozer2.oldUpCPS:=hoozer2.upCPS2 + flag:=0; + CASE "T" /* zero dncps rate */ + aePuts('') + hoozer2.dnCPS2:=longNumberInput(hoozer2.dnCPS2) + IF hoozer2.dnCPS2>65535 THEN hoozer2.oldDnCPS:=65535 ELSE hoozer2.oldDnCPS:=hoozer2.dnCPS2 + flag:=0 + CASE "U" /* Time_Limit */ + aePuts('') + hoozer.timeLimit:=Mul(numberInput(Div(hoozer.timeLimit,60)),60) + IF(hoozer.timeTotal Force Pwd Reset: \l\s[3]',tempStr2) + aePuts(tempStr) + + IF hoozer3.accountLocked THEN StrCopy(tempStr2,'Yes') ELSE StrCopy(tempStr2,'No') + StringF(tempStr,'C> Account Locked : \l\s',tempStr2) + aePuts(tempStr) + + StringF(tempStr,'D> Invalid Pwd Att: \l\d[3]',hoozer3.invalidAttempts) + aePuts(tempStr) + + formatLongDateTime(hoozer3.pwdLastUpdated,tempStr2) + StringF(tempStr,'Last Pwd Reset : \l\s',tempStr2) + aePuts(tempStr) + + SELECT hoozer3.pwdType + CASE PWD_LEGACY + StrCopy(tempStr2,'LEGACY ') + CASE PWD_PBKDF2_5 + StrCopy(tempStr2,'PBKDF2(5) ') + CASE PWD_PBKDF2_50 + StrCopy(tempStr2,'PBKDF2(50) ') + CASE PWD_PBKDF2_100 + StrCopy(tempStr2,'PBKDF2(100) ') + CASE PWD_PBKDF2_1000 + StrCopy(tempStr2,'PBKDF2(1000) ') + CASE PWD_PBKDF2_10000 + StrCopy(tempStr2,'PBKDF2(10000)') + ENDSELECT + + StringF(tempStr,'Pwd Type ......: \s',tempStr2) + aePuts(tempStr) + + ENDIF + displayAccountActions(who) ENDPROC @@ -22576,12 +22942,48 @@ PROC displayAccountInfo(who:LONG, page,hoozer:PTR TO user, hoozer2:PTR TO userKe StringF(tempStr,'\l\d[6]',Div((hoozer.chatLimit-hoozer.chatRemain),60)) aePuts(tempStr) ENDIF + + IF page=1 + IF hoozer3.forcePwdReset THEN StrCopy(tempStr2,'Yes') ELSE StrCopy(tempStr2,'No') + StringF(tempStr,'\l\s[3]',tempStr2) + aePuts(tempStr) + + IF hoozer3.accountLocked THEN StrCopy(tempStr2,'Yes') ELSE StrCopy(tempStr2,'No') + StringF(tempStr,'\l\s[3]',tempStr2) + aePuts(tempStr) + + StringF(tempStr,'\l\d[3]',hoozer3.invalidAttempts) + aePuts(tempStr) + + formatLongDateTime(hoozer3.pwdLastUpdated,tempStr2) + StringF(tempStr,'\l\s',tempStr2) + aePuts(tempStr) + + SELECT hoozer3.pwdType + CASE PWD_LEGACY + StrCopy(tempStr2,'LEGACY ') + CASE PWD_PBKDF2_5 + StrCopy(tempStr2,'PBKDF2(5) ') + CASE PWD_PBKDF2_50 + StrCopy(tempStr2,'PBKDF2(50) ') + CASE PWD_PBKDF2_100 + StrCopy(tempStr2,'PBKDF2(100) ') + CASE PWD_PBKDF2_1000 + StrCopy(tempStr2,'PBKDF2(1000) ') + CASE PWD_PBKDF2_10000 + StrCopy(tempStr2,'PBKDF2(10000)') + ENDSELECT + + StringF(tempStr,'\s',tempStr2) + aePuts(tempStr) + + ENDIF displayAccountActions(who) ENDPROC PROC bulkAccountEditor() DEF flag,command - DEF settings[16]:ARRAY OF LONG + DEF settings[18]:ARRAY OF LONG DEF areaName[255]:STRING DEF secLevel[3]:STRING DEF i,v,v2,r,p @@ -22592,7 +22994,7 @@ PROC bulkAccountEditor() displayBulkScreen() - FOR i:=0 TO 15 + FOR i:=0 TO 17 settings[i]:=String(15) ENDFOR StrCopy(areaName,'') @@ -22706,11 +23108,27 @@ PROC bulkAccountEditor() ELSE StrCopy(settings[15],'') ENDIF + CASE "!" + IF StrLen(settings[16])=0 + StrCopy(settings[16],'1') + ELSEIF StrCmp(settings[16],'1') + StrCopy(settings[16],'0') + ELSE + StrCopy(settings[16],'') + ENDIF + CASE "&" + IF StrLen(settings[17])=0 + StrCopy(settings[17],'1') + ELSEIF StrCmp(settings[17],'1') + StrCopy(settings[17],'0') + ELSE + StrCopy(settings[17],'') + ENDIF CASE "1" /* select area Name */ - aePuts(' ') + aePuts(' ') lineInput('',areaName,10,INPUT_TIMEOUT,areaName) CASE "2" /* select access Level */ - aePuts(' ') + aePuts(' ') lineInput('',secLevel,3,INPUT_TIMEOUT,secLevel) v,r:=Val(secLevel) IF r=0 THEN StrCopy(secLevel,'') @@ -22772,10 +23190,13 @@ PROC displayBulkScreen() aePuts('Y> Chat Limit ....:') aePuts('#> Times Called ..:') - aePuts('Filter Settings:') + aePuts('!> Force Pwd Reset:') + aePuts('&> Accnt Locked ..:') + + aePuts('Filter Settings:') - aePuts('1> Select Area Name :') - aePuts('2> Select Sec Level :') + aePuts('1> Select Area Name :') + aePuts('2> Select Sec Level :') aePuts('3> Include deactivated :') aePuts('~=Apply Changes @=Presets =Exit\b\n') ENDPROC @@ -22826,15 +23247,20 @@ PROC displayBulkSettings(settings:PTR TO LONG, areaName:PTR TO CHAR, secLevel:PT StringF(tempStr,' \s',IF StrLen(settings[15])=0 THEN 'Leave Unchanged' ELSE IF Val(settings[15])=0 THEN 'Deactivate ' ELSE 'Activate ') aePuts(tempStr) + StringF(tempStr,' \s',IF StrLen(settings[16])=0 THEN 'Leave Unchanged' ELSE IF Val(settings[16])=1 THEN 'Yes ' ELSE 'No ') + aePuts(tempStr) + StringF(tempStr,' \s',IF StrLen(settings[17])=0 THEN 'Leave Unchanged' ELSE IF Val(settings[17])=1 THEN 'Yes ' ELSE 'No ') + aePuts(tempStr) + i,tot:=calcAffected(areaName,secLevel) - StringF(tempStr,'[\d/\d] Users will be updated. ',i,tot) + StringF(tempStr,'[\d/\d] Users will be updated. ',i,tot) aePuts(tempStr) - StringF(tempStr,'\s',IF StrLen(areaName)=0 THEN 'N/A' ELSE areaName) + StringF(tempStr,'\s',IF StrLen(areaName)=0 THEN 'N/A' ELSE areaName) aePuts(tempStr) - StringF(tempStr,'\s',IF StrLen(secLevel)=0 THEN 'N/A' ELSE secLevel) + StringF(tempStr,'\s',IF StrLen(secLevel)=0 THEN 'N/A' ELSE secLevel) aePuts(tempStr) StringF(tempStr,'\s',IF includeDeact THEN 'Yes' ELSE 'No ') @@ -22953,6 +23379,13 @@ PROC applyBulkChanges(settings:PTR TO LONG,areaName:PTR TO CHAR,secLevel:PTR TO IF Val(settings[15])=0 THEN tempUser.slotNumber:=0 ELSE tempUser.slotNumber:=sn tempUserKeys.number:=tempUser.slotNumber ENDIF + IF StrLen(settings[16])>0 + IF Val(settings[16])=0 THEN tempUserMisc.forcePwdReset:=FALSE ELSE tempUserMisc.forcePwdReset:=TRUE + ENDIF + + IF StrLen(settings[17])>0 + IF Val(settings[17])=0 THEN tempUserMisc.accountLocked:=FALSE ELSE tempUserMisc.accountLocked:=TRUE + ENDIF Seek(fh,-SIZEOF user,OFFSET_CURRENT) Write(fh,tempUser,SIZEOF user) @@ -24862,8 +25295,8 @@ ENDPROC RESULT_SUCCESS PROC internalCommandW() DEF stat,option - DEF str[100]:STRING - DEF str2[100]:STRING + DEF str[255]:STRING + DEF str2[255]:STRING DEF temp IF checkSecurity(ACS_EDIT_USER_INFO)=FALSE THEN RETURN RESULT_NOT_ALLOWED @@ -25151,15 +25584,35 @@ PROC internalCommandW() CASE 6 ->EDIT PASSWORD IF (checkSecurity(ACS_EDIT_PASSWORD)=FALSE) THEN JUMP cant - aePuts('Password: ') - stat:=lineInput('','',50,INPUT_TIMEOUT,str) + + stat:=getPass2('Enter New Password: ',0,0,50,str) IF(stat<0) THEN RETURN stat IF(StrLen(str)=0) THEN JUMP cant - UpperStr(str) - stat:=calcPasswordHash(str) - StringF(str,'new hash: \h',stat) - debugLog(LOG_DEBUG,str) - loggedOnUser.pwdHash:=stat + + stat:=getPass2('Reenter New Password: ',0,0,50,str2) + IF(stat<0) THEN RETURN stat + IF(StrLen(str2)=0) THEN JUMP cant + + IF StrCmp(str,str2) + stat:=checkPasswordStrength(str) + IF stat=1 + stat:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_LENGTH') + StringF(str,'\b\nPassword length must be at least \d chars, changes not saved',stat) + aePuts(str) + Delay(60) + ELSEIF stat=2 + stat:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_STRENGTH') + StringF(str,'\b\nPassword must have at least \d of these:\b\n upper case,lower case, numeric and symbols - changes not saved',stat) + aePuts(str) + Delay(60) + ELSE + setNewPassword(loggedOnUser,loggedOnUserMisc,str) + loggedOnUserMisc.pwdLastUpdated:=getSystemTime() + ENDIF + ELSE + aePuts('\b\nPasswords do not match, changes not saved') + Delay(60) + ENDIF CASE 7 ->EDIT NUMBER OF SCREEN LINES REPEAT @@ -25454,8 +25907,8 @@ PROC internalCommandZOOM() aePuts('Not supported locally...\b\n') RETURN RESULT_SUCCESS ENDIF - dTBT:=0 - uTBT:=0 + convertToBCD(0,dTBT) + convertToBCD(0,uTBT) dlTTTM:=0 ulTTTM:=0 tTEFF:=NIL @@ -27619,7 +28072,7 @@ PROC processLoggedOnUser() timeLimit:=loggedOnUser.timeTotal-loggedOnUser.timeUsed IF (loggedOnUser.todaysBytesLimit<>0) - bytesADL:=loggedOnUser.todaysBytesLimit + bytesADL:=loggedOnUser.todaysBytesLimit-loggedOnUser.dailyBytesDld ELSE bytesADL:=$7fffffff ENDIF @@ -27998,7 +28451,13 @@ PROC processFtpLoggedOnUser() loggedOnUser.chatRemain:=loggedOnUser.chatLimit loggedOnUser.dailyBytesDld:=0 loggedOnUser.timeTotal:=loggedOnUser.timeLimit + loggedOnUser.todaysBytesLimit:=loggedOnUser.dailyBytesLimit ELSE + IF loggedOnUser.dailyBytesLimit=0 + loggedOnUser.todaysBytesLimit:=0 + ELSE + IF loggedOnUser.todaysBytesLimit0) - bytesADL:=loggedOnUser.todaysBytesLimit + bytesADL:=loggedOnUser.todaysBytesLimit-loggedOnUser.dailyBytesDld ELSE bytesADL:=$7fffffff ENDIF @@ -28257,8 +28716,8 @@ PROC checkPassword() stat:=lineInput('','',50,INPUT_TIMEOUT,tempStr) IF(stat<0) THEN RETURN RESULT_NO_CARRIER IF(StrLen(tempStr)>0) - UpperStr(tempStr) - loggedOnUser.pwdHash:=calcPasswordHash(tempStr) + setNewPassword(loggedOnUser,loggedOnUserMisc,tempStr) + loggedOnUserMisc.pwdLastUpdated:=getSystemTime() ENDIF ENDIF ENDIF @@ -28269,7 +28728,7 @@ PROC checkPassword() ENDIF ENDIF IF StrLen(resetCode)=0 - stat:=getPass2(passwordPrompt,0,loggedOnUser.pwdHash,50,tempStr) + stat:=getPass2(passwordPrompt,0,TRUE,50,tempStr) IF(stat<0) IF stat=RESULT_NO_CARRIER THEN RETURN RESULT_NO_CARRIER ELSE RETURN RESULT_SLEEP_LOGOFF ENDIF @@ -28536,7 +28995,7 @@ PROC processLogon() DEF newUser DEF userNum DEF stat,ch - DEF hrs,calcHrs,autovalPreset + DEF hrs,calcHrs,autovalPreset,pwdExpiryDays ripMode:=FALSE confNameType:=NAME_TYPE_USERNAME @@ -28811,6 +29270,7 @@ logonLoop: logoffLog('N') ENDIF + saveAccount(loggedOnUser,loggedOnUserKeys,loggedOnUserMisc,0,0) END loggedOnUser loggedOnUser:=NIL END loggedOnUserKeys @@ -28844,6 +29304,78 @@ logonLoop: RETURN ENDIF + IF loggedOnUserMisc.accountLocked + aePuts('\b\nYour account is locked out (possibly due to repeated password failures)\b\n\b\n') + aePuts('Leave a comment for the sysop...\b\n\b\n') + processCommand('C') + + aePuts('\b\nThanks you will now be disconnected...\b\n\b\n') + state:=STATE_LOGGING_OFF + RETURN + ENDIF + + pwdExpiryDays:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'PASSWORD_EXPIRY_DAYS') + IF pwdExpiryDays>=0 + IF (loggedOnUserMisc.pwdLastUpdated+Mul(pwdExpiryDays,86400))TRUE + IF stat=1 + stat:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_LENGTH') + StringF(tempStr,'\b\nPassword length must be at least \d chars, try again..\b\n\b\n',stat) + aePuts(tempStr) + ELSEIF stat=2 + stat:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_STRENGTH') + StringF(tempStr,'\b\nPassword must have at least \d of these:\b\n upper case,lower case, numeric and symbols, try again..\b\n\b\n',stat) + aePuts(tempStr) + ENDIF + ELSE + setNewPassword(loggedOnUser,loggedOnUserMisc,tempStr) + loggedOnUserMisc.pwdLastUpdated:=getSystemTime() + loggedOnUserMisc.forcePwdReset:=FALSE + ENDIF + ENDIF + ELSE + aePuts('\b\nPasswords do not match, please try again.\b\n\b\n') + ENDIF + ENDIF + ENDIF + retryCount++ + UNTIL (retryCount>3) OR (loggedOnUserMisc.forcePwdReset=FALSE) + + IF (loggedOnUserMisc.forcePwdReset) + aePuts('\b\nYou have not updated your password so you will now be disconnected...\b\n\b\n') + state:=STATE_LOGGING_OFF + RETURN + ENDIF + ENDIF + IF logonType>=LOGON_TYPE_REMOTE runExecuteOn('LOGON') IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_LOGON')) AND (StrLen(mailOptions.sysopEmail)>0) @@ -29232,16 +29764,41 @@ jLoop4: JUMP jLoop3 ENDIF - aePuts('Enter a PassWord: ') - stat:=lineInput('','',50,INPUT_TIMEOUT,string) +jLoop5: + + stat:=getPass2('Enter a PassWord: ',0,0,50,string) IF(stat<0) THEN RETURN stat IF(StrLen(string)=0) aePuts('\b\n') JUMP jLoop4 ENDIF - UpperStr(string) - loggedOnUser.pwdHash:=calcPasswordHash(string) + stat:=getPass2('Reenter the PassWord: ',0,0,50,str2) + IF(stat<0) THEN RETURN stat + + IF(StrCmp(string,str2)=0) + aePuts('\b\nPasswords do not match, try again..\b\n') + JUMP jLoop5 + ENDIF + + stat:=checkPasswordStrength(string) + IF stat<>TRUE + + IF stat=1 + stat:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_LENGTH') + StringF(string,'\b\nPassword length must be at least \d chars, try again..\b\n',stat) + aePuts(string) + ELSEIF stat=2 + stat:=readToolTypeInt(TOOLTYPE_BBSCONFIG,0,'MIN_PASSWORD_STRENGTH') + StringF(string,'\b\nPassword must have at least \d of these:\b\n upper case,lower case, numeric and symbols, try again..\b\n',stat) + aePuts(string) + ENDIF + JUMP jLoop5 + ENDIF + + setNewPassword(loggedOnUser,loggedOnUserMisc,string) + loggedOnUserMisc.pwdLastUpdated:=getSystemTime() + aePuts('\b\n') stat:=numberOfLinesTest() IF(stat<0) THEN RETURN stat @@ -30379,7 +30936,7 @@ PROC main() HANDLE netTrans:=0 ENDIF - saveA4() + saveA4(FindTask(0),{tasksA4}) StringF(bgCheckPortName,'bgCheckPort\d',node) @@ -30964,29 +31521,12 @@ PROC main() HANDLE ENDSELECT ENDPROC -PROC saveA4() - MOVEM.L D0-D7/A0-A6,-(A7) - MOVE.L 4,A6 - SUB.L A1,A1 - JSR -$126(A6) ->findtask - MOVE.L D0,D7 - - LEA regA4(PC),A0 - LEA tasksA4(PC),A1 - MOVE.L node,D0 - ADD.W D0,D0 - ADD.W D0,D0 - MOVE.L A4,0(A0,D0.W) - MOVE.L D7,0(A1,D0.W) - MOVEM.L (A7)+,D0-D7/A0-A6 -ENDPROC - -PROC saveA4thread(taskID) +PROC saveA4(taskID,tasktable) MOVEM.L D0-D7/A0-A6,-(A7) MOVE.L taskID,D7 LEA regA4(PC),A0 - LEA threadtasksA4(PC),A1 + MOVE.L tasktable,A1 MOVE.L node,D0 ADD.W D0,D0 ADD.W D0,D0 @@ -30995,7 +31535,7 @@ PROC saveA4thread(taskID) MOVEM.L (A7)+,D0-D7/A0-A6 ENDPROC -PROC loadA4() +PROC loadA4(tasktable) MOVEM.L D0-D7/A0-A3/A5-A6,-(A7) MOVE.L 4,A6 @@ -31004,7 +31544,7 @@ PROC loadA4() MOVE.L D0,D1 LEA regA4(PC),A0 - LEA tasksA4(PC),A1 + MOVE.L tasktable,A1 CLR.L D0 findA4task: MOVE.L 0(A1,D0.W),D2 @@ -31023,34 +31563,6 @@ taskfound: MOVEM.L (A7)+,D0-D7/A0-A3/A5-A6 ENDPROC -PROC loadA4thread() - MOVEM.L D0-D7/A0-A3/A5-A6,-(A7) - MOVE.L 4,A6 - SUB.L A1,A1 - JSR -$126(A6) ->findtask - MOVE.L D0,D1 - - LEA regA4(PC),A0 - LEA threadtasksA4(PC),A1 - CLR.L D0 -findA4threadtask: - MOVE.L 0(A1,D0.W),D2 - CMP.L D1,D2 - BEQ threadtaskfound - - ADD.L #4,D0 - CMP.L #128,D0 - BNE findA4threadtask - - MOVE.L #AG_BADPARM,D7 - JSR -$6c(A6) ->Alert(AG_BADPARM) - -threadtaskfound: - MOVE.L 0(A0,D0),A4 - MOVEM.L (A7)+,D0-D7/A0-A3/A5-A6 - -ENDPROC - tasksA4: LONG NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL LONG NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL diff --git a/makefile b/makefile index 9c630f4..824ff6e 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ options=DEBUG IGNORECACHE NILCHECK OPTI SYM SHOWFNAME compiler=EVO expprogramname=AmiExpress acpprogramname=ACP -version=5.5.0 +version=5.6.0-dev all: acp express5 jsonimport icon2cfg qwk ftn @@ -14,7 +14,7 @@ release: acp express5 jsonimport icon2cfg qwk ftn acp: acp.e acpversion.m axcommon.m jsonparser.m jsoncreate.m stringlist.m $(compiler) acp $(options) -express5: express.e expversion.m axcommon.m axconsts.m miscfuncs.m axobjects.m axenums.m stringlist.m errors.m mailssl.m ftpd.m httpd.m xymodem.m zmodem.m hydra.m tooltypes.m pwdhash.m bcd.m +express5: express.e expversion.m axcommon.m axconsts.m miscfuncs.m axobjects.m axenums.m stringlist.m errors.m mailssl.m ftpd.m httpd.m xymodem.m zmodem.m hydra.m tooltypes.m pwdhash.m bcd.m sha256.m $(compiler) express $(options) copy express express5 delete express @@ -40,10 +40,10 @@ jsonparser.m: jsonparser.e miscfuncs.m jsoncreate.m: jsoncreate.e miscfuncs.m jsonparser.m $(compiler) jsoncreate $(options) -zmodem.m: zmodem.e +zmodem.m: zmodem.e bcd.m $(compiler) zmodem $(options) -xymodem.m: xymodem.e +xymodem.m: xymodem.e bcd.m $(compiler) xymodem $(options) hydra.m: hydra.e @@ -91,17 +91,20 @@ acpversion.m: acpversion.e acpversion.e: verinfogen verinfogen acpversion.e $(acpprogramname) $(version) usedate -bcd.m: bcd.e +bcd.m: bcd.e axobjects.m $(compiler) bcd $(options) -ftpd.m: ftpd.e tooltypes.m stringlist.m axobjects.m axenums.m miscfuncs.m +sha256.m: sha256.e + $(compiler) sha256 $(options) + +ftpd.m: ftpd.e tooltypes.m stringlist.m axobjects.m axenums.m miscfuncs.m bcd.m $(compiler) ftpd $(options) httpd.m: httpd.e axcommon.m stringlist.m $(compiler) httpd $(options) clean: - delete expversion.e acpversion.e delete express verinfogen express5 acp qwk ftn jsonimport icon2cfg miscfuncs.m stringlist.m errors.m mailssl.m jsoncreate.m jsonparser.m axcommon.m ftpd.m httpd.m axconsts.m axobjects.m axenums.m zmodem.m xymodem.m hydra.m bcd.m expversion.m acpversion.m pwdhash.m tooltypes.m + delete expversion.e acpversion.e delete express verinfogen express5 acp qwk ftn jsonimport icon2cfg miscfuncs.m stringlist.m errors.m mailssl.m jsoncreate.m jsonparser.m axcommon.m ftpd.m httpd.m axconsts.m axobjects.m axenums.m zmodem.m xymodem.m hydra.m bcd.m expversion.m acpversion.m pwdhash.m tooltypes.m sha256.m .PHONY: expversion.e \ No newline at end of file diff --git a/sha256.e b/sha256.e new file mode 100644 index 0000000..807f4ce --- /dev/null +++ b/sha256.e @@ -0,0 +1,353 @@ +OPT MODULE + +CONST SIZE_OF_SHA_256_HASH=32 +CONST SIZE_OF_SHA_256_CHUNK=64 +CONST TOTAL_LEN_LEN=8 + +OBJECT sha_256 + hash:PTR TO CHAR + chunk[SIZE_OF_SHA_256_CHUNK]: ARRAY OF CHAR + chunk_pos:PTR TO CHAR + space_left:LONG + total_len:LONG + h[8]:ARRAY OF LONG +ENDOBJECT + +/* + * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here. + * When useful for clarification, portions of the pseudo-code are reproduced here too. + */ + +/* + * @brief Rotate a 32-bit value by a number of bits to the right. + * @param value The value to be rotated. + * @param count The number of bits to rotate by. + * @return The rotated value. + */ +PROC right_rot(value, count) + MOVE.L value,D0 + MOVE.L count,D1 + ROR.L D1,D0 +ENDPROC D0 + +/* + * @brief Update a hash value under calculation with a new chunk of data. + * @param h Pointer to the first hash item, of a total of eight. + * @param p Pointer to the chunk data, which has a standard length. + * + * @note This is the SHA-256 work horse. + */ +PROC consume_chunk(h:PTR TO LONG, p:PTR TO CHAR) + DEF i,j + DEF ah[8]:ARRAY OF LONG + DEF w[16]:ARRAY OF LONG + DEF s0,s1,ch + DEF k:PTR TO LONG + DEF temp1,temp2,maj + + /* Initialize working variables to current hash value: */ + FOR i:=0 TO 7 DO ah[i]:=h[i] + + /* + * The w-array is really w[64], but since we only need 16 of them at a time, we save stack by + * calculating 16 at a time. + * + * This optimization was not there initially and the rest of the comments about w[64] are kept in their + * initial state. + */ + + /* + * create a 64-entry message schedule array w[0..63] of 32-bit words (The initial values in w[0..63] + * don't matter, so many implementations zero them here) copy chunk into first 16 words w[0..15] of the + * message schedule array + */ + + /* Compression function main loop: */ + FOR i:=0 TO 3 + FOR j:=0 TO 15 + IF (i = 0) + w[j]:=Lsl(p[0],24) OR Lsl(p[1],16) OR Lsl(p[2],8) OR p[3] + p+=4 + ELSE + /* Extend the first 16 words into the remaining 48 words w[16..63] of the + * message schedule array: */ + s0:=Eor( + Eor( + right_rot(w[(j + 1) AND $f], 7), + right_rot(w[(j + 1) AND $f], 18)), + Lsr(w[(j + 1) AND $f],3)) + s1:=Eor + (Eor( + right_rot(w[(j + 14) AND $f], 17), + right_rot(w[(j + 14) AND $f], 19)), + Lsr(w[(j + 14) AND $f],10)) + w[j]:=w[j] + s0 + w[(j + 9) AND $f] + s1 + ENDIF + s1:=Eor(Eor(right_rot(ah[4], 6),right_rot(ah[4], 11)),right_rot(ah[4], 25)) + ch:=Eor((ah[4] AND ah[5]),(Not(ah[4]) AND ah[6])) + + /* + * Initialize array of round constants: + * (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): + */ + k:={kdata} + + temp1:=ah[7] + s1 + ch + k[Lsl(i,4) OR j] + w[j] + s0:= Eor(Eor(right_rot(ah[0], 2),right_rot(ah[0], 13)),right_rot(ah[0], 22)) + maj:= Eor(Eor(ah[0] AND ah[1],ah[0] AND ah[2]),ah[1] AND ah[2]) + temp2:=s0+maj + + ah[7]:=ah[6] + ah[6]:=ah[5] + ah[5]:=ah[4] + ah[4]:=ah[3]+temp1 + ah[3]:=ah[2] + ah[2]:=ah[1] + ah[1]:=ah[0] + ah[0]:=temp1+temp2 + ENDFOR + ENDFOR + + /* Add the compressed chunk to the current hash value: */ + FOR i:=0 TO 7 DO h[i]:=h[i]+ah[i] +ENDPROC + +/* + * Public functions. See header file for documentation. + */ + +PROC sha_256_init(sha_256:PTR TO sha_256, hash:PTR TO CHAR) + sha_256.hash:=hash + sha_256.chunk_pos:=sha_256.chunk + sha_256.space_left:=SIZE_OF_SHA_256_CHUNK + sha_256.total_len:=0 + + /* + * Initialize hash values (first 32 bits of the fractional parts of the square roots of the first 8 primes + * 2..19): + */ + sha_256.h[0]:=$6a09e667 + sha_256.h[1]:=$bb67ae85 + sha_256.h[2]:=$3c6ef372 + sha_256.h[3]:=$a54ff53a + sha_256.h[4]:=$510e527f + sha_256.h[5]:=$9b05688c + sha_256.h[6]:=$1f83d9ab + sha_256.h[7]:=$5be0cd19 +ENDPROC + +PROC sha_256_write(sha_256:PTR TO sha_256, data,len) + DEF p + DEF consumed_len + p:=data + sha_256.total_len:=sha_256.total_len+len + + WHILE (len > 0) + /* + * If the input chunks have sizes that are multiples of the calculation chunk size, no copies are + * necessary. We operate directly on the input data instead. + */ + IF ((sha_256.space_left = SIZE_OF_SHA_256_CHUNK) AND (len >= SIZE_OF_SHA_256_CHUNK)) + consume_chunk(sha_256.h, p) + len -= SIZE_OF_SHA_256_CHUNK + p += SIZE_OF_SHA_256_CHUNK + CONT TRUE + ENDIF + /* General case, no particular optimization. */ + consumed_len:=IF (len < sha_256.space_left) THEN len ELSE sha_256.space_left + CopyMem(p, sha_256.chunk_pos, consumed_len) + sha_256.space_left -= consumed_len + len -= consumed_len + p += consumed_len + IF (sha_256.space_left = 0) + consume_chunk(sha_256.h, sha_256.chunk) + sha_256.chunk_pos:=sha_256.chunk + sha_256.space_left:=SIZE_OF_SHA_256_CHUNK + ELSE + sha_256.chunk_pos:=sha_256.chunk_pos+consumed_len + ENDIF + ENDWHILE +ENDPROC + +PROC sha_256_close(sha_256:PTR TO sha_256) + + DEF pos:PTR TO CHAR + DEF space_left + DEF h:PTR TO LONG + DEF left,len,i,hash:PTR TO LONG + pos:=sha_256.chunk_pos + space_left:=sha_256.space_left + h:=sha_256.h + /* + * The current chunk cannot be full. Otherwise, it would already have be consumed. I.e. there is space left for + * at least one byte. The next step in the calculation is to add a single one-bit to the data. + */ + pos[]++:=$80 + space_left-- + + /* + * Now, the last step is to add the total data length at the end of the last chunk, and zero padding before + * that. But we do not necessarily have enough space left. If not, we pad the current chunk with zeroes, and add + * an extra chunk at the end. + */ + IF (space_left < TOTAL_LEN_LEN) + MemFill(pos,space_left,0) + consume_chunk(h, sha_256.chunk) + pos:=sha_256.chunk + space_left:=SIZE_OF_SHA_256_CHUNK + ENDIF + left:=space_left - TOTAL_LEN_LEN + MemFill(pos,left,0) + pos+= left + len:=sha_256.total_len + pos[7]:=Lsl(len,3) + len:=Lsr(len,5) + FOR i:=6 TO 0 STEP -1 + pos[i]:=len + len:=Lsr(len,8) + ENDFOR + consume_chunk(h, sha_256.chunk) + /* Produce the final hash value (big-endian): */ + hash:=sha_256.hash + FOR i:=0 TO 7 + hash[i]:=h[i] + ENDFOR + +ENDPROC sha_256.hash + +EXPORT PROC calc_sha_256(hash:PTR TO CHAR, input, len) + DEF sha_256:PTR TO sha_256 + + NEW sha_256 + sha_256_init(sha_256, hash) + sha_256_write(sha_256, input, len) + sha_256_close(sha_256) + END sha_256 +ENDPROC + +kdata: LONG $428a2f98, $71374491, $b5c0fbcf, $e9b5dba5, $3956c25b, $59f111f1, $923f82a4, + $ab1c5ed5, $d807aa98, $12835b01, $243185be, $550c7dc3, $72be5d74, $80deb1fe, + $9bdc06a7, $c19bf174, $e49b69c1, $efbe4786, $0fc19dc6, $240ca1cc, $2de92c6f, + $4a7484aa, $5cb0a9dc, $76f988da, $983e5152, $a831c66d, $b00327c8, $bf597fc7, + $c6e00bf3, $d5a79147, $06ca6351, $14292967, $27b70a85, $2e1b2138, $4d2c6dfc, + $53380d13, $650a7354, $766a0abb, $81c2c92e, $92722c85, $a2bfe8a1, $a81a664b, + $c24b8b70, $c76c51a3, $d192e819, $d6990624, $f40e3585, $106aa070, $19a4c116, + $1e376c08, $2748774c, $34b0bcb5, $391c0cb3, $4ed8aa4a, $5b9cca4f, $682e6ff3, + $748f82ee, $78a5636f, $84c87814, $8cc70208, $90befffa, $a4506ceb, $bef9a3f7, + $c67178f2 + +/* $OpenBSD: pkcs5_pbkdf2.c,v 1.11 2019/11/21 16:07:24 tedu Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * HMAC-SHA-1 (from RFC 2202). + */ +PROC hmac_sha1(text:PTR TO CHAR, text_len, key:PTR TO CHAR, key_len, digest:PTR TO CHAR) + DEF k_pad:PTR TO CHAR + DEF tk[SIZE_OF_SHA_256_HASH]:ARRAY OF CHAR + DEF i + + k_pad:=New(SIZE_OF_SHA_256_CHUNK+text_len) + + IF (key_len > SIZE_OF_SHA_256_CHUNK) + calc_sha_256(tk,key, key_len) + key:=tk + key_len:=SIZE_OF_SHA_256_HASH + ENDIF + + CopyMem(key,k_pad, key_len) + CopyMem(text,k_pad+SIZE_OF_SHA_256_CHUNK, text_len) + FOR i:=0 TO SIZE_OF_SHA_256_CHUNK-1 DO k_pad[i]:=Eor(k_pad[i],$36) + + calc_sha_256(digest,k_pad, SIZE_OF_SHA_256_CHUNK+text_len) + Dispose(k_pad) + + k_pad:=New(SIZE_OF_SHA_256_CHUNK+SIZE_OF_SHA_256_HASH) + CopyMem(key,k_pad,key_len) + CopyMem(digest, k_pad+SIZE_OF_SHA_256_CHUNK, SIZE_OF_SHA_256_HASH) + + FOR i:=0 TO SIZE_OF_SHA_256_CHUNK-1 DO k_pad[i]:=Eor(k_pad[i],$5c) + + calc_sha_256(digest,k_pad, SIZE_OF_SHA_256_CHUNK+SIZE_OF_SHA_256_HASH) + Dispose(k_pad) +ENDPROC + +/* + * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). + * Code based on IEEE Std 802.11-2007, Annex H.4.2. + */ +EXPORT PROC pkcs5_pbkdf2(pass:PTR TO CHAR, pass_len, salt:PTR TO CHAR, salt_len, key:PTR TO CHAR, key_len, rounds) + DEF asalt:PTR TO CHAR + DEF obuf[SIZE_OF_SHA_256_HASH]:ARRAY OF CHAR + DEF d1[SIZE_OF_SHA_256_HASH]: ARRAY OF CHAR + DEF d2[SIZE_OF_SHA_256_HASH]:ARRAY OF CHAR + DEF i,j,count,r + + IF ((rounds < 1) OR (key_len = 0)) THEN JUMP bad + + IF ((salt_len = 0) OR (salt_len > ($7fffffff - 4))) THEN JUMP bad + + IF ((asalt:=New(salt_len + 4))=0) THEN JUMP bad + + CopyMem(salt, asalt, salt_len) + + count:=0 + WHILE(key_len>0) + count++ + asalt[salt_len]:=Shr(count,24) + asalt[salt_len+1]:=Shr(count,16) + asalt[salt_len+2]:=Shr(count,8) + asalt[salt_len+3]:=count AND 255 + + hmac_sha1(asalt, salt_len + 4, pass, pass_len, d1) + CopyMem(d1,obuf,SIZE_OF_SHA_256_HASH) + + FOR i:=1 TO rounds-1 + hmac_sha1(d1, SIZE_OF_SHA_256_HASH, pass, pass_len, d2) + CopyMem(d2,d1,SIZE_OF_SHA_256_HASH) + FOR j:=0 TO SIZE_OF_SHA_256_HASH-1 + obuf[j]:=Eor(obuf[j],d1[j]) + ENDFOR + ENDFOR + + IF key_len < SIZE_OF_SHA_256_HASH THEN r:=key_len ELSE r:=SIZE_OF_SHA_256_HASH + CopyMem(obuf,key,r) + key+=r + key_len-=r + ENDWHILE + + MemFill(asalt,salt_len + 4,0) + Dispose(asalt) + + MemFill(d1,SIZE_OF_SHA_256_HASH,0) + MemFill(d2,SIZE_OF_SHA_256_HASH,0) + MemFill(obuf,SIZE_OF_SHA_256_HASH,0) + + RETURN 0 + +bad: + /* overwrite with 0 in case caller doesn't check return code */ + MemFill(key,key_len,0) +ENDPROC -1 + +EXPORT PROC calcPasswordSalt(s:PTR TO CHAR) + DEF i + FOR i:=0 TO 7 + s[i]:=Rnd(95)+32 + ENDFOR +ENDPROC diff --git a/zmodem.e b/zmodem.e index 1701e57..c777e85 100644 --- a/zmodem.e +++ b/zmodem.e @@ -468,7 +468,6 @@ EXPORT OBJECT zmodem_t block_size:LONG max_block_size:LONG max_file_size:LONG /* 0 = unlimited */ - log_level:PTR TO INT user_data:LONG /* Callbacks */ @@ -528,10 +527,6 @@ ENDPROC Not(crc) PROC lprintf(zm:PTR TO zmodem_t, level, str:PTR TO CHAR) DEF p IF(zm.zm_lputs=NIL) THEN RETURN -1 - - IF(zm.log_level<>NIL) - IF(level > zm.log_level) THEN RETURN 0 - ENDIF p:=zm.zm_lputs ENDPROC p(level,str) @@ -1415,7 +1410,7 @@ PROC zmodem_recv_data32(zm: PTR TO zmodem_t, p: PTR TO CHAR, maxlen, l: PTR TO L n++ ENDLOOP l[]:=l[]+n - + subpkt_type:=c AND $ff crc:=ucrc32(subpkt_type,crc) From 48c98a0e4b8fbbbc140864b307ec567972d99400 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 8 Dec 2022 13:31:10 +0000 Subject: [PATCH 02/47] check in missed files with changes relating to tracking uploads/downloads >2gb --- axobjects.e | 7 +- bcd.e | 53 +++++++++ ftpd.e | 39 +++---- hydra.e | 2 +- xymodem.e | 190 +++++++++++++++--------------- zmodem.e | 328 +++++++++++++++++++++++++--------------------------- 6 files changed, 328 insertions(+), 291 deletions(-) diff --git a/axobjects.e b/axobjects.e index 90c5b6b..9127521 100644 --- a/axobjects.e +++ b/axobjects.e @@ -124,8 +124,9 @@ EXPORT OBJECT zModem currentOperation: LONG freeDFlag: LONG fileList:PTR TO stdlist - current: LONG - total: LONG + currentUL: LONG + currentDL: LONG + totalDL: LONG shouldUpdateDownloadStats: CHAR needUpdateDownloadStats: CHAR ENDOBJECT @@ -274,7 +275,7 @@ ENDOBJECT EXPORT OBJECT bgCheckData semi: ss checkedCount: LONG - checkedBytes: LONG + checkedBytes[8]:ARRAY OF CHAR ENDOBJECT EXPORT OBJECT diskObjectCacheItem diff --git a/bcd.e b/bcd.e index 72f29cf..9316053 100644 --- a/bcd.e +++ b/bcd.e @@ -91,6 +91,29 @@ EXPORT PROC addBCD(bcdTotal:PTR TO CHAR, valToAdd) addBCD2(bcdTotal,bcdVal) ENDPROC +EXPORT PROC mulBCD(bcdVal:PTR TO CHAR,valToMul) + DEF tmpVal[8]:ARRAY OF CHAR + DEF i + CopyMem(bcdVal,tmpVal,8) + convertToBCD(0,bcdVal) + WHILE(valToMul) + FOR i:=1 TO Mod(valToMul,10) + addBCD2(bcdVal,tmpVal) + ENDFOR + + valToMul:=Div(valToMul,10) + tmpVal[0]:=Shl(tmpVal[0] AND $F,4) OR Shr(tmpVal[1] AND $F0,4) + tmpVal[1]:=Shl(tmpVal[1] AND $F,4) OR Shr(tmpVal[2] AND $F0,4) + tmpVal[2]:=Shl(tmpVal[2] AND $F,4) OR Shr(tmpVal[3] AND $F0,4) + tmpVal[3]:=Shl(tmpVal[3] AND $F,4) OR Shr(tmpVal[4] AND $F0,4) + tmpVal[4]:=Shl(tmpVal[4] AND $F,4) OR Shr(tmpVal[5] AND $F0,4) + tmpVal[5]:=Shl(tmpVal[5] AND $F,4) OR Shr(tmpVal[6] AND $F0,4) + tmpVal[6]:=Shl(tmpVal[6] AND $F,4) OR Shr(tmpVal[7] AND $F0,4) + tmpVal[7]:=Shl(tmpVal[7] AND $F,4) + + ENDWHILE +ENDPROC + EXPORT PROC divBCD1024(bcdVal:PTR TO CHAR) DEF decVal[16]:ARRAY OF CHAR @@ -120,6 +143,36 @@ EXPORT PROC divBCD1024(bcdVal:PTR TO CHAR) ENDFOR ENDPROC +EXPORT PROC divBCD(dividend:PTR TO CHAR, divisor) + DEF decVal[16]:ARRAY OF CHAR + DEF i,n=0,v,r + + FOR i:=0 TO 7 + decVal[n]:=Shr(dividend[i] AND $f0,4) + n++ + decVal[n]:=dividend[i] AND $f + n++ + ENDFOR + + v:=0 + r:=0 + FOR i:=0 TO 15 + IF r + r:=Mul(r,10) + r+=decVal[i]; + ELSE + r:=decVal[i]; + ENDIF + + v:=Mul(v,10) + IF r>=divisor + n:=Div(r,divisor) + v+=n + r:=r-Mul(n,divisor); + ENDIF + ENDFOR + +ENDPROC v EXPORT PROC convertFromBCD(inArray:PTR TO CHAR) DEF tempBCD[8]:ARRAY diff --git a/ftpd.e b/ftpd.e index 168e849..4909f14 100644 --- a/ftpd.e +++ b/ftpd.e @@ -33,7 +33,8 @@ MODULE 'socket', '*axobjects', '*axenums', '*tooltypes', - '*miscfuncs' + '*miscfuncs', + '*bcd' EXPORT OBJECT ftpData @@ -258,23 +259,24 @@ PROC uploadFileStart(ftpData:PTR TO ftpData,fn,resumepos) ADD.L #8,A7 ENDPROC -PROC checkDownloadRatio(ftpData:PTR TO ftpData,fn,pos,res:PTR TO CHAR) +PROC checkDownloadRatio(ftpData:PTR TO ftpData,fn,flen,res:PTR TO CHAR) DEF cdr cdr:=ftpData.checkDownloadRatio MOVE.L fn,-(A7) - MOVE.L pos,-(A7) + MOVE.L flen,-(A7) MOVE.L res,-(A7) cdr() ADD.L #12,A7 ENDPROC D0 -PROC downloadFileStart(ftpData:PTR TO ftpData,fn,pos) +PROC downloadFileStart(ftpData:PTR TO ftpData,fn,flen,pos) DEF fs fs:=ftpData.downloadFileStart MOVE.L fn,-(A7) + MOVE.L flen,-(A7) MOVE.L pos,-(A7) fs() - ADD.L #8,A7 + ADD.L #12,A7 ENDPROC PROC uploadFileEnd(ftpData:PTR TO ftpData,fn,result) @@ -446,17 +448,13 @@ ENDPROC PROC calcCPS(pd,t,t2) DEF cps,td + DEF bcdVal[8]:ARRAY OF CHAR cps:=0 - IF t$10000000) - pd:=Shr(pd,1) AND $7fffffff - td:=Div(td,50) - IF td<1 THEN td:=1 - cps:=Shl(Div(pd,td),1) - ELSE - cps:=Div(Mul(pd,50),td) - ENDIF + td:=t2-t + IF td + convertToBCD(pd,bcdVal) + mulBCD(bcdVal,50) + cps:=divBCD(bcdVal,td) ELSE cps:=pd ENDIF @@ -1619,7 +1617,7 @@ PROC cmdRetr(sb,ftp_c,data_s,data_c,filename:PTR TO CHAR,ftpData:PTR TO ftpData) DEF buff DEF asynclib DEF fn[255]:STRING - DEF r,l,pos,cps,lastpos + DEF r,l,pos,cps,lastpos,flen DEF fh DEF t,t2,startTime DEF candl=TRUE @@ -1656,7 +1654,9 @@ PROC cmdRetr(sb,ftp_c,data_s,data_c,filename:PTR TO CHAR,ftpData:PTR TO ftpData) getFileName(ftpData,filename,fn) fh:=0 + flen:=0 IF StrLen(fn) + flen:=getFileSize(fn) IF asynclib<>NIL writeLineEx(sb,ftp_c, '150 Opening BINARY connection with ASYNC\b\n') fh:=OpenAsync(fn,MODE_READ,32768) @@ -1678,18 +1678,15 @@ PROC cmdRetr(sb,ftp_c,data_s,data_c,filename:PTR TO CHAR,ftpData:PTR TO ftpData) pos:=ftpData.restPos IF asynclib<>NIL SeekAsync(fh,pos,MODE_START) - pos:=SeekAsync(fh,0,MODE_CURRENT) ELSE Seek(fh,pos,OFFSET_BEGINNING) - pos:=Seek(fh,0,OFFSET_CURRENT) ENDIF - IF (ftpData.checkDownloadRatio<>NIL) ANDALSO (checkDownloadRatio(ftpData,fn,pos,res)=FALSE) + IF (ftpData.checkDownloadRatio<>NIL) ANDALSO (checkDownloadRatio(ftpData,fn,flen,res)=FALSE) StringF(temp,'550 \s\b\n',res) writeLineEx(sb,ftp_c,temp) candl:=FALSE - ELSE - IF (ftpData.downloadFileStart<>NIL) THEN downloadFileStart(ftpData,fn,pos) ENDIF + IF (ftpData.downloadFileStart<>NIL) THEN downloadFileStart(ftpData,fn,flen,pos) ENDIF IF candl buff:=New(32768) diff --git a/hydra.e b/hydra.e index 5905c4b..f5f0451 100644 --- a/hydra.e +++ b/hydra.e @@ -2571,7 +2571,7 @@ PROC hydra(hyd:PTR TO hydra_t,txpathname:PTR TO CHAR,txalias:PTR TO CHAR) proc:=hyd.hyd_close proc(hyd.txfd) proc:=hyd.hyd_downloadcompleted - IF proc THEN proc(hyd.txfsize) + IF proc THEN proc(hyd.txfsize,hyd.txfsize-hyd.txoffset) hydra_pct(hyd,TRUE) t1,t2:=time() t:=Mul((t1-hyd.txstart1),50)+t2-hyd.txstart2 diff --git a/xymodem.e b/xymodem.e index f3f5b6a..bf7de5e 100644 --- a/xymodem.e +++ b/xymodem.e @@ -1,12 +1,6 @@ OPT LARGE,MODULE - MODULE 'dos/dos' - -EXPORT CONST LOG_DEBUG=4 -EXPORT CONST LOG_INFO=3 -EXPORT CONST LOG_NOTICE=2 -EXPORT CONST LOG_WARNING=1 -EXPORT CONST LOG_ERR=0 + MODULE 'dos/dos','*axenums','*bcd' CONST MAX_PATH=512 @@ -90,9 +84,9 @@ EXPORT OBJECT xymodem_t current_file_pos current_file_size total_files - total_bytes + total_bytes[8]:ARRAY OF CHAR files_remaining - bytes_remaining + bytes_remaining[8]:ARRAY OF CHAR errors fallback_to_xmodem @@ -154,6 +148,14 @@ PROC is_cancelled(xym: PTR TO xymodem_t) ENDIF ENDPROC xym.cancelled +PROC download_completed(xym:PTR TO xymodem_t,fname,fsize,sentsize) + DEF p + p:=xym.zm_download_completed + IF p<>NIL + RETURN p(fsize,sentsize) + ENDIF +ENDPROC + PROC upload_completed(xym:PTR TO xymodem_t,fname:PTR TO CHAR,filebytes) DEF p p:=xym.zm_upload_completed @@ -275,25 +277,25 @@ PROC xmodem_put_nak(xym:PTR TO xymodem_t, block_num) IF(dump_count) StringF(tempstr,'Block \d: Dumped \d bytes',block_num, dump_count) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) ENDIF IF(block_num<=1) IF((xym.mode AND (B2K OR GMODE))=(B2K OR GMODE)) -> A for X/Ymodem-G with 2-K block StringF(tempstr,'Block \d: Requesting mode: Streaming, 16-bit CRC, 2K Block', block_num) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) putcom(xym,"A") ELSEIF((xym.mode) AND GMODE) -> G for X/Ymodem-G StringF(tempstr,'Block \d: Requesting mode: Streaming, 16-bit CRC', block_num) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) putcom(xym,"G") ELSEIF ((xym.mode) AND CRC) -> C for CRC StringF(tempstr,'Block \d: Requesting mode: 16-bit CRC', block_num) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) putcom(xym,"C") ELSE -> NAK for checksum StringF(tempstr,'Block \d: Requesting mode: 8-bit Checksum', block_num) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) putcom(xym,NAK) ENDIF ELSE @@ -354,14 +356,14 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu CASE ETX -> 2048-byte blocks IF(xym.max_block_size < XMODEM_2K_BLOCK_SIZE) StringF(tempstr,'Block \d: 2048-byte blocks not supported',expected_block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) RETURN FAILURE ENDIF xym.block_size:=XMODEM_2K_BLOCK_SIZE CASE STX -> 1024-byte blocks IF(xym.max_block_size < XMODEM_MAX_BLOCK_SIZE) StringF(tempstr,'Block \d: 1024-byte blocks not supported',expected_block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) RETURN FAILURE ENDIF xym.block_size:=XMODEM_MAX_BLOCK_SIZE @@ -369,7 +371,7 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu StringF(tempstr,'Block \d: EOT received', expected_block_num) lprintf(xym,LOG_DEBUG,tempstr) IF(eot=FALSE) - lprintf(xym,LOG_INFO,'NAKing first EOT') + lprintf(xym,LOG_DEBUG,'NAKing first EOT') eot:=1 xmodem_put_nak(xym,expected_block_num) -> chuck's double EOT trick JUMP lp @@ -379,11 +381,11 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu IF(can=FALSE) -> must get two CANs in a row can:=1 StringF(tempstr,'Block \d: Received CAN Expected SOH, STX, or EOT',expected_block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) JUMP lp ENDIF StringF(tempstr,'Block \d: Canceled remotely', expected_block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) RETURN CAN CASE NOINP -> Nothing came in IF(eot) THEN RETURN EOT @@ -391,7 +393,7 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu DEFAULT chr(i,tempstr2) StringF(tempstr,'Block \d: Received \s Expected SOH, STX, or EOT',expected_block_num,tempstr2) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) IF (eot) THEN RETURN EOT RETURN NOINP ENDSELECT @@ -426,7 +428,7 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu IF(block_num<>(Eor(block_inv,255))) StringF(tempstr,'Block \d: Block number bit error (0x\h[2] vs 0x\h[2])',expected_block_num, block_num,Eor(block_inv,255)) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) RETURN FAILURE ENDIF @@ -436,14 +438,14 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu crc:=crc OR getcom(xym,xym.byte_timeout) IF(crc<>calc_crc) StringF(tempstr,'Block \d: CRC ERROR', block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) RETURN FAILURE ENDIF ELSE -> CHKSUM chksum:=getcom(xym,xym.byte_timeout) IF(chksum<>calc_chksum) StringF(tempstr,'Block \d: CHECKSUM ERROR', block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) RETURN FAILURE ENDIF ENDIF @@ -451,7 +453,7 @@ PROC xmodem_get_block(xym:PTR TO xymodem_t, block:PTR TO CHAR, expected_block_nu IF(block_num<>(expected_block_num AND 255)) StringF(tempstr,'Block number error (\d received, expected \d)',block_num,expected_block_num AND 255) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) IF (((xym.mode) AND XMODEM) AND (expected_block_num=1) AND (block_num=0)) THEN RETURN NOT_XMODEM @@ -539,7 +541,7 @@ PROC xmodem_get_ack(xym:PTR TO xymodem_t, tries, block_num) IF xym.g_delay>0 THEN Delay(xym.g_delay) IF(getcom(xym,0)=CAN) StringF(tempstr,'Block \d: !Canceled remotely', block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) xmodem_cancel(xym) RETURN CAN ENDIF @@ -554,7 +556,7 @@ PROC xmodem_get_ack(xym:PTR TO xymodem_t, tries, block_num) IF(i=CAN) IF(can) -> 2 CANs in a row StringF(tempstr,'Block \d: !Canceled remotely', block_num) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) xmodem_cancel(xym) RETURN CAN ENDIF @@ -564,7 +566,7 @@ PROC xmodem_get_ack(xym:PTR TO xymodem_t, tries, block_num) IF(i<>NOINP) chr(i,tempstr2) StringF(tempstr,'Block \d: !Received \s Expected ACK',block_num, tempstr2) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) IF (i<>CAN) THEN RETURN i ENDIF @@ -581,7 +583,7 @@ PROC xmodem_get_mode(xym:PTR TO xymodem_t) DEF tempstr[255]:STRING DEF tempstr2[255]:STRING - lprintf(xym,LOG_INFO,'Waiting for transfer mode request...') + lprintf(xym,LOG_DEBUG,'Waiting for transfer mode request...') xym.mode:=xym.mode AND Eor(GMODE OR CRC,255) errors:=0 @@ -593,12 +595,12 @@ lp2: SELECT i CASE NAK -> checksum - lprintf(xym,LOG_INFO,'Receiver requested mode: 8-bit Checksum') + lprintf(xym,LOG_DEBUG,'Receiver requested mode: 8-bit Checksum') xym.max_block_size:=XMODEM_MAX_BLOCK_SIZE xym.block_size:=XMODEM_MAX_BLOCK_SIZE RETURN TRUE CASE "C" - lprintf(xym,LOG_INFO,'Receiver requested mode: 16-bit CRC') + lprintf(xym,LOG_DEBUG,'Receiver requested mode: 16-bit CRC') IF(xym.crc_mode_supported=FALSE) THEN JUMP lp2 xym.max_block_size:=XMODEM_MAX_BLOCK_SIZE xym.block_size:=XMODEM_MAX_BLOCK_SIZE @@ -606,7 +608,7 @@ lp2: xym.mode:=xym.mode OR CRC RETURN TRUE CASE "A" - lprintf(xym,LOG_INFO,'Receiver requested mode: Streaming, 2k-block, 16-bit CRC') + lprintf(xym,LOG_DEBUG,'Receiver requested mode: Streaming, 2k-block, 16-bit CRC') IF ((xym.crc_mode_supported=FALSE) OR (xym.g_mode_supported=FALSE)) THEN JUMP lp2 xym.mode:=xym.mode OR (GMODE OR CRC OR B2K) @@ -614,7 +616,7 @@ lp2: xym.block_size:=XMODEM_2K_BLOCK_SIZE RETURN TRUE CASE "G" - lprintf(xym,LOG_INFO,'Receiver requested mode: Streaming, 16-bit CRC') + lprintf(xym,LOG_DEBUG,'Receiver requested mode: Streaming, 16-bit CRC') IF ((xym.crc_mode_supported=FALSE) OR (xym.g_mode_supported=FALSE)) THEN JUMP lp2 xym.max_block_size:=XMODEM_MAX_BLOCK_SIZE xym.block_size:=XMODEM_MAX_BLOCK_SIZE @@ -623,7 +625,7 @@ lp2: RETURN TRUE CASE CAN IF(can) - lprintf(xym,LOG_WARNING,'Canceled remotely') + lprintf(xym,LOG_WARN,'Canceled remotely') RETURN FALSE ENDIF can:=1 @@ -632,12 +634,12 @@ lp2: DEFAULT chr(i,tempstr2) StringF(tempstr,'Received \s Expected NAK, C, or G',tempstr2) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) ENDSELECT errors++ ENDWHILE - lprintf(xym,LOG_ERR,'Failed to get transfer mode request from receiver') + lprintf(xym,LOG_ERROR,'Failed to get transfer mode request from receiver') ENDPROC FALSE PROC xmodem_put_eot(xym:PTR TO xymodem_t) @@ -651,12 +653,12 @@ PROC xmodem_put_eot(xym:PTR TO xymodem_t) WHILE((errors<=xym.max_errors) AND (is_connected(xym))) StringF(tempstr,'Sending End-of-Text (EOT) indicator (\d)',errors+1) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) WHILE(((ch:=getcom(xym,0))<>NOINP) AND (is_connected(xym))) chr(ch,tempstr2) lprintf(tempstr,'Throwing out received: \s',tempstr2) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) ENDWHILE putcom(xym,EOT) @@ -666,7 +668,7 @@ PROC xmodem_put_eot(xym:PTR TO xymodem_t) chr(ch,tempstr2) StringF(tempstr,'Received \s',tempstr2) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) IF(ch=ACK) THEN RETURN TRUE IF ((ch=CAN) AND (cans>0)) THEN RETURN FALSE @@ -675,7 +677,7 @@ PROC xmodem_put_eot(xym:PTR TO xymodem_t) JUMP lp3 -> chuck's double EOT trick so don't complain ENDIF - lprintf(xym,LOG_WARNING,'Expected ACK') + lprintf(xym,LOG_WARN,'Expected ACK') lp3: errors++ @@ -702,7 +704,7 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, StringF(tempstr,'Sending file \s',fname) - lprintf(xym,LOG_ERR,tempstr) + lprintf(xym,LOG_ERROR,tempstr) xym.success:=FALSE fname2:=FilePart(fname) @@ -711,7 +713,7 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, fp:=doOpen(xym,fname,MODE_OLDFILE) IF fp=NIL StringF(tempstr,'Error opening file \s',fname) - lprintf(xym,LOG_ERR,tempstr) + lprintf(xym,LOG_ERROR,tempstr) RETURN FALSE ENDIF fsize:=getFileSize(xym,fp) @@ -719,12 +721,13 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, fp:=0 fsize:=0 ENDIF + xym.current_file_size:=fsize IF(xym.total_files=0) THEN xym.total_files:=1 - IF(xym.total_bytes=0) THEN xym.total_bytes:=fsize + IF(convertFromBCD(xym.total_bytes)=0) THEN convertToBCD(fsize,xym.total_bytes) IF(xym.files_remaining=0) THEN xym.files_remaining:=1 - IF(xym.bytes_remaining=0) THEN xym.bytes_remaining:=fsize + IF(convertFromBCD(xym.bytes_remaining)=0) THEN convertToBCD(fsize,xym.bytes_remaining) -> try IF((xym.mode) AND YMODEM) @@ -735,17 +738,18 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, AstrCopy(block,fname2,XMODEM_MAX_BLOCK_SIZE) - StringF(tempstr,'\d \d 0 0 \d \d' + formatBCD(xym.bytes_remaining,tempstr2) + StringF(tempstr,'\d \d 0 0 \d \s' ,fsize ,0 ->(uintmax_t)st.st_mtime ,xym.files_remaining ->-xym.sent_files - ,xym.bytes_remaining ->-xym.sent_bytes + ,tempstr2 ->-xym.sent_bytes ) AstrCopy(block+StrLen(block)+1,tempstr) block_len:=StrLen(block)+1+StrLen(tempstr) StringF(tempstr,'Sending YMODEM header block: ''\s''',block+StrLen(block)+1) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) xym.errors:=0 WHILE((xym.errors<=xym.max_errors) AND (is_cancelled(xym)=FALSE) AND (is_connected(xym))) @@ -753,7 +757,7 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, WHILE(((ch:=getcom(xym,0))<>NOINP) AND (is_connected(xym))) chr(ch,tempstr2) StringF(tempstr,'Throwing out received: \s',tempstr2) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) ENDWHILE xmodem_put_block(xym, block, IF block_len <=XMODEM_MIN_BLOCK_SIZE THEN XMODEM_MIN_BLOCK_SIZE ELSE xym.block_size, 0) xmodem_flush(xym) @@ -765,7 +769,7 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, IF(((i=NAK) OR (i="C") OR (i="G")) AND (xym.fallback_to_xmodem) AND ((xym.errors+1) = xym.fallback_to_xmodem)) StringF(tempstr,'Falling back to XMODEM mode after \d attempts',xym.fallback_to_xmodem) - lprintf(xym,LOG_NOTICE,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) xym.mode:=xym.mode AND Not(YMODEM) JUMP sbr2 ENDIF @@ -773,7 +777,7 @@ PROC xmodem_send_file(xym:PTR TO xymodem_t, fname:PTR TO CHAR, sent:PTR TO LONG, ENDWHILE sbr2: IF((xym.errors>xym.max_errors) OR (is_cancelled(xym))) - lprintf(xym,LOG_ERR,'Failed to send header block') + lprintf(xym,LOG_ERROR,'Failed to send header block') JUMP sbr3 ENDIF ENDIF @@ -797,7 +801,7 @@ sbr2: IF(xym.block_size>XMODEM_MIN_BLOCK_SIZE) IF((sent_bytes+xym.block_size) > fsize) IF((sent_bytes+xym.block_size-XMODEM_MIN_BLOCK_SIZE) >= fsize) - lprintf(xym,LOG_INFO,'Falling back to 128-byte blocks for end of file') + lprintf(xym,LOG_DEBUG,'Falling back to 128-byte blocks for end of file') xym.block_size:=XMODEM_MIN_BLOCK_SIZE ENDIF ENDIF @@ -808,7 +812,7 @@ sbr2: IF(((rd:=doRead(xym,fp,block,xym.block_size))<>xym.block_size) AND ((sent_bytes + rd) <> fsize)) StringF(tempstr,'ERROR reading \d bytes at file offset \d',xym.block_size,sent_bytes) - lprintf(xym,LOG_ERR,tempstr) + lprintf(xym,LOG_ERROR,tempstr) xym.errors:=xym.errors+1 JUMP lp4 ENDIF @@ -818,10 +822,10 @@ sbr2: IF((r:=xmodem_get_ack(xym, 5,block_num)) <> ACK) xym.errors:=xym.errors+1 StringF(tempstr,'Block \d: Error #\d at offset \d',block_num, xym.errors,sent_bytes) - lprintf(xym,LOG_WARNING,tempstr) + lprintf(xym,LOG_WARN,tempstr) IF (((r="C") OR (xym.errors=3)) AND (block_num=1) AND (xym.block_size>XMODEM_MIN_BLOCK_SIZE)) StringF(tempstr,'Block \d: Falling back to 128-byte blocks', block_num) - lprintf(xym,LOG_NOTICE,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) xym.block_size:=XMODEM_MIN_BLOCK_SIZE ENDIF ELSE @@ -839,7 +843,7 @@ lp4: ->#if 0 /* !SINGLE_THREADED */ -> lprintf(LOG_DEBUG,"Waiting for output buffer to empty... ") -> if(WaitForEvent(outbuf_empty,5000)<>WAIT_OBJECT_0) - -> lprintf(xym,LOG_WARNING,"FAILURE") + -> lprintf(xym,LOG_WARN,"FAILURE") ->#endif IF (xmodem_put_eot(xym)) -> end-of-text, wait for ACK success:=TRUE @@ -875,12 +879,12 @@ EXPORT PROC xymodem_send_files(ymodem,xym: PTR TO xymodem_t,sentptr: PTR TO LONG xym.mode:=(IF ymodem THEN YMODEM ELSE XMODEM) OR SEND xym.files_remaining:=xym.total_files - xym.bytes_remaining:=xym.total_bytes + CopyMem(xym.total_bytes,xym.bytes_remaining,8) WHILE(((ch:=getcom(xym,0))<>NOINP) AND (is_connected(xym))) chr(ch,tempstr2) lprintf(tempstr,'Throwing out received: \s',tempstr2) - lprintf(xym,LOG_INFO,tempstr) + lprintf(xym,LOG_DEBUG,tempstr) ENDWHILE @@ -894,7 +898,7 @@ EXPORT PROC xymodem_send_files(ymodem,xym: PTR TO xymodem_t,sentptr: PTR TO LONG IF res=FALSE THEN RETURN res IF (xym.success) - doDownloadCompleted(xym,fname,sent) + download_completed(xym,fname,xym.current_file_size,sent) ENDIF init:=FALSE @@ -903,9 +907,9 @@ EXPORT PROC xymodem_send_files(ymodem,xym: PTR TO xymodem_t,sentptr: PTR TO LONG res:=FALSE IF p<>NIL THEN res:=p(fname) xym.files_remaining:=xym.files_remaining-1 - xym.bytes_remaining:=xym.bytes_remaining-sent + subBCD(xym.bytes_remaining,sent) IF xym.files_remaining<0 THEN xym.files_remaining:=0 - IF xym.bytes_remaining<0 THEN xym.bytes_remaining:=0 + IF xym.bytes_remaining[0]=$99 THEN convertToBCD(0,xym.bytes_remaining) IF sentptr<>NIL THEN sentptr[]:=sentptr[]+sent ENDIF UNTIL res=FALSE @@ -962,7 +966,7 @@ EXPORT PROC xymodem_recv_files(ymodem,xym: PTR TO xymodem_t, download_dir:PTR TO file_bytes:=$7fffffff file_bytes_left:=file_bytes ELSE - lprintf(xym,LOG_INFO,'Fetching YMODEM header block') + lprintf(xym,LOG_DEBUG,'Fetching YMODEM header block') xym.errors:=0 WHILE((xym.errors<=xym.max_errors) AND (xym.cancelled=FALSE)) xmodem_put_nak(xym,0) @@ -977,17 +981,17 @@ EXPORT PROC xymodem_recv_files(ymodem,xym: PTR TO xymodem_t, download_dir:PTR TO IF(((xym.errors+1)>(xym.max_errors/3)) AND (i=NOINP) AND ((xym.mode AND (B2K OR GMODE))=(B2K OR GMODE))) /* Timeout */ xym.mode:=xym.mode AND Not(B2K) StringF(logtmp,'Falling back to Streaming \s',IF (xym.mode AND CRC) THEN 'CRC-16' ELSE 'Checksum') - lprintf(xym,LOG_WARNING,logtmp) + lprintf(xym,LOG_WARN,logtmp) xym.errors:=-1 ELSEIF(((xym.errors+1)>(xym.max_errors/3)) AND (i=NOINP) AND (xym.mode AND GMODE)) /* Timeout */ xym.mode:=xym.mode AND Not(GMODE) StringF(logtmp,'Falling back to \s',IF (xym.mode AND CRC) THEN 'CRC-16' ELSE 'Checksum') - lprintf(xym,LOG_WARNING,logtmp) + lprintf(xym,LOG_WARN,logtmp) xym.errors:=-1 ENDIF IF(i=NOT_YMODEM) StringF(logtmp,'Falling back to XMODEM\s',IF (xym.mode AND GMODE) THEN '-g' ELSE '') - lprintf(xym,LOG_WARNING,logtmp) + lprintf(xym,LOG_WARN,logtmp) xym.mode:=xym.mode AND Not(YMODEM) xym.mode:=xym.mode OR XMODEM OR CRC hold_update:=0 @@ -998,14 +1002,14 @@ EXPORT PROC xymodem_recv_files(ymodem,xym: PTR TO xymodem_t, download_dir:PTR TO hold_update:=old_hold StringF(logtmp,'Falling back to XMODEM\s',IF (xym.mode AND GMODE) THEN '-g' ELSE '') - lprintf(xym,LOG_WARNING,logtmp) + lprintf(xym,LOG_WARN,logtmp) StrCopy(str,fname) file_bytes:=$7fffffff file_bytes_left:=file_bytes JUMP rbr1 ENDIF IF(((xym.errors+1)>(xym.max_errors/3)) AND (xym.mode AND CRC) AND ((xym.mode AND GMODE)=FALSE)) - lprintf(xym,LOG_NOTICE,'Falling back to 8-bit Checksum mode') + lprintf(xym,LOG_DEBUG,'Falling back to 8-bit Checksum mode') xym.mode:=xym.mode AND Not(CRC) ENDIF xym.errors:=xym.errors+1 @@ -1017,7 +1021,7 @@ rbr1: ENDIF IF(i<>NOT_YMODEM) IF(block[0]=FALSE) - lprintf(xym,LOG_INFO,'Received YMODEM termination block') + lprintf(xym,LOG_DEBUG,'Received YMODEM termination block') JUMP end ENDIF file_bytes:=0 @@ -1062,10 +1066,10 @@ rbr1: StringF(str,'\s\s',download_dir,FilePart(fname)) StringF(logtmp,'File size: \d bytes', file_bytes) - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) IF(total_files>1) StringF(logtmp,'Remaining: \d bytes in \d files', total_bytes, total_files) - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) ENDIF ENDIF ENDIF @@ -1077,14 +1081,14 @@ rbr1: fnum++ IF dupe_check(xym,str) - lprintf(xym,LOG_WARNING,'dupe check triggered') + lprintf(xym,LOG_WARN,'dupe check triggered') xmodem_cancel(xym) JUMP end ENDIF WHILE(fexist(str) AND ((xym.mode AND OVERWRITE)=FALSE)) StringF(logtmp,'\s already exists',str) - lprintf(xym,LOG_WARNING,logtmp) + lprintf(xym,LOG_WARN,logtmp) IF(xmodem_duplicate(xym, str)=FALSE) xmodem_cancel(xym) JUMP end @@ -1094,7 +1098,7 @@ rbr1: fp:=doOpen(xym,str,MODE_NEWFILE) IF(fp=NIL) StringF(logtmp,'Error \d creating \s',IoErr(),str) - lprintf(xym,LOG_ERR,logtmp) + lprintf(xym,LOG_ERROR,logtmp) xmodem_cancel(xym) JUMP end ENDIF @@ -1105,14 +1109,14 @@ rbr1: ,IF xym.mode AND GMODE THEN 'XMODEM-g' ELSE 'XMODEM' ,IF xym.mode AND CRC THEN 'CRC-16' ELSE 'Checksum') - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) ELSE StringF(logtmp,'Receiving \s (\d KB) via \s \s' ,str ,Shr(file_bytes,10) AND $3ffffff ,IF xym.mode AND GMODE THEN 'YMODEM-g' ELSE 'YMODEM' ,IF xym.mode AND CRC THEN 'CRC-16' ELSE 'Checksum') - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) ENDIF t1,t2:=getXYmSystemTime() @@ -1135,7 +1139,7 @@ c1: xym.new_file:=FALSE IF(is_cancelled(xym)) - lprintf(xym,LOG_WARNING,'Cancelled locally') + lprintf(xym,LOG_WARN,'Cancelled locally') xmodem_cancel(xym) JUMP end ENDIF @@ -1160,20 +1164,20 @@ c1: xym.errors:=xym.errors+1 IF(xym.mode AND GMODE) StringF(logtmp,'Too many errors (\d)',xym.errors) - lprintf(xym,LOG_ERR,logtmp) + lprintf(xym,LOG_ERROR,logtmp) JUMP end ENDIF IF(xym.errors>xym.max_errors) StringF(logtmp,'Too many errors (\d)',xym.errors) - lprintf(xym,LOG_ERR,logtmp) + lprintf(xym,LOG_ERROR,logtmp) xmodem_cancel(xym) JUMP rbr2 ENDIF IF((i<>NOT_XMODEM) AND (block_num=1) AND (xym.errors>(Div(xym.max_errors,3))) AND (xym.mode AND CRC) AND ((xym.mode AND GMODE)=FALSE)) StringF(logtmp,'Falling back to 8-bit Checksum mode (error=\d)', i) - lprintf(xym,LOG_NOTICE,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) xym.mode:=xym.mode AND Not(CRC) ENDIF xmodem_put_nak(xym, block_num) @@ -1186,7 +1190,7 @@ c1: ENDIF IF(file_bytes_left<=0) /* No more bytes to receive */ - lprintf(xym,LOG_WARNING,'Sender attempted to send more bytes than were specified in header') + lprintf(xym,LOG_WARN,'Sender attempted to send more bytes than were specified in header') JUMP rbr2 ENDIF @@ -1195,7 +1199,7 @@ c1: IF(doWrite(xym,fp,block,wr)<>wr) StringF(logtmp,'Error writing \d bytes to file at offset \d',wr,pos) - lprintf(xym,LOG_ERR,logtmp) + lprintf(xym,LOG_ERROR,logtmp) xmodem_cancel(xym) JUMP end ENDIF @@ -1218,7 +1222,7 @@ rbr2: IF(file_bytes < getFileSize(xym,fp)) StringF(logtmp,'Truncating file to \d bytes', file_bytes) - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) ->chsize(fileno(fp),(ulong)file_bytes); /* 4GB limit! */ ELSE file_bytes:=getFileSize(xym,fp) @@ -1245,12 +1249,12 @@ rbr2: IF(success) upload_completed(xym,str,file_bytes) StringF(logtmp,'Successful - Time: \d:\d CPS: \d',Div(t,50),Mod(t,50),cps) - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) fcount++ ELSE upload_failed(xym,str) StringF(logtmp,'File Transfer \s', IF xym.cancelled THEN 'Cancelled' ELSE 'Failure') - lprintf(xym,LOG_ERR,logtmp) + lprintf(xym,LOG_ERROR,logtmp) ENDIF ->IF(!(modexymODEM) && ftime) THEN setfdate(str,ftime); @@ -1258,7 +1262,7 @@ rbr2: IF((success=FALSE) AND (file_bytes=0)) IF (DeleteFile(str)=FALSE) StringF(logtmp,'Unable to remove empty file \s', str) - lprintf(xym,LOG_ERR,logtmp) + lprintf(xym,LOG_ERROR,logtmp) ENDIF ENDIF @@ -1273,7 +1277,7 @@ rbr2: ,Mod(Div(total_bytes,cps),50) ,total_files ,Shr(total_bytes,10) AND $3ffffff) - lprintf(xym,LOG_INFO,logtmp) + lprintf(xym,LOG_DEBUG,logtmp) ENDIF ENDWHILE @@ -1352,21 +1356,13 @@ PROC getFileSize(xym,fp) p:=doSeek(xym,fp,0,OFFSET_END) ENDPROC doSeek(xym,fp,p,OFFSET_BEGINING) -PROC doDownloadCompleted(xym:PTR TO xymodem_t,fname,size) - DEF p - p:=xym.zm_download_completed - IF p<>NIL - RETURN p(size) - ENDIF -ENDPROC - PROC doOpen(xym:PTR TO xymodem_t,fname,mode) DEF p p:=xym.zm_fopen IF p<>NIL RETURN p(fname,mode) ENDIF - lprintf(xym,LOG_WARNING,'zm_fopen not set, defaulting to dos library Open') + lprintf(xym,LOG_WARN,'zm_fopen not set, defaulting to dos library Open') ENDPROC Open(fname,mode) PROC doClose(xym:PTR TO xymodem_t,fhandle) @@ -1375,7 +1371,7 @@ PROC doClose(xym:PTR TO xymodem_t,fhandle) IF p<>NIL RETURN p(fhandle) ENDIF - lprintf(xym,LOG_WARNING,'zm_fclose not set, defaulting to dos library Close') + lprintf(xym,LOG_WARN,'zm_fclose not set, defaulting to dos library Close') ENDPROC Close(fhandle) PROC doSeek(xym:PTR TO xymodem_t,fhandle,pos,origin) @@ -1384,7 +1380,7 @@ PROC doSeek(xym:PTR TO xymodem_t,fhandle,pos,origin) IF p<>NIL RETURN p(fhandle,pos,origin) ENDIF - lprintf(xym,LOG_WARNING,'zm_fseek not set, defaulting to dos library Seek') + lprintf(xym,LOG_WARN,'zm_fseek not set, defaulting to dos library Seek') ENDPROC Seek(fhandle,pos,origin) PROC doRead(xym:PTR TO xymodem_t,fhandle,buffer,length) @@ -1393,7 +1389,7 @@ PROC doRead(xym:PTR TO xymodem_t,fhandle,buffer,length) IF p<>NIL RETURN p(fhandle,buffer,length) ENDIF - ->lprintf(xym,LOG_WARNING,'zm_fread not set, defaulting to dos library FRead') + ->lprintf(xym,LOG_WARN,'zm_fread not set, defaulting to dos library FRead') ENDPROC Fread(fhandle,buffer,1,length) PROC doWrite(xym:PTR TO xymodem_t,fhandle,buffer,length) @@ -1402,7 +1398,7 @@ PROC doWrite(xym:PTR TO xymodem_t,fhandle,buffer,length) IF p<>NIL RETURN p(fhandle,buffer,length) ENDIF - ->lprintf(xym,LOG_WARNING,'zm_fwrite not set, defaulting to dos library FWrite') + ->lprintf(xym,LOG_WARN,'zm_fwrite not set, defaulting to dos library FWrite') ENDPROC Fwrite(fhandle,buffer,1,length) crc16tbl: INT $0000, $1021, $2042, $3063, $4084, $50A5, $60C6, $70E7, diff --git a/zmodem.e b/zmodem.e index c777e85..798722a 100644 --- a/zmodem.e +++ b/zmodem.e @@ -1,6 +1,6 @@ OPT LARGE,MODULE - MODULE 'dos/dos','socket' + MODULE 'dos/dos','socket','*axenums','*bcd','exec' /* way to update errors, error/resume position @@ -12,12 +12,6 @@ way to update errors, error/resume position /* $Id: crc16.c,v 1.7 2014/02/10 04:44:31 deuce Exp $ */ -EXPORT CONST ZM_LOG_DEBUG=4 -EXPORT CONST ZM_LOG_INFO=3 -EXPORT CONST ZM_LOG_NOTICE=2 -EXPORT CONST ZM_LOG_WARNING=1 -EXPORT CONST ZM_LOG_ERR=0 - CONST MAX_PATH=512 CONST NOINP=-1 /* input buffer empty (incom only) */ @@ -428,9 +422,9 @@ EXPORT OBJECT zmodem_t current_file_time:LONG current_file_num:LONG total_files:LONG - total_bytes:LONG + total_bytes[8]:ARRAY OF CHAR files_remaining:LONG - bytes_remaining:LONG + bytes_remaining[8]:ARRAY OF CHAR transfer_start_pos:LONG transfer_start_time1:LONG transfer_start_time2:INT @@ -547,6 +541,14 @@ PROC is_cancelled(zm: PTR TO zmodem_t) ENDIF ENDPROC FALSE +PROC download_completed(zm:PTR TO zmodem_t,fname,filesize,sentsize) + DEF p + p:=zm.zm_download_completed + IF p<>NIL + RETURN p(filesize,sentsize) + ENDIF +ENDPROC + PROC upload_completed(zm:PTR TO zmodem_t,fname:PTR TO CHAR,filebytes) DEF p p:=zm.zm_upload_completed @@ -559,12 +561,6 @@ PROC upload_failed(zm:PTR TO zmodem_t,fname:PTR TO CHAR) IF (p<>NIL) THEN p(fname) ENDPROC -PROC download_completed(zm:PTR TO zmodem_t,fname:PTR TO CHAR,filebytes) - DEF p - p:=zm.zm_download_completed - IF (p<>NIL) THEN p(fname,filebytes) -ENDPROC - PROC dupe_check(zm:PTR TO zmodem_t,fname) DEF res=FALSE DEF p @@ -853,7 +849,7 @@ PROC zmodem_send_hex(zm:PTR TO zmodem_t,val) StrCopy(xdigit,'0123456789abcdef') ->StringF(tempstr,'send_hex: \d \h[2] ',val,val) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) zmodem_send_raw(zm, xdigit[Shr(val,4)]) ENDPROC zmodem_send_raw(zm, xdigit[val AND 15]) @@ -879,7 +875,7 @@ PROC zmodem_send_hex_header(zm:PTR TO zmodem_t, p: PTR TO CHAR) type:=p[] ->chr(type,tempstr) ->StringF(tempstr2,'send_hex_header: \s', tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) zmodem_send_padded_zdle(zm) zmodem_send_raw(zm, ZHEX) @@ -939,7 +935,7 @@ PROC zmodem_send_bin32_header(zm:PTR TO zmodem_t, p: PTR TO CHAR) ->chr(p[],tempstr) ->StringF(tempstr2,'"send_bin32_header: \s',tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) zmodem_send_padded_zdle(zm) zmodem_send_raw(zm, ZBIN32) @@ -970,7 +966,7 @@ PROC zmodem_send_bin16_header(zm:PTR TO zmodem_t, p: PTR TO CHAR) ->chr(p[],tempstr) ->StringF(tempstr2,'send_bin16_header: \s',tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) zmodem_send_padded_zdle(zm) @@ -1013,7 +1009,7 @@ PROC zmodem_send_data32(zm: PTR TO zmodem_t, subpkt_type, p: PTR TO CHAR, l) ->chr(subpkt_type,tempstr) ->StringF(tempstr2,'send_data32: \s (\d bytes)', tempstr,l) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) crc:=$ffffffff @@ -1043,7 +1039,7 @@ PROC zmodem_send_data16(zm: PTR TO zmodem_t, subpkt_type,p: PTR TO CHAR, l) ->chr(subpkt_type,tempstr) ->StringF(tempstr2,'send_data16: \s (\d bytes)', tempstr,l) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) crc:=0 @@ -1090,7 +1086,7 @@ PROC zmodem_send_data(zm: PTR TO zmodem_t, subpkt_type, p: PTR TO CHAR, l) IF(zm.frame_in_transit)=0 /* Start of frame, include ZDATA header */ ->StringF(tempstr,'send_data: start of frame, offset \d',zm.current_file_pos) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) zmodem_send_pos_header(zm, ZDATA, zm.current_file_pos, /* Hex? */ FALSE) ENDIF ENDPROC zmodem_send_data_subpkt(zm, subpkt_type, p, l) @@ -1118,26 +1114,26 @@ EXPORT PROC zmodem_send_zfin(zm: PTR TO zmodem_t) DEF zfin_header zfin_header:=[ ZFIN, 0, 0, 0, 0 ]:CHAR - lprintf(zm,ZM_LOG_NOTICE,'Finishing Session (Sending ZFIN)') + lprintf(zm,LOG_DEBUG,'Finishing Session (Sending ZFIN)') ENDPROC zmodem_send_hex_header(zm,zfin_header) PROC zmodem_send_zabort(zm: PTR TO zmodem_t) - lprintf(zm,ZM_LOG_WARNING,'Aborting Transfer (Sending ZABORT)') + lprintf(zm,LOG_WARN,'Aborting Transfer (Sending ZABORT)') ENDPROC zmodem_send_pos_header(zm, ZABORT, 0, /* Hex? */ TRUE) PROC zmodem_send_znak(zm: PTR TO zmodem_t) - lprintf(zm,ZM_LOG_INFO,'Sending ZNAK') + lprintf(zm,LOG_DEBUG,'Sending ZNAK') ENDPROC zmodem_send_pos_header(zm, ZNAK, 0, /* Hex? */ TRUE) PROC zmodem_send_zskip(zm: PTR TO zmodem_t) - lprintf(zm,ZM_LOG_INFO,'Sending ZSKIP') + lprintf(zm,LOG_DEBUG,'Sending ZSKIP') ENDPROC zmodem_send_pos_header(zm, ZSKIP, 0, /* Hex? */ TRUE) PROC zmodem_send_zeof(zm: PTR TO zmodem_t, pos) DEF tempstr[255]:STRING StringF(tempstr,'Sending End-of-File (ZEOF) frame (pos=\d)', pos) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ENDPROC zmodem_send_pos_header(zm, ZEOF, pos, /* Hex? */ TRUE) /* @@ -1177,7 +1173,7 @@ noret: zm.n_cans:=zm.n_cans+1 IF(zm.n_cans = 5) zm.cancelled:=TRUE - lprintf(zm,ZM_LOG_WARNING,'recv_raw: Cancelled remotely') + lprintf(zm,LOG_WARN,'recv_raw: Cancelled remotely') /* return(TIMEOUT) removed June-12-2005 */ ENDIF ELSE @@ -1226,7 +1222,7 @@ iszdle: */ ->chr(c,tempstr) ->StringF(tempstr2,'x: encoding data subpacket type: \s',tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) RETURN (c OR ZDLEESC) ELSEIF (c=ZRUB0) RETURN $7f @@ -1235,7 +1231,7 @@ iszdle: ELSEIF (c=XON) OR (c=(XON OR $80)) OR (c=XOFF) OR (c=(XOFF OR $80)) OR (c=ZDLE) chr(c,tempstr) StringF(tempstr2,'"rx: dropping escaped flow ctrl char: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) ELSE IF(c < 0) THEN RETURN c @@ -1246,7 +1242,7 @@ iszdle: */ ->chr(c,tempstr) ->StringF(tempstr2,'rx: dropping unescaped ctrl char: \s',tempstr) - ->lprintf(zm,ZM_LOG_WARNING,tempstr2) + ->lprintf(zm,LOG_WARN,tempstr2) ->JUMP rxcont ELSE /* @@ -1256,7 +1252,7 @@ iszdle: IF((c AND $60) = $40) THEN RETURN Eor(c,$40) ->chr(c,tempstr) ->StringF(tempstr2,'"rx: illegal sequence: ZDLE \s',tempstr) - ->lprintf(zm,ZM_LOG_WARNING,tempstr2) + ->lprintf(zm,LOG_WARN,tempstr2) loop:=FALSE ENDIF ENDIF @@ -1290,7 +1286,7 @@ EXPORT PROC zmodem_rx(zm: PTR TO zmodem_t) ELSEIF (c=XON) OR (c=(XONOR80)) OR (c=XOFF) OR (c=(XOFFOR80)) chr(c,tempstr) StringF(tempstr2,'rx: dropping flow ctrl char: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) ELSE /* * if all control characters should be escaped and @@ -1299,7 +1295,7 @@ EXPORT PROC zmodem_rx(zm: PTR TO zmodem_t) IF((zm.escape_ctrl_chars AND (c >= 0) AND ((c AND $60)=0))) chr(c,tempstr) StringF(tempstr2,'rx: dropping unescaped ctrl char: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) ELSE /* * normal character; return it. @@ -1320,7 +1316,7 @@ EXPORT PROC zmodem_rx(zm: PTR TO zmodem_t) IF (c=XON) OR (c=(XON OR $80)) OR (c=XOFF) OR (c=(XOFF OR $80)) OR (c=ZDLE) chr(c,tempstr) StringF(tempstr2,'"rx: dropping escaped flow ctrl char: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) ELSEIF (c=ZCRCE) OR (c=ZCRCG) OR (c=ZCRCQ) OR (c=ZCRCW) /* these four are really nasty. * for convenience we just change them into @@ -1330,7 +1326,7 @@ EXPORT PROC zmodem_rx(zm: PTR TO zmodem_t) */ ->chr(c,tempstr) ->StringF(tempstr2,'x: encoding data subpacket type: \s',tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) RETURN (c OR ZDLEESC) ELSEIF (c=ZRUB0) RETURN $7f @@ -1346,7 +1342,7 @@ EXPORT PROC zmodem_rx(zm: PTR TO zmodem_t) */ ->chr(c,tempstr) ->StringF(tempstr2,'rx: dropping unescaped ctrl char: \s',tempstr) - ->lprintf(zm,ZM_LOG_WARNING,tempstr2) + ->lprintf(zm,LOG_WARN,tempstr2) ->JUMP rxcont ELSE /* @@ -1356,7 +1352,7 @@ EXPORT PROC zmodem_rx(zm: PTR TO zmodem_t) IF((c AND $60) = $40) THEN RETURN Eor(c,$40) ->chr(c,tempstr) ->StringF(tempstr2,'"rx: illegal sequence: ZDLE \s',tempstr) - ->lprintf(zm,ZM_LOG_WARNING,tempstr2) + ->lprintf(zm,LOG_WARN,tempstr2) loop:=FALSE ENDIF ENDIF @@ -1392,7 +1388,7 @@ PROC zmodem_recv_data32(zm: PTR TO zmodem_t, p: PTR TO CHAR, maxlen, l: PTR TO L DEF tempstr[255]:STRING DEF tempstr2[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_data32') + ->lprintf(zm,LOG_DEBUG,'recv_data32') crc:=$ffffffff @@ -1425,12 +1421,12 @@ PROC zmodem_recv_data32(zm: PTR TO zmodem_t, p: PTR TO CHAR, maxlen, l: PTR TO L IF(rxd_crc <> crc) chr(subpkt_type,tempstr) StringF(tempstr2,'CRC32 ERROR (\h[8], expected: \h[8]) Bytes=\d, subpacket-type=\s',rxd_crc, crc, l[], tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) RETURN CRCFAILED ENDIF /*chr(subpkt_type,tempstr) StringF(tempstr2,'GOOD CRC32: \h[8] (Bytes=\d, subpacket-type=\s)',crc, l[], tempstr) - lprintf(zm,ZM_LOG_DEBUG,tempstr2)*/ + lprintf(zm,LOG_DEBUG,tempstr2)*/ zm.ack_file_pos:=zm.ack_file_pos+l[] ENDPROC subpkt_type @@ -1445,7 +1441,7 @@ PROC zmodem_recv_data16(zm: PTR TO zmodem_t, p:PTR TO CHAR, maxlen, l: PTR TO L DEF tempstr[255]:STRING ->DEF tempstr2[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_data16') + ->lprintf(zm,LOG_DEBUG,'recv_data16') crc:=0 @@ -1474,11 +1470,11 @@ PROC zmodem_recv_data16(zm: PTR TO zmodem_t, p:PTR TO CHAR, maxlen, l: PTR TO L IF(rxd_crc <> crc) StringF(tempstr,'CRC16 ERROR (\h[4], expected: \h[4]) Bytes=\d',rxd_crc, crc, l[]) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) RETURN CRCFAILED ENDIF /*StringF(tempstr,'GOOD CRC16: \h[4] (Bytes=\d)', crc, l[]) - lprintf(zm,ZM_LOG_DEBUG,tempstr)*/ + lprintf(zm,LOG_DEBUG,tempstr)*/ zm.ack_file_pos:=zm.ack_file_pos+l[] @@ -1494,7 +1490,7 @@ PROC zmodem_recv_data(zm: PTR TO zmodem_t, p:PTR TO CHAR, maxlen, l: PTR TO LONG IF(l=NIL) THEN l:={n} ->StringF(tempstr,'recv_data (\d-bit)', IF zm.receive_32bit_data THEN 32 ELSE 16) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) /* * receive the right type of frame @@ -1512,7 +1508,7 @@ PROC zmodem_recv_data(zm: PTR TO zmodem_t, p:PTR TO CHAR, maxlen, l: PTR TO LONG ->chr(subpkt_type,tempstr) ->StringF(tempstr,'recv_data received subpacket-type: \s',tempstr2) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) SELECT subpkt_type /* @@ -1541,7 +1537,7 @@ PROC zmodem_recv_data(zm: PTR TO zmodem_t, p:PTR TO CHAR, maxlen, l: PTR TO LONG chr(subpkt_type,tempstr) StringF(tempstr,'Received invalid subpacket-type: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) ENDPROC INVALIDSUBPKT @@ -1603,7 +1599,7 @@ PROC zmodem_recv_hex(zm: PTR TO zmodem_t) ret:=(Shl(n1,4)) OR n0 ->StringF(tempstr,'recv_hex returning: 0x\h[2]', ret) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) ENDPROC ret /* @@ -1621,7 +1617,7 @@ PROC zmodem_recv_bin16_header(zm: PTR TO zmodem_t) DEF tempstr[255]:STRING DEF tempstr2[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_bin16_header') + ->lprintf(zm,LOG_DEBUG,'recv_bin16_header') crc:=0 @@ -1630,7 +1626,7 @@ PROC zmodem_recv_bin16_header(zm: PTR TO zmodem_t) IF(c < 0) chr(c,tempstr) StringF(tempstr2,'recv_bin16_header: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_DEBUG,tempstr2) RETURN FALSE ENDIF crc:=ucrc16(c,crc) @@ -1642,11 +1638,11 @@ PROC zmodem_recv_bin16_header(zm: PTR TO zmodem_t) IF(rxd_crc <> crc) StringF(tempstr,'CRC16 ERROR: 0x\h, expected: 0x\h', rxd_crc, crc) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) RETURN FALSE ENDIF /*StringF(tempstr,'GOOD CRC16: \h[4]', crc) - lprintf(zm,ZM_LOG_DEBUG,tempstr)*/ + lprintf(zm,LOG_DEBUG,tempstr)*/ zm.rxd_header_len:=5 @@ -1660,7 +1656,7 @@ PROC zmodem_recv_hex_header(zm: PTR TO zmodem_t) DEF rxd_crc DEF tempstr[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_hex_header') + ->lprintf(zm,LOG_DEBUG,'recv_hex_header') FOR i:=0 TO HDRLEN-1 c:=zmodem_recv_hex(zm) @@ -1688,11 +1684,11 @@ PROC zmodem_recv_hex_header(zm: PTR TO zmodem_t) IF(rxd_crc = crc) ->StringF(tempstr,'GOOD CRC16: \h[4]', crc) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) zm.rxd_header_len:=5 ELSE StringF(tempstr,'CRC16 ERROR: 0x\h, expected: 0x\h', rxd_crc, crc) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) RETURN FALSE ENDIF @@ -1716,7 +1712,7 @@ PROC zmodem_recv_bin32_header(zm: PTR TO zmodem_t) DEF rxd_crc DEF tempstr[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_bin32_header') + ->lprintf(zm,LOG_DEBUG,'recv_bin32_header') crc:=$ffffffff @@ -1737,11 +1733,11 @@ PROC zmodem_recv_bin32_header(zm: PTR TO zmodem_t) IF(rxd_crc<>crc) StringF(tempstr,'CRC32 ERROR (\h[8], expected: \h[8]',rxd_crc, crc) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) RETURN FALSE ENDIF ->StringF(tempstr,'GOOD CRC32: \h[8]', crc) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) zm.rxd_header_len:=5 ENDPROC TRUE @@ -1761,7 +1757,7 @@ PROC zmodem_recv_header_raw(zm: PTR TO zmodem_t, errors) DEF tempstr[255]:STRING DEF tempstr2[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_header_raw') + ->lprintf(zm,LOG_DEBUG,'recv_header_raw') zm.rxd_header_len:=0 @@ -1787,7 +1783,7 @@ zmrhcont: IF(c<>ZDLE) chr(c,tempstr) StringF(tempstr2,'recv_header_raw: Expected ZDLE, received: \s',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) JUMP zmrhcont ENDIF @@ -1812,15 +1808,15 @@ zmrhcont: IF(c < 0) chr(c,tempstr) StringF(tempstr2,'recv_header_raw: \s', tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_DEBUG,tempstr2) RETURN c ENDIF /* * unrecognized header style */ chr(c,tempstr) - StringF(tempstr2,'recv_header_raw: UNRECOGNIZED header style: \s',tempstr) - lprintf(zm,ZM_LOG_ERR,tempstr2) + StringF(tempstr2,'recv_header_raw: UNRECOGNIZED header style: \s',tempstr) + lprintf(zm,LOG_ERROR,tempstr2) IF(errors) THEN RETURN INVHDR JUMP zmrhcont ENDSELECT @@ -1859,7 +1855,7 @@ zmrhcont: ->#if 0 /* def _DEBUG */ ->frame_desc(frame_type,tempstr) ->StringF(tempstr2,'recv_header_raw received header type: \s',tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) ->#endif ENDPROC frame_type @@ -1872,13 +1868,13 @@ PROC zmodem_recv_header(zm: PTR TO zmodem_t) SELECT ret CASE TIMEOUT - lprintf(zm,ZM_LOG_WARNING,'recv_header TIMEOUT') + lprintf(zm,LOG_WARN,'recv_header TIMEOUT') CASE INVHDR - lprintf(zm,ZM_LOG_WARNING,'recv_header detected an invalid header') + lprintf(zm,LOG_WARN,'recv_header detected an invalid header') DEFAULT ->frame_desc(ret,tempstr) ->StringF(tempstr2,'recv_header returning: \s (pos=\d)',tempstr, frame_pos(zm, ret)) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) IF(ret=ZCAN) zm.cancelled:=TRUE @@ -1906,7 +1902,7 @@ PROC zmodem_recv_header_and_check(zm: PTR TO zmodem_t) ->frame_desc(type,tempstr) ->StringF(tempstr2,'recv_header_and_check returning: \s (pos=\d)',tempstr,frame_pos(zm, type)) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) IF(type=ZCAN) THEN zm.cancelled:=TRUE ENDPROC type @@ -1923,14 +1919,14 @@ PROC zmodem_recv_crc(zm: PTR TO zmodem_t, crc:PTR TO LONG) IF(zmodem_data_waiting(zm,zm.crc_timeout))=FALSE StringF(tempstr,'Timeout waiting for response (\d seconds)',zm.crc_timeout) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) RETURN FALSE ENDIF IF((type:=zmodem_recv_header(zm)))<>ZCRC frame_desc(type,tempstr) StringF(tempstr2,'Received \s instead of ZCRC', tempstr) - lprintf(zm,ZM_LOG_ERR,tempstr2) + lprintf(zm,LOG_ERROR,tempstr2) RETURN FALSE ENDIF IF(crc<>NIL) THEN crc[]:=zm.crc_request @@ -1956,12 +1952,12 @@ PROC zmodem_parse_zrinit(zm: PTR TO zmodem_t) IF(zm.can_overlap_io) THEN 'Can' ELSE 'Cannot', IF(zm.can_fcs_32) THEN 32 ELSE 16, IF(zm.escape_ctrl_chars) THEN 'ALL' ELSE 'Normal') - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) zm.recv_bufsize:=(zm.rxd_header[ZP0] OR (Shl(zm.rxd_header[ZP1],8))) IF(zm.recv_bufsize)<>0 StringF(tempstr,'Receiver specified buffer size of: \d', zm.recv_bufsize) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ENDIF ENDPROC @@ -2010,12 +2006,12 @@ PROC zmodem_handle_zrpos(zm: PTR TO zmodem_t, pos:PTR TO LONG) IF(pos[] <> zm.rxd_header_pos) pos[]:=zm.rxd_header_pos StringF(tempstr,'Resuming transfer from offset: \d',pos[]) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ENDIF RETURN TRUE ENDIF StringF(tempstr,'Invalid ZRPOS offset: \d', zm.rxd_header_pos) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) ENDPROC FALSE PROC zmodem_handle_zack(zm: PTR TO zmodem_t) @@ -2023,7 +2019,7 @@ PROC zmodem_handle_zack(zm: PTR TO zmodem_t) IF(zm.rxd_header_pos = zm.current_file_pos) THEN RETURN TRUE StringF(tempstr,'ZACK for incorrect offset (\d vs \d)',zm.rxd_header_pos, zm.current_file_pos) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) ENDPROC FALSE /* @@ -2049,7 +2045,7 @@ PROC zmodem_send_from(zm: PTR TO zmodem_t, fp, pos,sent: PTR TO LONG) startfrom:=pos IF doSeek(zm,fp,pos,OFFSET_BEGINING)=-1 StringF(tempstr,'ERROR \d seeking to file offset \d',IoErr(), pos) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) zmodem_send_pos_header(zm, ZFERR, pos, /* Hex? */ TRUE) RETURN ZFERR ENDIF @@ -2109,9 +2105,9 @@ PROC zmodem_send_from(zm: PTR TO zmodem_t, fp, pos,sent: PTR TO LONG) IF((type = ZCRCW) OR (type = ZCRCE)) ->chr(type,tempstr) ->StringF(tempstr2,'Sent end-of-frame (\s sub-packet)', tempstr) - ->lprintf(zm,ZM_LOG_DEBUG,tempstr2) + ->lprintf(zm,LOG_DEBUG,tempstr2) IF(type=ZCRCW) /* ZACK expected */ - ->lprintf(zm,ZM_LOG_DEBUG,'Waiting for ZACK') + ->lprintf(zm,LOG_DEBUG,'Waiting for ZACK') WHILE(is_connected(zm)) IF((ack:=zmodem_recv_header(zm)))<>ZACK THEN RETURN ack @@ -2129,7 +2125,7 @@ PROC zmodem_send_from(zm: PTR TO zmodem_t, fp, pos,sent: PTR TO LONG) IF(n < zm.block_size) StringF(tempstr,'send_from: end of file (or read error) reached at offset: \d',zm.current_file_pos) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) zmodem_send_zeof(zm, zm.current_file_pos) IF pos<>zm.current_file_pos THEN zm.send_successful:=TRUE @@ -2146,7 +2142,7 @@ PROC zmodem_send_from(zm: PTR TO zmodem_t, fp, pos,sent: PTR TO LONG) */ WHILE(zmodem_data_waiting(zm, IF zm.consecutive_errors THEN 1 ELSE 0) AND (is_cancelled(zm)=FALSE) AND (is_connected(zm))) - lprintf(zm,ZM_LOG_DEBUG,'Back-channel traffic detected:') + lprintf(zm,LOG_DEBUG,'Back-channel traffic detected:') IF((c:=zmodem_recv_raw(zm)))<0 THEN RETURN c IF(c = ZPAD) @@ -2159,12 +2155,12 @@ PROC zmodem_send_from(zm: PTR TO zmodem_t, fp, pos,sent: PTR TO LONG) rx_type:=zmodem_recv_header(zm) chr(rx_type,tempstr) StringF(tempstr2,'Received back-channel data: \s', tempstr) - lprintf(zm,ZM_LOG_DEBUG,tempstr2) + lprintf(zm,LOG_DEBUG,tempstr2) IF(rx_type >= 0) THEN RETURN rx_type ELSE chr(c,tempstr) StringF(tempstr2,'Received: \s',tempstr) - lprintf(zm,ZM_LOG_DEBUG,tempstr2) + lprintf(zm,LOG_DEBUG,tempstr2) ENDIF ENDWHILE @@ -2179,7 +2175,7 @@ PROC zmodem_send_from(zm: PTR TO zmodem_t, fp, pos,sent: PTR TO LONG) ENDWHILE zm.new_file:=FALSE - ->lprintf(zm,ZM_LOG_DEBUG,'send_from: returning unexpectedly!') + ->lprintf(zm,LOG_DEBUG,'send_from: returning unexpectedly!') /* * end of file reached. @@ -2194,7 +2190,7 @@ EXPORT PROC zmodem_send_files(zm: PTR TO zmodem_t,sentptr: PTR TO LONG, timetake DEF sent zm.files_remaining:=zm.total_files - zm.bytes_remaining:=zm.total_bytes + CopyMem(zm.total_bytes,zm.bytes_remaining,8) timetaken[]:=0 @@ -2207,7 +2203,7 @@ EXPORT PROC zmodem_send_files(zm: PTR TO zmodem_t,sentptr: PTR TO LONG, timetake IF res=FALSE THEN RETURN res IF (zm.send_successful) AND (zm.file_skipped=FALSE) - doDownloadCompleted(zm,fname,sent) + download_completed(zm,fname,zm.current_file_size,sent) ENDIF init:=FALSE @@ -2216,9 +2212,9 @@ EXPORT PROC zmodem_send_files(zm: PTR TO zmodem_t,sentptr: PTR TO LONG, timetake res:=FALSE IF p<>NIL THEN res:=p(fname) zm.files_remaining:=zm.files_remaining-1 - zm.bytes_remaining:=zm.bytes_remaining-sent + subBCD(zm.bytes_remaining,sent) IF zm.files_remaining<0 THEN zm.files_remaining:=0 - IF zm.bytes_remaining<0 THEN zm.bytes_remaining:=0 + IF zm.bytes_remaining[0]=$99 THEN convertToBCD(0,zm.bytes_remaining) IF sentptr<>NIL THEN sentptr[]:=sentptr[]+sent ENDIF UNTIL res=FALSE @@ -2254,7 +2250,7 @@ PROC zmodem_send_file(zm: PTR TO zmodem_t, fname: PTR TO CHAR, request_init,sent fp:=doOpen(zm,fname,MODE_OLDFILE) IF fp=NIL StringF(tempstr,'Error opening file \s',fname) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) RETURN FALSE ENDIF @@ -2273,22 +2269,22 @@ PROC zmodem_send_file(zm: PTR TO zmodem_t, fname: PTR TO CHAR, request_init,sent zm.file_skipped:=FALSE zm.send_successful:=FALSE - IF(zm.no_streaming) THEN lprintf(zm,ZM_LOG_WARNING,'Streaming disabled') + IF(zm.no_streaming) THEN lprintf(zm,LOG_WARN,'Streaming disabled') IF(request_init) zm.errors:=0 WHILE (zm.errors<=zm.max_errors) AND (is_cancelled(zm)=FALSE) AND (is_connected(zm)) IF(zm.errors) StringF(tempstr,'Sending ZRQINIT (\d of \d)',zm.errors+1,zm.max_errors+1) - lprintf(zm,ZM_LOG_NOTICE,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ELSE - lprintf(zm,ZM_LOG_INFO,'Sending ZRQINIT') + lprintf(zm,LOG_DEBUG,'Sending ZRQINIT') ENDIF i:=zmodem_get_zrinit(zm) EXIT i = ZRINIT frame_desc(i,tempstr) StringF(tempstr2,'send_file: received \s instead of ZRINIT',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) zm.errors:=zm.errors+1 ENDWHILE IF((zm.errors>=zm.max_errors) OR (is_cancelled(zm)) OR (is_connected(zm))=FALSE) @@ -2296,7 +2292,7 @@ PROC zmodem_send_file(zm: PTR TO zmodem_t, fname: PTR TO CHAR, request_init,sent RETURN FALSE ENDIF ENDIF - lprintf(zm,ZM_LOG_INFO,'Sending ZRQINIT done') + lprintf(zm,LOG_DEBUG,'Sending ZRQINIT done') zm.current_file_size:=getFileSize(zm,fp) strcopy(zm.current_file_name,fname) @@ -2318,13 +2314,13 @@ PROC zmodem_send_file(zm: PTR TO zmodem_t, fname: PTR TO CHAR, request_init,sent IF(zm.management_protect) zfile_frame[ZF1]:=ZF1_ZMPROT - lprintf(zm,ZM_LOG_DEBUG,'send_file: protecting destination') + lprintf(zm,LOG_DEBUG,'send_file: protecting destination') ELSEIF(zm.management_clobber) zfile_frame[ZF1]:=ZF1_ZMCLOB - lprintf(zm,ZM_LOG_DEBUG,'send_file: overwriting destination') + lprintf(zm,LOG_DEBUG,'send_file: overwriting destination') ELSEIF(zm.management_newer) zfile_frame[ZF1]:=ZF1_ZMNEW - lprintf(zm,ZM_LOG_DEBUG,'send_file: overwriting destination if newer') + lprintf(zm,LOG_DEBUG,'send_file: overwriting destination if newer') ELSE zfile_frame[ZF1]:=ZF1_ZMCRC ENDIF @@ -2358,11 +2354,13 @@ PROC zmodem_send_file(zm: PTR TO zmodem_t, fname: PTR TO CHAR, request_init,sent p:=p+StrLen(p) + 1 - StringF(tempstr,'\d \d 0 0 \d \d 0', + formatBCD(zm.bytes_remaining,tempstr2) + + StringF(tempstr,'\d \d 0 0 \d \s 0', zm.current_file_size, /* use for estimating only, could be zero! */ 0, ->(uintmax_t)s.st_mtime zm.files_remaining, - zm.bytes_remaining) + tempstr2) strcopy(p,tempstr,-1) p:=p+StrLen(p) + 1 @@ -2381,17 +2379,17 @@ zsendcont1: */ StringF(tempstr,'Sending ZFILE frame: ''\s''',zm.tx_data_subpacket+StrLen(zm.tx_data_subpacket)+1) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) IF((i:=zmodem_send_bin_header(zm,zfile_frame)))<>0 StringF(tempstr,'zmodem_send_bin_header returned \d',i) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) JUMP zsendcont1 ENDIF IF((i:=zmodem_send_data_subpkt(zm,ZCRCW,zm.tx_data_subpacket,p - zm.tx_data_subpacket)))<>0 StringF(tempstr,'zmodem_send_data_subpkt returned \d',i) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) JUMP zsendcont1 ENDIF /* @@ -2414,15 +2412,15 @@ zsendignore: ->if 0 ->StringF(tempstr,'type : \d',type) - ->lprintf(zm,ZM_LOG_INFO,tempstr) + ->lprintf(zm,LOG_DEBUG,tempstr) ->#endif IF(type = ZCRC) IF(zm.crc_request=0) - lprintf(zm,ZM_LOG_NOTICE,'Receiver requested CRC of entire file') + lprintf(zm,LOG_DEBUG,'Receiver requested CRC of entire file') ELSE StringF(tempstr,'Receiver requested CRC of first \d bytes',zm.crc_request) - lprintf(zm,ZM_LOG_NOTICE,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ENDIF zmodem_send_pos_header(zm,ZCRC,fcrc32(zm,fp,zm.crc_request),TRUE) type:=zmodem_recv_header(zm) @@ -2430,13 +2428,13 @@ zsendignore: IF(type = ZSKIP) zm.file_skipped:=TRUE - lprintf(zm,ZM_LOG_WARNING,'File skipped by receiver') + lprintf(zm,LOG_WARN,'File skipped by receiver') doClose(zm,fp) RETURN TRUE ENDIF IF (type=ZRINIT) - lprintf(zm,ZM_LOG_WARNING,'ignoring duplicate ZRINIT') + lprintf(zm,LOG_WARN,'ignoring duplicate ZRINIT') JUMP zsendignore ENDIF @@ -2459,7 +2457,7 @@ zsendignore: zm.consecutive_errors:=0 StringF(tempstr,'Sending \s from offset \d', fname, pos) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) zm.new_file:=TRUE loop:=TRUE @@ -2487,7 +2485,7 @@ zsendcont2: IF(type = ZSKIP) zm.file_skipped:=TRUE StringF(tempstr,'File skipped by receiver at offset: \d', pos + sent_bytes) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) /* ZOC sends a ZRINIT after mid-file ZSKIP, so consume the ZRINIT here */ zmodem_recv_header(zm) doClose(zm,fp) @@ -2510,7 +2508,7 @@ zsendcont2: chr(type,tempstr) StringF(tempstr,'Received \s at offset: \d', tempstr, zm.current_file_pos) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) IF((zm.block_size = zm.max_block_size) AND (zm.max_block_size > ZBLOCKLEN)) THEN zm.max_block_size:=Div(zm.max_block_size,2) @@ -2527,7 +2525,7 @@ zsendcont2: chr(type,tempstr) StringF(tempstr2,'Transfer failed on receipt of: \s', tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) END zfile_frame[5] doClose(zm,fp) ENDPROC FALSE @@ -2561,7 +2559,7 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte kbytes:=Shr(bytes,10) IF(kbytes<1) THEN kbytes:=0 StringF(tempstr,'Downloading \s \d KBytes) via Zmodem', zm.current_file_name, kbytes) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) REPEAT /* try */ skip:=TRUE @@ -2570,10 +2568,10 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte IF fpath[StrLen(fpath)-1]<>":" THEN StrAdd(fpath,'/') StringF(fpath,'\s\s',download_dir,zm.current_file_name) StringF(tempstr,'fpath=\s',fpath) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) IF(dupe_check(zm,fpath)) - lprintf(zm,ZM_LOG_DEBUG,'dupe check triggered') + lprintf(zm,LOG_DEBUG,'dupe check triggered') brk:=TRUE JUMP zreccont1 ENDIF @@ -2581,10 +2579,10 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte IF(fexist(fpath)) l:=flength(fpath) StringF(tempstr,'\s already exists (\d bytes)',fpath,l) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) IF(l>=bytes) StringF(tempstr,'Local file size \d >= remote file size \d',l,bytes) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) p:=zm.zm_duplicate_filename IF(p=NIL) brk:=TRUE @@ -2602,37 +2600,37 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte ENDIF IF((fp:=doOpen(zm,fpath,MODE_OLDFILE)))=NIL StringF(tempstr,'Error \d opening \s', IoErr(), fpath) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) brk:=TRUE JUMP zreccont1 ENDIF ->setvbuf(fp,NULL,_IOFBF,$10000) StringF(tempstr,'Requesting CRC of remote file: \s', zm.current_file_name) - lprintf(zm,ZM_LOG_NOTICE,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) IF(zmodem_request_crc(zm, l))=FALSE doClose(zm,fp) - lprintf(zm,ZM_LOG_ERR,'Failed to request CRC of remote file') + lprintf(zm,LOG_ERROR,'Failed to request CRC of remote file') brk:=TRUE JUMP zreccont1 ENDIF StringF(tempstr,'Calculating CRC of: \s', fpath) - lprintf(zm,ZM_LOG_NOTICE,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) crc:=fcrc32(zm,fp,l) /* Warning: 4GB limit! */ doClose(zm,fp) StringF(tempstr,'CRC of \s (\d bytes): \h[8]',fpath, l, crc) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) StringF(tempstr,'Waiting for CRC of remote file: \s', zm.current_file_name) - lprintf(zm,ZM_LOG_NOTICE,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) IF(zmodem_recv_crc(zm,{rcrc}))=FALSE - lprintf(zm,ZM_LOG_ERR,'Failed to get CRC of remote file') + lprintf(zm,LOG_ERROR,'Failed to get CRC of remote file') ->brk:=TRUE ->JUMP zreccont1 rcrc:=crc ENDIF IF(crc<>rcrc) StringF(tempstr,'Remote file has different CRC value: \h[8]', rcrc) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) p:=zm.zm_duplicate_filename IF(p) IF(p()) @@ -2644,12 +2642,12 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte JUMP zreccont1 ENDIF IF(l=bytes) - lprintf(zm,ZM_LOG_INFO,'CRC, length, and filename match.') + lprintf(zm,LOG_DEBUG,'CRC, length, and filename match.') brk:=TRUE JUMP zreccont1 ENDIF StringF(tempstr,'Resuming download of \s',fpath) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ENDIF t1,t2:=getZmSystemTime() @@ -2658,7 +2656,7 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte IF((fp:=doOpen(zm,fpath,MODE_READWRITE)))=NIL StringF(tempstr,'Error \d opening/creating/appending \s',IoErr(),fpath) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) brk:=TRUE JUMP zreccont1 ENDIF @@ -2668,7 +2666,7 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte doClose(zm,fp) StringF(tempstr,'Invalid file length \d: \s', start_bytes, fpath) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) brk:=TRUE JUMP zreccont1 ENDIF @@ -2687,15 +2685,15 @@ EXPORT PROC zmodem_recv_files(zm: PTR TO zmodem_t, download_dir:PTR TO CHAR,byte IF(errors AND (l=0)) /* aborted/failed download */ IF(DeleteFile(fpath)) /* don't save 0-byte file */ StringF(tempstr,'Error \d removing \s',IoErr(),fpath) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) ELSE StringF(tempstr,'Deleted 0-byte file \s',fpath) - lprintf(zm,ZM_LOG_INFO,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ENDIF ELSE IF(lNIL) THEN bytes_received[]:=bytes_received[]+b upload_completed(zm,fpath,l) @@ -2723,7 +2721,7 @@ zreccont1: UNTIL (loop=FALSE) OR (brk=TRUE) /* finally */ IF(skip) - lprintf(zm,ZM_LOG_DEBUG,'Skipping file') + lprintf(zm,LOG_DEBUG,'Skipping file') zmodem_send_zskip(zm) ENDIF zm.current_file_num:=zm.current_file_num+1 @@ -2746,20 +2744,20 @@ PROC zmodem_recv_init(zm: PTR TO zmodem_t) DEF tempstr[255]:STRING DEF tempstr2[255]:STRING - ->lprintf(zm,ZM_LOG_DEBUG,'recv_init') + ->lprintf(zm,LOG_DEBUG,'recv_init') ->#if 0 -> while(is_connected(zm) && !is_cancelled(zm) && (ch=zm.recv_byte(zm,0))!=NOINP) --> lprintf(zm,ZM_LOG_DEBUG,"Throwing out received: %s",chr((uchar)ch)) +-> lprintf(zm,LOG_DEBUG,"Throwing out received: %s",chr((uchar)ch)) ->#endif errors:=0 WHILE ((errors<=zm.max_errors) AND (is_cancelled(zm)=FALSE) AND (is_connected(zm))) IF(errors) StringF(tempstr,'Sending ZRINIT (\d of \d)',errors+1, zm.max_errors+1) - lprintf(zm,ZM_LOG_NOTICE,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ELSE - lprintf(zm,ZM_LOG_INFO,'Sending ZRINIT') + lprintf(zm,LOG_DEBUG,'Sending ZRINIT') ENDIF zmodem_send_zrinit(zm) @@ -2774,7 +2772,7 @@ PROC zmodem_recv_init(zm: PTR TO zmodem_t) chr(type,tempstr) StringF(tempstr2,'recv_init: Received \s',tempstr) - lprintf(zm,ZM_LOG_DEBUG,tempstr2) + lprintf(zm,LOG_DEBUG,tempstr2) IF(type=ZFILE) zmodem_parse_zfile_subpacket(zm) @@ -2788,9 +2786,9 @@ PROC zmodem_recv_init(zm: PTR TO zmodem_t) frame_desc(type,tempstr) StringF(tempstr2,'recv_init: Received \s instead of ZFILE or ZFIN',tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) StringF(tempstr,'ZF0=\h[2] ZF1=\h[2] ZF2=\h[2] ZF3=\h[2]',zm.rxd_header[ZF0],zm.rxd_header[ZF1],zm.rxd_header[ZF2],zm.rxd_header[ZF3]) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) errors++ zmicont1: @@ -2813,7 +2811,7 @@ PROC zmodem_parse_zfile_subpacket(zm: PTR TO zmodem_t) zm.current_file_size:=0 zm.current_file_time:=0 zm.files_remaining:=0 - zm.bytes_remaining:=0 + convertToBCD(0,zm.bytes_remaining) /* i=sscanf((char*)zm.rx_data_subpacket+strlen((char*)zm.rx_data_subpacket)+1,"%"SCNd64" %lo %o %lo %u %"SCNd64 ,&zm.current_file_size /* file size (decimal) */ @@ -2837,20 +2835,20 @@ PROC zmodem_parse_zfile_subpacket(zm: PTR TO zmodem_t) zm.files_remaining:=tmp s:=s+r tmp,r:=Val(s) - zm.bytes_remaining:=tmp + convertToBCD(tmp,zm.bytes_remaining) zm.current_file_time:=tmptime StringF(tempstr,'Zmodem file (ZFILE) data (\d fields): \d',i, zm.rx_data_subpacket+StrLen(zm.rx_data_subpacket)+1) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) IF(zm.files_remaining)=FALSE THEN zm.files_remaining:=1 - IF(zm.bytes_remaining)=FALSE THEN zm.bytes_remaining:= zm.current_file_size + IF(convertFromBCD(zm.bytes_remaining)=0) THEN convertToBCD(zm.current_file_size,zm.bytes_remaining) IF(zm.total_files)=FALSE THEN zm.total_files:=zm.files_remaining - IF(zm.total_bytes)=FALSE THEN zm.total_bytes:=zm.bytes_remaining + IF(convertFromBCD(zm.total_bytes))=0 THEN CopyMem(zm.bytes_remaining,zm.total_bytes,8) ENDPROC /* @@ -2870,7 +2868,7 @@ PROC zmodem_recv_file_data(zm: PTR TO zmodem_t, fp, offset) IF(doSeek(zm,fp,offset,OFFSET_BEGINNING))<0 StringF(tempstr,'ERROR \d seeking to file offset \d',IoErr(), offset) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) zmodem_send_pos_header(zm, ZFERR, offset, /* Hex? */ TRUE) RETURN 1 /* errors */ ENDIF @@ -2895,7 +2893,7 @@ PROC zmodem_recv_file_data(zm: PTR TO zmodem_t, fp, offset) IF((zm.max_file_size<>0) AND (pos >= zm.max_file_size)) StringF(tempstr,'Specified maximum file size (\d bytes) reached at offset \d',zm.max_file_size, pos) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) zmodem_send_pos_header(zm, ZFERR, pos, /* Hex? */ TRUE) brk:=TRUE @@ -2911,12 +2909,12 @@ PROC zmodem_recv_file_data(zm: PTR TO zmodem_t, fp, offset) IF(type=ENDOFFRAME) StringF(tempstr,'Received complete frame at offset: \d', pos) - lprintf(zm,ZM_LOG_DEBUG,tempstr) + lprintf(zm,LOG_DEBUG,tempstr) ELSE IF((type>0) AND (zm.local_abort=FALSE)) chr(type,tempstr) StringF(tempstr2,'Received \s at offset: \d', tempstr, pos) - lprintf(zm,ZM_LOG_DEBUG,tempstr2) + lprintf(zm,LOG_DEBUG,tempstr2) ENDIF errors++ ENDIF @@ -2961,7 +2959,7 @@ PROC zmodem_recv_file_frame(zm: PTR TO zmodem_t, fp,pos:PTR TO LONG) IF(zm.rxd_header_pos=pos[]) THEN RETURN type StringF(tempstr,'Ignoring ZEOF as all bytes (\d) have not been received',zm.rxd_header_pos) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) JUMP recframecont ELSEIF (type=ZFIN) OR (type=TIMEOUT) RETURN type @@ -2972,31 +2970,31 @@ PROC zmodem_recv_file_frame(zm: PTR TO zmodem_t, fp,pos:PTR TO LONG) frame_desc(type,tempstr) StringF(tempstr2,'Received \s instead of ZDATA frame', tempstr) - lprintf(zm,ZM_LOG_WARNING,tempstr2) + lprintf(zm,LOG_WARN,tempstr2) recframecont: attempt++ ENDLOOP - lprintf(zm,ZM_LOG_WARNING,'received ZDATA frame') + lprintf(zm,LOG_DEBUG,'received ZDATA frame') IF(zm.rxd_header_pos<>pos[]) StringF(tempstr,'Received wrong ZDATA frame (\d vs \d)"',zm.rxd_header_pos, pos[]) - lprintf(zm,ZM_LOG_WARNING,tempstr) + lprintf(zm,LOG_WARN,tempstr) RETURN FALSE ENDIF REPEAT - ->lprintf(zm,ZM_LOG_DEBUG,'recv_file_frame zmodem_recv_data') + ->lprintf(zm,LOG_DEBUG,'recv_file_frame zmodem_recv_data') type:=zmodem_recv_data(zm,zm.rx_data_subpacket,RXSUBPACKETSIZE,{n},TRUE) - ->lprintf(zm,ZM_LOG_DEBUG,'recv_file_frame zmodem_recv_data complete') + ->lprintf(zm,LOG_DEBUG,'recv_file_frame zmodem_recv_data complete') /* fprintf(stderr,"packet len %d type %d\n",n,type) */ IF ((type = ENDOFFRAME) OR (type = FRAMEOK)) IF(doWrite(zm,fp,zm.rx_data_subpacket,n)<>n) StringF(tempstr,'ERROR \d writing \d bytes at file offset \d',IoErr(), n,pos[]) - lprintf(zm,ZM_LOG_ERR,tempstr) + lprintf(zm,LOG_ERROR,tempstr) zmodem_send_pos_header(zm, ZFERR, pos[], /* Hex? */ TRUE) RETURN FALSE ENDIF @@ -3011,7 +3009,7 @@ recframecont: IF(is_cancelled(zm)) THEN RETURN ZCAN UNTIL type<>FRAMEOK - lprintf(zm,ZM_LOG_DEBUG,'recv_file_frame complete') + lprintf(zm,LOG_DEBUG,'recv_file_frame complete') ENDPROC type EXPORT PROC zmodem_init(zm: PTR TO zmodem_t, cbdata: PTR TO CHAR, @@ -3088,21 +3086,13 @@ EXPORT PROC zmodem_cleanup(zm: PTR TO zmodem_t) Dispose(zm.sendBuffer) ENDPROC -PROC doDownloadCompleted(zm:PTR TO zmodem_t,fname,size) - DEF p - p:=zm.zm_download_completed - IF p<>NIL - RETURN p(size) - ENDIF -ENDPROC - PROC doOpen(zm:PTR TO zmodem_t,fname,mode) DEF p p:=zm.zm_fopen IF p<>NIL RETURN p(fname,mode) ENDIF - lprintf(zm,ZM_LOG_WARNING,'zm_fopen not set, defaulting to dos library Open') + lprintf(zm,LOG_WARN,'zm_fopen not set, defaulting to dos library Open') ENDPROC Open(fname,mode) PROC doClose(zm:PTR TO zmodem_t,fhandle) @@ -3111,7 +3101,7 @@ PROC doClose(zm:PTR TO zmodem_t,fhandle) IF p<>NIL RETURN p(fhandle) ENDIF - lprintf(zm,ZM_LOG_WARNING,'zm_fclose not set, defaulting to dos library Close') + lprintf(zm,LOG_WARN,'zm_fclose not set, defaulting to dos library Close') ENDPROC Close(fhandle) PROC doSeek(zm:PTR TO zmodem_t,fhandle,pos,origin) @@ -3120,7 +3110,7 @@ PROC doSeek(zm:PTR TO zmodem_t,fhandle,pos,origin) IF p<>NIL RETURN p(fhandle,pos,origin) ENDIF - lprintf(zm,ZM_LOG_WARNING,'zm_fseek not set, defaulting to dos library Seek') + lprintf(zm,LOG_WARN,'zm_fseek not set, defaulting to dos library Seek') ENDPROC Seek(fhandle,pos,origin) PROC doRead(zm:PTR TO zmodem_t,fhandle,buffer,length) @@ -3129,7 +3119,7 @@ PROC doRead(zm:PTR TO zmodem_t,fhandle,buffer,length) IF p<>NIL RETURN p(fhandle,buffer,length) ENDIF - ->lprintf(zm,ZM_LOG_WARNING,'zm_fread not set, defaulting to dos library FRead') + ->lprintf(zm,LOG_WARN,'zm_fread not set, defaulting to dos library FRead') ENDPROC Fread(fhandle,buffer,1,length) PROC doWrite(zm:PTR TO zmodem_t,fhandle,buffer,length) @@ -3138,7 +3128,7 @@ PROC doWrite(zm:PTR TO zmodem_t,fhandle,buffer,length) IF p<>NIL RETURN p(fhandle,buffer,length) ENDIF - ->lprintf(zm,ZM_LOG_WARNING,'zm_fwrite not set, defaulting to dos library FWrite') + ->lprintf(zm,LOG_WARN,'zm_fwrite not set, defaulting to dos library FWrite') ENDPROC Fwrite(fhandle,buffer,1,length) crc16tbl: INT $0000, $1021, $2042, $3063, $4084, $50A5, $60C6, $70E7, From e7027f254642aeb5d7190976895b2bef9a34b230 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 4 Apr 2023 14:43:40 +0100 Subject: [PATCH 03/47] 1. record users last login IP 2. allow user logons to be limited by an ip mask 3. Use built in filesize function instead of creating our own 4. Improve file list scanning to strip ansi sequences 5. change log line for ftp downloads to match zmodem downloads 6. New user questions date/time format inconsistent with other files 7. Temporary new user questions file was not being cleared down 8. UDlog was not recording the user details correctly --- MiscFuncs.e | 46 +++++++++++++++----------- axobjects.e | 4 ++- express.e | 95 ++++++++++++++++++++++++++++++++++++----------------- ftpd.e | 8 ++--- icon2cfg.e | 2 +- tooltypes.e | 2 +- 6 files changed, 100 insertions(+), 57 deletions(-) diff --git a/MiscFuncs.e b/MiscFuncs.e index 36adeb3..0796292 100644 --- a/MiscFuncs.e +++ b/MiscFuncs.e @@ -24,25 +24,6 @@ EXPORT PROC setFDS(fds:PTR TO LONG,socketVal) fds[n]:=fds[n] OR (Shl(1,socketVal AND 31)) ENDPROC -EXPORT PROC getFileSize(s: PTR TO CHAR) -/* returns the file size of a given file or 8192 if an error occured */ - DEF fBlock: fileinfoblock - DEF fLock - DEF fsize=8192 - - IF((fLock:=Lock(s,ACCESS_READ)))=NIL - RETURN 8192 - ENDIF - - IF((fBlock:=AllocDosObject(DOS_FIB,NIL)))=NIL - UnLock(fLock) - RETURN 8192 - ENDIF - IF(Examine(fLock,fBlock)) THEN fsize:=fBlock.size - UnLock(fLock) - FreeDosObject(DOS_FIB,fBlock) -ENDPROC fsize - EXPORT PROC fileExists(filename) /* checks to see if a file exists and returns TRUE OR FALSE */ DEF lh @@ -288,7 +269,11 @@ EXPORT PROC formatUnsignedLong(val,outStr) RawDoFmt('%lu',{val},{asmputchar},outputTxt) StrCopy(outStr,outputTxt) -EXPORT ENDPROC +ENDPROC + +EXPORT PROC formatIP(val,outStr) + StringF(outStr,'\d.\d.\d.\d',Shr(val,24) AND $FF,Shr(val,16) AND $FF,Shr(val,8) AND $FF,val AND $FF) +ENDPROC EXPORT PROC formatLongDate(cDateVal,outDateStr) DEF d : PTR TO datestamp @@ -647,6 +632,27 @@ EXPORT PROC parsePatternNoCase2(source:PTR TO CHAR,dest:PTR TO CHAR, len) DisposeLink(s) ENDPROC r +EXPORT PROC dirLineNewFile(s:PTR TO CHAR) + DEF str,res,ch + + str:=AstrClone(s) + stripAnsi2(str) + ch:=str[0] + res:=(ch<>0) AND (ch<>32) AND (ch<>"\n") + DisposeLink(str) +ENDPROC res + +EXPORT PROC stripAnsi2(s:PTR TO CHAR) + DEF ansi:ansi + DEF newStr + + stripAnsi(0,0,1,0,ansi) + newStr:=String(StrLen(s)) + stripAnsi(s,newStr,0,0,ansi) + StrCopy(s,newStr) + DisposeLink(newStr) +ENDPROC + EXPORT PROC stripAnsi(s: PTR TO CHAR, d: PTR TO CHAR, resetit, strip, ansi:PTR TO ansi) DEF i,j,k,p,c IF resetit diff --git a/axobjects.e b/axobjects.e index 9127521..289577e 100644 --- a/axobjects.e +++ b/axobjects.e @@ -94,7 +94,9 @@ EXPORT OBJECT userMisc accountLocked:CHAR invalidAttempts:CHAR pwdLastUpdated:LONG - unused[94]:ARRAY OF CHAR + lastIP:LONG + ipMask:LONG + unused[86]:ARRAY OF CHAR ENDOBJECT EXPORT OBJECT tempAccess diff --git a/express.e b/express.e index e493fc0..4adb129 100644 --- a/express.e +++ b/express.e @@ -152,7 +152,7 @@ DEF ulTTTM=0 DEF dlTTTM=0 DEF dTBT[8]:ARRAY OF CHAR DEF uTBT[8]:ARRAY OF CHAR -DEF beenUDd=0 +DEF beenUDd=FALSE DEF lcFileXfr=0 DEF recFileNames:PTR TO stringlist DEF skipdFiles:PTR TO stringlist @@ -2489,7 +2489,7 @@ PROC loadTranslator(translator:PTR TO translator,fileName) DEF tempstr2[255]:STRING DEF tempstr3[255]:STRING - fsize:=getFileSize(fileName) + fsize:=FileLength(fileName) translator.translationText:=New(fsize+4) ->allocate some memory, two extra bytes for ending colon and space and some in case there is no newline workMem:=New(fsize+2) ->allocate some memory (two extra bytes in case there is no newline at the end of the file) fh:=Open(fileName,MODE_OLDFILE) @@ -4302,7 +4302,6 @@ PROC runDoor(cmd,type,command,tooltype,params,resident,doorTrap,privcmd,pri=0,st WHILE(msg:=GetMsg(mp)) msgcmd:=msg.command - stripAnsi(msg.string,tempstring,0,0,ansi) StringF(tempstring,'msg request: \d',msgcmd) debugLog(LOG_DEBUG,tempstring) @@ -7980,6 +7979,7 @@ PROC processLoggingOff() pagedFlag:=FALSE chatFlag:=FALSE blockOLM:=FALSE + beenUDd:=FALSE IF(sopt.toggles[TOGGLES_QUIETSTART]) quietFlag:=TRUE ELSE @@ -12306,7 +12306,7 @@ PROC flagFrom(s: PTR TO CHAR) StringF(tempStr,'\sdir\d',currentConfDir,maxDirs) IF(fp:=Open(tempStr,MODE_OLDFILE))<>0 WHILE(((ReadStr(fp,tempStr)<>-1) OR (StrLen(tempStr)>0)) AND (stat<>1)) - IF(StrLen(tempStr)>0) AND (tempStr[0]<>" ") + IF(dirLineNewFile(tempStr)) i:=0 WHILE((i" ")) tempStr2[i]:=tempStr[i] @@ -12791,7 +12791,8 @@ PROC statPrint(s: PTR TO CHAR) IF(dStatBar AND (statWriteIO<>NIL)) IF(bitPlanes<3) - stripAnsi(s,str,0,0,ansi) + StrCopy(str,s) + stripAnsi2(str) statWriteIO.data:=str statWriteIO.length:=-1 statWriteIO.command:=CMD_WRITE @@ -14885,7 +14886,7 @@ PROC ftpDownloadFileStart(fileName:PTR TO CHAR,filelen,resume) zModemInfo.freeDFlag:=FALSE AstrCopy(zModemInfo.fileName,fn,255) ENDIF - + zModemInfo.filesize:=filelen zModemInfo.resumePos:=resume zModemInfo.transPos:=0 @@ -14927,7 +14928,7 @@ PROC ftpDownloadFileEnd(fileName:PTR TO CHAR, result) IF ftpConn dlTTTM:=Div(dlTTTM,50) IF result - StringF(tempStr,'\t 1 file(s), \dk bytes, \d minutes \d seconds \d cps, N/A % efficiency.',Shr(zModemInfo.filesize-zModemInfo.resumePos,10) AND $003fffff,Div(dlTTTM,60),Mod(dlTTTM,60),tTCPS) + StringF(tempStr,'\t 1 files, \dk bytes, \d minutes \d seconds \d cps, N/A % efficiency.',Shr(zModemInfo.filesize-zModemInfo.resumePos,10) AND $003fffff,Div(dlTTTM,60),Mod(dlTTTM,60),tTCPS) callersLog(tempStr) udLog(tempStr) ELSE @@ -15792,6 +15793,7 @@ PROC displayUserToCallersLog(udonly) IF(udonly=FALSE) loggedOnUser.timesCalled:=loggedOnUser.timesCalled+1 callersLog(tempStr) + saveIPAddr() IF(logonType>=LOGON_TYPE_REMOTE) AND (checkToolTypeExists(TOOLTYPE_NODE,node,'LOG_HOST')) StringF(tempStr,'\tTelnet login address: \s (\s)',hostName,hostIP) callersLog(tempStr) @@ -15802,8 +15804,30 @@ PROC displayUserToCallersLog(udonly) ENDPROC -PROC isascii(n) -ENDPROC n<=127 +PROC saveIPAddr() + DEF v[5]:STRING + DEF i,v2, ip,p, p2 + p:=0 + ip:=0 + FOR i:=0 TO 3 + IF p>=0 + p2:=InStr(hostIP,'.',p) + v2:=0 + IF p2>=0 + StrCopy(v,hostIP+p,p2-p) + p:=p2+1 + ELSE + StrCopy(v,hostIP+p) + p:=StrLen(hostIP) + ENDIF + v2:=Val(v) + ip:=Shl(ip,8) OR v2 + ENDIF + ENDFOR + loggedOnUserMisc.lastIP:=ip +ENDPROC + +PROC isascii(n) IS n<=127 ->gets the actual name of a file (eg. you pass it a filename and it finds the correct case for it, so you can preserve the case) PROC getFileName(s: PTR TO CHAR) @@ -15869,7 +15893,7 @@ PROC fileCopy(from,to) DEF tempstr[255]:STRING ->if(Rename(from,to)) return(2); - buf,bufsize:=dynAllocate(getFileSize(from)+8192) + buf,bufsize:=dynAllocate(FileLength(from)+8192) IF(buf<>NIL) /* got a buffer full of mem */ IF(fhs:=Open(to,MODE_OLDFILE)) @@ -17213,7 +17237,7 @@ PROC scanHoldDesc() lcFileXfr:=TRUE aePuts('Preparing Lost Carrier File(s) for File Description(s)\b\n\b\n') WHILE((ReadStr(fi,string)<>-1) OR (StrLen(string)>0)) - IF(string[0]<>" ") + IF(dirLineNewFile(string)) IF ((p:=InStr(string,' '))>=0) THEN SetStr(string,p) StringF(text,'\sLCFILES/\s',currentConfDir,string) @@ -18768,9 +18792,9 @@ PROC uploadaFile(uLFType,cmd,attach,alreadyUploaded=FALSE) -> JOE tTEFF:=0 tTCPS:=0 - IF(beenUDd=0) + IF(beenUDd=FALSE) displayUserToCallersLog(1) - beenUDd:=1 + beenUDd:=TRUE ENDIF fileReceive(path,uLFType) /* path of upload */ @@ -19334,7 +19358,7 @@ PROC doBackgroundCheck(fname:PTR TO CHAR) Close(fh) ENDIF - fsize:=getFileSize(fileName) + fsize:=FileLength(fileName) status2:=RESULT_NOT_ALLOWED @@ -22301,7 +22325,7 @@ PROC conferenceMaintenance() getConfLocation(conf,confLoc) getMailStatFile(conf,msgBase) getConfDbFileName(conf,msgBase,tempstr) - size:=Div(getFileSize(tempstr),SIZEOF confBase) + size:=Div(FileLength(tempstr),SIZEOF confBase) REPEAT conCursorOff() @@ -22447,7 +22471,7 @@ PROC conferenceMaintenance() aePuts('Resizing, Please Standby') resizeConfDB(conf,msgBase,n) getConfDbFileName(conf,msgBase,tempstr) - size:=Div(getFileSize(tempstr),SIZEOF confBase) + size:=Div(FileLength(tempstr),SIZEOF confBase) ENDIF CASE "E" IF dirCacheEnabled @@ -22512,7 +22536,7 @@ PROC conferenceMaintenance() getMailStatFile(conf,msgBase) getConfLocation(conf,confLoc) getConfDbFileName(conf,msgBase,tempstr) - size:=Div(getFileSize(tempstr),SIZEOF confBase) + size:=Div(FileLength(tempstr),SIZEOF confBase) CASE "+" msgBase:=msgBase+1 IF msgBase>getConfMsgBaseCount(conf) @@ -22524,7 +22548,7 @@ PROC conferenceMaintenance() getMailStatFile(conf,msgBase) getConfLocation(conf,confLoc) getConfDbFileName(conf,msgBase,tempstr) - size:=Div(getFileSize(tempstr),SIZEOF confBase) + size:=Div(FileLength(tempstr),SIZEOF confBase) ENDSELECT aePuts(' ') @@ -22756,6 +22780,10 @@ PROC displayAccount(who:LONG, page, hoozer:PTR TO user, hoozer2: PTR TO userKeys StringF(tempStr,'Pwd Type ......: \s',tempStr2) aePuts(tempStr) + formatIP(hoozer3.lastIP,tempStr2) + StringF(tempStr,'Last IP Addr ..: \s',tempStr2) + aePuts(tempStr) + ENDIF displayAccountActions(who) @@ -22977,6 +23005,10 @@ PROC displayAccountInfo(who:LONG, page,hoozer:PTR TO user, hoozer2:PTR TO userKe StringF(tempStr,'\s',tempStr2) aePuts(tempStr) + formatIP(hoozer3.lastIP,tempStr2) + StringF(tempStr,'\l\s',tempStr2) + aePuts(tempStr) + ENDIF displayAccountActions(who) ENDPROC @@ -26534,7 +26566,7 @@ PROC maintenanceFileDelete(dirname:PTR TO CHAR, srchold, fname:PTR TO CHAR,match found:=0 currpos:=Seek(fh2,0,OFFSET_CURRENT) WHILE(Fgets(fh2,dirline,255)<>NIL) - IF(dirline[0]<>" ") + IF(dirLineNewFile(dirline)) StrCopy(compareFname,dirline,12) UpperStr(compareFname) IF(StrCmp(compareFname,padfname)) AND (currpos=matchposition) @@ -26733,7 +26765,7 @@ PROC maintenanceFileMove(dirname:PTR TO CHAR, srchold, fname:PTR TO CHAR,datestr found:=0 currpos:=Seek(fh2,0,OFFSET_CURRENT) WHILE(Fgets(fh2,dirline,255)<>NIL) - IF(dirline[0]<>" ") + IF(dirLineNewFile(dirline)) StrCopy(compareFname,dirline,12) UpperStr(compareFname) IF(StrCmp(compareFname,padfname)) AND (currpos=matchposition) @@ -26742,7 +26774,7 @@ PROC maintenanceFileMove(dirname:PTR TO CHAR, srchold, fname:PTR TO CHAR,datestr brk:=FALSE ->we've found our file in the source dir, scan the dest dir for the correct position to put it WHILE(Fgets(fh4,dirline2,255)<>NIL) - IF(dirline2[0]<>" ") + IF(dirLineNewFile(dirline2)) StrCopy(tempstr,dirline2) tempstr[13]:=" " parseParams(tempstr) @@ -26984,7 +27016,7 @@ PROC maintenanceFileSearch(holddir,fname:PTR TO CHAR,searchList: PTR TO stringli RETURN RESULT_FAILURE,0,0 ENDIF ENDIF - IF(StrLen(image)>0) AND (image[0]<>" ") + IF(dirLineNewFile(image)) StrCopy(dirfname,image,12) StrCopy(tempStr,image,12) i:=0 @@ -27030,7 +27062,7 @@ PROC maintenanceFileSearch(holddir,fname:PTR TO CHAR,searchList: PTR TO stringli aePuts(image) aePuts('\b\n') prev:=Seek(fi,0,OFFSET_CURRENT) - WHILE(Fgets(fi,image,252)<>NIL) AND (image[0]=" ") AND (countNIL) AND (dirLineNewFile(image)=FALSE) AND (count0) AND (image[0]<>" ") + IF (dirLineNewFile(image)) IF (x<100) current:=myzip+Shl(x,8)+1 ->ln(1,x) current[0]:=0 @@ -27493,7 +27525,7 @@ PROC myNewFiles(params) WHILE(Fgets(fp1,c,250)<>NIL) c[250]:=0 SetStr(c,StrLen(c)) - IF((c[0]=" ") OR (c[0]=0) OR(c[0]="\n")) THEN JUMP fgetnext + IF(dirLineNewFile(c)=FALSE) THEN JUMP fgetnext parseParams(c) IF(parsedParams.count()>0) THEN StrCopy(fn,parsedParams.item(0)) @@ -29865,9 +29897,10 @@ ENDPROC PROC doNewUserQuestions() DEF filename[200]:STRING, afilename[200]:STRING DEF ch,stat,lock - DEF c[200]:STRING,string[200]:STRING,datestr[20]:STRING + DEF c[200]:STRING,string[200]:STRING,datestr[20]:STRING,timestr[20]:STRING DEF fp2,fp1 DEF temp1[255]:STRING + DEF calldate StringF(filename,'\sNode\d/Script\d',cmds.bbsLoc,node,onlineBaud) IF checkToolTypeExists(TOOLTYPE_NODE,node,'CENTRAL_ANSWERS') @@ -29884,13 +29917,15 @@ qAgain: StringF(string,'\sNode\d/TempAns',cmds.bbsLoc,node) - IF((fp1:=Open(string,MODE_READWRITE))=0) THEN RETURN RESULT_GOODBYE - Seek(fp1,0,OFFSET_END) + IF((fp1:=Open(string,MODE_NEWFILE))=0) THEN RETURN RESULT_GOODBYE + + calldate:=getSystemTime() + formatLongDate(calldate,datestr) + formatLongTime(calldate,timestr) - formatLongDateTime(getSystemTime(),datestr) fileWriteLn(fp1,'**************************************************************') - StringF(temp1,'\s [\d] \s (\s) \s',datestr,loggedOnUser.slotNumber,loggedOnUser.name,connectString,loggedOnUser.location) + StringF(temp1,'\s (\s) [\d] \s (\s) \s',datestr,timestr,loggedOnUser.slotNumber,loggedOnUser.name,connectString,loggedOnUser.location) fileWriteLn(fp1,temp1) Close(fp1) diff --git a/ftpd.e b/ftpd.e index 4909f14..e1de247 100644 --- a/ftpd.e +++ b/ftpd.e @@ -991,8 +991,8 @@ PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, IF(Fgets(fh,tempstr,255)<>NIL) AND (StrLen(tempstr)>0) tempstr[255]:=0 - SetStr(tempstr,StrLen(tempstr)) - IF (tempstr[0]<>32) AND (tempstr[0]<>0) AND (tempstr[0]<>"\n") + SetStr(tempstr,StrLen(tempstr)) + IF (dirLineNewFile(tempstr)) t:=TrimStr(tempstr+14) spPos:=InStr(t,' ') StrCopy(dtStr,TrimStr(t+spPos)) @@ -1013,7 +1013,7 @@ PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, found:=FALSE REPEAT IF StrLen(tempstr)>0 - IF (tempstr[0]<>32) AND (tempstr[0]<>0) AND (tempstr[0]<>"\n") + IF dirLineNewFile(tempstr) IF found=FALSE t:=TrimStr(tempstr+14) @@ -1656,7 +1656,7 @@ PROC cmdRetr(sb,ftp_c,data_s,data_c,filename:PTR TO CHAR,ftpData:PTR TO ftpData) fh:=0 flen:=0 IF StrLen(fn) - flen:=getFileSize(fn) + flen:=FileLength(fn) IF asynclib<>NIL writeLineEx(sb,ftp_c, '150 Opening BINARY connection with ASYNC\b\n') fh:=OpenAsync(fn,MODE_READ,32768) diff --git a/icon2cfg.e b/icon2cfg.e index bb471dc..942dd8a 100644 --- a/icon2cfg.e +++ b/icon2cfg.e @@ -95,7 +95,7 @@ PROC main() HANDLE ENDIF ENDIF - fileBuf:=New(getFileSize(fn2)+1) ->allow an extra char in case file does not end in LF + fileBuf:=New(FileLength(fn2)+1) ->allow an extra char in case file does not end in LF IF fileBuf<>NIL fh:=Open(sourceFile,MODE_OLDFILE) IF fh<>0 diff --git a/tooltypes.e b/tooltypes.e index 814c43f..1ca7aeb 100644 --- a/tooltypes.e +++ b/tooltypes.e @@ -268,7 +268,7 @@ EXPORT PROC getOrCreateCacheItem(fileName:PTR TO CHAR) do:=GetDefDiskObject(WBPROJECT) ENDIF IF do<>NIL - fileBuf:=New(getFileSize(fn2)+1) ->allow an extra char in case file does not end in LF + fileBuf:=New(FileLength(fn2)+1) ->allow an extra char in case file does not end in LF fh:=Open(fn2,MODE_OLDFILE) IF fh<>0 From 3683479e5d44e7be03285aec42a812163f410888 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 2 May 2023 14:00:20 +0100 Subject: [PATCH 04/47] Express: 1) correct memory leak with tags structures --- express.e | 60 ++++++++++++++++++++++++------------------------------- ftpd.e | 4 ++-- mailssl.e | 4 ++-- 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/express.e b/express.e index 4adb129..9e27d4d 100644 --- a/express.e +++ b/express.e @@ -404,14 +404,6 @@ RAISE ERR_BRKR IF CxBroker()=NIL, ERR_PORT IF CreateMsgPort()=NIL, ERR_ASL IF AllocAslRequest()=NIL -PROC countTags(tags:PTR TO LONG) - DEF n=0 - WHILE tags[n]<>TAG_DONE - n:=n+2 - ENDWHILE - n++ -ENDPROC - PROC calcEfficiency(cps,baud) DEF res IF cps>21474836 @@ -1639,7 +1631,7 @@ PROC asl(s: PTR TO CHAR,slines=NIL:PTR TO stringlist) HANDLE ENDIF EXCEPT DO IF fr THEN FreeAslRequest(fr) - IF tags THEN END tags[countTags(tags)] + IF tags THEN FastDisposeList(tags) IF aslbase THEN CloseLibrary(aslbase) SELECT exception CASE ERR_ASL @@ -3276,7 +3268,7 @@ PROC startProcess(exestring, stacksize, priority, async, doorTrap) filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,doorTrapFH,SYS_ASYNCH,async,NP_STACKSIZE,stacksize,NP_PRIORITY,priority,TAG_DONE] temp:=SystemTagList(exestring,filetags) - END filetags[countTags(filetags)] + FastDisposeList(filetags) IF (byteSignExtend(cmds.taskPri)<=priority) SetTaskPri(task,cmds.taskPri) @@ -6618,18 +6610,18 @@ PROC runExecuteOn(execOn:PTR TO CHAR) StringF(toolTypeText,'EXECUTE_ON_\s',execOn) IF (readToolType(TOOLTYPE_BBSCONFIG,0,toolTypeText,tempstr1)) - filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,0,SYS_ASYNCH,FALSE,TAG_DONE]:LONG + filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,0,SYS_ASYNCH,FALSE,TAG_DONE] processMci(tempstr1,tempstr2) SystemTagList(tempstr2,filetags) - END filetags[countTags(filetags)] + FastDisposeList(filetags) ENDIF StringF(toolTypeText,'EXECUTE_ASYNC_ON_\s',execOn) IF (readToolType(TOOLTYPE_BBSCONFIG,0,toolTypeText,tempstr1)) - filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,0,SYS_ASYNCH,TRUE,TAG_DONE]:LONG + filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,0,SYS_ASYNCH,TRUE,TAG_DONE] processMci(tempstr1,tempstr2) SystemTagList(tempstr2,filetags) - END filetags[countTags(filetags)] + FastDisposeList(filetags) ENDIF ENDPROC @@ -7047,7 +7039,7 @@ PROC toggleStatusDisplay() ENDIF statChatFlag() ENDIF - END tags[countTags(tags)] + FastDisposeList(tags) IF pubLock THEN UnlockPubScreen(NIL,pubLock) ENDIF ENDPROC @@ -9123,7 +9115,7 @@ PROC remoteShell() HANDLE StringF(temp,'newshell fifo:\s/rwkecs',fifoName) tags:=NEW [SYS_INPUT,0,SYS_OUTPUT,0,SYS_ASYNCH,1,TAG_DONE] SystemTagList(temp,tags) - END tags[countTags(tags)] + FastDisposeList(tags) pmask:=Shl(1,ioSink.sigbit) @@ -14638,7 +14630,7 @@ PROC updateZDisplay() DrawBevelBoxA(windowZmodem.rport,9,129,316,10,tags2) FreeVisualInfo(vi) - END tags2[countTags(tags2)] + FastDisposeList(tags2) CloseLibrary(gadtoolsbase) ENDIF @@ -16208,7 +16200,7 @@ PROC hydstatus(hyd:PTR TO hydra_t,xmit) DrawBevelBoxA(rport,9,129,276,10,tags2) FreeVisualInfo(vi) - END tags2[countTags(tags2)] + FastDisposeList(tags2) CloseLibrary(gadtoolsbase) ENDIF ENDPROC/*hydra_status()*/ @@ -16677,10 +16669,10 @@ PROC createBackgroundFileCheckThread() bgStack:=readToolTypeInt(TOOLTYPE_NODE,node,'BGFILECHECKSTACK') IF bgStack<=0 THEN bgStack:=20000 - tags:=NEW [NP_ENTRY,{backgroundFileCheckThread},NP_STACKSIZE,bgStack,TAG_DONE]:LONG + tags:=NEW [NP_ENTRY,{backgroundFileCheckThread},NP_STACKSIZE,bgStack,TAG_DONE] Forbid() proc:=CreateNewProc(tags) - END tags[countTags(tags)] + FastDisposeList(tags) IF proc<>NIL saveA4(proc.task,{threadtasksA4}) ELSE @@ -17698,7 +17690,7 @@ PROC batchasl(where: PTR TO CHAR) HANDLE ENDIF EXCEPT DO IF fr THEN FreeAslRequest(fr) - IF tags THEN END tags[countTags(tags)] + IF tags THEN FastDisposeList(tags) IF aslbase THEN CloseLibrary(aslbase) SELECT exception CASE ERR_ASL @@ -18330,11 +18322,11 @@ debugLog(LOG_ERROR,'debug10d2') StrAdd(options,checkFile) StringF(fileName,'\sOutPut_Of_Test',nodeWorkDir) IF((fi:=Open(fileName,MODE_NEWFILE)))<>0 - filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,fi,NP_STACKSIZE,stack,NP_PRIORITY,pri,TAG_DONE]:LONG + filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,fi,NP_STACKSIZE,stack,NP_PRIORITY,pri,TAG_DONE] debugLog(LOG_ERROR,'debug10d3') SystemTagList(options,filetags) debugLog(LOG_ERROR,'debug10d4') - END filetags[countTags(filetags)] + FastDisposeList(filetags) Close(fi) debugLog(LOG_ERROR,'debug10d5') @@ -18344,12 +18336,12 @@ debugLog(LOG_ERROR,'debug10d6') IF(readToolType(TOOLTYPE_FCHECK,temp,'SCRIPT',s)) StrAdd(s,' ') IF(fi:=Open('NIL:',MODE_NEWFILE))<>0 - filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,fi,NP_STACKSIZE,stack,NP_PRIORITY,pri,TAG_DONE]:LONG + filetags:=NEW [SYS_INPUT,0,SYS_OUTPUT,fi,NP_STACKSIZE,stack,NP_PRIORITY,pri,TAG_DONE] debugLog(LOG_ERROR,'debug10d7') StringF(options,'\s \s \s \d',s,checkFile,FilePart(checkFile),node) SystemTagList(options,filetags) debugLog(LOG_ERROR,'debug10d8') - END filetags[countTags(filetags)] + FastDisposeList(filetags) Close(fi) ENDIF ENDIF @@ -30242,7 +30234,7 @@ PROC openHydraStat() ENDIF hydraWindow1:=OpenWindowTagList(NIL,tags) - END tags[countTags(tags)] + FastDisposeList(tags) IF (hydraWindow1) AND (fontHandle<>NIL) THEN SetFont(hydraWindow1.rport,fontHandle) @@ -30282,7 +30274,7 @@ PROC openHydraStat() hydraWindow2:=OpenWindowTagList(NIL,tags) IF (hydraWindow2) AND (fontHandle<>NIL) THEN SetFont(hydraWindow2.rport,fontHandle) - END tags[countTags(tags)] + FastDisposeList(tags) IF pub tags:=NEW [WA_CLOSEGADGET,1, @@ -30320,7 +30312,7 @@ PROC openHydraStat() hydraWindow3:=OpenWindowTagList(NIL,tags) IF (hydraWindow3) AND (fontHandle<>NIL) THEN SetFont(hydraWindow3.rport,fontHandle) - END tags[countTags(tags)] + FastDisposeList(tags) initHydraStatCon() @@ -30443,11 +30435,11 @@ PROC openZmodemStat() DrawBevelBoxA(windowZmodem.rport,9,129,316,10,tags2) FreeVisualInfo(vi) - END tags2[countTags(tags2)] + FastDisposeList(tags2) CloseLibrary(gadtoolsbase) ENDIF ENDIF - END tags[countTags(tags)] + FastDisposeList(tags) ENDPROC @@ -30585,7 +30577,7 @@ PROC openExpressScreen() SA_COLORS,cols, TAG_DONE] screen:=OpenScreenTagList(NIL,opentags) - END opentags[countTags(opentags)] + FastDisposeList(opentags) END pens[pensize] END cols[colsize] @@ -30610,7 +30602,7 @@ PROC openExpressScreen() WA_IDCMP,IDCMP_CLOSEWINDOW, TAG_DONE] windowClose:=OpenWindowTagList(NIL,opentags) - END opentags[countTags(opentags)] + FastDisposeList(opentags) ENDIF IF windowClose=NIL THEN RETURN ERR_WINDOW @@ -30637,7 +30629,7 @@ PROC openExpressScreen() WA_FLAGS,WFLG_ACTIVATE, TAG_DONE] window:=OpenWindowTagList(NIL,opentags) - END opentags[countTags(opentags)] + FastDisposeList(opentags) IF (window) AND (fontHandle<>NIL) THEN SetFont(window.rport,fontHandle) ELSE opentags:=NEW [WA_BORDERLESS,1,WA_CUSTOMSCREEN,screen, @@ -30650,7 +30642,7 @@ PROC openExpressScreen() WA_FLAGS,WFLG_ACTIVATE, TAG_DONE] window:=OpenWindowTagList(NIL,opentags) - END opentags[countTags(opentags)] + FastDisposeList(opentags) ENDIF ENDIF diff --git a/ftpd.e b/ftpd.e index e1de247..00544ca 100644 --- a/ftpd.e +++ b/ftpd.e @@ -2046,7 +2046,7 @@ PROC createThread(num,node,sockid,ftpData:PTR TO ftpData) DEF name[255]:STRING StringF(name,'ftpThread\d-\d',node,num) - tags:=NEW [NP_ENTRY,{ftpThread},NP_NAME,name,NP_STACKSIZE,10000,0]:LONG + tags:=NEW [NP_ENTRY,{ftpThread},NP_NAME,name,NP_STACKSIZE,10000,0] ftpData.sockId:=sockid @@ -2054,7 +2054,7 @@ PROC createThread(num,node,sockid,ftpData:PTR TO ftpData) proc:=CreateNewProc(tags) saveA4(proc,ftpData,node) Permit() - END tags[7] + FastDisposeList(tags) ENDPROC EXPORT PROC ftpServerMode(ftpData:PTR TO ftpData, ftp_c,ftpHost:PTR TO CHAR,uploadPath:PTR TO CHAR,ftpDataPorts:PTR TO LONG,filenameCAPS) diff --git a/mailssl.e b/mailssl.e index 9c66c29..21db3cc 100644 --- a/mailssl.e +++ b/mailssl.e @@ -454,11 +454,11 @@ EXPORT PROC initssl(createctx) HANDLE tags:=NEW [AMISSL_ERRNOPTR,{sslerrno},AMISSL_SOCKETBASE,socketbase,0] IF (InitAmiSSLA(tags) <> 0) - END tags[5] + FastDisposeList(tags) WriteF('Couldn''t initialize AmiSSL!\n'); Raise(ERR_SSL) ENDIF - END tags[5] + FastDisposeList(tags) /* Basic intialization. Next few steps (up to SSL_new()) need * to be done only once per AmiSSL opener. From e748f8cdf521ff07e5979fdb31ef3dcc41809fca Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 6 Jun 2023 12:18:08 +0100 Subject: [PATCH 05/47] 1) Change default password encryption to legacy to allow downgrade capability 2) Remove very old debug code 3) Allow multiple sub directories for ftp 4) Update download directory caching to be used for ftp as well 5) Optimise ftp directory listing speed --- axenums.e | 2 +- express.e | 160 +++++++++++++++++++++------------ ftpd.e | 263 ++++++++++++++++++++++++++++++++++-------------------- sha256.e | 252 +++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 515 insertions(+), 162 deletions(-) diff --git a/axenums.e b/axenums.e index 25de8f3..68c1bf3 100644 --- a/axenums.e +++ b/axenums.e @@ -22,7 +22,7 @@ EXPORT ENUM LOGON_TYPE_LOGGED_OFF=0, LOGON_TYPE_SYSOP=1, LOGON_TYPE_LOCAL=2, LOG EXPORT ENUM RESULT_FAILURE=-1, RESULT_SUCCESS=0, RESULT_NOT_ALLOWED=1, RESULT_ABORT=-2, RESULT_TIMEOUT=-3, RESULT_NO_CARRIER=-4, RESULT_GOODBYE=-5, RESULT_SLEEP_LOGOFF=-6, RESULT_STANDARD_LOGOFF=-7, RESULT_CONNECT=-8, RESULT_NOT_TESTED=2, RESULT_LCFILES=9,RESULT_PRIVATE=10, RESULT_SIGNALLED=11, RESULT_NOT_FOUND=12 -EXPORT ENUM ERR_MEMORY,ERR_MEMORY2,ERR_MSGBASE,ERR_MEMORY3,ERR_FILELIST,ERR_NOFILES,ERR_FILEEXAMINE,ERR_WORKDIROPEN,ERR_LOCK,ERR_FREESPACE,ERR_SYMBOLS,ERR_FIB_MEMORY,ERR_NO_BULLS,ERR_NO_CONFFLAGS +EXPORT ENUM ERR_MEMORY,ERR_MEMORY2,ERR_MSGBASE,ERR_MEMORY3,ERR_FILELIST,ERR_NOFILES,ERR_FILEEXAMINE,ERR_WORKDIROPEN,ERR_LOCK,ERR_FREESPACE,ERR_SYMBOLS,ERR_FIB_MEMORY,ERR_NO_BULLS,ERR_NO_CONFFLAGS, ERR_NODEPARAM EXPORT ENUM MAIL_READ=1,MAIL_CREATE=2, MAIL_SCAN=3, MAIL_STATS=4, MAIL_SYSOP_COMMENT=6, MAIL_ZOOM=7 diff --git a/express.e b/express.e index 9e27d4d..303d85c 100644 --- a/express.e +++ b/express.e @@ -40,7 +40,7 @@ DEF serverin DEF singleNode=0: PTR TO singlePort DEF masterNode=0: PTR TO multiPort -DEF debug=FALSE + DEF consoleDebugLevel=LOG_NONE DEF debugLogLevel=LOG_ERROR DEF inputLogging=FALSE @@ -944,7 +944,7 @@ PROC setNewPassword(user:PTR TO user, userMisc:PTR TO userMisc, newpass:PTR TO C ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_10000') passType:=PWD_PBKDF2_10000 ELSE - passType:=PWD_PBKDF2_100 + passType:=PWD_LEGACY ENDIF userMisc.pwdType:=passType @@ -1559,7 +1559,7 @@ PROC getPass2(prompt: PTR TO CHAR,password:PTR TO CHAR,userPwd, max:LONG,outstr= ELSEIF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','PBKDF2_10000') passType:=PWD_PBKDF2_10000 ELSE - passType:=PWD_PBKDF2_100 + passType:=PWD_LEGACY ENDIF IF loggedOnUserMisc.pwdType<>passType @@ -7545,6 +7545,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) loggedOnUserMisc:=NEW loggedOnUserMisc loadAccount(1,loggedOnUser,loggedOnUserKeys,loggedOnUserMisc) masterLoadPointers(loggedOnUser) + setEnvStat(ENV_SYSOP) conferenceMaintenance() END loggedOnUser END loggedOnUserKeys @@ -12505,7 +12506,7 @@ PROC checkFIBForFileSize(fullPath:PTR TO CHAR, checkConfNum, fBlock:PTR TO filei ENDIF ENDPROC dp -PROC checkForFileSize(checkFilename:PTR TO CHAR, checkConfNum, tfsizeList:PTR TO stdlist, freeDFlagList:PTR TO stdlist, cfn:PTR TO stdlist, z) +PROC checkForFileSize(checkFilename:PTR TO CHAR, subDirs:PTR TO CHAR, checkConfNum, tfsizeList:PTR TO stdlist, freeDFlagList:PTR TO stdlist, cfn:PTR TO stdlist, z) DEF stat,pstat=1,i DEF fflag=0,wflag=0,doflag=0 @@ -12594,13 +12595,15 @@ jumpIn: IF(wflag=0) IF(sysopdl=0) StrCopy(final,path) + StrAdd(final,subDirs) + checkPathSlash(final) StrAdd(final,checkFilename) ELSE StrCopy(final,checkFilename) IF(findAssign(final)) THEN JUMP outst ENDIF StringF(ramDir,'RAM:DirCaches/Conf\dDir\d',checkConfNum,drivenum-1) - IF fileExists(ramDir) + IF (StrLen(subDirs)=0) AND (fileExists(ramDir)) ft:=Open(ramDir,MODE_OLDFILE) IF ft<>0 fLock:=NIL @@ -12629,7 +12632,7 @@ jumpIn: IF(doflag) IF fLock=NIL StringF(ramDir,'RAM:DirCaches/Conf\dDir\d',checkConfNum,drivenum-1) - IF fileExists(ramDir) + IF (StrLen(subDirs)=0) AND (fileExists(ramDir)) ft:=Open(ramDir,MODE_OLDFILE) ENDIF IF((fLock:=Lock(final,ACCESS_READ))=0) @@ -12657,6 +12660,7 @@ debugcount:=0 xit:=ExNext(fLock,fBlock)=0 ELSE xit:=(Fgets(ft,tempstr,255)=0) + IF (StrLen(tempstr)>18) AND (tempstr[8]=" ") AND (tempstr[17]=" ") THEN StrCopy(tempstr,tempstr+18) ENDIF EXIT xit @@ -12676,8 +12680,13 @@ gotit: IF(sysopdl) StrCopy(final,checkFilename) ELSE + + StrCopy(final,path) + StrAdd(final,subDirs) + checkPathSlash(final) + IF ft<>0 - StringF(final,'\s\s',path,tempstr) + StrAdd(final,tempstr) fLock2:=Lock(final,ACCESS_READ) IF fLock2 Examine(fLock2,fBlock) @@ -12686,7 +12695,7 @@ gotit: res:=FALSE ENDIF ELSE - StringF(final,'\s\s',path,fBlock.filename) + StrAdd(final,fBlock.filename) ENDIF ENDIF @@ -12827,42 +12836,6 @@ PROC regServer() DEF port:PTR TO mp DEF tempstr[255]:STRING - IF debug - cmds:=NEW cmds - AstrCopy(cmds.bbsLoc,'BBS:',41) - - loadAccount(1,tempUser,tempUserKeys,tempUserMisc) - - AstrCopy(cmds.bbsName,'somebbs',41) - - AstrCopy(cmds.sysopName,tempUser.name,31) - - StringF(mybbsLoc,'\s','someplace') - - sopt:=NEW sopt - - sopt.leftEdge:=0 - sopt.topEdge:=0 - sopt.width:=640 - sopt.height:=256 - sopt.bitPlanes:=3 - - readToolType(TOOLTYPE_NODE,node,'SCREENS',tempstr) - AstrCopy(sopt.nodeScreens,tempstr) - - sopt.statBar:=0 - - sopt.toggles[TOGGLES_RED1]:=FALSE - sopt.toggles[TOGGLES_MULTICOM]:=FALSE - sopt.iconify:=FALSE - - cmds.numConf:=4 - - cmds.openingBaud:=115200 - cmds.taskPri:=240 - RETURN - ENDIF - masterMsg.command:=SV_START WHILE((port:=FindPort('AE.Master'))=NIL) AND (SetSignal(0,SIGBREAKF_CTRL_C)=0) Delay(25) @@ -15153,12 +15126,12 @@ PROC ftpAuth(userName:PTR TO CHAR,password:PTR TO CHAR) IF StriCmp(userName,loggedOnUser.name,31)=FALSE THEN RETURN FALSE ENDPROC checkUserPassword(loggedOnUser,loggedOnUserMisc,password) -PROC ftpFindFile(filename:PTR TO CHAR,outFullFilename:PTR TO CHAR) +PROC ftpFindFile(filename:PTR TO CHAR,subdirs:PTR TO CHAR, outFullFilename:PTR TO CHAR) DEF fileList:PTR TO stdlist DEF fileItem:PTR TO flagFileItem fileList:=NEW fileList.stdlist(1) - checkForFileSize(filename,-1,NIL,NIL,fileList,0) + checkForFileSize(filename,subdirs,-1,NIL,NIL,fileList,0) IF fileList.count()>0 fileItem:=fileList.item(0) StrCopy(outFullFilename,fileItem.fileName) @@ -15755,7 +15728,7 @@ PROC checklist(lfnames: PTR TO stdlist, sizeList:PTR TO stdlist, freeDFlagList:P FOR i:=0 TO lfnames.count()-1 item:=lfnames.item(i) IF(StrLen(item.fileName)>0) - status:=checkForFileSize(item.fileName,item.confNum,sizeList,freeDFlagList,clrfinal,0) + status:=checkForFileSize(item.fileName,'',item.confNum,sizeList,freeDFlagList,clrfinal,0) IF((status=RESULT_SIGNALLED) OR (status=RESULT_PRIVATE)) THEN RETURN RESULT_SUCCESS ENDIF ENDFOR @@ -19911,7 +19884,7 @@ arestart: ENDFOR ENDIF - status:=checkForFileSize(tempStr,currentConf,tfsizes,freeDFlags,finalList,0) + status:=checkForFileSize(tempStr,'',currentConf,tfsizes,freeDFlags,finalList,0) IF((status=RESULT_FAILURE) OR (status=RESULT_SIGNALLED) OR (status=RESULT_PRIVATE)) Throw(ERR_EXCEPT,RESULT_SUCCESS) ENDIF @@ -22297,6 +22270,65 @@ PROC resizeConfDB(confnum,msgBaseNum,newSize) END cb2 ENDPROC +PROC makeFtpDirCache(confLoc:PTR TO CHAR, confnum, dirnum, dlpath:PTR TO CHAR, subdir:PTR TO CHAR) + DEF dirCache[255]:STRING + DEF fh + DEF lock + DEF f_info: PTR TO fileinfoblock + DEF stat=0 + DEF tempstr[255]:STRING + DEF tempstr2[255]:STRING + DEF i,s,t + + WriteF('dlpath=\s\n',dlpath) + + f_info:=AllocDosObject(DOS_FIB,NIL) + IF(f_info)=NIL + RETURN + ENDIF + + lock:=Lock(dlpath,ACCESS_READ) + IF(lock)=0 + FreeDosObject(DOS_FIB,f_info) + RETURN + ENDIF + + IF(Examine(lock,f_info))=0 + UnLock(lock) + FreeDosObject(DOS_FIB,f_info) + RETURN + ENDIF + + StringF(dirCache,'\sDirCaches/Conf\dDir\d\s\s',confLoc,confnum,dirnum,IF StrLen(subdir)>0 THEN '_' ELSE '',subdir) + fh:=Open(dirCache,MODE_NEWFILE) + IF fh<>0 + IF(f_info.direntrytype>0) + WHILE(((ExNext(lock,f_info))<>0)) + IF (StrCmp('.dircache',f_info.filename)=FALSE) + t:=dateStampToDateTime(f_info.datestamp) + s:=f_info.size + IF (f_info.direntrytype>0) + IF s=0 + StringF(tempstr,'\s\s/',dlpath,f_info.filename) + StringF(tempstr2,'\s\s\s',subdir,IF StrLen(subdir)>0 THEN '_' ELSE '',f_info.filename) + makeFtpDirCache(confLoc,confnum,dirnum,tempstr,tempstr2) + s:=-1 + ENDIF + ENDIF + StringF(tempstr,'\z\h[8] \z\h[8] \s\n',t,s,f_info.filename) + WriteF(tempstr) + Write(fh,tempstr,StrLen(tempstr)) + ENDIF + ENDWHILE + ENDIF + Close(fh) + ENDIF + + UnLock(lock) + FreeDosObject(DOS_FIB,f_info) + +ENDPROC + PROC conferenceMaintenance() DEF conf,flag=0,ch,size,n,f,m DEF tempstr[255]:STRING @@ -22309,6 +22341,7 @@ PROC conferenceMaintenance() DEF lock,fh DEF num,num2,match DEF msgBase + DEF flg2 conf:=1 msgBase:=1 @@ -22507,9 +22540,15 @@ PROC conferenceMaintenance() ENDWHILE IF match=FALSE - StringF(tempstr,'LIST FILES LFORMAT %N "\s" >"\sDirCaches/Conf\dDir\d"',path,confLoc,conf,num-1) - Execute(tempstr,0,0) - StringF(tempstr,'COPY "\sDirCaches/Conf\dDir\d" ram:DirCaches/',confLoc,conf,num-1) + + IF checkToolTypeExists(TOOLTYPE_CONF,conf,'FTP_NO_DIRLIST') + makeFtpDirCache(confLoc,conf,num-1,path,'') + ELSE + StringF(tempstr,'LIST FILES LFORMAT %N "\s" >"\sDirCaches/Conf\dDir\d"',path,confLoc,conf,num-1) + Execute(tempstr,0,0) + ENDIF + + StringF(tempstr,'COPY "\sDirCaches/Conf\dDir\d#?" ram:DirCaches/',confLoc,conf,num-1) Execute(tempstr,0,0) ENDIF StringF(path,'DLPATH.\d',num++) @@ -28279,6 +28318,7 @@ PROC processFtpLogon() StrCopy(sendStr,'430 That account has problems\b\n') telnetSend(sendStr,EstrLen(sendStr)) state:=STATE_LOGGING_OFF + RETURN ENDIF IF ftpAuth(userName,password)=FALSE @@ -28436,6 +28476,7 @@ PROC processFtpLoggedOnUser() DEF cnums:PTR TO stdlist DEF confULBlock:PTR TO stringlist DEF ftpData:PTR TO ftpData + DEF res setEnvStat(ENV_IDLE) @@ -28527,7 +28568,14 @@ PROC processFtpLoggedOnUser() ENDIF ENDFOR - IF readToolType(TOOLTYPE_XFERLIB,'FTP','FTPHOST',tempstr)=FALSE + res:=FALSE + FOR i:=0 TO xprLib.count()-1 + IF(StriCmp(xprLib.item(i),'FTP')) + IF readToolType(TOOLTYPE_XFERLIB,i,'FTPHOST',tempstr) THEN res:=TRUE + ENDIF + ENDFOR + + IF res=FALSE IF readToolType(TOOLTYPE_BBSCONFIG,'','FTPHOST',tempstr)=FALSE StrCopy(tempstr,'127.0.0.1') ENDIF @@ -28805,7 +28853,7 @@ PROC checkPassword() purgeLineEnd() IF(lfh:=Open('NIL:',MODE_OLDFILE))<>0 StringF(tempStr,'\sUtils/uucico -D \s -U \d -Getty -xx',cmds.bbsLoc,cmds.serDev,cmds.serDevUnit) - Execute(tempStr,IF debug THEN 0 ELSE lfh,IF debug THEN 0 ELSE lfh) + Execute(tempStr,lfh,lfh) Close(lfh) ENDIF purgeLineStart() @@ -30881,7 +30929,7 @@ PROC main() HANDLE IF StrLen(arg1)>0 node:=Val(arg1) ELSE - debug:=TRUE + Raise(ERR_NODEPARAM) ENDIF stripAnsi(0,0,1,0,ansi) @@ -31360,7 +31408,7 @@ PROC main() HANDLE SetTaskPri(FindTask(0),cmds.taskPri) ENDIF - IF (debug) OR (sopt.iconify=FALSE) THEN openExpressScreen() + IF (sopt.iconify=FALSE) THEN openExpressScreen() formatLongDateTime(getSystemTime(),tempstr) StringF(tempstr2,'####### BBS Node \d started on \s #######\n',node,tempstr) @@ -31537,6 +31585,8 @@ PROC main() HANDLE debugLog(LOG_ERROR,tempstr) CASE ERR_FDSRANGE debugLog(LOG_ERROR,'FDS Range error') + CASE ERR_NODEPARAM + WriteF('Express should not be launched manually\n.') CASE "NIL" StringF(tempstr,'NIL pointer error at line \d',exceptioninfo) debugLog(LOG_ERROR,tempstr) diff --git a/ftpd.e b/ftpd.e index 00544ca..3dd6ccc 100644 --- a/ftpd.e +++ b/ftpd.e @@ -337,11 +337,11 @@ PROC getPath(ftpData:PTR TO ftpData,confNum,subDir:PTR TO CHAR,outpath) gp(confNum,subDir,outpath) ENDPROC -PROC findFile(ftpData:PTR TO ftpData,fileName,outpath) +PROC findFile(ftpData:PTR TO ftpData,fileName,subDirs,outpath) DEF ff ff:=ftpData.findFile - ff(fileName,outpath) + ff(fileName,subDirs,outpath) ENDPROC PROC aePuts(ftpData:PTR TO ftpData, s:PTR TO CHAR) @@ -497,12 +497,8 @@ PROC getFileName(ftpData:PTR TO ftpData, filename:PTR TO CHAR,outFilename:PTR TO item:=fileList.item(i) IF StriCmp(FilePart(item.fileName),filename) THEN StrCopy(outFilename,item.fileName) ENDFOR - ELSEIF StrLen(ftpData.subDirPath)>0 - StrCopy(outFilename,ftpData.subDirPath) - checkPathSlash(outFilename) - StrAdd(outFilename,filename) ELSEIF ftpData.findFile<>NIL - findFile(ftpData,filename,outFilename) + findFile(ftpData,filename,ftpData.subDirPath,outFilename) ENDIF ENDPROC @@ -840,13 +836,10 @@ PROC downloadDir(sb,data_c, ftpData:PTR TO ftpData,cmdType) ENDPROC TRUE PROC fullDir(sb,data_c, ftpData:PTR TO ftpData,cmdType) - DEF fileNames:PTR TO stringlist - DEF fileSizes:PTR TO stdlist - DEF fileDates:PTR TO stdlist - DEF filedate:datestamp + DEF i DEF tempstr[255]:STRING DEF dirline[255]:STRING - DEF i + DEF filedate:datestamp IF (ftpData.currentConf=0) dateTimeToDateStamp(getSystemTime(),filedate) @@ -870,84 +863,144 @@ PROC fullDir(sb,data_c, ftpData:PTR TO ftpData,cmdType) callersLog(ftpData,'\tDirectory Scan via ftp') ENDIF - fileNames,fileSizes,fileDates:=makeConfFileList(ftpData) - - FOR i:=0 TO fileNames.count()-1 - - dateTimeToDateStamp(fileDates.item(i),filedate) - - IF fileSizes.item(i)=-1 - IF cmdType=CMDTYPE_MLSD - formatFileDate2(filedate,tempstr) - StringF(dirline,'Type=dir;Modify=\s;Perm=r; \s\b\n',tempstr,FilePart(fileNames.item(i))) - ELSEIF cmdType=CMDTYPE_NLST - StrCopy(dirline,fileNames.item(i)) - ELSE /*cmdType=CMDTYPE_LIST as default*/ - formatFileDate(filedate,tempstr) - StringF(dirline,'dr--r--r-- 1 root root \r\d[10] \s \s\b\n',0,tempstr,FilePart(fileNames.item(i))) - ENDIF - ELSE - IF cmdType=CMDTYPE_MLSD - formatFileDate2(filedate,tempstr) - StringF(dirline,'Type=file;Size=\d;Modify=\s;Perm=r; \s\b\n',fileSizes.item(i),tempstr,FilePart(fileNames.item(i))) - ELSEIF cmdType=CMDTYPE_NLST - StrCopy(dirline,fileNames.item(i)) - ELSE /*cmdType=CMDTYPE_LIST as default*/ - formatFileDate(filedate,tempstr) - StringF(dirline,'-r--r--r-- 1 root root \r\d[10] \s \s\b\n',fileSizes.item(i),tempstr,FilePart(fileNames.item(i))) - ENDIF + makeConfFileList(ftpData,cmdType,sb,data_c) + +ENDPROC + +PROC sendFileDetails(filename:PTR TO CHAR, fileSize, fileDate, cmdType, sb, data_c, output) + DEF filedatets:datestamp + DEF tempstr[255]:STRING + DEF dirline[255]:STRING + + dateTimeToDateStamp(fileDate,filedatets) + + IF fileSize=-1 + IF cmdType=CMDTYPE_MLSD + formatFileDate2(filedatets,tempstr) + StringF(dirline,'Type=dir;Modify=\s;Perm=r; \s\b\n',tempstr,FilePart(filename)) + ELSEIF cmdType=CMDTYPE_NLST + StrCopy(dirline,filename) + ELSE /*cmdType=CMDTYPE_LIST as default*/ + formatFileDate(filedatets,tempstr) + StringF(dirline,'dr--r--r-- 1 root root \r\d[10] \s \s\b\n',0,tempstr,FilePart(filename)) ENDIF + ELSE + IF cmdType=CMDTYPE_MLSD + formatFileDate2(filedatets,tempstr) + StringF(dirline,'Type=file;Size=\d;Modify=\s;Perm=r; \s\b\n',fileSize,tempstr,FilePart(filename)) + ELSEIF cmdType=CMDTYPE_NLST + StrCopy(dirline,filename) + ELSE /*cmdType=CMDTYPE_LIST as default*/ + formatFileDate(filedatets,tempstr) + StringF(dirline,'-r--r--r-- 1 root root \r\d[10] \s \s\b\n',fileSize,tempstr,FilePart(filename)) + ENDIF + ENDIF + IF output + IF ((EstrLen(output)+EstrLen(dirline))>StrMax(output)) + writeLineEx(sb,data_c, output) + StrCopy(output,'') + ENDIF + StrAdd(output,dirline) + ELSE writeLineEx(sb,data_c, dirline) - ENDFOR - - END fileNames - END fileSizes - END fileDates + ENDIF ENDPROC -PROC makeList(path:PTR TO CHAR, fib:PTR TO fileinfoblock, fileNames:PTR TO stringlist, fileSizes:PTR TO stdlist,fileDates:PTR TO stdlist, startDate) +PROC makeList(path:PTR TO CHAR,dirCache:PTR TO CHAR,fib:PTR TO fileinfoblock, startDate, cmdType, sb, data_c) DEF fLock - DEF d + DEF d,fh + DEF dirLine[40]:STRING + DEF tmp[10]:STRING + DEF c=FALSE + DEF mem,fs,p,cnt + DEF output + + output:=String(10000) + + fs:=FileLength(dirCache) + IF fs>0 + /*IF (mem:=New(fs+1)) + fh:=Open(dirCache,MODE_OLDFILE) + Read(fh,mem,fs) + p:=0 + WHILE (p=0 + StrCopy(dirLine,mem+p,cnt) + p:=p+cnt+1 + ELSE + StrCopy(dirLine,mem+p) + p:=fs + ENDIF + IF StrLen(dirLine)>18 + c:=TRUE + StrCopy(tmp,'$') + StrAdd(tmp,dirLine,8) + d:=Val(tmp) + IF d>=startDate + StrCopy(tmp,'$') + StrAdd(tmp,dirLine+9,8) + sendFileDetails(dirLine+18,Val(tmp),d,cmdType, sb, data_c, output) + ENDIF + ENDIF + ENDWHILE + Close(fh) + Dispose(mem) + ELSE*/ + fh:=Open(dirCache,MODE_OLDFILE) + IF fh<>0 + WHILE(Fgets(fh,dirLine,40)<>NIL) + IF StrLen(dirLine)>18 + c:=TRUE + StrCopy(tmp,'$') + StrAdd(tmp,dirLine,8) + d:=Val(tmp) + IF d>=startDate + StrCopy(tmp,'$') + StrAdd(tmp,dirLine+9,8) + sendFileDetails(dirLine+18,Val(tmp),d,cmdType, sb, data_c, output) + ENDIF + ENDIF + ENDWHILE + Close(fh) + ENDIF + //ENDIF + IF (output ANDALSO (EstrLen(output)>0)) + writeLineEx(sb,data_c, output) + ENDIF + IF c + DisposeLink(output) + RETURN + ENDIF + + ENDIF + IF((fLock:=Lock(path,ACCESS_READ))) IF((Examine(fLock,fib))) IF(fib.direntrytype > 0) WHILE(ExNext(fLock,fib)) - d:=dateStampToDateTime(fib.datestamp) - IF d>=startDate - fileNames.add(fib.filename) - IF fib.direntrytype>0 THEN fileSizes.add(-1) ELSE fileSizes.add(fib.size) - fileDates.add(d) + IF StrCmp(fib.filename,'.dircache')=FALSE + d:=dateStampToDateTime(fib.datestamp) + IF d>=startDate + sendFileDetails(fib.filename,IF fib.direntrytype>0 THEN -1 ELSE fib.size,d,cmdType, sb, data_c, output) + ENDIF ENDIF ENDWHILE ENDIF ENDIF UnLock(fLock) ENDIF + IF (output ANDALSO (EstrLen(output)>0)) THEN writeLineEx(sb,data_c, output) + DisposeLink(output) ENDPROC -PROC makeFtpListFromSubDir(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, fileSizes:PTR TO stdlist,fileDates:PTR TO stdlist, startDate) +PROC makeFtpListFromDlDirs(ftpData:PTR TO ftpData, startDate, cmdType, sb, data_c) DEF path[255]:STRING + DEF dirCache[255]:STRING DEF fib:PTR TO fileinfoblock - - StrCopy(path,ftpData.subDirPath) - - IF((fib:=AllocDosObject(DOS_FIB,NIL)))=NIL - RETURN FALSE - ENDIF - - checkPathSlash(path) - - makeList(path,fib, fileNames,fileSizes,fileDates,startDate) - - FreeDosObject(DOS_FIB,fib) -ENDPROC - -PROC makeFtpListFromDlDirs(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, fileSizes:PTR TO stdlist,fileDates:PTR TO stdlist, startDate) - DEF path[255]:STRING - DEF fib:PTR TO fileinfoblock - DEF dirNum + DEF dirNum,i IF((fib:=AllocDosObject(DOS_FIB,NIL)))=NIL RETURN FALSE @@ -957,8 +1010,15 @@ PROC makeFtpListFromDlDirs(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, StringF(path,'DLPATH.\d',dirNum++) WHILE(readToolType(TOOLTYPE_CONF,ftpData.confNums.item(ftpData.currentConf-1),path,path)) checkPathSlash(path) + IF StrLen(ftpData.subDirPath) + StrAdd(path,ftpData.subDirPath) + checkPathSlash(path) + ENDIF - makeList(path,fib, fileNames,fileSizes,fileDates,startDate) + StringF(dirCache,'RAM:DirCaches/Conf\dDir\d\s\s',ftpData.currentConf,dirNum-1,IF StrLen(ftpData.subDirPath)>0 THEN '_' ELSE '', ftpData.subDirPath) + FOR i:=14 TO StrLen(dirCache)-1 DO IF dirCache[i]="/" THEN dirCache[i]:="_" + + makeList(path,dirCache,fib,startDate,cmdType,sb,data_c) StringF(path,'DLPATH.\d',dirNum++) ENDWHILE @@ -966,7 +1026,7 @@ PROC makeFtpListFromDlDirs(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, ENDPROC -PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, fileSizes:PTR TO stdlist,fileDates:PTR TO stdlist, startDate) +PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, startDate, cmdType, sb, data_c) DEF dtStr[20]:STRING DEF sizeStr[20]:STRING DEF dtcomp1,dtcomp2 @@ -974,9 +1034,12 @@ PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, DEF dirFile[255]:STRING DEF tempstr[255]:STRING DEF fh,t,sz,m,d,y + DEF output DEF maxDirs + output:=String(10000) + maxDirs:=readToolTypeInt(TOOLTYPE_CONF,ftpData.confNums.item(ftpData.currentConf-1),'NDIRS') formatLongDate(startDate,dtStr) @@ -1040,11 +1103,8 @@ PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, IF (InStr(sizeStr,'M')>=0) THEN sz:=Mul(sz,1048576) spPos:=InStr(tempstr,' ') - SetStr(tempstr,spPos) - - fileNames.add(tempstr) - fileSizes.add(sz) - fileDates.add(encodeDate(m,d,y)) + SetStr(tempstr,spPos) + sendFileDetails(tempstr,sz,encodeDate(m,d,y),cmdType, sb, data_c, output) ENDIF ENDIF ENDIF @@ -1056,12 +1116,11 @@ PROC makeFtpListFromDirList(ftpData:PTR TO ftpData, fileNames:PTR TO stringlist, fh:=Open(dirFile,MODE_OLDFILE) ENDIF ENDWHILE + IF (output ANDALSO (EstrLen(output)>0)) THEN writeLineEx(sb,data_c, output) + DisposeLink(output) ENDPROC -PROC makeConfFileList(ftpData:PTR TO ftpData) - DEF fileNames:PTR TO stringlist - DEF fileSizes:PTR TO stdlist - DEF fileDates:PTR TO stdlist +PROC makeConfFileList(ftpData:PTR TO ftpData, cmdType, sb, data_c) DEF startDate,dayOffset dayOffset:=readToolTypeInt(TOOLTYPE_CONF,ftpData.confNums.item(ftpData.currentConf-1),'FTP_DIR_DAYS') @@ -1070,20 +1129,17 @@ PROC makeConfFileList(ftpData:PTR TO ftpData) startDate:=getSystemDate()-dayOffset - fileNames:=NEW fileNames.stringlist(256) - fileSizes:=NEW fileSizes.stdlist(256) - fileDates:=NEW fileDates.stdlist(256) IF ftpData.currentConf>0 IF (StrLen(ftpData.subDirPath)>0) - makeFtpListFromSubDir(ftpData,fileNames,fileSizes,fileDates,startDate) + makeFtpListFromDlDirs(ftpData,startDate,cmdType, sb, data_c) ELSEIF checkToolTypeExists(TOOLTYPE_CONF,ftpData.confNums.item(ftpData.currentConf-1),'FTP_NO_DIRLIST') - makeFtpListFromDlDirs(ftpData,fileNames,fileSizes,fileDates,startDate) + makeFtpListFromDlDirs(ftpData,startDate,cmdType, sb, data_c) ELSE - makeFtpListFromDirList(ftpData,fileNames,fileSizes,fileDates,startDate) + makeFtpListFromDirList(ftpData,startDate,cmdType, sb, data_c) ENDIF ENDIF -ENDPROC fileNames,fileSizes,fileDates +ENDPROC PROC cmdUser(sb,ftp_c,params:PTR TO CHAR,ftpData:PTR TO ftpData) ->WriteF('user=\s\b\n',params) @@ -1108,10 +1164,11 @@ PROC cmdPwd(sb,ftp_c,ftpData:PTR TO ftpData) StrCopy(sendStr, '257 "/" is current directory.\b\n') writeLineEx(sb,ftp_c,sendStr) ELSE + StringF(dirName,'/\r\z\d[3]-\s',ftpData.currentConf,ftpData.confNames.item(ftpData.currentConf-1)) IF StrLen(ftpData.subDirPath)>0 StrAdd(dirName,'/') - StrAdd(dirName,FilePart(ftpData.subDirPath)) + StrAdd(dirName,ftpData.subDirPath) ENDIF StringF(sendStr, '257 "\s" is current directory.\b\n',dirName) writeLineEx(sb,ftp_c,sendStr) @@ -1142,7 +1199,7 @@ PROC cmdCwd(sb,ftp_c,ftpData:PTR TO ftpData,path:PTR TO CHAR) DEF sendStr[255]:STRING DEF temp[255]:STRING DEF outFileName[255]:STRING - DEF stat,i + DEF stat,i,p IF ftpData.mode=MODE_FULLSERVER IF StrCmp(path,'/') @@ -1156,7 +1213,13 @@ PROC cmdCwd(sb,ftp_c,ftpData:PTR TO ftpData,path:PTR TO CHAR) writeLineEx(sb,ftp_c,sendStr) IF StrLen(ftpData.subDirPath)>0 - StrCopy(ftpData.subDirPath,'') + IF InStr(ftpData.subDirPath,'/')>=0 + p:=StrLen(ftpData.subDirPath)-1 + WHILE ftpData.subDirPath[p]<>"/" DO p-- + SetStr(ftpData.subDirPath,p) + ELSE + StrCopy(ftpData.subDirPath,'') + ENDIF ELSE ftpData.currentConf:=0 ENDIF @@ -1191,33 +1254,39 @@ PROC cmdCwd(sb,ftp_c,ftpData:PTR TO ftpData,path:PTR TO CHAR) FOR i:=0 TO ftpData.confNames.count()-1 StringF(temp,'/\r\z\d[3]-\s/',i+1,ftpData.confNames.item(i)) - IF StrCmp(temp,path,StrLen(temp)) THEN stat:=i + IF StrCmp(temp,path,StrLen(temp)) + stat:=i + StrCopy(path,path+StrLen(temp)) + ENDIF ENDFOR IF stat=-1 IF ftpData.currentConf=0 FOR i:=0 TO ftpData.confNames.count()-1 StringF(temp,'\r\z\d[3]-\s/',i+1,ftpData.confNames.item(i)) - IF StrCmp(temp,path,StrLen(temp)) THEN stat:=i + IF StrCmp(temp,path,StrLen(temp)) + stat:=i + StrCopy(path,path+StrLen(temp)) + ENDIF ENDFOR ENDIF ENDIF IF stat>=0 ftpData.currentConf:=stat+1 - - getPath(ftpData,ftpData.confNums.item(ftpData.currentConf-1),FilePart(path),outFileName) + getPath(ftpData,ftpData.confNums.item(ftpData.currentConf-1),path,outFileName) IF StrLen(outFileName)>0 - StrCopy(ftpData.subDirPath,outFileName) + StrCopy(ftpData.subDirPath,path) ELSE stat:=-1 ENDIF ELSE IF ftpData.currentConf<>0 + IF StrLen(ftpData.subDirPath)>0 THEN StringF(path,'\s/\s',ftpData.subDirPath,path) getPath(ftpData,ftpData.confNums.item(ftpData.currentConf-1),path,outFileName) IF StrLen(outFileName)>0 + StrCopy(ftpData.subDirPath,path) stat:=1 - StrCopy(ftpData.subDirPath,outFileName) ENDIF ENDIF ENDIF @@ -2071,7 +2140,7 @@ EXPORT PROC ftpServerMode(ftpData:PTR TO ftpData, ftp_c,ftpHost:PTR TO CHAR,uplo ftpData.workingPath:=String(255) ftpData.uploadPath:=String(255) ftpData.hostName:=String(255) - ftpData.subDirPath:=String(255) + ftpData.subDirPath:=String(1000) ftpData.dataPorts:=ftpDataPorts ftpData.ftpDir:={fullDir} ftpData.currentConf:=0 diff --git a/sha256.e b/sha256.e index 807f4ce..e19a2d9 100644 --- a/sha256.e +++ b/sha256.e @@ -1,5 +1,8 @@ OPT MODULE +CONST SHA1_DIGEST_SIZE=20 +CONST SIZE_OF_SHA_1_CHUNK=64 + CONST SIZE_OF_SHA_256_HASH=32 CONST SIZE_OF_SHA_256_CHUNK=64 CONST TOTAL_LEN_LEN=8 @@ -13,6 +16,12 @@ OBJECT sha_256 h[8]:ARRAY OF LONG ENDOBJECT +OBJECT sha1_ctx + state[5]:ARRAY OF LONG + count[2]:ARRAY OF LONG + buffer[SIZE_OF_SHA_1_CHUNK]:ARRAY OF CHAR +ENDOBJECT + /* * Comments from pseudo-code at https://en.wikipedia.org/wiki/SHA-2 are reproduced here. * When useful for clarification, portions of the pseudo-code are reproduced here too. @@ -30,6 +39,11 @@ PROC right_rot(value, count) ROR.L D1,D0 ENDPROC D0 +PROC left_rot(value, count) + MOVE.L value,D0 + MOVE.L count,D1 + ROL.L D1,D0 +ENDPROC D0 /* * @brief Update a hash value under calculation with a new chunk of data. * @param h Pointer to the first hash item, of a total of eight. @@ -112,9 +126,192 @@ PROC consume_chunk(h:PTR TO LONG, p:PTR TO CHAR) FOR i:=0 TO 7 DO h[i]:=h[i]+ah[i] ENDPROC -/* - * Public functions. See header file for documentation. - */ +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) block[i] +#define blk(i) (block[i AND 15]:= left_rot(Eor(Eor(Eor(block[(i+13) AND 15],block[(i+8) AND 15]),block[(i+2) AND 15]),block[i AND 15]),1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ + +#define r0(v, w, x, y, z, i) z:=z+Eor(w AND Eor(x,y),y)+blk0(i)+$5a827999+left_rot(v,5) +#define r1(v, w, x, y, z, i) z:=z+Eor(w AND Eor(x,y),y)+blk(i)+$5a827999+left_rot(v,5) +#define r2(v, w, x, y, z, i) z:=z+Eor(Eor(w,x),y)+blk(i)+$6ed9eba1+left_rot(v,5) +#define r3(v, w, x, y, z, i) z:=z+(((w OR x) AND y) OR (w AND x))+blk(i)+$8f1bbcdc+left_rot(v,5) +#define r4(v, w, x, y, z, i) z:=z+Eor(Eor(w,x),y)+blk(i)+$ca62c1d6+left_rot(v,5) + +PROC sha1_transform(state:PTR TO LONG,buffer:PTR TO CHAR) + DEF a,b,c,d,e + DEF block[16]:ARRAY OF LONG + + CopyMem(buffer,block,64) + + /* Copy context->state[] to working vars */ + a:=state[0] + b:=state[1] + c:=state[2] + d:=state[3] + e:=state[4] + + /* 4 rounds of 20 operations each. Loop unrolled. */ + r0(a, b, c, d, e, 0);b:=left_rot(b,30) + r0(e, a, b, c, d, 1);a:=left_rot(a,30) + r0(d, e, a, b, c, 2);e:=left_rot(e,30) + r0(c, d, e, a, b, 3);d:=left_rot(d,30) + r0(b, c, d, e, a, 4);c:=left_rot(c,30) + r0(a, b, c, d, e, 5);b:=left_rot(b,30) + r0(e, a, b, c, d, 6);a:=left_rot(a,30) + r0(d, e, a, b, c, 7);e:=left_rot(e,30) + r0(c, d, e, a, b, 8);d:=left_rot(d,30) + r0(b, c, d, e, a, 9);c:=left_rot(c,30) + r0(a, b, c, d, e, 10);b:=left_rot(b,30) + r0(e, a, b, c, d, 11);a:=left_rot(a,30) + r0(d, e, a, b, c, 12);e:=left_rot(e,30) + r0(c, d, e, a, b, 13);d:=left_rot(d,30) + r0(b, c, d, e, a, 14);c:=left_rot(c,30) + r0(a, b, c, d, e, 15);b:=left_rot(b,30) + r1(e, a, b, c, d, 16);a:=left_rot(a,30) + r1(d, e, a, b, c, 17);e:=left_rot(e,30) + r1(c, d, e, a, b, 18);d:=left_rot(d,30) + r1(b, c, d, e, a, 19);c:=left_rot(c,30) + r2(a, b, c, d, e, 20);b:=left_rot(b,30) + r2(e, a, b, c, d, 21);a:=left_rot(a,30) + r2(d, e, a, b, c, 22);e:=left_rot(e,30) + r2(c, d, e, a, b, 23);d:=left_rot(d,30) + r2(b, c, d, e, a, 24);c:=left_rot(c,30) + r2(a, b, c, d, e, 25);b:=left_rot(b,30) + r2(e, a, b, c, d, 26);a:=left_rot(a,30) + r2(d, e, a, b, c, 27);e:=left_rot(e,30) + r2(c, d, e, a, b, 28);d:=left_rot(d,30) + r2(b, c, d, e, a, 29);c:=left_rot(c,30) + r2(a, b, c, d, e, 30);b:=left_rot(b,30) + r2(e, a, b, c, d, 31);a:=left_rot(a,30) + r2(d, e, a, b, c, 32);e:=left_rot(e,30) + r2(c, d, e, a, b, 33);d:=left_rot(d,30) + r2(b, c, d, e, a, 34);c:=left_rot(c,30) + r2(a, b, c, d, e, 35);b:=left_rot(b,30) + r2(e, a, b, c, d, 36);a:=left_rot(a,30) + r2(d, e, a, b, c, 37);e:=left_rot(e,30) + r2(c, d, e, a, b, 38);d:=left_rot(d,30) + r2(b, c, d, e, a, 39);c:=left_rot(c,30) + r3(a, b, c, d, e, 40);b:=left_rot(b,30) + r3(e, a, b, c, d, 41);a:=left_rot(a,30) + r3(d, e, a, b, c, 42);e:=left_rot(e,30) + r3(c, d, e, a, b, 43);d:=left_rot(d,30) + r3(b, c, d, e, a, 44);c:=left_rot(c,30) + r3(a, b, c, d, e, 45);b:=left_rot(b,30) + r3(e, a, b, c, d, 46);a:=left_rot(a,30) + r3(d, e, a, b, c, 47);e:=left_rot(e,30) + r3(c, d, e, a, b, 48);d:=left_rot(d,30) + r3(b, c, d, e, a, 49);c:=left_rot(c,30) + r3(a, b, c, d, e, 50);b:=left_rot(b,30) + r3(e, a, b, c, d, 51);a:=left_rot(a,30) + r3(d, e, a, b, c, 52);e:=left_rot(e,30) + r3(c, d, e, a, b, 53);d:=left_rot(d,30) + r3(b, c, d, e, a, 54);c:=left_rot(c,30) + r3(a, b, c, d, e, 55);b:=left_rot(b,30) + r3(e, a, b, c, d, 56);a:=left_rot(a,30) + r3(d, e, a, b, c, 57);e:=left_rot(e,30) + r3(c, d, e, a, b, 58);d:=left_rot(d,30) + r3(b, c, d, e, a, 59);c:=left_rot(c,30) + r4(a, b, c, d, e, 60);b:=left_rot(b,30) + r4(e, a, b, c, d, 61);a:=left_rot(a,30) + r4(d, e, a, b, c, 62);e:=left_rot(e,30) + r4(c, d, e, a, b, 63);d:=left_rot(d,30) + r4(b, c, d, e, a, 64);c:=left_rot(c,30) + r4(a, b, c, d, e, 65);b:=left_rot(b,30) + r4(e, a, b, c, d, 66);a:=left_rot(a,30) + r4(d, e, a, b, c, 67);e:=left_rot(e,30) + r4(c, d, e, a, b, 68);d:=left_rot(d,30) + r4(b, c, d, e, a, 69);c:=left_rot(c,30) + r4(a, b, c, d, e, 70);b:=left_rot(b,30) + r4(e, a, b, c, d, 71);a:=left_rot(a,30) + r4(d, e, a, b, c, 72);e:=left_rot(e,30) + r4(c, d, e, a, b, 73);d:=left_rot(d,30) + r4(b, c, d, e, a, 74);c:=left_rot(c,30) + r4(a, b, c, d, e, 75);b:=left_rot(b,30) + r4(e, a, b, c, d, 76);a:=left_rot(a,30) + r4(d, e, a, b, c, 77);e:=left_rot(e,30) + r4(c, d, e, a, b, 78);d:=left_rot(d,30) + r4(b, c, d, e, a, 79);c:=left_rot(c,30) + + /* Add the working vars back into context.state[] */ + state[0]:=state[0]+a + state[1]:=state[1]+b + state[2]:=state[2]+c + state[3]:=state[3]+d + state[4]:=state[4]+e + + /* Wipe variables */ + a:=0 + b:=0 + c:=0 + d:=0 + e:=0 + +ENDPROC + +PROC sha1_init(context:PTR TO sha1_ctx) + /* SHA1 initialization constants */ + context.state[0]:=$67452301 + context.state[1]:=$efcdab89 + context.state[2]:=$98badcfe + context.state[3]:=$10325476 + context.state[4]:=$c3d2e1f0 + context.count[0]:=0 + context.count[1]:=0 +ENDPROC + +PROC sha1_update(context:PTR TO sha1_ctx, p,len) + DEF data:PTR TO CHAR + DEF i,j + data:=p + + j:=(Shr(context.count[0],3)) AND 63 + context.count[0]:=context.count[0] + Shl(len,3) + IF (context.count[0] < Shl(len,3)) + context.count[1]:=context.count[1]+1 + ENDIF + context.count[1]:=context.count[1] + Lsr(len,29) + IF ((j + len) > 63) + i:=64 - j + CopyMem(data, context.buffer+j, i) + sha1_transform(context.state, context.buffer) + WHILE ((i+63)= 4 THEN 0 ELSE 1)],((3 - (i AND 3)) * 8))) AND 255) + ENDFOR + sha1_update(context, [128]:CHAR, 1) + WHILE ((context.count[0] AND 504) <> 448) + sha1_update(context, [0]:CHAR, 1) + ENDWHILE + sha1_update(context, finalcount, 8) /* Should cause SHA1_Transform */ + FOR i:=0 TO SHA1_DIGEST_SIZE-1 + digest[i]:=((Shr(context.state[Shr(i,2)],((3 - (i AND 3)) * 8))) AND 255) + ENDFOR + + /* Wipe variables */ + i:=0 + MemFill(context.buffer,64,0) + MemFill(context.state,20,0) + MemFill(context.count,8,0) + MemFill(finalcount,8,0) /* SWR */ + + sha1_transform(context.state, context.buffer); +ENDPROC PROC sha_256_init(sha_256:PTR TO sha_256, hash:PTR TO CHAR) sha_256.hash:=hash @@ -215,6 +412,16 @@ PROC sha_256_close(sha_256:PTR TO sha_256) ENDPROC sha_256.hash +EXPORT PROC calc_sha_1(hash:PTR TO CHAR, input, len) + DEF context:PTR TO sha1_ctx + + NEW context + sha1_init(context) + sha1_update(context, input, len) + sha1_final(hash,context) + END context +ENDPROC + EXPORT PROC calc_sha_256(hash:PTR TO CHAR, input, len) DEF sha_256:PTR TO sha_256 @@ -254,10 +461,37 @@ kdata: LONG $428a2f98, $71374491, $b5c0fbcf, $e9b5dba5, $3956c25b, $59f111f1, $ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* - * HMAC-SHA-1 (from RFC 2202). - */ -PROC hmac_sha1(text:PTR TO CHAR, text_len, key:PTR TO CHAR, key_len, digest:PTR TO CHAR) +EXPORT PROC hmac_sha1(text:PTR TO CHAR, text_len, key:PTR TO CHAR, key_len, digest:PTR TO CHAR) + DEF k_pad:PTR TO CHAR + DEF tk[SHA1_DIGEST_SIZE]:ARRAY OF CHAR + DEF i + + k_pad:=New(SIZE_OF_SHA_1_CHUNK+text_len) + + IF (key_len > SIZE_OF_SHA_1_CHUNK) + calc_sha_1(tk,key, key_len) + key:=tk + key_len:=SHA1_DIGEST_SIZE + ENDIF + + CopyMem(key,k_pad, key_len) + CopyMem(text,k_pad+SIZE_OF_SHA_1_CHUNK, text_len) + FOR i:=0 TO SIZE_OF_SHA_1_CHUNK-1 DO k_pad[i]:=Eor(k_pad[i],$36) + + calc_sha_1(digest,k_pad, SIZE_OF_SHA_1_CHUNK+text_len) + Dispose(k_pad) + + k_pad:=New(SIZE_OF_SHA_1_CHUNK+SHA1_DIGEST_SIZE) + CopyMem(key,k_pad,key_len) + CopyMem(digest, k_pad+SIZE_OF_SHA_1_CHUNK, SHA1_DIGEST_SIZE) + + FOR i:=0 TO SIZE_OF_SHA_1_CHUNK-1 DO k_pad[i]:=Eor(k_pad[i],$5c) + + calc_sha_1(digest,k_pad, SIZE_OF_SHA_1_CHUNK+SHA1_DIGEST_SIZE) + Dispose(k_pad) +ENDPROC + +EXPORT PROC hmac_sha256(text:PTR TO CHAR, text_len, key:PTR TO CHAR, key_len, digest:PTR TO CHAR) DEF k_pad:PTR TO CHAR DEF tk[SIZE_OF_SHA_256_HASH]:ARRAY OF CHAR DEF i @@ -314,11 +548,11 @@ EXPORT PROC pkcs5_pbkdf2(pass:PTR TO CHAR, pass_len, salt:PTR TO CHAR, salt_len, asalt[salt_len+2]:=Shr(count,8) asalt[salt_len+3]:=count AND 255 - hmac_sha1(asalt, salt_len + 4, pass, pass_len, d1) + hmac_sha256(asalt, salt_len + 4, pass, pass_len, d1) CopyMem(d1,obuf,SIZE_OF_SHA_256_HASH) FOR i:=1 TO rounds-1 - hmac_sha1(d1, SIZE_OF_SHA_256_HASH, pass, pass_len, d2) + hmac_sha256(d1, SIZE_OF_SHA_256_HASH, pass, pass_len, d2) CopyMem(d2,d1,SIZE_OF_SHA_256_HASH) FOR j:=0 TO SIZE_OF_SHA_256_HASH-1 obuf[j]:=Eor(obuf[j],d1[j]) From 9252cc4cdabc2d18a60e7ea4140116365eef7295 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 6 Jun 2023 14:42:43 +0100 Subject: [PATCH 06/47] 1) Allow SM_ mci command in all mci text 2) Remove file missing check for MCI doors --- express.e | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/express.e b/express.e index 303d85c..d53a033 100644 --- a/express.e +++ b/express.e @@ -4193,7 +4193,7 @@ PROC runDoor(cmd,type,command,tooltype,params,resident,doorTrap,privcmd,pri=0,st StrCopy(runOnExit,'') StrCopy(runOnExit2,'') - IF (resident=FALSE) AND ((type<>DOORTYPE_MCI) OR (StrLen(cmd)>0)) + IF (resident=FALSE) AND ((type<>DOORTYPE_MCI) AND (StrLen(cmd)>0)) IF (fileExists(cmd)=FALSE) IF privcmd=FALSE aePuts('\b\nError, can''t locate Custom Command\b\n') @@ -5513,10 +5513,8 @@ PROC processMciCmd(mcidata,len,pos,outdata = NIL) pos:=pos+nval+t ELSEIF StrCmp(cmd,'SM_',3) pos:=pos+3 - IF outdata=NIL - nval:=EstrLen(cmd)-3 - midStr2(currentMenuName,mcidata,pos,nval) - ENDIF + nval:=EstrLen(cmd)-3 + midStr2(currentMenuName,mcidata,pos,nval) pos:=pos+EstrLen(currentMenuName)+t ELSEIF StrCmp(cmd,'q') pos:=pos+1+t From 38d7f7d6c6437c083d541405d70a520b3e7471d6 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 30 Jun 2023 16:39:52 +0100 Subject: [PATCH 07/47] Express 1) Add support for auto sending username/password when making outgoing telnet connections 2) Telnet control codes not correctly filtered when connected to outgoing telnet 3) revert part of previous change "Allow SM_ mci command in all mci text" 4) Refactor MAIL_ON and EXECUTE_ON functions 5) user TOP CPS not updated on FTP transfers 6) Logon MAIL_ON and EXECUTE_ON functions were not executed for ftp calls 7) Add warning on account editor if exiting without saving 8) remove some unused variables --- axcommon.e | 4 + express.e | 355 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 261 insertions(+), 98 deletions(-) diff --git a/axcommon.e b/axcommon.e index f157702..f1396c9 100644 --- a/axcommon.e +++ b/axcommon.e @@ -327,6 +327,10 @@ EXPORT CONST DT_SIZEDOWNLOAD=704 EXPORT CONST CON_CURSOR=705 EXPORT CONST TELNET_CONNECT=706 EXPORT CONST GET_CMD_TOOLTYPE=707 +EXPORT CONST TELNET_USERNAME_PROMPT=708 +EXPORT CONST TELNET_USERNAME=709 +EXPORT CONST TELNET_PASSWORD_PROMPT=710 +EXPORT CONST TELNET_PASSWORD=711 /* end of new /X 5 host commands */ diff --git a/express.e b/express.e index d53a033..fec5b05 100644 --- a/express.e +++ b/express.e @@ -396,6 +396,11 @@ DEF currentMenuName[255]:STRING DEF defaultMenuName[255]:STRING DEF menuPause=TRUE +DEF telnetUsername[100]:STRING +DEF telnetPassword[100]:STRING +DEF telnetUsernamePrompt[100]:STRING +DEF telnetPasswordPrompt[100]:STRING + DEF quietDownload=FALSE DEF unknownValue=0 DEF memConf=0:PTR TO LONG ->shared with tooltypes.e @@ -928,8 +933,6 @@ ENDPROC TRUE PROC setNewPassword(user:PTR TO user, userMisc:PTR TO userMisc, newpass:PTR TO CHAR) DEF passType - DEF tempStr - DEF i IF checkToolType(TOOLTYPE_BBSCONFIG,0,'PASSWORD_SECURITY','LEGACY') passType:=PWD_LEGACY @@ -977,10 +980,9 @@ PROC setNewPassword(user:PTR TO user, userMisc:PTR TO userMisc, newpass:PTR TO C ENDPROC PROC checkUserPassword(user:PTR TO user, userMisc:PTR TO userMisc, testpass:PTR TO CHAR) - DEF tempStr DEF tmpHash[32]:ARRAY OF CHAR DEF tempPass[100]:STRING - DEF i,res,maxAttempts + DEF res,maxAttempts SELECT userMisc.pwdType CASE PWD_LEGACY StrCopy(tempPass,testpass) @@ -2367,7 +2369,7 @@ PROC readMayGetChar(msgport, checkTelnet, whereto) temp:=0 IF checkTelnet AND (telnetSocket>=0) - IF Recv(telnetSocket,whereto,1,0)=1 + IF Recv(telnetSocket,whereto,1,0)=1 temp:=whereto[] IF (lastIAC=0) AND (temp=255) lastIAC:=1 @@ -3031,7 +3033,7 @@ PROC telnetConnect(host:PTR TO CHAR,port) DEF tlastIAC2=FALSE DEF tlastIAC3=FALSE DEF last - DEF c,c2 + DEF c,c2,ch DEF cmd1,cmd2 DEF sigs @@ -3135,29 +3137,32 @@ PROC telnetConnect(host:PTR TO CHAR,port) IF checkInput() c:=0 WHILE (checkInput()) AND (c<100) - ibuf[c]:=readChar(1,0,TRUE) - IF (ibuf[c]=UPARROW) AND (c<97) - ibuf[c]:=27 - ibuf[c+1]:="[" - ibuf[c+2]:="A" - c:=c+2 - ELSEIF (ibuf[c]=DOWNARROW) AND (c<97) - ibuf[c]:=27 - ibuf[c+1]:="[" - ibuf[c+2]:="B" - c:=c+2 - ELSEIF (ibuf[c]=RIGHTARROW) AND (c<97) - ibuf[c]:=27 - ibuf[c+1]:="[" - ibuf[c+2]:="C" - c:=c+2 - ELSEIF (ibuf[c]=LEFTARROW) AND (c<97) - ibuf[c]:=27 - ibuf[c+1]:="[" - ibuf[c+2]:="D" - c:=c+2 + ch:=readChar(1,0,TRUE) + IF ch>=0 + ibuf[c]:=ch + IF (ibuf[c]=UPARROW) AND (c<97) + ibuf[c]:=27 + ibuf[c+1]:="[" + ibuf[c+2]:="A" + c:=c+2 + ELSEIF (ibuf[c]=DOWNARROW) AND (c<97) + ibuf[c]:=27 + ibuf[c+1]:="[" + ibuf[c+2]:="B" + c:=c+2 + ELSEIF (ibuf[c]=RIGHTARROW) AND (c<97) + ibuf[c]:=27 + ibuf[c+1]:="[" + ibuf[c+2]:="C" + c:=c+2 + ELSEIF (ibuf[c]=LEFTARROW) AND (c<97) + ibuf[c]:=27 + ibuf[c+1]:="[" + ibuf[c+2]:="D" + c:=c+2 + ENDIF + c++ ENDIF - c++ ENDWHILE conCursorOn() @@ -3175,6 +3180,9 @@ PROC telnetConnect(host:PTR TO CHAR,port) e:=Errno() IF e<>35 THEN done:=TRUE ELSEIF b>0 + readBuffer[b]:=0 + ->hexdump(readBuffer,b) + c:=0 c2:=0 REPEAT @@ -3230,6 +3238,21 @@ PROC telnetConnect(host:PTR TO CHAR,port) UNTIL c>=b IF c2>0 THEN aePuts2(readBuffer,c2) + IF (StrLen(telnetUsername)>0) AND (StrLen(telnetUsernamePrompt)>0) + IF InStr(readBuffer,telnetUsernamePrompt)>=0 + StringF(tempstr,'\s\b\n',telnetUsername) + Send(s,tempstr,EstrLen(tempstr),0) + StrCopy(telnetUsername,'') + ENDIF + ENDIF + IF (StrLen(telnetPassword)>0) AND (StrLen(telnetPasswordPrompt)>0) + IF InStr(readBuffer,telnetPasswordPrompt)>=0 + StringF(tempstr,'\s\b\n',telnetPassword) + Send(s,tempstr,EstrLen(tempstr),0) + StrCopy(telnetPassword,'') + ENDIF + ENDIF + ENDIF IF((logonType>=LOGON_TYPE_REMOTE) AND (checkCarrier()=FALSE)) THEN done:=TRUE @@ -4073,6 +4096,14 @@ PROC processXimMsg(msgcmd,msg:PTR TO jhMessage,tooltype,command,privcmd,params,n ENDIF CASE TELNET_CONNECT telnetConnect(msg.string,msg.data) + CASE TELNET_USERNAME_PROMPT + StrCopy(telnetUsernamePrompt,msg.string) + CASE TELNET_USERNAME + StrCopy(telnetUsername,msg.string) + CASE TELNET_PASSWORD_PROMPT + StrCopy(telnetPasswordPrompt,msg.string) + CASE TELNET_PASSWORD + StrCopy(telnetPassword,msg.string) CASE GET_CMD_TOOLTYPE StrCopy(tempstring,'') msg.data:=readToolType(tooltype,command,msg.string,tempstring) @@ -5513,8 +5544,10 @@ PROC processMciCmd(mcidata,len,pos,outdata = NIL) pos:=pos+nval+t ELSEIF StrCmp(cmd,'SM_',3) pos:=pos+3 - nval:=EstrLen(cmd)-3 - midStr2(currentMenuName,mcidata,pos,nval) + IF outdata=NIL + nval:=EstrLen(cmd)-3 + midStr2(currentMenuName,mcidata,pos,nval) + ENDIF pos:=pos+EstrLen(currentMenuName)+t ELSEIF StrCmp(cmd,'q') pos:=pos+1+t @@ -6623,6 +6656,63 @@ PROC runExecuteOn(execOn:PTR TO CHAR) ENDIF ENDPROC +PROC doUploadNotify() + DEF str[255]:STRING + DEF string[255]:STRING + runExecuteOn('UPLOAD') + + IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_UPLOAD')) AND (StrLen(mailOptions.sysopEmail)>0) + StringF(str,'\s: Ami-Express upload notification',cmds.bbsName) + StringF(string,'This is a notification that \s from \s has uploaded\n\n',loggedOnUser.name,loggedOnUser.location) + sendMail(str,string,FALSE, NIL,0,mailOptions.sysopEmail) + ENDIF +ENDPROC + +PROC doCommentNotify(fromName:PTR TO CHAR, subject:PTR TO CHAR) + DEF tempStr[255]:STRING + DEF tempStr2[255]:STRING + runExecuteOn('SYSOP_COMMENT') + IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_SYSOP_COMMENT')) AND (StrLen(mailOptions.sysopEmail)>0) + StringF(tempStr,'\s: Ami-Express sysop message notification',cmds.bbsName) + StringF(tempStr2,'This is a notification that \s has sent you a message.\n\nSubject: \s\n\n',fromName,subject) + sendMail(tempStr,tempStr2,TRUE, msgBuf,lines,mailOptions.sysopEmail) + ENDIF +ENDPROC + +PROC doLogonNotify() + DEF tempStr[255]:STRING + DEF tempStr2[255]:STRING + runExecuteOn('LOGON') + IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_LOGON')) AND (StrLen(mailOptions.sysopEmail)>0) + StringF(tempStr,'\s: Ami-Express logon notification',cmds.bbsName) + StringF(tempStr2,'This is a notification that \s from \s has logged on\n\n',loggedOnUser.name,loggedOnUser.location) + sendMail(tempStr,tempStr2,FALSE, NIL,0,mailOptions.sysopEmail) + ENDIF +ENDPROC + +PROC doNewUserNotify() + DEF tempStr[255]:STRING + DEF tempStr2[255]:STRING + runExecuteOn('NEW_USER') + + IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_NEW_USER')) AND (StrLen(mailOptions.sysopEmail)>0) + StringF(tempStr,'\s: Ami-Express new user notification',cmds.bbsName) + StringF(tempStr2,'This is a notification that a new user called \s from \s has registered.',loggedOnUser.name,loggedOnUser.location) + sendMail(tempStr,tempStr2,FALSE,msgBuf,lines,mailOptions.sysopEmail) + ENDIF +ENDPROC + +PROC doLogoffNotify() + DEF tempstr[255]:STRING + DEF tempstr2[255]:STRING + runExecuteOn('LOGOFF') + IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_LOGOFF')) AND (StrLen(mailOptions.sysopEmail)>0) + StringF(tempstr,'\s: Ami-Express logoff notification',cmds.bbsName) + StringF(tempstr2,'This is a notification that \s from \s has logged off\n\n',loggedOnUser.name,loggedOnUser.location) + sendMail(tempstr,tempstr2,FALSE, NIL,0,mailOptions.sysopEmail) + ENDIF +ENDPROC + PROC displayFile(filename, allowMCI=TRUE, resetNonStop=TRUE, resetLineCount=TRUE) DEF fh DEF firstline=TRUE @@ -7960,7 +8050,6 @@ ENDPROC PROC processLoggingOff() DEF tempstr[255]:STRING - DEF tempstr2[255]:STRING writeLogoffLog('logging off 1 (start)',TRUE) @@ -8051,14 +8140,8 @@ PROC processLoggingOff() saveAccount(loggedOnUser,loggedOnUserKeys,loggedOnUserMisc,0,0) /* Reseave users account after logoff */ writeLogoffLog('logging off 13',FALSE) - runExecuteOn('LOGOFF') - writeLogoffLog('logging off 14',FALSE) - IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_LOGOFF')) AND (StrLen(mailOptions.sysopEmail)>0) - StringF(tempstr,'\s: Ami-Express logoff notification',cmds.bbsName) - StringF(tempstr2,'This is a notification that \s from \s has logged off\n\n',loggedOnUser.name,loggedOnUser.location) - sendMail(tempstr,tempstr2,FALSE, NIL,0,mailOptions.sysopEmail) - ENDIF + doLogoffNotify() StrCopy(reservedName,'') @@ -8112,6 +8195,11 @@ PROC processLoggingOff() stateData:=0 writeLogoffLog('logging off 22',FALSE) + StrCopy(telnetUsername,'') + StrCopy(telnetPassword,'') + StrCopy(telnetUsernamePrompt,'') + StrCopy(telnetPasswordPrompt,'') + quickFlag:=FALSE ansiColour:=TRUE ripMode:=FALSE @@ -10546,12 +10634,7 @@ PROC saveNewMSG(gfh,mh:PTR TO mailHeader) UnLock(msgbaselock) IF (tempUser.slotNumber=1) - runExecuteOn('SYSOP_COMMENT') - IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_SYSOP_COMMENT')) AND (StrLen(mailOptions.sysopEmail)>0) - StringF(tempStr,'\s: Ami-Express sysop message notification',cmds.bbsName) - StringF(tempStr2,'This is a notification that \s has sent you a message.\n\nSubject: \s\n\n',mh.fromName,mh.subject) - sendMail(tempStr,tempStr2,TRUE, msgBuf,lines,mailOptions.sysopEmail) - ENDIF + doCommentNotify(mh.fromName,mh.subject) ENDIF IF(rzmsg) @@ -12750,7 +12833,6 @@ gotit: fLock:=0 IF(z=1) THEN JUMP outst ENDIF -nxt: StringF(tempstr,'DLPATH.\d',drivenum++) UNTIL pstat=0 @@ -12832,7 +12914,6 @@ ENDPROC regServer() PROC regServer() DEF port:PTR TO mp - DEF tempstr[255]:STRING masterMsg.command:=SV_START WHILE((port:=FindPort('AE.Master'))=NIL) AND (SetSignal(0,SIGBREAKF_CTRL_C)=0) @@ -13505,10 +13586,16 @@ ENDPROC RESULT_GOODBYE /*PROC hexdump(buf,size) DEF i,j FOR i:=0 TO size-1 - WriteF('\h[2] ',buf[i]) - IF Mod(i,16)=15 - j:=i-15 - IF j<0 THEN j:=0 + WriteF('\r\z\h[2] ',buf[i]) + IF (Mod(i,16)=15) OR (i=(size-1)) + IF (i=size-1) + j:=i + WHILE (Mod(j,16)<15) + WriteF(' ') + j++ + ENDWHILE + ENDIF + j:=i & $fffffff0 REPEAT IF (buf[j]<32) OR (buf[j]>127) WriteF('.') @@ -14816,7 +14903,13 @@ PROC ftpUploadFileEnd(fileName:PTR TO CHAR,success) ELSE callersLog('\tUpload Failed..') ENDIF - + + IF (tTCPS > loggedOnUserKeys.upCPS2) + loggedOnUserKeys.upCPS2:=tTCPS + IF tTCPS>65535 THEN tTCPS:=65535 + loggedOnUserKeys.oldUpCPS:=tTCPS + ENDIF + FOR i:=0 TO skipdFiles.count()-1 StringF(str,'\tSkipped \s',skipdFiles.item(i)) callersLog(str) @@ -14900,6 +14993,13 @@ PROC ftpDownloadFileEnd(fileName:PTR TO CHAR, result) ENDIF ENDIF + /* is this baud higher then max cps down ? */ + IF(tTCPS > loggedOnUserKeys.dnCPS2) + loggedOnUserKeys.dnCPS2:=tTCPS + IF tTCPS>65535 THEN tTCPS:=65535 + loggedOnUserKeys.oldDnCPS:=tTCPS + ENDIF + IF (result) removeFlagFromList(FilePart(fileItem.fileName),fileItem.confNum) ENDIF @@ -18807,13 +18907,7 @@ PROC uploadaFile(uLFType,cmd,attach,alreadyUploaded=FALSE) -> JOE callersLog(str) udLog(str) - runExecuteOn('UPLOAD') - - IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_UPLOAD')) AND (StrLen(mailOptions.sysopEmail)>0) - StringF(str,'\s: Ami-Express logoff notification',cmds.bbsName) - StringF(string,'This is a notification that \s from \s has logged off\n\n',loggedOnUser.name,loggedOnUser.location) - sendMail(str,string,FALSE, NIL,0,mailOptions.sysopEmail) - ENDIF + doUploadNotify() ELSE callersLog('\tUpload Failed..') udLog('\tUpload Failed..') @@ -19985,7 +20079,7 @@ breakd: aePuts(string) aePuts('\b\n\b\n') - /* is this baud higher then max cps up ? */ + /* is this baud higher then max cps down ? */ IF(pcps > loggedOnUserKeys.dnCPS2) loggedOnUserKeys.dnCPS2:=pcps IF pcps>65535 THEN pcps:=65535 @@ -20915,6 +21009,17 @@ PROC findUserAnswers(which,answersFilename:PTR TO CHAR) IF (i>MAXNODES) OR (lock=0) THEN StrCopy(answersFilename,'') ENDPROC StrLen(answersFilename)>0 +PROC checkChanges(changes) + DEF ch + IF changes=FALSE THEN RETURN TRUE + aePuts('You have unsaved changes. Do you wish to lose them (Y/N)? ') + ch:=readChar(INPUT_TIMEOUT) + IF(ch<0) THEN RETURN TRUE + aePuts('') + + IF((ch="Y") OR (ch="y")) THEN RETURN TRUE +ENDPROC FALSE + PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: PTR TO userMisc,f6) DEF flag, command @@ -20923,6 +21028,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: DEF checkLock DEF page=0 DEF value1,value2 + DEF changes=FALSE nofkeys:=1 displayAccount(which,page,hoozer,hoozer2,hoozer3,f6) @@ -20954,31 +21060,41 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: SELECT command CASE "\t" - flag:=2 + IF f6 ORELSE checkChanges(changes) + flag:=2 + ENDIF CASE "X" /* NO-SAVE */ - aePuts('No-Save\b\n') - flag:=1 + IF f6 ORELSE checkChanges(changes) + aePuts('No-Save\b\n') + flag:=1 + ENDIF CASE " " page:=Eor(page,1) sendCLS() displayAccount(which,page,hoozer,hoozer2,hoozer3,f6) CASE "+" IF(onlineEdit=FALSE) - which:=which+1 - IF(loadAccount(which,hoozer,hoozer2,hoozer3)<>RESULT_FAILURE) - displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) - ELSE - which:=1 - loadAccount(which,hoozer,hoozer2,hoozer3) - displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) + IF checkChanges(changes) + which:=which+1 + changes:=FALSE + IF(loadAccount(which,hoozer,hoozer2,hoozer3)<>RESULT_FAILURE) + displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) + ELSE + which:=1 + loadAccount(which,hoozer,hoozer2,hoozer3) + displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) + ENDIF ENDIF ENDIF CASE "-" IF(onlineEdit=FALSE) - which:=which-1 - IF(which<1) THEN which:=findLastAccount() - loadAccount(which,hoozer,hoozer2,hoozer3) - displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) + IF checkChanges(changes) + which:=which-1 + changes:=FALSE + IF(which<1) THEN which:=findLastAccount() + loadAccount(which,hoozer,hoozer2,hoozer3) + displayAccountInfo(which,page,hoozer,hoozer2,hoozer3,f6) + ENDIF ENDIF CASE "~" /* SAVE */ aePuts('Save\b\n') @@ -21002,6 +21118,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: StringF(tempStr,'\tLOCAL Account Maintenance on Account \d',hoozer.slotNumber) ENDIF callersLog(tempStr) + changes:=FALSE CASE "!" /* Credit Maintenance */ creditMaintenance(which,hoozer,hoozer2,hoozer3,f6) displayAccount(which,page,hoozer,hoozer2,hoozer3,f6) @@ -21030,6 +21147,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: StringF(tempStr,'Preset \d. ',preset) aePuts(tempStr) + changes:=TRUE hoozer.newUser:=0 applyPreset(hoozer,TOOLTYPE_PRESET,preset) @@ -21058,6 +21176,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: stat:=which hoozer.slotNumber:=0 hoozer2.number:=0 + changes:=TRUE stat:=saveAccount(hoozer,hoozer2,hoozer3,stat,1) IF(stat<>RESULT_SUCCESS) THEN aePuts('Can''t Save account\b\n') @@ -21066,6 +21185,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: flag:=0 CASE "9" /* RE-ACTIVATE */ aePuts('Re-Activate\b\n') + changes:=TRUE hoozer.slotNumber:=which flag:=0 ENDSELECT @@ -21079,18 +21199,21 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: AstrCopy(hoozer.name,tempStr,31) UpperStr(tempStr) AstrCopy(hoozer2.userName,tempStr,31) + changes:=TRUE flag:=0 CASE "B" /* Real Name */ aePuts('') StrCopy(tempStr,hoozer3.realName) lineInput('',tempStr,25,INPUT_TIMEOUT,tempStr) AstrCopy(hoozer3.realName,tempStr,26) + changes:=TRUE flag:=0 CASE "C" /* Location */ aePuts('') StrCopy(tempStr,hoozer.location) lineInput('',tempStr,29,INPUT_TIMEOUT,tempStr) AstrCopy(hoozer.location,tempStr,30) + changes:=TRUE flag:=0 CASE "D" /* PASS */ IF((logonType>=LOGON_TYPE_REMOTE) AND (f6=FALSE)) @@ -21107,6 +21230,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: IF StrLen(tempStr)>0 setNewPassword(hoozer,hoozer3,tempStr) hoozer3.pwdLastUpdated:=getSystemTime() + changes:=TRUE ENDIF ENDIF ELSE @@ -21120,6 +21244,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: IF StrLen(tempStr)>0 setNewPassword(hoozer,hoozer3,tempStr) hoozer3.pwdLastUpdated:=getSystemTime() + changes:=TRUE ENDIF ENDIF flag:=0 @@ -21128,16 +21253,19 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: StrCopy(tempStr,hoozer.phoneNumber) lineInput('',tempStr,12,INPUT_TIMEOUT,tempStr) AstrCopy(hoozer.phoneNumber,tempStr,13) + changes:=TRUE flag:=0 CASE "F" /* conference access */ aePuts('') StrCopy(tempStr,hoozer.conferenceAccess) lineInput('',tempStr,9,INPUT_TIMEOUT,tempStr) AstrCopy(hoozer.conferenceAccess,tempStr,10) + changes:=TRUE flag:=0 CASE "G" /* RATIO */ aePuts('') hoozer.secLibrary:=numberInput(hoozer.secLibrary) + changes:=TRUE flag:=0 CASE "H" /* SEC_Level */ IF((logonType>=LOGON_TYPE_REMOTE) AND (f6=FALSE)) @@ -21149,6 +21277,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: aePuts('') hoozer.secStatus:=numberInput(hoozer.secStatus) ENDIF + changes:=TRUE flag:=0 CASE "I" /* Ratio Type */ aePuts('') @@ -21162,49 +21291,58 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: IF(hoozer.secBoard=0) THEN aePuts(' <-Byte)') IF(hoozer.secBoard=1) THEN aePuts(' <-B/F) ') IF(hoozer.secBoard=2) THEN aePuts(' <-File)') + changes:=TRUE flag:=0 CASE "J" /* conference ReJoin */ aePuts('') value1,value2:=rJoinInput(hoozer.confRJoin, hoozer.msgBaseRJoin) hoozer.confRJoin:=value1 hoozer.msgBaseRJoin:=value2 + changes:=TRUE flag:=0 CASE "K" /* UPLOADS */ aePuts('') hoozer.uploads:=numberInput(hoozer.uploads) + changes:=TRUE flag:=0 CASE "L" /* MESSAGES_POSTED */ aePuts('') hoozer.messagesPosted:=numberInput(hoozer.messagesPosted) + changes:=TRUE flag:=0 CASE "M" /* DOWNLOADS */ aePuts('') hoozer.downloads:=numberInput(hoozer.downloads) + changes:=TRUE flag:=0 CASE "N" /* New user ?? */ aePuts(' ') command:=yesNo(0) IF(command) THEN hoozer.newUser:=1 ELSE hoozer.newUser:=0 + changes:=TRUE flag:=0 CASE "#" aePuts('') hoozer.timesCalled:=numberInput(hoozer.timesCalled) + changes:=TRUE flag:=0 CASE "%" aePuts('') hoozer2.timesOnToday:=numberInput(getTodaysCalls(hoozer,hoozer2)) + changes:=TRUE flag:=0 CASE "O" /* Bytes Uploaded */ aePuts('') bcdNumberInput(hoozer3.uploadBytesBCD) hoozer.bytesUpload:=convertFromBCD(hoozer3.uploadBytesBCD) - + changes:=TRUE flag:=0 CASE "P" /* Bytes Downloaded */ aePuts('') bcdNumberInput(hoozer3.downloadBytesBCD) hoozer.bytesDownload:=convertFromBCD(hoozer3.downloadBytesBCD) + changes:=TRUE flag:=0 CASE "Q" /* Daily Bytes Limit */ aePuts(' ') @@ -21216,6 +21354,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: hoozer.dailyBytesLimit:=longNumberInput(hoozer.dailyBytesLimit) hoozer.todaysBytesLimit:=hoozer.dailyBytesLimit IF hoozer.todaysBytesLimit<>0 THEN hoozer.todaysBytesLimit:=hoozer.todaysBytesLimit+temp + changes:=TRUE flag:=0 CASE "R" /* Time_Total */ aePuts('') @@ -21227,15 +21366,19 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: hoozer.timeTotal:=hoozer.timeLimit ENDIF ENDIF + changes:=TRUE + flag:=0; CASE "S" /* zero upcps rate */ aePuts('') hoozer2.upCPS2:=longNumberInput(hoozer2.upCPS2) IF hoozer2.upCPS2>65535 THEN hoozer2.oldUpCPS:=65535 ELSE hoozer2.oldUpCPS:=hoozer2.upCPS2 + changes:=TRUE flag:=0; CASE "T" /* zero dncps rate */ aePuts('') hoozer2.dnCPS2:=longNumberInput(hoozer2.dnCPS2) IF hoozer2.dnCPS2>65535 THEN hoozer2.oldDnCPS:=65535 ELSE hoozer2.oldDnCPS:=hoozer2.dnCPS2 + changes:=TRUE flag:=0 CASE "U" /* Time_Limit */ aePuts('') @@ -21250,6 +21393,7 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: IF(loggedOnUser.slotNumber=hoozer.slotNumber) timeLimit:=hoozer.timeTotal-hoozer.timeUsed ENDIF + changes:=TRUE flag:=0 CASE "V" /* TIME_USED */ aePuts('') @@ -21257,10 +21401,12 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: IF(loggedOnUser.slotNumber=hoozer.slotNumber) timeLimit:=hoozer.timeTotal-hoozer.timeUsed ENDIF + changes:=TRUE flag:=0; CASE "W" /*uucpa*/ aePuts('') hoozer.uucpa:=uucpNumberInput(hoozer.uucpa) + changes:=TRUE flag:=0 CASE "Y" /* chat limit */ aePuts('') @@ -21268,11 +21414,13 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: hoozer.chatLimit:=Mul(numberInput(Div(hoozer.chatLimit,60)),60) hoozer.chatRemain:=hoozer.chatLimit-temp IF hoozer.chatRemain<0 THEN hoozer.chatRemain:=0 + changes:=TRUE flag:=0 CASE "Z" /* chat used */ aePuts('') hoozer.chatRemain:=hoozer.chatLimit-Mul(numberInput(Div(hoozer.chatLimit-hoozer.chatRemain,60)),60) IF hoozer.chatRemain<0 THEN hoozer.chatRemain:=0 + changes:=TRUE flag:=0 ENDSELECT ELSEIF page=1 @@ -21284,20 +21432,24 @@ PROC editInfo(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: AstrCopy(hoozer.name,tempStr,31) UpperStr(tempStr) AstrCopy(hoozer2.userName,tempStr,31) + changes:=TRUE flag:=0 CASE "B" /* Password reset */ aePuts(' ') command:=yesNo(0) IF(command) THEN hoozer3.forcePwdReset:=1 ELSE hoozer3.forcePwdReset:=0 + changes:=TRUE flag:=0 CASE "C" /* account locked */ aePuts(' ') command:=yesNo(0) IF(command) THEN hoozer3.accountLocked:=1 ELSE hoozer3.accountLocked:=0 + changes:=TRUE flag:=0 CASE "D" /* invalid attempts */ aePuts('') hoozer3.invalidAttempts:=numberInput(hoozer3.invalidAttempts) + changes:=TRUE flag:=0 ENDSELECT ENDIF @@ -21547,6 +21699,7 @@ PROC creditMaintenance(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, DEF yesno[3]:STRING DEF flag=FALSE,remain,ch,stat DEF checkLock + DEF changes=FALSE IF (logonType=LOGON_TYPE_REMOTE) AND (checkSecurity(ACS_CREDIT_ACCESS)=FALSE) AND (f6=FALSE) RETURN 0 @@ -21616,16 +21769,16 @@ PROC creditMaintenance(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, ch:=readChar(INPUT_TIMEOUT) - aePuts(' ') + aePuts(' ') IF(ch<0) THEN RETURN ch ch:=UpperChar(ch) SELECT ch CASE "\t" - flag:=2 + IF f6 ORELSE checkChanges(changes) THEN flag:=2 CASE "X" - flag:=1 + IF f6 ORELSE checkChanges(changes) THEN flag:=1 ENDSELECT IF checkLock @@ -21633,29 +21786,38 @@ PROC creditMaintenance(which:LONG, hoozer:PTR TO user, hoozer2:PTR TO userKeys, CASE "1" aePuts('') hoozer.creditDays:=numberInput(hoozer.creditDays) + changes:=TRUE CASE "2" aePuts('') hoozer.creditAmount:=numberInput(hoozer.creditAmount) + changes:=TRUE CASE "3" aePuts('') hoozer.creditTotalToDate:=numberInput(hoozer.creditTotalToDate) hoozer.creditTotalDate:=getSystemDate() + changes:=TRUE CASE "4" hoozer.creditTracking:=Eor(hoozer.creditTracking,TRACK_UPLOADS_BIT) + changes:=TRUE CASE "5" hoozer.creditTracking:=Eor(hoozer.creditTracking,TRACK_DOWNLOADS_BIT) + changes:=TRUE CASE "U" hoozer.creditTotalToDate:=hoozer.creditTotalToDate+hoozer.creditAmount hoozer.creditTotalDate:=getSystemDate() + changes:=TRUE CASE "R" hoozer.creditStartDate:=getSystemDate() + changes:=TRUE CASE "T" hoozer.creditDays:=0 + changes:=TRUE CASE "~" IF (logonType0) AND (hoozer.creditStartDate=0) THEN hoozer.creditStartDate:=getSystemDate() aePuts('Saving Account...') + changes:=FALSE formatLongDate(getSystemDate(),currdatestr) formatLongTime(getSystemDate(),currtimestr) @@ -21698,6 +21860,7 @@ PROC conferenceAccounting(hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: DEF i,m,flag=0,conf,msgbase,ch,oldval DEF checkLock DEF oldBCD[8]:ARRAY OF CHAR + DEF changes=FALSE IF loggedOnUser<>NIL THEN masterSavePointers(loggedOnUser) @@ -21869,7 +22032,9 @@ PROC conferenceAccounting(hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: ENDIF CASE "\t" - flag:=1 + IF checkChanges(changes) + flag:=1 + ENDIF ENDSELECT IF checkLock @@ -21877,6 +22042,7 @@ PROC conferenceAccounting(hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: CASE "G" aePuts('') cb.ratio:=numberInput(cb.ratio) + changes:=TRUE CASE "I" aePuts('') cb.ratioType:=numberInput(cb.ratioType) @@ -21884,16 +22050,19 @@ PROC conferenceAccounting(hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: sendBELL() cb.ratioType:=0 ENDIF + changes:=TRUE CASE "K" aePuts('') oldval:=cb.upload cb.upload:=numberInput(cb.upload) IF(checkSecurity(ACS_CONFERENCE_ACCOUNTING)) THEN hoozer.uploads:=hoozer.uploads-oldval+cb.upload + changes:=TRUE CASE "M" aePuts('') oldval:=cb.downloads cb.downloads:=numberInput(cb.downloads) IF(checkSecurity(ACS_CONFERENCE_ACCOUNTING)) THEN hoozer.downloads:=hoozer.downloads-oldval+cb.downloads + changes:=TRUE CASE "O" aePuts('') @@ -21907,6 +22076,7 @@ PROC conferenceAccounting(hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: addBCD2(hoozer3.uploadBytesBCD,cb.uploadBytesBCD) hoozer.bytesUpload:=convertFromBCD(hoozer3.uploadBytesBCD) ENDIF + changes:=TRUE CASE "P" aePuts('') FOR i:=0 TO 7 @@ -21919,15 +22089,18 @@ PROC conferenceAccounting(hoozer:PTR TO user, hoozer2:PTR TO userKeys, hoozer3: addBCD2(hoozer3.downloadBytesBCD,cb.downloadBytesBCD) hoozer.bytesDownload:=convertFromBCD(hoozer3.downloadBytesBCD) ENDIF + changes:=TRUE CASE "L" aePuts('') oldval:=cb.messagesPosted cb.messagesPosted:=numberInput(cb.messagesPosted) hoozer.messagesPosted:=hoozer.messagesPosted-oldval+cb.messagesPosted + changes:=TRUE CASE "~" aePuts('Save\b\n') masterSavePointers(hoozer) + changes:=FALSE IF (logonType>=LOGON_TYPE_REMOTE) StringF(tempstr,'\tREMOTE Conference Maintenance on Account \d, Conference \s',hoozer.slotNumber,conf) @@ -22273,13 +22446,10 @@ PROC makeFtpDirCache(confLoc:PTR TO CHAR, confnum, dirnum, dlpath:PTR TO CHAR, s DEF fh DEF lock DEF f_info: PTR TO fileinfoblock - DEF stat=0 DEF tempstr[255]:STRING DEF tempstr2[255]:STRING - DEF i,s,t - - WriteF('dlpath=\s\n',dlpath) - + DEF s,t + f_info:=AllocDosObject(DOS_FIB,NIL) IF(f_info)=NIL RETURN @@ -22339,7 +22509,6 @@ PROC conferenceMaintenance() DEF lock,fh DEF num,num2,match DEF msgBase - DEF flg2 conf:=1 msgBase:=1 @@ -28374,6 +28543,8 @@ PROC processFtpLogon() loggedOnUserKeys.baud:=19200 masterLoadPointers(loggedOnUser) + doLogonNotify() + statPrintUser(loggedOnUser,loggedOnUserKeys,loggedOnUserMisc) IF (StrLen(mybbsLoc)>0) @@ -29447,12 +29618,7 @@ logonLoop: ENDIF IF logonType>=LOGON_TYPE_REMOTE - runExecuteOn('LOGON') - IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_LOGON')) AND (StrLen(mailOptions.sysopEmail)>0) - StringF(tempStr,'\s: Ami-Express logon notification',cmds.bbsName) - StringF(tempStr2,'This is a notification that \s from \s has logged on\n\n',loggedOnUser.name,loggedOnUser.location) - sendMail(tempStr,tempStr2,FALSE, NIL,0,mailOptions.sysopEmail) - ENDIF + doLogonNotify() ENDIF statPrintUser(loggedOnUser,loggedOnUserKeys,loggedOnUserMisc) @@ -29726,14 +29892,7 @@ PROC newUserAccount(userName: PTR TO CHAR) clearMsgPointers() masterSavePointers(loggedOnUser) - runExecuteOn('NEW_USER') - - IF (checkToolTypeExists(TOOLTYPE_BBSCONFIG,0,'MAIL_ON_NEW_USER')) AND (StrLen(mailOptions.sysopEmail)>0) - StringF(tempStr,'\s: Ami-Express new user notification',cmds.bbsName) - StringF(tempStr2,'This is a notification that a new user called \s from \s has registered.',loggedOnUser.name,loggedOnUser.location) - sendMail(tempStr,tempStr2,FALSE,msgBuf,lines,mailOptions.sysopEmail) - ENDIF - + doNewUserNotify() IF displayScreen(SCREEN_JOINED) THEN doPause() ENDPROC stat From df9be8b6305bad4f61ecea8b86a04f0fbce7ec77 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Wed, 9 Aug 2023 11:13:51 +0100 Subject: [PATCH 08/47] add MUI based setup tool --- axSetupTool/axSetupTool.e | 102 ++ axSetupTool/axSetupTool.info | Bin 0 -> 790 bytes axSetupTool/axedit.e | 1630 ++++++++++++++++++++ axSetupTool/axsys.MUIB | Bin 0 -> 20713 bytes axSetupTool/configObject.e | 241 +++ axSetupTool/controls.e | 345 +++++ axSetupTool/frmAccess.e | 87 ++ axSetupTool/frmAddComplexItem.e | 928 +++++++++++ axSetupTool/frmAddItem.e | 164 ++ axSetupTool/frmBase.e | 103 ++ axSetupTool/frmCommands.e | 152 ++ axSetupTool/frmConfEdit.e | 1081 +++++++++++++ axSetupTool/frmEditList.e | 2564 +++++++++++++++++++++++++++++++ axSetupTool/frmMain.e | 388 +++++ axSetupTool/frmNodeEdit.e | 1362 ++++++++++++++++ axSetupTool/frmPresetsEdit.e | 380 +++++ axSetupTool/frmSettingsEdit.e | 1149 ++++++++++++++ axSetupTool/makefile | 65 + axSetupTool/miscfuncs.e | 39 + axSetupTool/tooltypes.e | 439 ++++++ 20 files changed, 11219 insertions(+) create mode 100644 axSetupTool/axSetupTool.e create mode 100644 axSetupTool/axSetupTool.info create mode 100644 axSetupTool/axedit.e create mode 100644 axSetupTool/axsys.MUIB create mode 100644 axSetupTool/configObject.e create mode 100644 axSetupTool/controls.e create mode 100644 axSetupTool/frmAccess.e create mode 100644 axSetupTool/frmAddComplexItem.e create mode 100644 axSetupTool/frmAddItem.e create mode 100644 axSetupTool/frmBase.e create mode 100644 axSetupTool/frmCommands.e create mode 100644 axSetupTool/frmConfEdit.e create mode 100644 axSetupTool/frmEditList.e create mode 100644 axSetupTool/frmMain.e create mode 100644 axSetupTool/frmNodeEdit.e create mode 100644 axSetupTool/frmPresetsEdit.e create mode 100644 axSetupTool/frmSettingsEdit.e create mode 100644 axSetupTool/makefile create mode 100644 axSetupTool/miscfuncs.e create mode 100644 axSetupTool/tooltypes.e diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e new file mode 100644 index 0000000..7abc5e0 --- /dev/null +++ b/axSetupTool/axSetupTool.e @@ -0,0 +1,102 @@ +OPT OSVERSION = 37,STACK=60000 +OPT PREPROCESS + +/* + about / help screens + exit menu + help texts + + user editor + callers log viewer + msgbase viewer + screens viewer + restart nodes/server +*/ + +->///////////////////////////////////////////////////////////////////////////// +->//////////////////////////////////////////////////////////// MODULE ... ///// +->///////////////////////////////////////////////////////////////////////////// +MODULE 'locale' +MODULE 'muimaster' , 'libraries/mui' +MODULE 'utility/tagitem' +MODULE 'tools/boopsi' +MODULE 'icon' + +MODULE '*frmMain','*axedit' + +PROC main() HANDLE + DEF frmMain: PTR TO frmMain + DEF app: PTR TO app_obj + IF ( muimasterbase := OpenLibrary( 'muimaster.library' , MUIMASTER_VMIN ) ) = NIL THEN Throw( "LIB" , "muim" ) + IF (iconbase := OpenLibrary( 'icon.library' , 0 )) = NIL THEN Throw( "LIB" , "icon" ) + + NEW app.create(NIL) + + NEW frmMain.create(app) + frmMain.domain() + +EXCEPT DO + + SELECT exception + + CASE "LIB" + + SELECT exceptioninfo + + CASE "muim" + + error_simple( 'Can''t open muimaster.library !' ) + + CASE "icon" + + error_simple( 'Can''t open icon.library !' ) + + ENDSELECT + + CASE "MEM" + + error_simple( 'Not enough memory !' ) + + CASE "MUI" + + SELECT exceptioninfo + + CASE MUIE_OutOfMemory + + error_simple( 'Not enough memory !' ) + + CASE MUIE_OutOfGfxMemory + + error_simple( 'Not enough chip memory !' ) + + CASE MUIE_MissingLibrary + + error_simple( 'Can''t open a needed library !' ) + + CASE MUIE_NoARexx + + error_simple( 'Can''t create arexx port !' ) + + DEFAULT + + error_simple( 'Internal problem !' ) + + ENDSELECT + + ENDSELECT + + app.dispose() + END app + END frmMain + IF iconbase THEN CloseLibrary( iconbase ) + IF muimasterbase THEN CloseLibrary( muimasterbase ) +ENDPROC + + +->///////////////////////////////////////////////////////////////////////////// +->/////////////////// Prints an error message with an intuition requester ///// +->///////////////////////////////////////////////////////////////////////////// +PROC error_simple( message : PTR TO CHAR ) IS EasyRequestArgs( NIL , [ 20 , 0 , + 'error !' , + message , + '_OK' ] , NIL , NIL ) diff --git a/axSetupTool/axSetupTool.info b/axSetupTool/axSetupTool.info new file mode 100644 index 0000000000000000000000000000000000000000..8f8c23c8e6e3a772517c6649daf83aa870ae9202 GIT binary patch literal 790 zcmeHDu}T9$5Ph2su7%`Mq)2hH)p4zM0U?*#Li_|lu}I@th}~sD3yYwQAK^z>Tu`E* z_zNDKh*dxYbH#G;ZA{R{O6(k%w{K?N%rcYLA>gbF4blZNn7LFM*R&Pt^$*f~)akgsP$KxL18z`O1>0e#wD0V3^h0ZDX{0(Ng; zAc~uODkoRDX5Je{)aZUfebltiX|L{C`3zkX#kwAil^6W2^e z+#jUGEH~UGJtUQ;O;p?#sKId`F5iOF#KP$_X)=gZagH=@ro c@E*j(M$jRS!_LO&d(Z5~4^RI${)-!b07#9YZ2$lO literal 0 HcmV?d00001 diff --git a/axSetupTool/axedit.e b/axSetupTool/axedit.e new file mode 100644 index 0000000..ae4e75e --- /dev/null +++ b/axSetupTool/axedit.e @@ -0,0 +1,1630 @@ +OPT MODULE +OPT PREPROCESS + + +->///////////////////////////////////////////////////////////////////////////// +->////////////////////////////////////////////////////// External modules ///// +->///////////////////////////////////////////////////////////////////////////// +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi' +MODULE 'utility/tagitem' , 'utility/hooks' + + +->///////////////////////////////////////////////////////////////////////////// +->//////////////////////////////////////////////////// Object definitions ///// +->///////////////////////////////////////////////////////////////////////////// +EXPORT OBJECT app_display + editConfs : hook +ENDOBJECT + +EXPORT OBJECT app_obj + app : PTR TO LONG + winMain : PTR TO LONG + mn_label_1 : PTR TO LONG + mnlabel1Donotremovefolder1 : PTR TO LONG + mnlabel1Removefolder1 : PTR TO LONG + mnlabel1Ask1 : PTR TO LONG + mnlabel1NodeDelete : PTR TO LONG + mnlabel1Donotremovefolder2 : PTR TO LONG + mnlabel1Removefolder2 : PTR TO LONG + mnlabel1Ask2 : PTR TO LONG + btnSystem : PTR TO LONG + btnServer : PTR TO LONG + btnBackup : PTR TO LONG + btnRestrict : PTR TO LONG + btnNodes : PTR TO LONG + btnConfs : PTR TO LONG + btnSecurity : PTR TO LONG + btnCommands : PTR TO LONG + btnComputers : PTR TO LONG + btnProtocols : PTR TO LONG + btnNamesNotAllowed : PTR TO LONG + btnScreenTypes : PTR TO LONG + btnLanguages : PTR TO LONG + btnDrives : PTR TO LONG + btnCheckers : PTR TO LONG + btnConnect : PTR TO LONG + btnZoom : PTR TO LONG + btnUsers : PTR TO LONG + tx_label_0 : PTR TO LONG + btnAbout : PTR TO LONG + btnHelp : PTR TO LONG + btnExit : PTR TO LONG + wi_conf_edit : PTR TO LONG + btnFirstConf : PTR TO LONG + btnPrevConf : PTR TO LONG + strConfName : PTR TO LONG + strConfNum : PTR TO LONG + btnNextConf : PTR TO LONG + btnLastConf : PTR TO LONG + btnAddConf : PTR TO LONG + btnConfClone : PTR TO LONG + btnRemoveConf : PTR TO LONG + gr_conf_pages : PTR TO LONG + gr_conf_settings : PTR TO LONG + lv_download_paths : PTR TO LONG + pa_downloadpath : PTR TO LONG + stR_PA_downloadpath : PTR TO LONG + bt_dlpath_add : PTR TO LONG + bt_dlpath_remove : PTR TO LONG + lv_upload_paths : PTR TO LONG + pa_uploadpath : PTR TO LONG + stR_PA_uploadpath : PTR TO LONG + bt_ulpath_add : PTR TO LONG + bt_ulpath_remove : PTR TO LONG + lvMsgbases : PTR TO LONG + btnMsgbaseAdd : PTR TO LONG + btnMsgbaseEdit : PTR TO LONG + btnMsgbaseDelete : PTR TO LONG + btnSaveConf : PTR TO LONG + btnCancelConf : PTR TO LONG + wi_nodeEdit : PTR TO LONG + btnFirstNode : PTR TO LONG + btnPrevNode : PTR TO LONG + str_Node_Number : PTR TO LONG + btnNextNode : PTR TO LONG + btnLastNode : PTR TO LONG + btnAddNode : PTR TO LONG + btnNodeClone : PTR TO LONG + btnRemoveNode : PTR TO LONG + gr_node_pages : PTR TO LONG + gr_node_settings : PTR TO LONG + gr_node_more_settings : PTR TO LONG + gr_node_serial_settings : PTR TO LONG + gr_node_window_settings : PTR TO LONG + gr_node_time_settings : PTR TO LONG + str300start : PTR TO LONG + str300end : PTR TO LONG + str1200start : PTR TO LONG + str1200end : PTR TO LONG + str2400start : PTR TO LONG + str2400end : PTR TO LONG + str4800start : PTR TO LONG + str4800end : PTR TO LONG + str9600start : PTR TO LONG + str9600end : PTR TO LONG + str12000start : PTR TO LONG + str12000end : PTR TO LONG + str14400start : PTR TO LONG + str14400end : PTR TO LONG + str16800start : PTR TO LONG + str16800end : PTR TO LONG + str19200start : PTR TO LONG + str19200end : PTR TO LONG + str21600start : PTR TO LONG + str21600end : PTR TO LONG + str24000start : PTR TO LONG + str24000end : PTR TO LONG + str26400start : PTR TO LONG + str26400end : PTR TO LONG + str28800start : PTR TO LONG + str28800end : PTR TO LONG + str31200start : PTR TO LONG + str31200end : PTR TO LONG + str33600start : PTR TO LONG + str33600end : PTR TO LONG + str38400start : PTR TO LONG + str38400end : PTR TO LONG + str57600start : PTR TO LONG + str57600end : PTR TO LONG + str115200start : PTR TO LONG + str115200end : PTR TO LONG + btnNodeSave : PTR TO LONG + btnNodeCancel : PTR TO LONG + wi_listEdit : PTR TO LONG + grp_arrange : PTR TO LONG + lv_list : PTR TO LONG + grp_computers_add : PTR TO LONG + strListItem : PTR TO LONG + btnItemAdd : PTR TO LONG + btnItemEdit : PTR TO LONG + btnItemRemove : PTR TO LONG + btnListSave : PTR TO LONG + btnListCancel : PTR TO LONG + wi_security : PTR TO LONG + btnAccess : PTR TO LONG + btnAreas : PTR TO LONG + btnPresets : PTR TO LONG + wi_systemdata : PTR TO LONG + gr_settings : PTR TO LONG + btnSettingsSave : PTR TO LONG + btnSettingsCancel : PTR TO LONG + wi_add_item : PTR TO LONG + gr_item_detail1 : PTR TO LONG + la_item_detail1 : PTR TO LONG + stR_item_detail1e : PTR TO LONG + gr_item_detail2 : PTR TO LONG + la_item_detail2 : PTR TO LONG + stR_item_detail2 : PTR TO LONG + bt_new_item_save : PTR TO LONG + bt_new_item_cancel : PTR TO LONG + wi_presets : PTR TO LONG + ra_presets : PTR TO LONG + gr_preset_settings : PTR TO LONG + btnPresetSave : PTR TO LONG + btnPresetClose : PTR TO LONG + wi_areas : PTR TO LONG + la_area : PTR TO LONG + stR_area : PTR TO LONG + gr_area_main : PTR TO LONG + bt_area_save : PTR TO LONG + bt_area_cancel : PTR TO LONG + wi_commands : PTR TO LONG + grpCommands : PTR TO LONG + btnBBSCmd : PTR TO LONG + btnSysCmd : PTR TO LONG + stR_TX_label_0 : PTR TO CHAR + stR_gr_conf_pages : PTR TO LONG + stR_gr_node_pages : PTR TO LONG + ra_presetsContent : PTR TO LONG +ENDOBJECT + + +->///////////////////////////////////////////////////////////////////////////// +->/////////// Creates one instance of one object or the whole application ///// +->///////////////////////////////////////////////////////////////////////////// +PROC create( display : PTR TO app_display ) OF app_obj + + DEF mnlabel1File , mnlabel1Help , mnlabel1About , mnlabel1Exit + DEF mnlabel1Settings , mnlabel1ConferenceDelete , grOUP_ROOT_0 + DEF gr_grp_1 , gr_grp_2 , im_label_2 , grOUP_ROOT_2 + DEF gr_confselect , obj_aux0 , obj_aux1 , obj_aux2 , obj_aux3 + DEF gr_grp_13 , gr_downloadpaths , gr_grp_20 , gr_uploadpaths + DEF gr_grp_22 , gr_messagebases , gr_grp_46 , gr_save + DEF grOUP_ROOT_3 , gr_nodeSelect , obj_aux4 , obj_aux5 + DEF lbl300start , lbl300end , lbl1200start , lbl1200end + DEF lbl2400start , lbl2400end , lbl4800start , lbl4800end + DEF lbl9600start , lbl9600end , lbl12000start , lbl12000end + DEF lbl14400start , lbl14400end , lbl16800start , lbl16800end + DEF lbl19200start , lbl19200end , lbl21600start , lbl21600end + DEF lbl24000start , lbl24000end , lbl26400start , lbl26400end + DEF lbl28800start , lbl28800end , lbl31200start , lbl31200end + DEF lbl33600start , lbl33600end , lbl38400start , lbl38400end + DEF lbl57600start , lbl57600end , lbl115200start , lbl115200end + DEF gr_nodesave , grp_root_listitems , space_28 , gr_grp_28 + DEF grOUP_ROOT_5 , grOUP_ROOT_6 , gr_settingsSaveCancel + DEF grOUP_ROOT_7 , gr_item_buttons , grOUP_ROOT_8 , gr_grp_39 + DEF gr_grp_36 , gr_grp_38 , grOUP_ROOT_9 , gr_grp_43 + DEF gr_area_save + + self.stR_TX_label_0 := '\ec/X\nSetup Tool' + self.stR_gr_conf_pages := [ + 'Main' , + 'Download Paths' , + 'Upload Paths' , + 'Message bases' , + NIL ] + self.stR_gr_node_pages := [ + 'Node Settings' , + 'More Settings' , + 'Serial/Modem' , + 'Window Settings' , + 'Time restrictions' , + NIL ] + self.ra_presetsContent := [ + '1' , + '2' , + '3' , + '4' , + '5' , + '6' , + '7' , + '8' , + '9' , + NIL ] + + self.btnSystem := SimpleButton( 'System' ) + + self.btnServer := SimpleButton( 'Server' ) + + self.btnBackup := SimpleButton( 'Backup' ) + + self.btnRestrict := SimpleButton( 'Restricted' ) + + self.btnNodes := SimpleButton( 'Nodes' ) + + self.btnConfs := SimpleButton( 'Conferences' ) + + self.btnSecurity := SimpleButton( 'Security' ) + + self.btnCommands := SimpleButton( 'Commands' ) + + self.btnComputers := SimpleButton( 'Computers' ) + + self.btnProtocols := SimpleButton( 'Protocols' ) + + self.btnNamesNotAllowed := SimpleButton( 'Names Not Allowed' ) + + self.btnScreenTypes := SimpleButton( 'Screen Types' ) + + self.btnLanguages := SimpleButton( 'Languages' ) + + self.btnDrives := SimpleButton( 'Drives' ) + + self.btnCheckers := SimpleButton( 'File Checkers' ) + + self.btnConnect := SimpleButton( 'Connect' ) + + self.btnZoom := SimpleButton( 'Zoom' ) + + self.btnUsers := SimpleButton( 'Users' ) + + gr_grp_1 := GroupObject , + MUIA_HelpNode , 'GR_grp_1' , + MUIA_Weight , 66 , + MUIA_Frame , MUIV_Frame_Button , + MUIA_Group_Columns , 3 , + Child , self.btnSystem , + Child , self.btnServer , + Child , self.btnBackup , + Child , self.btnRestrict , + Child , self.btnNodes , + Child , self.btnConfs , + Child , self.btnSecurity , + Child , self.btnCommands , + Child , self.btnComputers , + Child , self.btnProtocols , + Child , self.btnNamesNotAllowed , + Child , self.btnScreenTypes , + Child , self.btnLanguages , + Child , self.btnDrives , + Child , self.btnCheckers , + Child , self.btnConnect , + Child , self.btnZoom , + Child , self.btnUsers , + End + + self.tx_label_0 := TextObject , + MUIA_Background , MUII_TextBack , + MUIA_Frame , MUIV_Frame_Group , + MUIA_Text_Contents , self.stR_TX_label_0 , + MUIA_Text_SetMin , MUI_TRUE , + End + + im_label_2 := ImageObject , + MUIA_Image_Spec , '5:bbs:Storage/Icons/ICONIFIED.info' , + MUIA_Frame , MUIV_Frame_ImageButton , + MUIA_Image_FreeVert , MUI_TRUE , + MUIA_Image_FreeHoriz , MUI_TRUE , + MUIA_FixHeight , 21 , + MUIA_FixWidth , 38 , + End + + self.btnAbout := SimpleButton( 'About' ) + + self.btnHelp := SimpleButton( 'Help' ) + + self.btnExit := SimpleButton( 'Exit' ) + + gr_grp_2 := GroupObject , + MUIA_HelpNode , 'GR_grp_2' , + MUIA_Weight , 32 , + MUIA_Frame , MUIV_Frame_Button , + MUIA_Group_SameWidth , MUI_TRUE , + MUIA_Group_VertSpacing , 5 , + Child , self.tx_label_0 , + Child , im_label_2 , + Child , self.btnAbout , + Child , self.btnHelp , + Child , self.btnExit , + End + + grOUP_ROOT_0 := GroupObject , + MUIA_Group_Horiz , MUI_TRUE , + Child , gr_grp_1 , + Child , gr_grp_2 , + End + + mnlabel1Help := MenuitemObject , + MUIA_Menuitem_Title , 'Help' , + End + + mnlabel1About := MenuitemObject , + MUIA_Menuitem_Title , 'About' , + End + + mnlabel1Exit := MenuitemObject , + MUIA_Menuitem_Title , 'Exit' , + End + + mnlabel1File := MenuitemObject , + MUIA_Menuitem_Title , 'File' , + MUIA_Family_Child , mnlabel1Help , + MUIA_Family_Child , mnlabel1About , + MUIA_Family_Child , mnlabel1Exit , + End + + self.mnlabel1Donotremovefolder1 := MenuitemObject , + MUIA_Menuitem_Title , 'Do not remove folder' , + MUIA_Menuitem_Checkit , MUI_TRUE , + End + + self.mnlabel1Removefolder1 := MenuitemObject , + MUIA_Menuitem_Title , 'Remove Folder' , + MUIA_Menuitem_Checkit , MUI_TRUE , + End + + self.mnlabel1Ask1 := MenuitemObject , + MUIA_Menuitem_Title , 'Ask' , + MUIA_Menuitem_Checkit , MUI_TRUE , + End + + mnlabel1ConferenceDelete := MenuitemObject , + MUIA_Menuitem_Title , 'Conference Delete' , + MUIA_Family_Child , self.mnlabel1Donotremovefolder1 , + MUIA_Family_Child , self.mnlabel1Removefolder1 , + MUIA_Family_Child , self.mnlabel1Ask1 , + End + + self.mnlabel1Donotremovefolder2 := MenuitemObject , + MUIA_Menuitem_Title , 'Do not remove folder' , + MUIA_Menuitem_Checkit , MUI_TRUE , + End + + self.mnlabel1Removefolder2 := MenuitemObject , + MUIA_Menuitem_Title , 'Remove Folder' , + MUIA_Menuitem_Checkit , MUI_TRUE , + End + + self.mnlabel1Ask2 := MenuitemObject , + MUIA_Menuitem_Title , 'Ask' , + MUIA_Menuitem_Checkit , MUI_TRUE , + End + + self.mnlabel1NodeDelete := MenuitemObject , + MUIA_Menuitem_Title , 'Node Delete' , + MUIA_Family_Child , self.mnlabel1Donotremovefolder2 , + MUIA_Family_Child , self.mnlabel1Removefolder2 , + MUIA_Family_Child , self.mnlabel1Ask2 , + End + + mnlabel1Settings := MenuitemObject , + MUIA_Menuitem_Title , 'Settings' , + MUIA_Family_Child , mnlabel1ConferenceDelete , + MUIA_Family_Child , self.mnlabel1NodeDelete , + End + + self.mn_label_1 := MenustripObject , + MUIA_Family_Child , mnlabel1File , + MUIA_Family_Child , mnlabel1Settings , + End + + self.winMain := WindowObject , + MUIA_Window_Title , 'Ami-Express Setup Tool' , + MUIA_Window_Menustrip , self.mn_label_1 , + MUIA_Window_ID , "0WIN" , + MUIA_Window_AppWindow , MUI_TRUE , + WindowContents , grOUP_ROOT_0 , + End + + self.btnFirstConf := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '<<' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnFirstConf' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnPrevConf := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '<' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnPrevConf' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.strConfName := StringObject , + MUIA_Disabled , MUI_TRUE , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'strConfName' , + End + + obj_aux1 := Label2( 'Conference' ) + + obj_aux0 := GroupObject , + MUIA_Group_Columns , 2 , + Child , obj_aux1 , + Child , self.strConfName , + End + + self.strConfNum := StringObject , + MUIA_Disabled , MUI_TRUE , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'strConfNum' , + MUIA_String_Accept , '-0123456789' , + End + + obj_aux3 := Label2( 'Number' ) + + obj_aux2 := GroupObject , + MUIA_Group_Columns , 2 , + MUIA_Weight , 0 , + Child , obj_aux3 , + Child , self.strConfNum , + End + + self.btnNextConf := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '>' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnNextConf' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnLastConf := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '>>' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnLastConf' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnAddConf := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Add' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnAddConf' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnConfClone := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Clone' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnConfClone' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnRemoveConf := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Remove' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnRemoveConf' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + gr_confselect := GroupObject , + MUIA_HelpNode , 'GR_confselect' , + MUIA_Frame , MUIV_Frame_Group , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnFirstConf , + Child , self.btnPrevConf , + Child , obj_aux0 , + Child , obj_aux2 , + Child , self.btnNextConf , + Child , self.btnLastConf , + Child , self.btnAddConf , + Child , self.btnConfClone , + Child , self.btnRemoveConf , + End + + self.gr_conf_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_conf_settings' , + MUIA_Group_Columns , 4 , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_conf_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_conf_settings , + End + + self.lv_download_paths := ListObject , + MUIA_Frame , MUIV_Frame_InputList , + End + + self.lv_download_paths := ListviewObject , + MUIA_HelpNode , 'LV_download_paths' , + MUIA_Listview_MultiSelect , MUIV_Listview_MultiSelect_Default , + MUIA_Listview_List , self.lv_download_paths , + End + + self.stR_PA_downloadpath := StringMUI( '' , 80 ) + + self.pa_downloadpath := PopButton( MUII_PopDrawer ) + + self.pa_downloadpath := PopaslObject , + MUIA_HelpNode , 'PA_downloadpath' , + MUIA_Popasl_Type , 0 , + MUIA_Popstring_String , self.stR_PA_downloadpath , + MUIA_Popstring_Button , self.pa_downloadpath , + End + + self.bt_dlpath_add := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Add' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'BT_dlpath_add' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.bt_dlpath_remove := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Remove' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'BT_dlpath_remove' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + gr_grp_20 := GroupObject , + MUIA_HelpNode , 'GR_grp_20' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.pa_downloadpath , + Child , self.bt_dlpath_add , + Child , self.bt_dlpath_remove , + End + + gr_downloadpaths := GroupObject , + MUIA_HelpNode , 'GR_downloadpaths' , + Child , self.lv_download_paths , + Child , gr_grp_20 , + End + + self.lv_upload_paths := ListObject , + MUIA_Frame , MUIV_Frame_InputList , + End + + self.lv_upload_paths := ListviewObject , + MUIA_HelpNode , 'LV_upload_paths' , + MUIA_Listview_MultiSelect , MUIV_Listview_MultiSelect_Default , + MUIA_Listview_List , self.lv_upload_paths , + End + + self.stR_PA_uploadpath := StringMUI( '' , 80 ) + + self.pa_uploadpath := PopButton( MUII_PopDrawer ) + + self.pa_uploadpath := PopaslObject , + MUIA_HelpNode , 'PA_uploadpath' , + MUIA_Popasl_Type , 0 , + MUIA_Popstring_String , self.stR_PA_uploadpath , + MUIA_Popstring_Button , self.pa_uploadpath , + End + + self.bt_ulpath_add := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Add' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'BT_ulpath_add' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.bt_ulpath_remove := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Remove' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'BT_ulpath_remove' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + gr_grp_22 := GroupObject , + MUIA_HelpNode , 'GR_grp_22' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.pa_uploadpath , + Child , self.bt_ulpath_add , + Child , self.bt_ulpath_remove , + End + + gr_uploadpaths := GroupObject , + MUIA_HelpNode , 'GR_uploadpaths' , + Child , self.lv_upload_paths , + Child , gr_grp_22 , + End + + self.lvMsgbases := ListObject , + MUIA_Frame , MUIV_Frame_InputList , + End + + self.lvMsgbases := ListviewObject , + MUIA_HelpNode , 'lvMsgbases' , + MUIA_Listview_MultiSelect , MUIV_Listview_MultiSelect_Default , + MUIA_Listview_List , self.lvMsgbases , + End + + self.btnMsgbaseAdd := SimpleButton( 'Add' ) + + self.btnMsgbaseEdit := SimpleButton( 'Ediit' ) + + self.btnMsgbaseDelete := SimpleButton( 'Remove' ) + + gr_grp_46 := GroupObject , + MUIA_HelpNode , 'GR_grp_46' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnMsgbaseAdd , + Child , self.btnMsgbaseEdit , + Child , self.btnMsgbaseDelete , + End + + gr_messagebases := GroupObject , + MUIA_HelpNode , 'GR_messagebases' , + Child , self.lvMsgbases , + Child , gr_grp_46 , + End + + self.gr_conf_pages := RegisterObject , + MUIA_Register_Titles , self.stR_gr_conf_pages , + MUIA_HelpNode , 'gr_conf_pages' , + Child , self.gr_conf_settings , + Child , gr_downloadpaths , + Child , gr_uploadpaths , + Child , gr_messagebases , + End + + gr_grp_13 := GroupObject , + MUIA_HelpNode , 'GR_grp_13' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.gr_conf_pages , + End + + self.btnSaveConf := SimpleButton( 'Save' ) + + self.btnCancelConf := SimpleButton( 'Close' ) + + gr_save := GroupObject , + MUIA_HelpNode , 'GR_save' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnSaveConf , + Child , self.btnCancelConf , + End + + grOUP_ROOT_2 := GroupObject , + Child , gr_confselect , + Child , gr_grp_13 , + Child , gr_save , + End + + self.wi_conf_edit := WindowObject , + MUIA_Window_Title , 'Conference Editor' , + MUIA_Window_ID , "1WIN" , + WindowContents , grOUP_ROOT_2 , + End + + self.btnFirstNode := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '<<' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnFirstNode' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnPrevNode := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '<' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnPrevNode' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.str_Node_Number := StringObject , + MUIA_Disabled , MUI_TRUE , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str_Node_Number' , + MUIA_String_Accept , '-0123456789' , + End + + obj_aux5 := Label2( 'Node Number' ) + + obj_aux4 := GroupObject , + MUIA_Group_Columns , 2 , + Child , obj_aux5 , + Child , self.str_Node_Number , + End + + self.btnNextNode := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '>' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnNextNode' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnLastNode := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , '>>' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnLastNode' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnAddNode := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Add' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnAddNode' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnNodeClone := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Clone' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnNodeClone' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnRemoveNode := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Remove' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnRemoveNode' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + gr_nodeSelect := GroupObject , + MUIA_HelpNode , 'GR_nodeSelect' , + MUIA_Frame , MUIV_Frame_Group , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnFirstNode , + Child , self.btnPrevNode , + Child , obj_aux4 , + Child , self.btnNextNode , + Child , self.btnLastNode , + Child , self.btnAddNode , + Child , self.btnNodeClone , + Child , self.btnRemoveNode , + End + + self.gr_node_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_node_settings' , + MUIA_Group_Columns , 2 , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_node_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_node_settings , + End + + self.gr_node_more_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_node_more_settings' , + MUIA_Group_Columns , 2 , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_node_more_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_node_more_settings , + End + + self.gr_node_serial_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_node_serial_settings' , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_node_serial_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_node_serial_settings , + End + + self.gr_node_window_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_node_window_settings' , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_node_window_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_node_window_settings , + End + + lbl300start := Label( '300 Baud' ) + + self.str300start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str300start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl300end := Label( '\ecto' ) + + self.str300end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str300end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl1200start := Label( '1200 Baud' ) + + self.str1200start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str1200start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl1200end := Label( '\ecto' ) + + self.str1200end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str1200end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl2400start := Label( '2400 Baud' ) + + self.str2400start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str2400start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl2400end := Label( '\ecto' ) + + self.str2400end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str2400end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl4800start := Label( '4800 Baud' ) + + self.str4800start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str4800start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl4800end := Label( '\ecto' ) + + self.str4800end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str4800end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl9600start := Label( '9600 Baud' ) + + self.str9600start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str9600start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl9600end := Label( '\ecto' ) + + self.str9600end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str9600end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl12000start := Label( '12000 Baud' ) + + self.str12000start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str12000start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl12000end := Label( '\ecto' ) + + self.str12000end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str12000end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl14400start := Label( '14400 Baud' ) + + self.str14400start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str14400start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl14400end := Label( '\ecto' ) + + self.str14400end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str14400end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl16800start := Label( '16800 Baud' ) + + self.str16800start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str16800start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl16800end := Label( '\ecto' ) + + self.str16800end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str16800end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl19200start := Label( '19200 Baud' ) + + self.str19200start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str19200start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl19200end := Label( '\ecto' ) + + self.str19200end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str19200end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl21600start := Label( '21600 Baud' ) + + self.str21600start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str21600start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl21600end := Label( '\ecto' ) + + self.str21600end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str21600end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl24000start := Label( '24000 Baud' ) + + self.str24000start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str24000start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl24000end := Label( '\ecto' ) + + self.str24000end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str24000end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl26400start := Label( '26400 Baud' ) + + self.str26400start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str26400start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl26400end := Label( '\ecto' ) + + self.str26400end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str26400end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl28800start := Label( '28800 Baud' ) + + self.str28800start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str28800start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl28800end := Label( '\ecto' ) + + self.str28800end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str28800end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl31200start := Label( '31200 Baud' ) + + self.str31200start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str31200start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl31200end := Label( '\ecto' ) + + self.str31200end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str31200end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl33600start := Label( '33600 Baud' ) + + self.str33600start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str33600start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl33600end := Label( '\ecto' ) + + self.str33600end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str33600end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl38400start := Label( '38400 Baud' ) + + self.str38400start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str38400start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl38400end := Label( '\ecto' ) + + self.str38400end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str38400end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl57600start := Label( '57600 Baud' ) + + self.str57600start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str57600start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl57600end := Label( '\ecto' ) + + self.str57600end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str57600end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl115200start := Label( '115200 Baud' ) + + self.str115200start := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str115200start' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + lbl115200end := Label( '\ecto' ) + + self.str115200end := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'str115200end' , + MUIA_String_Accept , '0123456789' , + MUIA_String_MaxLen , 5 , + End + + self.gr_node_time_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_node_time_settings' , + MUIA_Group_Columns , 4 , + MUIA_Group_SameWidth , MUI_TRUE , + MUIA_Group_HorizSpacing , 4 , + Child , lbl300start , + Child , self.str300start , + Child , lbl300end , + Child , self.str300end , + Child , lbl1200start , + Child , self.str1200start , + Child , lbl1200end , + Child , self.str1200end , + Child , lbl2400start , + Child , self.str2400start , + Child , lbl2400end , + Child , self.str2400end , + Child , lbl4800start , + Child , self.str4800start , + Child , lbl4800end , + Child , self.str4800end , + Child , lbl9600start , + Child , self.str9600start , + Child , lbl9600end , + Child , self.str9600end , + Child , lbl12000start , + Child , self.str12000start , + Child , lbl12000end , + Child , self.str12000end , + Child , lbl14400start , + Child , self.str14400start , + Child , lbl14400end , + Child , self.str14400end , + Child , lbl16800start , + Child , self.str16800start , + Child , lbl16800end , + Child , self.str16800end , + Child , lbl19200start , + Child , self.str19200start , + Child , lbl19200end , + Child , self.str19200end , + Child , lbl21600start , + Child , self.str21600start , + Child , lbl21600end , + Child , self.str21600end , + Child , lbl24000start , + Child , self.str24000start , + Child , lbl24000end , + Child , self.str24000end , + Child , lbl26400start , + Child , self.str26400start , + Child , lbl26400end , + Child , self.str26400end , + Child , lbl28800start , + Child , self.str28800start , + Child , lbl28800end , + Child , self.str28800end , + Child , lbl31200start , + Child , self.str31200start , + Child , lbl31200end , + Child , self.str31200end , + Child , lbl33600start , + Child , self.str33600start , + Child , lbl33600end , + Child , self.str33600end , + Child , lbl38400start , + Child , self.str38400start , + Child , lbl38400end , + Child , self.str38400end , + Child , lbl57600start , + Child , self.str57600start , + Child , lbl57600end , + Child , self.str57600end , + Child , lbl115200start , + Child , self.str115200start , + Child , lbl115200end , + Child , self.str115200end , + End + + self.gr_node_time_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_node_time_settings , + End + + self.gr_node_pages := RegisterObject , + MUIA_Register_Titles , self.stR_gr_node_pages , + MUIA_HelpNode , 'gr_node_pages' , + Child , self.gr_node_settings , + Child , self.gr_node_more_settings , + Child , self.gr_node_serial_settings , + Child , self.gr_node_window_settings , + Child , self.gr_node_time_settings , + End + + self.btnNodeSave := SimpleButton( 'Save' ) + + self.btnNodeCancel := SimpleButton( 'Close' ) + + gr_nodesave := GroupObject , + MUIA_HelpNode , 'GR_nodesave' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnNodeSave , + Child , self.btnNodeCancel , + End + + grOUP_ROOT_3 := GroupObject , + Child , gr_nodeSelect , + Child , self.gr_node_pages , + Child , gr_nodesave , + End + + self.wi_nodeEdit := WindowObject , + MUIA_Window_Title , 'Node Editor' , + MUIA_Window_ID , "2WIN" , + WindowContents , grOUP_ROOT_3 , + End + + self.lv_list := ListObject , + MUIA_Frame , MUIV_Frame_InputList , + End + + self.lv_list := ListviewObject , + MUIA_HelpNode , 'LV_list' , + MUIA_Listview_MultiSelect , MUIV_Listview_MultiSelect_Default , + MUIA_Listview_List , self.lv_list , + End + + self.strListItem := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'strListItem' , + End + + self.btnItemAdd := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Add' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnItemAdd' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnItemEdit := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Edit' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnItemEdit' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + self.btnItemRemove := TextObject , + ButtonFrame , + MUIA_Weight , 0 , + MUIA_Background , MUII_ButtonBack , + MUIA_Text_Contents , 'Remove' , + MUIA_Text_PreParse , '\ec' , + MUIA_HelpNode , 'btnItemRemove' , + MUIA_InputMode , MUIV_InputMode_RelVerify , + End + + space_28 := VSpace( 0 ) + + self.grp_computers_add := GroupObject , + MUIA_HelpNode , 'grp_computers_add' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.strListItem , + Child , self.btnItemAdd , + Child , self.btnItemEdit , + Child , self.btnItemRemove , + Child , space_28 , + End + + self.grp_arrange := GroupObject , + MUIA_HelpNode , 'grp_arrange' , + Child , self.lv_list , + Child , self.grp_computers_add , + End + + self.btnListSave := SimpleButton( 'Save' ) + + self.btnListCancel := SimpleButton( 'Close' ) + + gr_grp_28 := GroupObject , + MUIA_HelpNode , 'GR_grp_28' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnListSave , + Child , self.btnListCancel , + End + + grp_root_listitems := GroupObject , + Child , self.grp_arrange , + Child , gr_grp_28 , + End + + self.wi_listEdit := WindowObject , + MUIA_Window_Title , 'Edit ' , + MUIA_Window_ID , "3WIN" , + WindowContents , grp_root_listitems , + End + + self.btnAccess := SimpleButton( 'Access Levels' ) + + self.btnAreas := SimpleButton( 'Areas' ) + + self.btnPresets := SimpleButton( 'Presets' ) + + grOUP_ROOT_5 := GroupObject , + Child , self.btnAccess , + Child , self.btnAreas , + Child , self.btnPresets , + End + + self.wi_security := WindowObject , + MUIA_Window_Title , 'Security' , + MUIA_Window_ID , "4WIN" , + WindowContents , grOUP_ROOT_5 , + End + + self.gr_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_settings' , + MUIA_Group_Columns , 2 , + End + + self.gr_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_settings , + End + + self.btnSettingsSave := SimpleButton( 'Save' ) + + self.btnSettingsCancel := SimpleButton( 'Close' ) + + gr_settingsSaveCancel := GroupObject , + MUIA_HelpNode , 'GR_settingsSaveCancel' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnSettingsSave , + Child , self.btnSettingsCancel , + End + + grOUP_ROOT_6 := GroupObject , + Child , self.gr_settings , + Child , gr_settingsSaveCancel , + End + + self.wi_systemdata := WindowObject , + MUIA_Window_Title , 'System Data' , + MUIA_Window_ID , "5WIN" , + WindowContents , grOUP_ROOT_6 , + End + + self.la_item_detail1 := Label( 'item label' ) + + self.stR_item_detail1e := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'STR_item_detail1e' , + End + + self.gr_item_detail1 := GroupObject , + MUIA_HelpNode , 'GR_item_detail1' , + MUIA_Group_Columns , 2 , + Child , self.la_item_detail1 , + Child , self.stR_item_detail1e , + End + + self.la_item_detail2 := Label( 'detail' ) + + self.stR_item_detail2 := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'STR_item_detail2' , + End + + self.gr_item_detail2 := GroupObject , + MUIA_HelpNode , 'GR_item_detail2' , + MUIA_Group_Columns , 2 , + Child , self.la_item_detail2 , + Child , self.stR_item_detail2 , + End + + self.bt_new_item_save := SimpleButton( 'Ok' ) + + self.bt_new_item_cancel := SimpleButton( 'Cancel' ) + + gr_item_buttons := GroupObject , + MUIA_HelpNode , 'GR_item_buttons' , + MUIA_Group_Columns , 2 , + Child , self.bt_new_item_save , + Child , self.bt_new_item_cancel , + End + + grOUP_ROOT_7 := GroupObject , + Child , self.gr_item_detail1 , + Child , self.gr_item_detail2 , + Child , gr_item_buttons , + End + + self.wi_add_item := WindowObject , + MUIA_Window_Title , 'Add ' , + MUIA_Window_ID , "6WIN" , + WindowContents , grOUP_ROOT_7 , + End + + self.ra_presets := RadioObject , + MUIA_HelpNode , 'RA_presets' , + MUIA_Radio_Entries , self.ra_presetsContent , + End + + gr_grp_36 := GroupObject , + MUIA_HelpNode , 'GR_grp_36' , + Child , self.ra_presets , + End + + self.gr_preset_settings := GroupObject , + MUIA_HelpNode , 'GR_preset_settings' , + MUIA_Group_Columns , 2 , + End + + gr_grp_39 := GroupObject , + MUIA_HelpNode , 'GR_grp_39' , + MUIA_Group_Horiz , MUI_TRUE , + Child , gr_grp_36 , + Child , self.gr_preset_settings , + End + + self.btnPresetSave := SimpleButton( 'Save' ) + + self.btnPresetClose := SimpleButton( 'Close' ) + + gr_grp_38 := GroupObject , + MUIA_HelpNode , 'GR_grp_38' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.btnPresetSave , + Child , self.btnPresetClose , + End + + grOUP_ROOT_8 := GroupObject , + Child , gr_grp_39 , + Child , gr_grp_38 , + End + + self.wi_presets := WindowObject , + MUIA_Window_Title , 'Edit Presets' , + MUIA_Window_ID , "7WIN" , + WindowContents , grOUP_ROOT_8 , + End + + self.la_area := Label( 'Area Name' ) + + self.stR_area := StringObject , + MUIA_Frame , MUIV_Frame_String , + MUIA_HelpNode , 'STR_area' , + End + + gr_grp_43 := GroupObject , + MUIA_HelpNode , 'GR_grp_43' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.la_area , + Child , self.stR_area , + End + + self.gr_area_main := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_area_main' , + MUIA_Group_Columns , 2 , + End + + self.gr_area_main := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_area_main , + End + + self.bt_area_save := SimpleButton( 'Ok' ) + + self.bt_area_cancel := SimpleButton( 'Cancel' ) + + gr_area_save := GroupObject , + MUIA_HelpNode , 'GR_area_save' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.bt_area_save , + Child , self.bt_area_cancel , + End + + grOUP_ROOT_9 := GroupObject , + Child , gr_grp_43 , + Child , self.gr_area_main , + Child , gr_area_save , + End + + self.wi_areas := WindowObject , + MUIA_Window_Title , 'window_title' , + MUIA_Window_ID , "8WIN" , + WindowContents , grOUP_ROOT_9 , + End + + self.btnBBSCmd := SimpleButton( 'Edit BBSCmd' ) + + self.btnSysCmd := SimpleButton( 'Edit SysCmd' ) + + self.grpCommands := GroupObject , + Child , self.btnBBSCmd , + Child , self.btnSysCmd , + End + + self.wi_commands := WindowObject , + MUIA_Window_Title , 'Commands' , + MUIA_Window_ID , "9WIN" , + WindowContents , self.grpCommands , + End + + self.app := ApplicationObject , + //( IF icon THEN MUIA_Application_DiskObject ELSE TAG_IGNORE ) , icon , + //( IF arexx THEN MUIA_Application_Commands ELSE TAG_IGNORE ) , ( IF arexx THEN arexx.commands ELSE NIL ) , + //( IF arexx THEN MUIA_Application_RexxHook ELSE TAG_IGNORE ) , ( IF arexx THEN arexx.error ELSE NIL ) , + //( IF menu THEN MUIA_Application_Menu ELSE TAG_IGNORE ) , menu , + MUIA_Application_Author , 'Darren Coles' , + MUIA_Application_Base , 'NONE' , + MUIA_Application_Title , 'Ami-Express Configuration Editor' , + MUIA_Application_Version , '$VER: NONE XX.XX (XX.XX.XX)' , + MUIA_Application_Copyright , 'NOBODY' , + MUIA_Application_Description , 'NONE' , + MUIA_Application_HelpFile , 'axsys.guide' , + SubWindow , self.winMain , + SubWindow , self.wi_conf_edit , + SubWindow , self.wi_nodeEdit , + SubWindow , self.wi_listEdit , + SubWindow , self.wi_security , + SubWindow , self.wi_systemdata , + SubWindow , self.wi_add_item , + SubWindow , self.wi_presets , + SubWindow , self.wi_areas , + SubWindow , self.wi_commands , + End + +ENDPROC self.app + + +->///////////////////////////////////////////////////////////////////////////// +->////////////////////////// Disposes the object or the whole application ///// +->///////////////////////////////////////////////////////////////////////////// +PROC dispose() OF app_obj IS ( IF self.app THEN Mui_DisposeObject( self.app ) ELSE NIL ) + + diff --git a/axSetupTool/axsys.MUIB b/axSetupTool/axsys.MUIB new file mode 100644 index 0000000000000000000000000000000000000000..0d994838d2776571416f717b6e2196d530736afa GIT binary patch literal 20713 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

BQut$VFQ_@!V0f0nI`=mD~)cb#hVF zQRGU1wk_>r($~OqNlqbG!Rf^0W5^|2yYSq8zuACBaw@qQPV3~Ns-wu20Igd(Y8G?* zD5sK};dEm1QRJenU3l*BqM7HCoIA%J>KJlUfVM3)&0({k%LNsBRitjLK89d! zZOiVj6mW)7#sdd_}uwIlu@2>MjSsT~$#SCS-^Qd!KOgOxueBP$_Jn zg-sdwqQ2(pk?ciPc2>5i2$mlr!Jy=Xiw@EHrEEvBg0E&BsxLmImv3nNl*Rn zaV0%AfD)>(NlBu$b|jv$9YvrLaj3YMVQ+v!fHXjf6CKZ0LQ|aWh0|@YP;P4jQ*L{l z3`^Xz)m2L8{RUx4*r{iI zf@LtUjRICDAdo!MwRd)p<0!^}m(#K|_)!7qVJjzb;9A?@Y5{$dQwie+F@zq#;vc-; zY4syF)8KN=c3YhgZ;{uY(*FOE5d_V0gp4wvWGJRMQoz&ri}lSp5bY zEYvV1&-G*Ih&_(&tTi81RhPLdFCC_czn=>L_n0g*Kq64ZQmEfm<>T?ZI-j~M!~3w6|82e>Pv zH5Z^k-vN?=j~av77$gkZl+DL_fzZ}ChVVB27#dhvlM1!V@$<6$NA^2XMq^luywix8 zX{yj$_KcQBU s%qOxl{V+oj^6F}Sy{@!}k8%c4TtX{}2%*96MAbnP#WiT)ukio>0X0Zf4FCWD literal 0 HcmV?d00001 diff --git a/axSetupTool/configObject.e b/axSetupTool/configObject.e new file mode 100644 index 0000000..6cc8a8d --- /dev/null +++ b/axSetupTool/configObject.e @@ -0,0 +1,241 @@ + +OPT MODULE + + MODULE '*/stringlist' + +EXPORT OBJECT fChecker + filename:PTR TO CHAR + checker:PTR TO CHAR + error1:PTR TO CHAR + error2:PTR TO CHAR + error3:PTR TO CHAR + error4:PTR TO CHAR + error5:PTR TO CHAR + error6:PTR TO CHAR + error7:PTR TO CHAR + error8:PTR TO CHAR + error9:PTR TO CHAR + error10:PTR TO CHAR + options:PTR TO CHAR + priority:PTR TO CHAR + script:PTR TO CHAR + stack:PTR TO CHAR +ENDOBJECT + +EXPORT PROC create() OF fChecker + self.filename:=String(255) + self.checker:=String(255) + self.error1:=String(255) + self.error2:=String(255) + self.error3:=String(255) + self.error4:=String(255) + self.error5:=String(255) + self.error6:=String(255) + self.error7:=String(255) + self.error8:=String(255) + self.error9:=String(255) + self.error10:=String(255) + self.options:=String(255) + self.priority:=String(255) + self.script:=String(255) + self.stack:=String(255) +ENDPROC + +EXPORT PROC end() OF fChecker + DisposeLink(self.filename) + DisposeLink(self.checker) + DisposeLink(self.error1) + DisposeLink(self.error2) + DisposeLink(self.error3) + DisposeLink(self.error4) + DisposeLink(self.error5) + DisposeLink(self.error6) + DisposeLink(self.error7) + DisposeLink(self.error8) + DisposeLink(self.error9) + DisposeLink(self.error10) + DisposeLink(self.options) + DisposeLink(self.priority) + DisposeLink(self.script) + DisposeLink(self.stack) +ENDPROC + +EXPORT OBJECT protocol + filename:PTR TO CHAR + options:PTR TO CHAR + httpHost:PTR TO CHAR + httpTemp:PTR TO CHAR + ftpHost:PTR TO CHAR + ftpAuth:CHAR + txWindow:PTR TO CHAR + rxWindow:PTR TO CHAR +ENDOBJECT + +EXPORT PROC create() OF protocol + self.filename:=String(255) + self.options:=String(255) + self.httpHost:=String(255) + self.httpTemp:=String(255) + self.ftpHost:=String(255) + self.ftpAuth:=0 + self.txWindow:=String(255) + self.rxWindow:=String(255) +ENDPROC + +EXPORT PROC end() OF protocol + DisposeLink(self.filename) + DisposeLink(self.options) + DisposeLink(self.httpHost) + DisposeLink(self.httpTemp) + DisposeLink(self.ftpHost) + DisposeLink(self.txWindow) + DisposeLink(self.rxWindow) +ENDPROC + +EXPORT OBJECT command + filename:PTR TO CHAR + name:PTR TO CHAR + location:PTR TO CHAR + access:PTR TO CHAR + internal:PTR TO CHAR + mimicVer:PTR TO CHAR + password:PTR TO CHAR + passParams:PTR TO CHAR + priority:PTR TO CHAR + resident:CHAR + quickMode:CHAR + stack:PTR TO CHAR + type:PTR TO CHAR + trapon:CHAR + expertMode:CHAR + doorSilent:CHAR + logInputs:CHAR + scriptCheck:CHAR + multiNode:CHAR + banner:PTR TO CHAR +ENDOBJECT + +EXPORT PROC create() OF command + self.filename:=String(255) + self.name:=String(255) + self.location:=String(255) + self.access:=String(255) + self.internal:=String(255) + self.mimicVer:=String(255) + self.password:=String(255) + self.passParams:=String(255) + self.priority:=String(255) + self.resident:=0 + self.quickMode:=0 + self.stack:=String(255) + self.type:=String(255) + self.trapon:=0 + self.expertMode:=0 + self.doorSilent:=0 + self.logInputs:=0 + self.scriptCheck:=0 + self.multiNode:=0 + self.banner:=String(255) +ENDPROC + +EXPORT PROC end() OF command + DisposeLink(self.filename) + DisposeLink(self.name) + DisposeLink(self.location) + DisposeLink(self.access) + DisposeLink(self.internal) + DisposeLink(self.mimicVer) + DisposeLink(self.password) + DisposeLink(self.passParams) + DisposeLink(self.priority) + DisposeLink(self.stack) + DisposeLink(self.type) + DisposeLink(self.banner) +ENDPROC + +EXPORT OBJECT msgbase + name:PTR TO CHAR + location:PTR TO CHAR + extSend:CHAR + username:CHAR + realname:CHAR + internetname:CHAR +ENDOBJECT + +EXPORT PROC create() OF msgbase + self.name:=String(255) + self.location:=String(255) + self.extSend:=0 + self.username:=0 + self.realname:=0 + self.internetname:=0 +ENDPROC + +EXPORT PROC end() OF msgbase + DisposeLink(self.name) + DisposeLink(self.location) +ENDPROC + +EXPORT OBJECT area + filename:PTR TO CHAR + confList:PTR TO LONG +ENDOBJECT + +EXPORT PROC create() OF area + self.filename:=String(255) + self.confList:=0 +ENDPROC + +EXPORT PROC end() OF area + DisposeLink(self.filename) +ENDPROC + + +EXPORT OBJECT accessLevel + filename:PTR TO CHAR + accessList:PTR TO stringlist +ENDOBJECT + +EXPORT PROC create() OF accessLevel + DEF newList:PTR TO stringlist + self.filename:=String(255) + + NEW newList.stringlist(200) + self.accessList:=newList + +ENDPROC + +EXPORT PROC end() OF accessLevel + DisposeLink(self.filename) + END self.accessList +ENDPROC + +EXPORT PROC getAccessLevels() + DEF result:PTR TO LONG + result:= + ['ACS.MAX_PAGES','ACS.ACCOUNT_EDITING','ACS.READ_BULLETINS','ACS.COMMENT_TO_SYSOP','ACS.DOWNLOAD','ACS.UPLOAD','ACS.ENTER_MESSAGE','ACS.FILE_LISTINGS','ACS.JOIN_CONFERENCE','ACS.NEW_FILES_SINCE', + 'ACS.PAGE_SYSOP','ACS.READ_MESSAGE','ACS.REMOTE_SHELL','ACS.DISPLAY_USER_STATS','ACS.VIEW_A_FILE','ACS.EDIT_USER_INFO','ACS.EDIT_INTERNET_NAME','ACS.EDIT_USER_LOCATION', + 'ACS.EDIT_PHONE_NUMBER','ACS.EDIT_PASSWORD','ACS.ZIPPY_TEXT_SEARCH','ACS.OVERRIDE_CHAT','ACS.SYSOP_DOWNLOAD','ACS.SYSOP_VIEW','ACS.SYSOP_READ','ACS.KEEP_UPLOAD_CREDIT', + 'ACS.OVERRIDE_TIMES','ACS.CLEAR_SCREEN_MSG','ACS.FREE_RESUMING','ACS.ONE_TIME_BULLETINS','ACS.DO_CALLERSLOG','ACS.SENTBY_FILES','ACS.DO_UD_LOG','ACS.SCREEN_TO_FRONT', + 'ACS.DEFAULT_CHAT_ON','ACS.EALL_MESSAGES','ACS.DUPE_FILECHECK','ACS.MESSAGE_EDIT','ACS.LIST_NODES','ACS.MSG_LEVEL','ACS.MSG_EXPERATION','ACS.DELETE_MESSAGE','ACS.ATTACH_FILES', + 'ACS.CUSTOMCOMMANDS','ACS.JOIN_SUB_CONFERENCE','ACS.ZOOM_MAIL','ACS.MCI_MSG','ACS.EDIT_DIRS','ACS.EDIT_FILES','ACS.BREAK_CHAT','ACS.QUIET_NODE','ACS.SYSOP_COMMANDS','ACS.WHO_IS_ONLINE', + 'ACS.RELOGON','ACS.ULSTATS','ACS.XPR_RECEIVE','ACS.XPR_SEND','ACS.WILDCARDS','ACS.CONFERENCE_ACCOUNTING','ACS.PRI_MSGFILES','ACS.PUB_MSGFILES','ACS.FULL_EDIT','ACS.CONFFLAGS', + 'ACS.OLM','ACS.HIDE_FILES','ACS.SHOW_PAYMENTS','ACS.CREDIT_ACCESS','ACS.VOTE','ACS.MODIFY_VOTE','ACS.FILE_EXPANSION','ACS.EDIT_REAL_NAME','ACS.EDIT_USER_NAME','ACS.CENSORED', + 'ACS.ACCOUNT_VIEW','ACS.TRANSLATION','ACS.UNKNOWN','ACS.CREATE_CONFERENCE','ACS.LOCAL_DOWNLOADS','ACS.OVERRIDE_DEFAULTS','ACS.HOLD_ACCESS','ACS.EDIT_EMAIL', + 'ACS.READ_PRIV_EALL','ACS.READ_PRIV_ALL','ACS.OVERRIDE_TIMELIMIT','ACS.OVERRIDE_CHATLIMIT','ACS.NO_TIMEOUT','ACS.USER_ULSTATS'] +ENDPROC result + +EXPORT PROC getAccessNames() + DEF result:PTR TO LONG + result:= + ['Max sysop pages','Account editing','Read bulletins','Comment to sysop','Download files','Upload files','Send message','View file listings','Join a conference','View new files', + 'Page sysop','Read messages','Remote shell','Display user stats','View a file','Edit user info','Edit internet name','Edit location', + 'Edit phone number','Edit password','Text search (zippy)','Override chat','Sysop download','Sysop view','Sysop read','Upload credit (unused)', + 'Override times','Clear screen (unused)','Free resuming (unused)','One time bulletins (unused)','Enable callerslog (unused)','Add sentby line (unused)','Enable UD log (unused)','Bring screen to front (unused)', + 'Default chat on (unused)','Send EALL messages','dupe filecheck (unused)','Edit messages','View callerslogs','Message Level (unused)','Message expiration (unused)','Delete Messages','Attach files to messages', + 'Custom commands (unused)','Join sub conf (unused)','Zoom mail','Enable MCI messages','Edit Dirs','Edit Files','Break from chat','Allow quiet mode','Sysop commands','See node users (WHO)', + 'Relogon','Show sysop UL stats','External protocol upload','External protocol download','Wildcards (unused)','Enable conference accounting','Private messages','Public messages','Change screen editor','Edit conf flags', + 'Online messages','Hide filenames in WHO','Show Payments','Credit Account Access','Voting','Edit Votes','Enable file expansion','Edit real name','Edit user name','User censored', + 'Account view (unused)','Enable translation','Unknown (unused)','Create conference (unused)','Local downloads','Override defaults','Allow hold access','Edit emails', + 'Read private EALL msgs','Read private ALL msgs','Override time limits','Override chat limits','Don''t time out','Show user upload stats'] +ENDPROC result \ No newline at end of file diff --git a/axSetupTool/controls.e b/axSetupTool/controls.e new file mode 100644 index 0000000..9680637 --- /dev/null +++ b/axSetupTool/controls.e @@ -0,0 +1,345 @@ + OPT MODULE + +MODULE 'muimaster','libraries/mui','tools/boopsi','intuition/classusr','utility/hooks','tools/installhook','libraries/asl' + +EXPORT ENUM TYPE_STRING,TYPE_INT,TYPE_CYCLE,TYPE_CHECKBOX,TYPE_DIRSELECT,TYPE_FILESELECT,TYPE_MODESELECT +EXPORT OBJECT control + hook:PTR TO LONG + hook2:PTR TO LONG + muiLabel: PTR TO LONG + group: PTR TO LONG + muiControl: PTR TO LONG + type:INT +ENDOBJECT + +PROC makeLabel(caption,helpText) OF control + DEF lbl + lbl := TextObject , + MUIA_Text_PreParse , '\el' , + MUIA_Text_Contents , caption , + MUIA_ShortHelp,helpText, + MUIA_Weight,0, + MUIA_InnerLeft , 0 , + MUIA_InnerRight , 0 , + End +ENDPROC lbl + +EXPORT PROC createString(labelCaption,helpText,app,changeHook, window) OF control + self.hook:=0 + self.hook2:=0 + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.group:=NIL + self.muiControl:=StringObject, + MUIA_Frame,MUIV_Frame_String, + MUIA_ShortHelp,helpText, + MUIA_Weight,100, + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window ]) + + self.type:=TYPE_STRING +ENDPROC + +EXPORT PROC createStringInt(labelCaption,helpText,app,changeHook, window) OF control + self.hook:=0 + self.hook2:=0 + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.group:=NIL + self.muiControl:=StringObject, + MUIA_Frame,MUIV_Frame_String, + MUIA_ShortHelp,helpText, + MUIA_Weight,100, + MUIA_String_Accept , '0123456879', + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window ]) + self.type:=TYPE_INT +ENDPROC + +EXPORT PROC createCycle(labelCaption,helpText,values,app,changeHook, window) OF control + self.hook:=0 + self.hook2:=0 + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.group:=NIL + self.muiControl:=CycleObject, + MUIA_Frame,MUIV_Frame_Button, + MUIA_ShortHelp,helpText, + MUIA_Weight,100, + MUIA_Cycle_Entries,values, + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_Cycle_Active , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window ]) + + self.type:=TYPE_CYCLE +ENDPROC + +EXPORT PROC createCheckBox(labelCaption,helpText,app,changeHook, window) OF control + self.hook:=0 + self.hook2:=0 + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.muiControl:=CheckMark( FALSE ) + self.group:=GroupObject , + MUIA_ShortHelp,helpText, + MUIA_Group_Horiz , MUI_TRUE , + Child , HVSpace , + Child , self.muiControl , + Child , HVSpace , + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_Selected , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window ]) + self.type:=TYPE_CHECKBOX +ENDPROC + +PROC setaslflags() OF control + DEF tags:PTR TO LONG + MOVE.L A1,tags + + WHILE tags[]<>0 DO tags++ + tags[]:=ASLFR_DRAWERSONLY + tags++ + tags[]:=-1 + tags++ + tags[]:=0 + +ENDPROC TRUE + +EXPORT PROC createDirSelect(labelCaption,helpText,app,changeHook, window) OF control + DEF hook:PTR TO hook + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.group:=NIL + NEW hook + self.hook:=hook + installhook( hook, {setaslflags}) + self.hook2:=0 + + self.muiControl:=PopaslObject, + MUIA_ShortHelp,helpText, + MUIA_Popasl_Type,0, + MUIA_Weight,100, + MUIA_Popasl_StartHook,hook, + MUIA_Popstring_String,StringMUI( '' , 80 ), + MUIA_Popstring_Button,PopButton( MUII_PopDrawer ), + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window ]) + + self.type:=TYPE_DIRSELECT +ENDPROC + +EXPORT PROC createFileSelect(labelCaption,helpText,app,changeHook, window) OF control + self.hook:=0 + self.hook2:=0 + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.group:=NIL + self.muiControl:=PopaslObject, + MUIA_ShortHelp,helpText, + MUIA_Popasl_Type,0, + MUIA_Weight,100, + MUIA_Popstring_String,StringMUI( '' , 80 ), + MUIA_Popstring_Button,PopButton( MUII_PopFile ), + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window ]) + + self.type:=TYPE_FILESELECT +ENDPROC + +PROC setaslmodeflags() OF control + DEF tags:PTR TO LONG + DEF control:PTR TO LONG + DEF str,val + MOVE.L A1,tags + MOVE.L A2,control + + get(control,MUIA_String_Contents,{str}) + + IF StrLen(str)=0 + val:=$8000 + ELSE + val:=Val(str) + ENDIF + + WHILE tags[]<>0 DO tags++ + tags[]:=ASLSM_INITIALDISPLAYID + tags++ + tags[]:=val + tags++ + tags[]:=0 + +ENDPROC TRUE + +PROC getmodeid() OF control + DEF asl:PTR TO screenmoderequester + DEF control + DEF str[20]:STRING + MOVE.L A1,asl + MOVE.L A2,control + StringF(str,'\d',asl.displayid) + set(control,MUIA_String_Contents,str) +ENDPROC + +EXPORT PROC createModeSelect(labelCaption,helpText,app,changeHook, window) OF control + DEF hook:PTR TO hook + NEW hook + self.hook:=hook + NEW hook + self.hook2:=hook + installhook( self.hook, {setaslmodeflags}) + installhook( self.hook2, {getmodeid}) + self.muiLabel:=self.makeLabel(labelCaption,helpText) + self.group:=NIL + self.muiControl:=PopaslObject, + MUIA_ShortHelp,helpText, + MUIA_Popasl_Type,2, + MUIA_Popasl_StartHook,self.hook, + MUIA_Popasl_StopHook,self.hook2, + MUIA_Weight,100, + MUIA_Popstring_String,StringMUI( '' , 80 ), + MUIA_Popstring_Button,PopButton( MUII_PopFile ), + End + + domethod( self.muiControl, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + app, + 3 , + MUIM_CallHook , changeHook, window]) + + self.type:=TYPE_MODESELECT +ENDPROC + +EXPORT PROC addToGroup(group) OF control + domethod(group,[OM_ADDMEMBER,self.muiLabel]) + IF self.group + domethod(group,[OM_ADDMEMBER,self.group]) + ELSE + domethod(group,[OM_ADDMEMBER,self.muiControl]) + ENDIF +ENDPROC + +EXPORT PROC removeFromGroup(group) OF control + domethod(group,[OM_REMMEMBER,self.muiLabel]) + IF self.group + domethod(group,[OM_REMMEMBER,self.group]) + ELSE + domethod(group,[OM_REMMEMBER,self.muiControl]) + ENDIF +ENDPROC + +EXPORT PROC setValueStr(newValue) OF control + SELECT self.type + CASE TYPE_STRING + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_DIRSELECT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_FILESELECT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_MODESELECT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_INT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + //CASE TYPE_CHECKBOX + //do nothing + //CASE TYPE_CYCLE + //do nothing + ENDSELECT +ENDPROC + +EXPORT PROC setValue(newValue) OF control + SELECT self.type + CASE TYPE_STRING + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_DIRSELECT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_FILESELECT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_MODESELECT + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,newValue]) + CASE TYPE_INT + IF newValue=-1 + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Contents,'']) + ELSE + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_String_Integer,newValue]) + ENDIF + CASE TYPE_CHECKBOX + domethod(self.muiControl,[MUIM_NoNotifySet,MUIA_Selected,IF newValue THEN MUI_TRUE ELSE FALSE]) + //CASE TYPE_CYCLE + //do nothing + ENDSELECT +ENDPROC + +EXPORT PROC getValue() OF control + DEF currVal,index,items:PTR TO LONG + SELECT self.type + CASE TYPE_STRING + get(self.muiControl, MUIA_String_Contents,{currVal}) + CASE TYPE_DIRSELECT + get(self.muiControl, MUIA_String_Contents,{currVal}) + CASE TYPE_FILESELECT + get(self.muiControl, MUIA_String_Contents,{currVal}) + CASE TYPE_INT + get(self.muiControl, MUIA_String_Contents,{currVal}) + CASE TYPE_CHECKBOX + get(self.muiControl,MUIA_Selected,{currVal}) + CASE TYPE_CYCLE + get(self.muiControl,MUIA_Cycle_Active,{index}) + IF index>=0 + get(self.muiControl,MUIA_Cycle_Entries,{items}) + currVal:=items[index] + ENDIF + CASE TYPE_MODESELECT + get(self.muiControl, MUIA_String_Contents,{currVal}) + ENDSELECT +ENDPROC currVal + +EXPORT PROC setValueIndex(newIndex) OF control + IF self.type=TYPE_CYCLE + set(self.muiControl,MUIA_Cycle_Active,newIndex) + ENDIF +ENDPROC + +EXPORT PROC getValueIndex() OF control + DEF index=-1 + IF self.type=TYPE_CYCLE + get(self.muiControl,MUIA_Cycle_Active,{index}) + ENDIF +ENDPROC index + +EXPORT PROC disable(newVal) OF control + set( self.muiControl, MUIA_Disabled , IF newVal THEN MUI_TRUE ELSE FALSE) +ENDPROC + +EXPORT PROC end() OF control + Mui_DisposeObject(self.muiLabel) + IF self.group + Mui_DisposeObject(self.group) + ELSE + Mui_DisposeObject(self.muiControl) + ENDIF + IF self.hook THEN END self.hook + IF self.hook2 THEN END self.hook2 +ENDPROC + diff --git a/axSetupTool/frmAccess.e b/axSetupTool/frmAccess.e new file mode 100644 index 0000000..5742365 --- /dev/null +++ b/axSetupTool/frmAccess.e @@ -0,0 +1,87 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' +MODULE '*axedit','*frmBase','*frmPresetsEdit','*frmEditList' + +EXPORT OBJECT frmAccess OF frmBase + btnAccess : PTR TO LONG + btnAreas : PTR TO LONG + btnPresets : PTR TO LONG + + acpConfigName : PTR TO CHAR + + btnAccessClick: hook + btnAreasClick: hook + btnPresetsClick: hook +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmAccess + DEF group + SUPER self.create(app) + self.winMain:=app.wi_security + + self.btnAccess:=app.btnAccess + self.btnAreas:=app.btnAreas + self.btnPresets:=app.btnPresets +ENDPROC + +PROC goAccess() OF frmAccess + DEF editList:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW editList.create(self.app) + editList.editAccessLevel(self.acpConfigName) + END editList + self.wake() +ENDPROC + +PROC goAreas() OF frmAccess + DEF editList:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW editList.create(self.app) + editList.editAreas(self.acpConfigName) + END editList + self.wake() +ENDPROC + +PROC goPresets() OF frmAccess + DEF presetsEdit:PTR TO frmPresetsEdit + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW presetsEdit.create(self.app) + presetsEdit.editPresets(self.acpConfigName) + END presetsEdit + self.wake() +ENDPROC + +PROC addNotifications() OF frmAccess + + self.setupButtonClick(self.btnAccess,self.btnAccessClick,{goAccess}) + self.setupButtonClick(self.btnAreas,self.btnAreasClick,{goAreas}) + self.setupButtonClick(self.btnPresets,self.btnPresetsClick,{goPresets}) +ENDPROC + +PROC removeNotifications() OF frmAccess + domethod(self.btnAccess,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnAreas,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnPresets,[MUIM_KillNotify,MUIA_Pressed]) +ENDPROC + +PROC editAccess(acpConfigName:PTR TO CHAR) OF frmAccess + self.addNotifications() + + self.acpConfigName:=acpConfigName + + self.showModal() + self.removeNotifications() +ENDPROC diff --git a/axSetupTool/frmAddComplexItem.e b/axSetupTool/frmAddComplexItem.e new file mode 100644 index 0000000..af3f62b --- /dev/null +++ b/axSetupTool/frmAddComplexItem.e @@ -0,0 +1,928 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','dos/dos','libraries/asl' +MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' +MODULE '*axedit','*frmBase','*controls','*/stringlist','*tooltypes','*configobject' + +EXPORT OBJECT frmAddComplexItem OF frmBase + lblAreaName: LONG + txtAreaName: LONG + grpAreaSettings: LONG + confControls: PTR TO stdlist + accessControls: PTR TO stdlist + fCheckControls: PTR TO stdlist + protocolControls: PTR TO stdlist + commandControls: PTR TO stdlist + msgbaseControls: PTR TO stdlist + acpName: PTR TO CHAR + confConfig: PTR TO CHAR + changed: LONG + btnSave: LONG + btnCancel: LONG + setChangedHook:hook + existingItems:PTR TO stringlist +ENDOBJECT + +PROC setChangedFlag() OF frmAddComplexItem + DEF txtval + MOVE.L (A1),self + GetA4() + self.changed:=TRUE + get(self.txtAreaName, MUIA_String_Contents,{txtval}) + + IF ((self.changed) AND (StrLen(txtval)>0)) + set( self.btnSave,MUIA_Disabled,FALSE) + ELSE + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + ENDIF +ENDPROC + +PROC addNotifications() OF frmAddComplexItem + domethod( self.btnCancel , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + domethod( self.btnSave , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , ID_SAVE ] ) + + domethod( self.txtAreaName , [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + self.app.app, + 3 , + MUIM_CallHook , self.setChangedHook, self] ) + +ENDPROC + +PROC removeNotifications() OF frmAddComplexItem + domethod(self.btnCancel,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnSave,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.txtAreaName,[MUIM_KillNotify,MUIA_String_Contents]) +ENDPROC + +PROC create(app:PTR TO app_obj) OF frmAddComplexItem + DEF group + SUPER self.create(app) + self.winMain:=app.wi_areas + + self.btnSave:=app.bt_area_save + self.btnCancel:=app.bt_area_cancel + + get(app.gr_area_main,MUIA_Scrollgroup_Contents,{group}) + self.grpAreaSettings:=group + self.lblAreaName:=app.la_area + self.txtAreaName:=app.stR_area +ENDPROC + +PROC freeControl(control:PTR TO control) OF frmAddComplexItem + control.removeFromGroup(self.grpAreaSettings) + END control +ENDPROC + +PROC canClose() OF frmAddComplexItem + MOVE.L (A1),self + GetA4() + IF self.changed + IF self.unsavedChangesWarning()=0 THEN RETURN FALSE + ENDIF +ENDPROC TRUE + +PROC canSave() OF frmAddComplexItem + DEF win,newName,i + + MOVE.L (A1),self + GetA4() + + get(self.winMain,MUIA_Window_Window,{win}) + get(self.txtAreaName, MUIA_String_Contents,{newName}) + + IF self.existingItems ANDALSO self.existingItems.contains(newName) + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'An item already exists with this name.', + '_OK' ] , NIL , NIL ) + RETURN FALSE + ENDIF +ENDPROC TRUE + +PROC unsavedChangesWarning() OF frmAddComplexItem + DEF win + get(self.winMain,MUIA_Window_Window,{win}) + IF EasyRequestArgs( win , [ 20 , 0 , + 'Unsaved changes' , + 'You have unsaved changes,\nif you continue you will lose them.', + '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE +ENDPROC TRUE + +PROC editArea(acpName,areaName,oldArea:PTR TO area, existingAreas:PTR TO stdlist) OF frmAddComplexItem + DEF res,v1=0,v2=0 + DEF confControls:PTR TO stdlist + DEF bbsPath[255]:STRING + DEF confCount,i + DEF tempStr[255]:STRING + DEF confName[100]:STRING + DEF control:PTR TO control + DEF closeHook:PTR TO hook + DEF canSaveHook:PTR TO hook + DEF newArea:PTR TO area + DEF existingList:PTR TO stringlist + DEF areaItem:PTR TO area + + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + NEW canSaveHook + installhook(canSaveHook,{canSave}) + self.canSaveHook:=canSaveHook + + set( self.winMain, MUIA_Window_Title,'Edit Area Access') + set( self.winMain, MUIA_Window_ID, "FARE") + + set( self.lblAreaName, MUIA_Text_Contents,'Area Name') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + NEW existingList.stringlist(existingAreas.count()) + self.existingItems:=existingList + FOR i:=0 TO existingAreas.count()-1 + areaItem:=existingAreas.item(i) + IF areaItem<>oldArea THEN existingList.add(areaItem.filename) + ENDFOR + + self.acpName:=acpName + newArea:=0 + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + self.confConfig:=String(255) + StringF(self.confConfig,'\sCONFCONFIG',bbsPath) + + confCount:=readToolTypeInt(self.confConfig,'NCONFS') + + set(self.txtAreaName, MUIA_String_Contents,areaName) + + domethod(self.grpAreaSettings,[MUIM_Group_InitChange]) + + set(self.grpAreaSettings, MUIA_Group_Columns , 2) + + NEW confControls.stdlist(25) + self.confControls:=confControls + + FOR i:=1 TO confCount + + StringF(tempStr,'NAME.\d',i) + readToolType(self.confConfig,tempStr,confName) + + NEW control.createCheckBox(confName,'',self.app.app,self.setChangedHook,self) + + self.confControls.add(control) + control.addToGroup(self.grpAreaSettings) + + IF oldArea + IF oldArea.confList + control.setValue(IF oldArea.confList[i-1] THEN MUI_TRUE ELSE FALSE) + ENDIF + ENDIF + ENDFOR + domethod(self.grpAreaSettings,[MUIM_Group_ExitChange]) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addNotifications() + + res:=self.showModal() + IF res + NEW newArea.create() + newArea.confList:=List(confCount) + get(self.txtAreaName, MUIA_String_Contents,{v1}) + StrCopy(newArea.filename,v1) + FOR i:=0 TO confCount-1 + control:=confControls.item(i) + ListAddItem(newArea.confList,IF control.getValue() THEN TRUE ELSE FALSE) + ENDFOR + ENDIF + + self.removeNotifications() + FOR i:=0 TO confCount-1 + control:=confControls.item(i) + self.freeControl(control) + ENDFOR + + + END existingList + END confControls + END closeHook + END canSaveHook + + DisposeLink(self.confConfig) +ENDPROC res,v1,newArea + +PROC editAccess(acpName,accessName,oldAccessLevel:PTR TO accessLevel, existingAccessLevels:PTR TO stdlist) OF frmAddComplexItem + DEF res,v1=0,v2=0 + DEF accessControls:PTR TO stdlist + DEF accessControlCodes:PTR TO stringlist + DEF bbsPath[255]:STRING + DEF i + DEF tempStr[255]:STRING + DEF control:PTR TO control + DEF canSaveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF newAccessLevel:PTR TO accessLevel + DEF acsNames:PTR TO LONG + DEF acsValues:PTR TO LONG + DEF existingList:PTR TO stringlist + DEF accessLevel:PTR TO accessLevel + + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + NEW canSaveHook + installhook(canSaveHook,{canSave}) + self.canSaveHook:=canSaveHook + + set( self.winMain, MUIA_Window_Title,'Edit Area Access') + set( self.winMain, MUIA_Window_ID, "FACS") + + set( self.lblAreaName, MUIA_Text_Contents,'Access Level') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + NEW existingList.stringlist(existingAccessLevels.count()) + self.existingItems:=existingList + FOR i:=0 TO existingAccessLevels.count()-1 + accessLevel:=existingAccessLevels.item(i) + IF accessLevel<>oldAccessLevel THEN existingList.add(accessLevel.filename) + ENDFOR + + self.acpName:=acpName + newAccessLevel:=0 + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + set(self.txtAreaName, MUIA_String_Contents,accessName) + + domethod(self.grpAreaSettings,[MUIM_Group_InitChange]) + + set(self.grpAreaSettings, MUIA_Group_Columns , 4) + + NEW accessControlCodes.stringlist(25) + + NEW accessControls.stdlist(25) + self.accessControls:=accessControls + + acsNames:=getAccessNames() + acsValues:=getAccessLevels() + + FOR i:=0 TO ListLen(acsValues)-1 + IF i=0 + NEW control.createStringInt(acsNames[i],'',self.app.app,self.setChangedHook,self) + ELSE + NEW control.createCheckBox(acsNames[i],'',self.app.app,self.setChangedHook,self) + ENDIF + accessControls.add(control) + accessControlCodes.add(acsValues[i]) + control.addToGroup(self.grpAreaSettings) + ENDFOR + + IF oldAccessLevel + FOR i:=0 TO accessControlCodes.count()-1 + control:=accessControls.item(i) + IF i=0 + control.setValueStr(oldAccessLevel.accessList.item(0)) + ELSE + control.setValue(IF oldAccessLevel.accessList.contains(accessControlCodes.item(i)) THEN MUI_TRUE ELSE FALSE) + ENDIF + ENDFOR + ENDIF + + domethod(self.grpAreaSettings,[MUIM_Group_ExitChange]) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addNotifications() + + res:=self.showModal() + IF res + NEW newAccessLevel.create() + + get(self.txtAreaName, MUIA_String_Contents,{v1}) + StrCopy(newAccessLevel.filename,v1) + FOR i:=0 TO accessControls.count()-1 + control:=accessControls.item(i) + IF i=0 + newAccessLevel.accessList.add(control.getValue()) + ELSE + IF control.getValue() + newAccessLevel.accessList.add(accessControlCodes.item(i)) + ENDIF + ENDIF + ENDFOR + ENDIF + + FOR i:=0 TO accessControls.count()-1 + control:=accessControls.item(i) + self.freeControl(control) + ENDFOR + self.removeNotifications() + + END existingList + END accessControls + END accessControlCodes + END closeHook + END canSaveHook +ENDPROC res,v1,newAccessLevel + +PROC editFileCheck(acpName,fCheckName,oldfCheck:PTR TO fChecker,existingFcheckers:PTR TO stdlist) OF frmAddComplexItem + DEF res,v1=0,v2=0 + DEF fCheckControls:PTR TO stdlist + DEF bbsPath[255]:STRING + DEF i + DEF tempStr[255]:STRING + DEF control:PTR TO control + DEF closeHook:PTR TO hook + DEF canSaveHook:PTR TO hook + DEF newfChecker:PTR TO fChecker + DEF controlChecker:PTR TO control + DEF controlError1:PTR TO control + DEF controlError2:PTR TO control + DEF controlError3:PTR TO control + DEF controlError4:PTR TO control + DEF controlError5:PTR TO control + DEF controlError6:PTR TO control + DEF controlError7:PTR TO control + DEF controlError8:PTR TO control + DEF controlError9:PTR TO control + DEF controlError10:PTR TO control + DEF controlOptions:PTR TO control + DEF controlPriority:PTR TO control + DEF controlScript:PTR TO control + DEF controlStack:PTR TO control + DEF existingList:PTR TO stringlist + DEF fCheckItem:PTR TO command + + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + NEW canSaveHook + installhook(canSaveHook,{canSave}) + self.canSaveHook:=canSaveHook + + set( self.winMain, MUIA_Window_Title,'Edit File Checker') + set( self.winMain, MUIA_Window_ID, "EFCH") + + set( self.lblAreaName, MUIA_Text_Contents,'File Type') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + NEW existingList.stringlist(existingFcheckers.count()) + self.existingItems:=existingList + FOR i:=0 TO existingFcheckers.count()-1 + fCheckItem:=existingFcheckers.item(i) + IF fCheckItem<>oldfCheck THEN existingList.add(fCheckItem.filename) + ENDFOR + + self.acpName:=acpName + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + set(self.txtAreaName, MUIA_String_Contents,fCheckName) + + domethod(self.grpAreaSettings,[MUIM_Group_InitChange]) + + set(self.grpAreaSettings, MUIA_Group_Columns , 2) + + NEW fCheckControls.stdlist(25) + self.fCheckControls:=fCheckControls + + newfChecker:=0 + + NEW controlChecker.createString('Checker','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlChecker) + NEW controlError1.createString('Error 1','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError1) + NEW controlError2.createString('Error 2','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError2) + NEW controlError3.createString('Error 3','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError3) + NEW controlError4.createString('Error 4','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError4) + NEW controlError5.createString('Error 5','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError5) + NEW controlError6.createString('Error 6','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError6) + NEW controlError7.createString('Error 7','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError7) + NEW controlError8.createString('Error 8','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError8) + NEW controlError9.createString('Error 9','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError9) + NEW controlError10.createString('Error 10','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlError10) + + NEW controlOptions.createString('Options','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlOptions) + + NEW controlPriority.createStringInt('Priority','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlPriority) + + NEW controlScript.createString('Script','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlScript) + + NEW controlStack.createStringInt('Stack','',self.app.app,self.setChangedHook,self) + fCheckControls.add(controlStack) + + FOR i:=0 TO fCheckControls.count()-1 + control:=fCheckControls.item(i) + control.addToGroup(self.grpAreaSettings) + ENDFOR + + domethod(self.grpAreaSettings,[MUIM_Group_ExitChange]) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addNotifications() + + IF oldfCheck + //set controls according to oldfcheck + + controlChecker.setValue(oldfCheck.checker) + controlError1.setValue(oldfCheck.error1) + controlError2.setValue(oldfCheck.error2) + controlError3.setValue(oldfCheck.error3) + controlError4.setValue(oldfCheck.error4) + controlError5.setValue(oldfCheck.error5) + controlError6.setValue(oldfCheck.error6) + controlError7.setValue(oldfCheck.error7) + controlError8.setValue(oldfCheck.error8) + controlError9.setValue(oldfCheck.error9) + controlError10.setValue(oldfCheck.error10) + controlOptions.setValue(oldfCheck.options) + controlPriority.setValueStr(oldfCheck.priority) + controlScript.setValue(oldfCheck.script) + controlStack.setValueStr(oldfCheck.stack) + ENDIF + self.changed:=FALSE + + res:=self.showModal() + IF res + + NEW newfChecker.create() + //set fchecker according to controls + get(self.txtAreaName, MUIA_String_Contents,{v1}) + StrCopy(newfChecker.filename,v1) + StrCopy(newfChecker.checker,controlChecker.getValue()) + StrCopy(newfChecker.error1,controlError1.getValue()) + StrCopy(newfChecker.error2,controlError2.getValue()) + StrCopy(newfChecker.error3,controlError3.getValue()) + StrCopy(newfChecker.error4,controlError4.getValue()) + StrCopy(newfChecker.error5,controlError5.getValue()) + StrCopy(newfChecker.error6,controlError6.getValue()) + StrCopy(newfChecker.error7,controlError7.getValue()) + StrCopy(newfChecker.error8,controlError8.getValue()) + StrCopy(newfChecker.error9,controlError9.getValue()) + StrCopy(newfChecker.error10,controlError10.getValue()) + StrCopy(newfChecker.options,controlOptions.getValue()) + StrCopy(newfChecker.priority,controlPriority.getValue()) + StrCopy(newfChecker.script,controlScript.getValue()) + StrCopy(newfChecker.stack,controlStack.getValue()) + ENDIF + + FOR i:=0 TO fCheckControls.count()-1 + control:=fCheckControls.item(i) + self.freeControl(control) + ENDFOR + self.removeNotifications() + + END existingList + END fCheckControls + END closeHook + END canSaveHook +ENDPROC res,v1,newfChecker + +PROC editProtocol(acpName,protocolName,oldProtocol:PTR TO protocol,existingProtocols:PTR TO stdlist) OF frmAddComplexItem + DEF res,v1=0,v2=0 + DEF protocolControls:PTR TO stdlist + DEF bbsPath[255]:STRING + DEF i + DEF tempStr[255]:STRING + DEF control:PTR TO control + DEF closeHook:PTR TO hook + DEF canSaveHook:PTR TO hook + DEF newProtocol:PTR TO protocol + DEF controlOptions:PTR TO control + DEF controlHttpHost:PTR TO control + DEF controlHttpTemp:PTR TO control + DEF controlFtpAuth:PTR TO control + DEF controlFtpHost:PTR TO control + DEF controlRxWindow:PTR TO control + DEF controlTxWindow:PTR TO control + DEF existingList:PTR TO stringlist + DEF protocolItem:PTR TO protocol + + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + NEW canSaveHook + installhook(canSaveHook,{canSave}) + self.canSaveHook:=canSaveHook + + set( self.winMain, MUIA_Window_Title,'Edit Protocol') + set( self.winMain, MUIA_Window_ID, "EPCL") + + set( self.lblAreaName, MUIA_Text_Contents,'Protocol') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + NEW existingList.stringlist(existingProtocols.count()) + self.existingItems:=existingList + FOR i:=0 TO existingProtocols.count()-1 + protocolItem:=existingProtocols.item(i) + IF protocolItem<>oldProtocol THEN existingList.add(protocolItem.filename) + ENDFOR + + self.acpName:=acpName + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + set(self.txtAreaName, MUIA_String_Contents,protocolName) + + domethod(self.grpAreaSettings,[MUIM_Group_InitChange]) + + set(self.grpAreaSettings, MUIA_Group_Columns , 2) + + NEW protocolControls.stdlist(25) + self.protocolControls:=protocolControls + + newProtocol:=0 + + NEW controlOptions.createString('Options','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlOptions) + NEW controlRxWindow.createStringInt('Hydra Rx Window','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlRxWindow) + NEW controlTxWindow.createStringInt('Hydra Tx Window','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlTxWindow) + NEW controlHttpHost.createString('Http Host','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlHttpHost) + NEW controlHttpTemp.createDirSelect('Http TempDir','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlHttpTemp) + NEW controlFtpHost.createString('Ftp Host','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlFtpHost) + NEW controlFtpAuth.createCheckBox('Ftp Authentication','',self.app.app,self.setChangedHook,self) + protocolControls.add(controlFtpAuth) + + FOR i:=0 TO protocolControls.count()-1 + control:=protocolControls.item(i) + control.addToGroup(self.grpAreaSettings) + ENDFOR + + domethod(self.grpAreaSettings,[MUIM_Group_ExitChange]) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addNotifications() + + IF oldProtocol + //set controls according to oldProtocol + + controlOptions.setValue(oldProtocol.options) + controlHttpHost.setValue(oldProtocol.httpHost) + controlHttpTemp.setValue(oldProtocol.httpTemp) + controlFtpAuth.setValue(oldProtocol.ftpAuth) + controlFtpHost.setValue(oldProtocol.ftpHost) + controlRxWindow.setValueStr(oldProtocol.rxWindow) + controlTxWindow.setValueStr(oldProtocol.txWindow) + ENDIF + self.changed:=FALSE + + res:=self.showModal() + IF res + get(self.txtAreaName, MUIA_String_Contents,{v1}) + NEW newProtocol.create() + //set protocol according to controls + StrCopy(newProtocol.filename,v1) + StrCopy(newProtocol.options,controlOptions.getValue()) + StrCopy(newProtocol.httpHost,controlHttpHost.getValue()) + StrCopy(newProtocol.httpTemp,controlHttpTemp.getValue()) + newProtocol.ftpAuth:=controlFtpAuth.getValue() + StrCopy(newProtocol.ftpHost,controlFtpHost.getValue()) + StrCopy(newProtocol.rxWindow,controlRxWindow.getValue()) + StrCopy(newProtocol.txWindow,controlTxWindow.getValue()) + + ENDIF + + FOR i:=0 TO protocolControls.count()-1 + control:=protocolControls.item(i) + self.freeControl(control) + ENDFOR + self.removeNotifications() + + + END existingList + END protocolControls + END closeHook + END canSaveHook +ENDPROC res,v1,newProtocol + + +PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,existingCommands:PTR TO stdlist) OF frmAddComplexItem + DEF res,v1=0,v2=0 + DEF commandControls:PTR TO stdlist + DEF bbsPath[255]:STRING + DEF i,item + DEF tempStr[255]:STRING + DEF control:PTR TO control + DEF closeHook:PTR TO hook + DEF canSaveHook:PTR TO hook + DEF newCommand:PTR TO command + DEF controlName:PTR TO control + DEF controlLocation:PTR TO control + DEF controlAccess:PTR TO control + DEF controlInternal:PTR TO control + DEF controlMimicVer:PTR TO control + DEF controlPassword:PTR TO control + DEF controlPassParams:PTR TO control + DEF controlPriority:PTR TO control + DEF controlResident:PTR TO control + DEF controlQuickMode:PTR TO control + DEF controlStack:PTR TO control + DEF controlType:PTR TO control + DEF controlTrapon:PTR TO control + DEF controlExpertMode:PTR TO control + DEF controlDoorSilent:PTR TO control + DEF controlLogInputs:PTR TO control + DEF controlScriptCheck:PTR TO control + DEF controlMultiNode:PTR TO control + DEF controlBanner:PTR TO control + DEF typeList:PTR TO LONG + DEF existingList:PTR TO stringlist + DEF cmdItem:PTR TO command + + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + NEW canSaveHook + installhook(canSaveHook,{canSave}) + self.canSaveHook:=canSaveHook + + set( self.winMain, MUIA_Window_Title,'Edit Command') + set( self.winMain, MUIA_Window_ID, "ECMD") + + set( self.lblAreaName, MUIA_Text_Contents,'Command') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + NEW existingList.stringlist(existingCommands.count()) + self.existingItems:=existingList + FOR i:=0 TO existingCommands.count()-1 + cmdItem:=existingCommands.item(i) + IF cmdItem<>oldCommand THEN existingList.add(cmdItem.filename) + ENDFOR + + self.acpName:=acpName + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + set(self.txtAreaName, MUIA_String_Contents,commandName) + + domethod(self.grpAreaSettings,[MUIM_Group_InitChange]) + + set(self.grpAreaSettings, MUIA_Group_Columns , 2) + + NEW commandControls.stdlist(25) + self.commandControls:=commandControls + + newCommand:=0 + + typeList:=['XIM','AIM','TIM','IIM','SIM','MCI',0] + + installhook( self.setChangedHook, {setChangedFlag}) + + NEW controlName.createString('Name','',self.app.app,self.setChangedHook,self) + commandControls.add(controlName) + NEW controlLocation.createString('Location','',self.app.app,self.setChangedHook,self) + commandControls.add(controlLocation) + NEW controlAccess.createStringInt('Access','',self.app.app,self.setChangedHook,self) + commandControls.add(controlAccess) + NEW controlInternal.createString('Internal','',self.app.app,self.setChangedHook,self) + commandControls.add(controlInternal) + NEW controlMimicVer.createString('Mimic Version','',self.app.app,self.setChangedHook,self) + commandControls.add(controlMimicVer) + NEW controlPassword.createString('Password','',self.app.app,self.setChangedHook,self) + commandControls.add(controlPassword) + NEW controlPassParams.createCycle('Pass Params','',['N/A','No execute','Swap and retain','Swap, retain and redo','Bypass BBSCMD',0],self.app.app,self.setChangedHook,self) + commandControls.add(controlPassParams) + NEW controlPriority.createStringInt('Priority','',self.app.app,self.setChangedHook,self) + commandControls.add(controlPriority) + NEW controlStack.createStringInt('Stack','',self.app.app,self.setChangedHook,self) + commandControls.add(controlStack) + NEW controlType.createCycle('Type','',typeList,self.app.app,self.setChangedHook,self) + commandControls.add(controlType) + NEW controlBanner.createString('Banner','',self.app.app,self.setChangedHook,self) + commandControls.add(controlBanner) + + NEW controlResident.createCheckBox('Resident','',self.app.app,self.setChangedHook,self) + commandControls.add(controlResident) + NEW controlQuickMode.createCheckBox('Quick Mode','',self.app.app,self.setChangedHook,self) + commandControls.add(controlQuickMode) + NEW controlTrapon.createCheckBox('Trap On','',self.app.app,self.setChangedHook,self) + commandControls.add(controlTrapon) + NEW controlExpertMode.createCheckBox('Expert mode','',self.app.app,self.setChangedHook,self) + commandControls.add(controlExpertMode) + NEW controlDoorSilent.createCheckBox('Silent','',self.app.app,self.setChangedHook,self) + commandControls.add(controlDoorSilent) + NEW controlLogInputs.createCheckBox('Log Inputs','',self.app.app,self.setChangedHook,self) + commandControls.add(controlLogInputs) + NEW controlScriptCheck.createCheckBox('Script Check','',self.app.app,self.setChangedHook,self) + commandControls.add(controlScriptCheck) + NEW controlMultiNode.createCheckBox('Multinode','',self.app.app,self.setChangedHook,self) + commandControls.add(controlMultiNode) + + FOR i:=0 TO commandControls.count()-1 + control:=commandControls.item(i) + control.addToGroup(self.grpAreaSettings) + ENDFOR + + domethod(self.grpAreaSettings,[MUIM_Group_ExitChange]) + + self.addNotifications() + + IF oldCommand + //set controls according to oldCommand + controlName.setValue(oldCommand.name) + controlLocation.setValue(oldCommand.location) + controlAccess.setValueStr(oldCommand.access) + controlInternal.setValue(oldCommand.internal) + controlMimicVer.setValue(oldCommand.mimicVer) + controlPassword.setValue(oldCommand.password) + + IF EstrLen(oldCommand.passParams)=0 + controlPassParams.setValueIndex(0) + ELSE + controlPassParams.setValueIndex(Val(oldCommand.passParams)) + ENDIF + controlPriority.setValueStr(oldCommand.priority) + controlResident.setValue(oldCommand.resident) + controlQuickMode.setValue(oldCommand.quickMode) + controlStack.setValueStr(oldCommand.stack) + + i:=0 + ForAll({item},typeList,`IF item ANDALSO StriCmp(item,oldCommand.type) THEN controlType.setValueIndex(i++) ELSE i++) + controlTrapon.setValue(oldCommand.trapon) + controlExpertMode.setValue(oldCommand.expertMode) + controlDoorSilent.setValue(oldCommand.doorSilent) + controlLogInputs.setValue(oldCommand.logInputs) + controlScriptCheck.setValue(oldCommand.scriptCheck) + controlMultiNode.setValue(oldCommand.multiNode) + controlBanner.setValue(oldCommand.banner) + ENDIF + self.changed:=FALSE + + res:=self.showModal() + IF res + NEW newCommand.create() + //set command according to controls + + get(self.txtAreaName, MUIA_String_Contents,{v1}) + + StrCopy(newCommand.filename,v1) + StrCopy(newCommand.name,controlName.getValue()) + StrCopy(newCommand.location,controlLocation.getValue()) + StrCopy(newCommand.access,controlAccess.getValue()) + StrCopy(newCommand.internal,controlInternal.getValue()) + StrCopy(newCommand.mimicVer,controlMimicVer.getValue()) + StrCopy(newCommand.password,controlPassword.getValue()) + v2:=controlPassParams.getValueIndex() + IF v2=0 + StrCopy(newCommand.passParams,'') + ELSE + StringF(newCommand.passParams,'\d',v2) + ENDIF + + StrCopy(newCommand.priority,controlPriority.getValue()) + newCommand.resident:=controlResident.getValue() + newCommand.quickMode:=controlQuickMode.getValue() + StrCopy(newCommand.stack,controlStack.getValue()) + StrCopy(newCommand.type,typeList[controlType.getValueIndex()]) + newCommand.trapon:=controlTrapon.getValue() + newCommand.expertMode:=controlExpertMode.getValue() + newCommand.doorSilent:=controlDoorSilent.getValue() + newCommand.logInputs:=controlLogInputs.getValue() + newCommand.scriptCheck:=controlScriptCheck.getValue() + newCommand.multiNode:=controlMultiNode.getValue() + StrCopy(newCommand.banner,controlBanner.getValue()) + ENDIF + + FOR i:=0 TO commandControls.count()-1 + control:=commandControls.item(i) + self.freeControl(control) + ENDFOR + self.removeNotifications() + + END commandControls + END existingList + END closeHook + END canSaveHook +ENDPROC res,v1,newCommand + + +PROC editMsgbase(acpName,msgbaseName,oldMsgbase:PTR TO msgbase) OF frmAddComplexItem + DEF res,v1=0,v2=0 + DEF msgbaseControls:PTR TO stdlist + DEF bbsPath[255]:STRING + DEF i + DEF tempStr[255]:STRING + DEF control:PTR TO control + DEF closeHook:PTR TO hook + DEF newMsgbase:PTR TO msgbase + DEF controlMsgbaseLocation:PTR TO control + DEF controlExtSend:PTR TO control + DEF controlUserNames:PTR TO control + DEF controlRealNames:PTR TO control + DEF controlInternetNames:PTR TO control + + + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + set( self.winMain, MUIA_Window_Title,'Edit Messagebase') + set( self.winMain, MUIA_Window_ID, "EMBS") + + set( self.lblAreaName, MUIA_Text_Contents,'Name') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + self.acpName:=acpName + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + set(self.txtAreaName, MUIA_String_Contents,msgbaseName) + + domethod(self.grpAreaSettings,[MUIM_Group_InitChange]) + + set(self.grpAreaSettings, MUIA_Group_Columns , 2) + + NEW msgbaseControls.stdlist(10) + self.msgbaseControls:=msgbaseControls + + newMsgbase:=0 + + NEW controlMsgbaseLocation.createDirSelect('Location','',self.app.app,self.setChangedHook,self) + msgbaseControls.add(controlMsgbaseLocation) + NEW controlExtSend.createCheckBox('Send External','',self.app.app,self.setChangedHook,self) + msgbaseControls.add(controlExtSend) + NEW controlUserNames.createCheckBox('Uses Usernames','',self.app.app,self.setChangedHook,self) + msgbaseControls.add(controlUserNames) + NEW controlRealNames.createCheckBox('Uses real names','',self.app.app,self.setChangedHook,self) + msgbaseControls.add(controlRealNames) + NEW controlInternetNames.createCheckBox('Uses internet names','',self.app.app,self.setChangedHook,self) + msgbaseControls.add(controlInternetNames) + + FOR i:=0 TO msgbaseControls.count()-1 + control:=msgbaseControls.item(i) + control.addToGroup(self.grpAreaSettings) + ENDFOR + + domethod(self.grpAreaSettings,[MUIM_Group_ExitChange]) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addNotifications() + + IF oldMsgbase + //set controls according to oldMsgbase + controlMsgbaseLocation.setValue(oldMsgbase.location) + controlExtSend.setValue(oldMsgbase.extSend) + controlUserNames.setValue(oldMsgbase.username) + controlRealNames.setValue(oldMsgbase.realname) + controlInternetNames.setValue(oldMsgbase.internetname) + ENDIF + self.changed:=FALSE + + res:=self.showModal() + IF res + NEW newMsgbase.create() + //set protocol according to controls + StrCopy(newMsgbase.location,controlMsgbaseLocation.getValue()) + newMsgbase.extSend:=controlExtSend.getValue() + newMsgbase.username:=controlUserNames.getValue() + newMsgbase.realname:=controlRealNames.getValue() + newMsgbase.internetname:=controlInternetNames.getValue() + ENDIF + + FOR i:=0 TO msgbaseControls.count()-1 + control:=msgbaseControls.item(i) + self.freeControl(control) + ENDFOR + self.removeNotifications() + + get(self.txtAreaName, MUIA_String_Contents,{v1}) + + END msgbaseControls + END closeHook +ENDPROC res,v1,newMsgbase diff --git a/axSetupTool/frmAddItem.e b/axSetupTool/frmAddItem.e new file mode 100644 index 0000000..7624252 --- /dev/null +++ b/axSetupTool/frmAddItem.e @@ -0,0 +1,164 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','dos/dos','libraries/asl' +MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' +MODULE '*axedit','*frmBase' + +EXPORT OBJECT frmAddItem OF frmBase + lblItemDetail1: LONG + lblItemDetail2: LONG + txtItemDetail1: LONG + txtItemDetail2: LONG + grpItemDetail2: LONG + btnSave: LONG + btnCancel: LONG + changeHook: hook +ENDOBJECT + +PROC changed() OF frmAddItem + MOVE.L (A1),self + GetA4() + + set( self.btnSave , MUIA_Disabled , FALSE) +ENDPROC + +PROC addNotifications() OF frmAddItem + domethod( self.btnCancel , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + domethod( self.btnSave , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , ID_SAVE ] ) + + domethod( self.txtItemDetail1, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + self.app.app, + 3 , + MUIM_CallHook , self.changeHook, self ]) + + domethod( self.txtItemDetail2, [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + self.app.app, + 3 , + MUIM_CallHook , self.changeHook, self ]) + + installhook( self.changeHook, {changed}) + +ENDPROC + +PROC removeNotifications() OF frmAddItem + domethod(self.btnCancel,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnSave,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.txtItemDetail1,[MUIM_KillNotify,MUIA_String_Contents]) + domethod(self.txtItemDetail2,[MUIM_KillNotify,MUIA_String_Contents]) +ENDPROC + +PROC create(app:PTR TO app_obj) OF frmAddItem + DEF group + SUPER self.create(app) + self.winMain:=app.wi_add_item + + self.btnSave:=app.bt_new_item_save + self.btnCancel:=app.bt_new_item_cancel + self.lblItemDetail1:=app.la_item_detail1 + self.lblItemDetail2:=app.la_item_detail2 + self.txtItemDetail1:=app.stR_item_detail1e + self.txtItemDetail2:=app.stR_item_detail2 + self.grpItemDetail2:=app.gr_item_detail2 +ENDPROC + +PROC addScreen(title) OF frmAddItem + DEF res,v1=0,v2=0 + set( self.winMain, MUIA_Window_Title,'Add Screen') + set( self.lblItemDetail1, MUIA_Text_Contents,'Screen Title') + set( self.lblItemDetail2, MUIA_Text_Contents,'Extension') + + set( self.btnSave,MUIA_Disabled,FALSE) + + set( self.txtItemDetail1, MUIA_String_Contents,title) + set( self.txtItemDetail2, MUIA_String_Contents,'') + + self.addNotifications() + + res:=self.showModal() + IF res + get( self.txtItemDetail1, MUIA_String_Contents,{v1}) + get( self.txtItemDetail2, MUIA_String_Contents,{v2}) + ENDIF + self.removeNotifications() + +ENDPROC res,v1,v2 + +PROC editScreen(title,extension) OF frmAddItem + DEF res,v1=0,v2=0 + set( self.winMain, MUIA_Window_Title,'Edit Screen') + set( self.lblItemDetail1, MUIA_Text_Contents,'Screen Title') + set( self.lblItemDetail2, MUIA_Text_Contents,'Extension') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + set( self.txtItemDetail1, MUIA_String_Contents,title) + set( self.txtItemDetail2, MUIA_String_Contents,extension) + + self.addNotifications() + + res:=self.showModal() + IF res + get( self.txtItemDetail1, MUIA_String_Contents,{v1}) + get( self.txtItemDetail2, MUIA_String_Contents,{v2}) + ENDIF + self.removeNotifications() + +ENDPROC res,v1,v2 + +PROC editConnectionString(connectString,baudString) OF frmAddItem + DEF res,v1=0,v2=0 + set( self.winMain, MUIA_Window_Title,'Edit Connection String') + set( self.lblItemDetail1, MUIA_Text_Contents,'Connection String') + set( self.lblItemDetail2, MUIA_Text_Contents,'Baud Rate') + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + set( self.txtItemDetail1, MUIA_String_Contents,connectString) + set( self.txtItemDetail2, MUIA_String_Contents,baudString) + + self.addNotifications() + + res:=self.showModal() + IF res + get( self.txtItemDetail1, MUIA_String_Contents,{v1}) + get( self.txtItemDetail2, MUIA_String_Contents,{v2}) + ENDIF + self.removeNotifications() + +ENDPROC res,v1,v2 + +PROC editSingleItem(title,itemDesc,value) OF frmAddItem + DEF res,v1=0,v2=0 + set( self.winMain, MUIA_Window_Title,title) + + set( self.grpItemDetail2, MUIA_ShowMe , FALSE) + + set( self.lblItemDetail1, MUIA_Text_Contents,itemDesc) + set( self.txtItemDetail1, MUIA_String_Contents,value) + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + + self.addNotifications() + + res:=self.showModal() + IF res + get( self.txtItemDetail1, MUIA_String_Contents,{v1}) + ENDIF + self.removeNotifications() + set( self.grpItemDetail2, MUIA_ShowMe , MUI_TRUE) + +ENDPROC res,v1 diff --git a/axSetupTool/frmBase.e b/axSetupTool/frmBase.e new file mode 100644 index 0000000..5656b5d --- /dev/null +++ b/axSetupTool/frmBase.e @@ -0,0 +1,103 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','tools/installhook','amigalib/boopsi' +MODULE 'utility/tagitem' , 'utility/hooks','*axedit' + +EXPORT CONST ID_SAVE=1 + +EXPORT OBJECT frmBase + app : PTR TO app_obj + winMain : PTR TO LONG + saveHook : PTR TO hook + canSaveHook : PTR TO hook + closeHook : PTR TO hook +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmBase + self.app:=app + self.saveHook:=NIL + self.canSaveHook:=NIL + self.closeHook:=NIL +ENDPROC + +PROC show() OF frmBase + set( self.winMain ,MUIA_Window_Open , MUI_TRUE ) +ENDPROC + +PROC hide() OF frmBase + set( self.winMain ,MUIA_Window_Open , FALSE ) +ENDPROC + +PROC sleep() OF frmBase + set( self.winMain ,MUIA_Window_Sleep , MUI_TRUE ) +ENDPROC + +PROC wake() OF frmBase + set( self.winMain ,MUIA_Window_Sleep , FALSE ) +ENDPROC + +PROC setupButtonClick(button, hook, code) OF frmBase + domethod( button , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 3, + MUIM_CallHook , hook, self ] ) + installhook( hook , code) +ENDPROC + +PROC showModal() OF frmBase + DEF running = TRUE , result_domethod , signal,result = FALSE + + self.show() + + + domethod( self.winMain , [ + MUIM_Notify , MUIA_Window_CloseRequest , MUI_TRUE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + WHILE running + + result_domethod := domethod( self.app.app, [ MUIM_Application_Input , {signal} ] ) + SELECT result_domethod + + CASE MUIA_Window_CloseRequest + IF self.closeHook + IF callHookA(self.closeHook,0,{self}) + running := FALSE + result:=FALSE + ENDIF + ELSE + running := FALSE + result:=FALSE + ENDIF + + CASE ID_SAVE + IF self.saveHook + callHookA(self.saveHook,0,{self}) + ELSE + IF self.canSaveHook + IF callHookA(self.canSaveHook,0,{self}) + running := FALSE + result:=TRUE + ENDIF + ELSE + running := FALSE + result:=TRUE + ENDIF + ENDIF + + CASE MUIV_Application_ReturnID_Quit + running := FALSE + result:=FALSE + ENDSELECT + + IF ( signal AND running ) THEN Wait( signal ) + ENDWHILE + domethod(self.winMain,[MUIM_KillNotify,MUIA_Window_CloseRequest]) + + self.hide() +ENDPROC result diff --git a/axSetupTool/frmCommands.e b/axSetupTool/frmCommands.e new file mode 100644 index 0000000..f9e752f --- /dev/null +++ b/axSetupTool/frmCommands.e @@ -0,0 +1,152 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' +MODULE '*axedit','*frmBase','*frmEditList','*tooltypes','*/stringlist' + +EXPORT OBJECT frmCommands OF frmBase + btnBBSCmd : PTR TO LONG + btnSysCmd : PTR TO LONG + btnList : PTR TO stdlist + + acpConfigName : PTR TO CHAR + + btnBBSCmdClick: hook + btnSysCmdClick: hook + editBtnClick : hook +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmCommands + DEF group + SUPER self.create(app) + self.winMain:=app.wi_commands + + self.btnBBSCmd:=app.btnBBSCmd + self.btnSysCmd:=app.btnSysCmd +ENDPROC + +PROC btnClick() OF frmCommands + DEF editList:PTR TO frmEditList + DEF btn,text + MOVE.L (A1),self + MOVE.L 4(A1),btn + + btn:=self.btnList.item(btn) + get( btn, MUIA_Text_Contents, {text}) + + self.sleep() + NEW editList.create(self.app) + editList.editCommands(self.acpConfigName,text+5) + END editList + self.wake() + GetA4() +ENDPROC + +PROC goBBSCmd() OF frmCommands + DEF editList:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW editList.create(self.app) + editList.editCommands(self.acpConfigName,'BBSCmd') + END editList + self.wake() +ENDPROC + +PROC goSysCmd() OF frmCommands + DEF editList:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW editList.create(self.app) + editList.editCommands(self.acpConfigName,'SysCmd') + END editList + self.wake() +ENDPROC + + +PROC addNotifications() OF frmCommands + DEF i + self.setupButtonClick(self.btnBBSCmd,self.btnBBSCmdClick,{goBBSCmd}) + self.setupButtonClick(self.btnSysCmd,self.btnSysCmdClick,{goSysCmd}) + + FOR i:=0 TO self.btnList.count()-1 + domethod( self.btnList.item(i) , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 4, + MUIM_CallHook , self.editBtnClick, self, i ] ) + ENDFOR + +ENDPROC + +PROC removeNotifications() OF frmCommands + DEF i + domethod(self.btnBBSCmd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnSysCmd,[MUIM_KillNotify,MUIA_Pressed]) + FOR i:=0 TO self.btnList.count()-1 + domethod(self.btnList.item(i),[MUIM_KillNotify,MUIA_Pressed]) + ENDFOR + +ENDPROC + +PROC editCommands(acpConfigName:PTR TO CHAR) OF frmCommands + DEF nodeCount,confCount,i + DEF btn:PTR TO LONG + DEF btnText[255]:STRING + DEF btnList:stdlist + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + + self.acpConfigName:=acpConfigName + set(self.app.grpCommands, MUIA_Group_Columns , 3) + + nodeCount:=readToolTypeInt(acpConfigName,'NODES') + + readToolType(acpConfigName,'BBS_LOCATION',bbsPath) + StringF(confConfig,'\sCONFCONFIG',bbsPath) + confCount:=readToolTypeInt(confConfig,'NCONFS') + + NEW btnList.stdlist(20) + self.btnList:=btnList + + installhook( self.editBtnClick, {btnClick}) + + FOR i:=0 TO nodeCount-1 + StringF(btnText,'Edit Node\dCmd',i) + btn:=SimpleButton(btnText) + btnList.add(btn) + domethod(self.app.grpCommands,[OM_ADDMEMBER,btn]) + StringF(btnText,'Edit Node\dSysCmd',i) + btn:=SimpleButton(btnText) + btnList.add(btn) + domethod(self.app.grpCommands,[OM_ADDMEMBER,btn]) + ENDFOR + + FOR i:=1 TO confCount-1 + StringF(btnText,'Edit Conf\dCmd',i) + btn:=SimpleButton(btnText) + btnList.add(btn) + domethod(self.app.grpCommands,[OM_ADDMEMBER,btn]) + StringF(btnText,'Edit Conf\dSysCmd',i) + btn:=SimpleButton(btnText) + btnList.add(btn) + domethod(self.app.grpCommands,[OM_ADDMEMBER,btn]) + ENDFOR + self.addNotifications() + + self.showModal() + + self.removeNotifications() + FOR i:=0 TO btnList.count()-1 + btn:=btnList.item(i) + domethod(self.app.grpCommands,[OM_REMMEMBER,btn]) + Mui_DisposeObject(btn) + ENDFOR + END btnList + +ENDPROC diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e new file mode 100644 index 0000000..1fafcfc --- /dev/null +++ b/axSetupTool/frmConfEdit.e @@ -0,0 +1,1081 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui','dos' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*frmAddComplexItem','*configObject','*/stringlist' + +EXPORT OBJECT frmConfEdit OF frmBase + confConfig : PTR TO CHAR + controlList : LONG + + strConfNumber : PTR TO LONG + strConfName : PTR TO LONG + grpConfSettings : PTR TO LONG + grpConfPages : PTR TO LONG + strConfName2 : PTR TO control + paConfPath : PTR TO control + boolFreeDownloads : PTR TO control + strForwardMail : PTR TO control + boolForceNewscan : PTR TO control + boolUseUsernames : PTR TO control + boolUseInternetNames : PTR TO control + strMenuPrompt : PTR TO control + strUploadPrompt : PTR TO control + paLocalULPath : PTR TO control + intFtpDirDays : PTR TO control + strFtpDirName : PTR TO control + boolCustomMail : PTR TO control + boolNoNewscan : PTR TO control + boolDefaultNewscan : PTR TO control + boolDefaultNewfiles: PTR TO control + boolDefaultZoom : PTR TO control + boolUseRealname : PTR TO control + boolShowNewFiles : PTR TO control + boolNoNewFiles : PTR TO control + boolNoFtpUploads : PTR TO control + boolFtpNoDirlist : PTR TO control + lvDownloadPaths : PTR TO LONG + strDownloadPath : PTR TO LONG + lvUploadPaths : PTR TO LONG + strUploadPath : PTR TO LONG + btnFirstConf : PTR TO LONG + btnPrevConf : PTR TO LONG + btnNextConf : PTR TO LONG + btnLastConf : PTR TO LONG + btnAddConf : PTR TO LONG + btnCloneConf : PTR TO LONG + btnRemoveConf : PTR TO LONG + btnConfSave : PTR TO LONG + btnConfCancel : PTR TO LONG + btnUlPathAdd : PTR TO LONG + btnUlPathRemove : PTR TO LONG + btnDlPathAdd : PTR TO LONG + btnDlPathRemove : PTR TO LONG + btnAddMsgbase : PTR TO LONG + btnEditMsgbase : PTR TO LONG + btnRemoveMsgbase : PTR TO LONG + + lvMsgBases : PTR TO LONG + + btnFirstConfClick: hook + btnLastConfClick: hook + btnNextConfClick: hook + btnPrevConfClick: hook + btnAddConfClick: hook + btnCloneConfClick: hook + btnRemoveConfClick: hook + btnDlPathAddClick: hook + btnDlPathRemoveClick: hook + btnUlPathAddClick: hook + btnUlPathRemoveClick: hook + + btnAddMsgbasesClick: hook + btnEditMsgbasesClick: hook + btnRemoveMsgbasesClick: hook + + setChangedHook:hook + strDlPathOnChange: hook + strUlPathOnChange: hook + uploadListOnChange: hook + downloadListOnChange: hook + msgbaseListOnChange: hook + + acpName:PTR TO CHAR + confCount:INT + currConf:INT + changed:INT + newConf:INT + olddlpathcount:INT + oldulpathcount:INT + oldmsgbasecount:INT + msgbaseLists: PTR TO stdlist +ENDOBJECT + +PROC dlPathChange() OF frmConfEdit + DEF str + MOVE.L (A1),self + GetA4() + get(self.strDownloadPath, MUIA_String_Contents,{str}) + set( self.btnDlPathAdd , MUIA_Disabled , IF StrLen(str)=0 THEN MUI_TRUE ELSE FALSE) + self.changed:=TRUE +ENDPROC + +PROC dlpathlistChange() OF frmConfEdit + DEF entry + MOVE.L (A1),self + GetA4() + get(self.lvDownloadPaths,MUIA_List_Active,{entry}) + set( self.btnDlPathRemove , MUIA_Disabled , IF entry=MUIV_List_Active_Off THEN MUI_TRUE ELSE FALSE) +ENDPROC + +PROC ulPathChange() OF frmConfEdit + DEF str + MOVE.L (A1),self + GetA4() + get(self.strUploadPath, MUIA_String_Contents,{str}) + set( self.btnUlPathAdd , MUIA_Disabled , IF StrLen(str)=0 THEN MUI_TRUE ELSE FALSE) + self.changed:=TRUE +ENDPROC + +PROC ulpathlistChange() OF frmConfEdit + DEF entry + MOVE.L (A1),self + GetA4() + get(self.lvUploadPaths,MUIA_List_Active,{entry}) + set( self.btnUlPathRemove , MUIA_Disabled , IF entry=MUIV_List_Active_Off THEN MUI_TRUE ELSE FALSE) +ENDPROC + +PROC msgBaseChange() OF frmConfEdit + DEF entry + MOVE.L (A1),self + GetA4() + get(self.lvMsgBases,MUIA_List_Active,{entry}) + set( self.btnEditMsgbase , MUIA_Disabled , IF entry=MUIV_List_Active_Off THEN MUI_TRUE ELSE FALSE) + set( self.btnRemoveMsgbase , MUIA_Disabled , IF entry=MUIV_List_Active_Off THEN MUI_TRUE ELSE FALSE) +ENDPROC + +PROC ulpathItemAdd() OF frmConfEdit + DEF str + MOVE.L (A1),self + GetA4() + + get(self.strUploadPath, MUIA_String_Contents,{str}) + domethod( self.lvUploadPaths , [ MUIM_List_InsertSingle , str , MUIV_List_Insert_Bottom ] ) + get (self.strUploadPath,MUIA_Popstring_String,{str}) + set(str, MUIA_String_Contents,'') + set( self.btnConfSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC ulpathItemRemove() OF frmConfEdit + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.lvUploadPaths,MUIA_List_Active,{entry}) + + domethod(self.lvUploadPaths, [ MUIM_List_Remove, entry] ) + set( self.btnConfSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC dlpathItemAdd() OF frmConfEdit + DEF str + MOVE.L (A1),self + GetA4() + + get(self.strDownloadPath, MUIA_String_Contents,{str}) + domethod( self.lvDownloadPaths , [ MUIM_List_InsertSingle , str , MUIV_List_Insert_Bottom ] ) + get (self.strDownloadPath,MUIA_Popstring_String,{str}) + set(str, MUIA_String_Contents,'') + + set( self.btnConfSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC dlpathItemRemove() OF frmConfEdit + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.lvDownloadPaths,MUIA_List_Active,{entry}) + + domethod(self.lvDownloadPaths, [ MUIM_List_Remove, entry] ) + set( self.btnConfSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC msgBaseItemAdd() OF frmConfEdit + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF msgbase:PTR TO msgbase + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + res,v1,msgbase:=frmAddComplexItem.editMsgbase(self.acpName,'',NIL) + IF res + domethod( self.lvMsgBases , [ MUIM_List_InsertSingle , v1 , MUIV_List_Insert_Bottom ] ) + self.msgbaseLists.add(msgbase) + self.changed:=TRUE + set( self.btnConfSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddComplexItem +ENDPROC + +PROC msgBaseItemEdit() OF frmConfEdit + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF msgbase:PTR TO msgbase + DEF msgbase2:PTR TO msgbase + DEF i + + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + + get(self.lvMsgBases,MUIA_List_Active,{entry}) + domethod(self.lvMsgBases,[MUIM_List_GetEntry,entry,{str}]) + + msgbase2:=self.msgbaseLists.item(entry) + + res,v1,msgbase:=frmAddComplexItem.editMsgbase(self.acpName,str,msgbase2) + IF res + domethod( self.lvMsgBases , [ MUIM_List_InsertSingle , v1 , entry+1 ] ) + domethod( self.lvMsgBases , [ MUIM_List_Remove, entry ] ) + self.changed:=TRUE + set( self.btnConfSave , MUIA_Disabled , FALSE) + + //copy protocol to protocol2 + StrCopy(msgbase2.location,msgbase.location) + msgbase2.extSend:=msgbase.extSend + msgbase2.username:=msgbase.username + msgbase2.realname:=msgbase.realname + msgbase2.internetname:=msgbase.internetname + ENDIF + END frmAddComplexItem +ENDPROC + +PROC msgBaseItemRemove() OF frmConfEdit + DEF entry,v1 + DEF msgbase:PTR TO msgbase + MOVE.L (A1),self + GetA4() + + get(self.lvMsgBases,MUIA_List_Active,{entry}) + + domethod(self.lvMsgBases,[MUIM_List_GetEntry,entry,{v1}]) + + msgbase:=self.msgbaseLists.item(entry) + END msgbase + self.msgbaseLists.remove(entry) + domethod( self.lvMsgBases , [ MUIM_List_Remove, entry] ) + set( self.btnConfSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + + +PROC create(app:PTR TO app_obj) OF frmConfEdit + DEF list,group + SUPER self.create(app) + self.winMain:=app.wi_conf_edit + + self.strConfName:=app.strConfName + self.strConfNumber:=app.strConfNum + self.btnFirstConf:=app.btnFirstConf + self.btnPrevConf:=app.btnPrevConf + self.btnNextConf:=app.btnNextConf + self.btnLastConf:=app.btnLastConf + self.btnAddConf:=app.btnAddConf + self.btnCloneConf:=app.btnConfClone + self.btnRemoveConf:=app.btnRemoveConf + self.btnConfSave:=app.btnSaveConf + self.btnConfCancel:=app.btnCancelConf + + self.btnAddMsgbase:=app.btnMsgbaseAdd + self.btnEditMsgbase:=app.btnMsgbaseEdit + self.btnRemoveMsgbase:=app.btnMsgbaseDelete + + self.lvMsgBases:=app.lvMsgbases + + self.lvDownloadPaths:=app.lv_download_paths + self.strDownloadPath:=app.pa_downloadpath + self.lvUploadPaths:=app.lv_upload_paths + self.strUploadPath:=app.pa_uploadpath + + self.btnUlPathAdd:=app.bt_ulpath_add + self.btnUlPathRemove:=app.bt_ulpath_remove + self.btnDlPathAdd:=app.bt_dlpath_add + self.btnDlPathRemove:=app.bt_dlpath_remove + + self.grpConfPages:=app.gr_conf_pages + get(app.gr_conf_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpConfSettings:=group + + set(self.grpConfSettings, MUIA_Group_Columns , 4) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(75)) + + get(self.lvDownloadPaths,MUIA_Listview_List,{list}) + set(list,MUIA_List_ConstructHook,MUIV_List_ConstructHook_String) + set(list,MUIA_List_DestructHook,MUIV_List_DestructHook_String) + + get(self.lvUploadPaths,MUIA_Listview_List,{list}) + set(list,MUIA_List_ConstructHook,MUIV_List_ConstructHook_String) + set(list,MUIA_List_DestructHook,MUIV_List_DestructHook_String) + + get(self.lvMsgBases,MUIA_Listview_List,{list}) + set(list,MUIA_List_ConstructHook,MUIV_List_ConstructHook_String) + set(list,MUIA_List_DestructHook,MUIV_List_DestructHook_String) + +ENDPROC + +PROC cloneNewConf() OF frmConfEdit + DEF tempStr[255]:STRING + MOVE.L (A1),self + GetA4() + + IF self.loadConf(self.currConf) + set(self.strConfName, MUIA_String_Contents,'**NEW**') + + + self.changed:=TRUE + self.newConf:=TRUE + self.confCount:=self.confCount+1 + self.currConf:=self.confCount + + StringF(tempStr,'\d',self.currConf) + set(self.strConfNumber, MUIA_String_Contents,tempStr) + + set( self.btnPrevConf, MUIA_Disabled , FALSE) + set( self.btnNextConf, MUIA_Disabled , MUI_TRUE) + set( self.btnRemoveConf, MUIA_Disabled , FALSE) + + + set( self.btnConfSave,MUIA_Disabled,FALSE) + set( self.btnAddConf,MUIA_Disabled,MUI_TRUE) + set( self.btnCloneConf,MUIA_Disabled,MUI_TRUE) + ENDIF +ENDPROC + +PROC createNewConf() OF frmConfEdit + MOVE.L (A1),self + GetA4() + + IF self.loadConf(self.confCount+1) + set(self.strConfName, MUIA_String_Contents,'**NEW**') + self.changed:=TRUE + self.newConf:=TRUE + self.confCount:=self.confCount+1 + set( self.btnConfSave,MUIA_Disabled,FALSE) + set( self.btnAddConf,MUIA_Disabled,MUI_TRUE) + set( self.btnCloneConf,MUIA_Disabled,MUI_TRUE) + ENDIF +ENDPROC + +PROC deleteConfFolder(conf) OF frmConfEdit + DEF deleteStr[255]:STRING + DEF confPath[255]:STRING + DEF tempStr[255]:STRING + + StringF(tempStr,'LOCATION.\d',conf) + readToolType(self.confConfig,tempStr,confPath) + IF EstrLen(confPath)>0 + StringF(deleteStr,'DELETE \s ALL',confPath) + Execute(deleteStr,0,0) + + StringF(deleteStr,'DELETE \s.info ALL',confPath) + Execute(deleteStr,0,0) + ENDIF +ENDPROC + +PROC deleteCurrentConf() OF frmConfEdit + DEF deleteOption + DEF tempStr[255]:STRING + MOVE.L (A1),self + GetA4() + + get (self.app.mnlabel1Donotremovefolder1 , MUIA_Menuitem_Checked, {deleteOption}) + IF deleteOption + deleteOption:=1 + ELSE + get (self.app.mnlabel1Removefolder1, MUIA_Menuitem_Checked, {deleteOption}) + IF deleteOption + deleteOption:=2 + ELSE + deleteOption:=3 + ENDIF + ENDIF + + IF self.deleteConfWarning()=FALSE THEN RETURN + + IF self.loadConf(self.confCount-1) + self.confCount:=self.currConf + + //update confconfig + StringF(tempStr,'\d',self.confCount) + writeToolType(self.confConfig,'NCONFS',tempStr) + + StringF(tempStr,'NAME.\d',self.currConf+1) + deleteToolType(self.confConfig,tempStr) + + StringF(tempStr,'LOCATION.\d',self.currConf+1) + deleteToolType(self.confConfig,tempStr) + + set( self.btnNextConf, MUIA_Disabled , MUI_TRUE) + set( self.btnRemoveConf, MUIA_Disabled , (self.currConf0 + makeDir(msgbase.location) + ENDIF + ENDFOR + + ENDIF + + IF self.boolFreeDownloads.getValue() THEN writeToolType(confPath,'FREEDOWNLOADS') ELSE deleteToolType(confPath,'FREEDOWNLOADS') + + writeToolType(confPath,'FORWARDMAIL',self.strForwardMail.getValue()) + + IF self.boolForceNewscan.getValue() THEN writeToolType(confPath,'FORCE_NEWSCAN') ELSE deleteToolType(confPath,'FORCE_NEWSCAN') + IF self.boolUseUsernames.getValue() THEN writeToolType(confPath,'USERNAME') ELSE deleteToolType(confPath,'USERNAME') + IF self.boolUseInternetNames.getValue() THEN writeToolType(confPath,'INTERNETNAME') ELSE deleteToolType(confPath,'INTERNETNAME') + + writeToolType(confPath,'MENU_PROMPT',self.strMenuPrompt.getValue()) + writeToolType(confPath,'ULPROMPT',self.strUploadPrompt.getValue()) + writeToolType(confPath,'LOCAL_UPLOAD_PATH',self.paLocalULPath.getValue()) + writeToolType(confPath,'FTP_DIR_DAYS',self.intFtpDirDays.getValue()) + writeToolType(confPath,'FTPDIRNAME',self.strFtpDirName.getValue()) + + + IF self.boolCustomMail.getValue() THEN writeToolType(confPath,'CUSTOM') ELSE deleteToolType(confPath,'CUSTOM') + IF self.boolNoNewscan.getValue() THEN writeToolType(confPath,'NO_NEWSCAN') ELSE deleteToolType(confPath,'NO_NEWSCAN') + IF self.boolDefaultNewscan.getValue() THEN writeToolType(confPath,'DEFAULT_NEWSCAN') ELSE deleteToolType(confPath,'DEFAULT_NEWSCAN') + IF self.boolDefaultNewfiles.getValue() THEN writeToolType(confPath,'DEFAULT_NEW_FILES') ELSE deleteToolType(confPath,'DEFAULT_NEW_FILES') + IF self.boolDefaultZoom.getValue() THEN writeToolType(confPath,'DEFAULT_ZOOM') ELSE deleteToolType(confPath,'DEFAULT_ZOOM') + IF self.boolUseRealname.getValue() THEN writeToolType(confPath,'REALNAME') ELSE deleteToolType(confPath,'REALNAME') + IF self.boolShowNewFiles.getValue() THEN writeToolType(confPath,'SHOW_NEW_FILES') ELSE deleteToolType(confPath,'SHOW_NEW_FILES') + IF self.boolNoNewFiles.getValue() THEN writeToolType(confPath,'NO_NEW_FILES') ELSE deleteToolType(confPath,'NO_NEW_FILES') + IF self.boolNoFtpUploads.getValue() THEN writeToolType(confPath,'NO_FTP_UPLOADS') ELSE deleteToolType(confPath,'NO_FTP_UPLOADS') + IF self.boolFtpNoDirlist.getValue() THEN writeToolType(confPath,'FTP_NO_DIRLIST') ELSE deleteToolType(confPath,'FTP_NO_DIRLIST') + + get(self.lvDownloadPaths,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lvDownloadPaths,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'DLPATH.\d',i) + writeToolType(confPath,temppath,entry) + ENDFOR + + FOR i:=count+1 TO self.olddlpathcount + StringF(temppath,'DLPATH.\d',i) + deleteToolType(confPath,temppath) + ENDFOR + + get(self.lvUploadPaths,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lvUploadPaths,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'ULPATH.\d',i) + writeToolType(confPath,temppath,entry) + ENDFOR + + FOR i:=count+1 TO self.oldulpathcount + StringF(temppath,'ULPATH.\d',i) + deleteToolType(confPath,temppath) + ENDFOR + + StrCopy(temppath,confPath) + AddPart(temppath,'msgbases',255) + SetStr(temppath) + get(self.lvMsgBases,MUIA_List_Entries,{count}) + + FOR i:=1 TO count + domethod(self.lvMsgBases,[MUIM_List_GetEntry,i-1,{entry}]) + + StringF(tempStr,'NAME.\d',i) + IF (count=1) AND StrCmp(entry,'Default') + writeToolType(temppath,tempStr,'') + ELSE + writeToolType(temppath,tempStr,entry) + ENDIF + + msgbase:=self.msgbaseLists.item(i-1) + StringF(tempStr,'LOCATION.\d',i) + writeToolType(temppath,tempStr,msgbase.location) + StringF(tempStr,'EXTSEND.\d',i) + writeToolType(temppath,tempStr,IF msgbase.extSend THEN -1 ELSE FALSE) + StringF(tempStr,'USERNAME.\d',i) + writeToolType(temppath,tempStr,IF msgbase.username THEN -1 ELSE FALSE) + StringF(tempStr,'REALNAME.\d',i) + writeToolType(temppath,tempStr,IF msgbase.realname THEN -1 ELSE FALSE) + StringF(tempStr,'INTERNETNAME.\d',i) + writeToolType(temppath,tempStr,IF msgbase.internetname THEN -1 ELSE FALSE) + ENDFOR + + FOR i:=count+1 TO self.oldmsgbasecount + StringF(tempStr,'NAME.\d',i) + deleteToolType(temppath,tempStr) + StringF(tempStr,'LOCATION.\d',i) + deleteToolType(temppath,tempStr) + StringF(tempStr,'EXTSEND.\d',i) + deleteToolType(temppath,tempStr) + StringF(tempStr,'USERNAME.\d',i) + deleteToolType(temppath,tempStr) + StringF(tempStr,'REALNAME.\d',i) + deleteToolType(temppath,tempStr) + StringF(tempStr,'INTERNETNAME.\d',i) + deleteToolType(temppath,tempStr) + ENDFOR + saveCachedChanges() + + + set( self.btnConfSave,MUIA_Disabled,MUI_TRUE) + set( self.btnAddConf,MUIA_Disabled,FALSE) + set( self.btnCloneConf,MUIA_Disabled,FALSE) + self.changed:=FALSE + self.newConf:=FALSE + self.wake() + +ENDPROC + +PROC loadConf(conf) OF frmConfEdit + DEF tempStr[255]:STRING + DEF bbsPath[255]:STRING + DEF confName[100]:STRING + DEF confPath[255]:STRING + DEF temppath[255]:STRING + DEF tempTooltype[255]:STRING + DEF i,val + DEF msgbase:PTR TO msgbase + + IF self.changed + IF self.unsavedChangesWarning()=FALSE THEN RETURN FALSE + ENDIF + + IF self.newConf THEN self.confCount:=self.confCount-1 + self.currConf:=conf + + StringF(tempStr,'NAME.\d',conf) + readToolType(self.confConfig,tempStr,confName) + + StringF(tempStr,'LOCATION.\d',conf) + readToolType(self.confConfig,tempStr,confPath) + + StringF(tempStr,'\d',conf) + set(self.strConfNumber, MUIA_String_Contents,tempStr) + set(self.strConfName, MUIA_String_Contents,confName) + self.strConfName2.setValue(confName) + self.paConfPath.setValue(confPath) + set( self.btnPrevConf, MUIA_Disabled , conf<=1) + set( self.btnNextConf, MUIA_Disabled , conf>=self.confCount) + set( self.btnRemoveConf, MUIA_Disabled , (conf0 + domethod( self.lvDownloadPaths , [ MUIM_List_InsertSingle , tempStr , MUIV_List_Insert_Bottom ] ) + i++ + ENDIF + UNTIL EstrLen(tempStr)=0 + self.olddlpathcount:=i + + i:=1 + REPEAT + StringF(temppath,'ULPATH.\d',i) + readToolType(confPath,temppath,tempStr) + IF EstrLen(tempStr)>0 + domethod( self.lvUploadPaths , [ MUIM_List_InsertSingle , tempStr , MUIV_List_Insert_Bottom ] ) + i++ + ENDIF + UNTIL EstrLen(tempStr)=0 + self.oldulpathcount:=i + + domethod( self.lvMsgBases , [ MUIM_List_Clear] ) + + FOR i:=0 TO self.msgbaseLists.count()-1 + msgbase:=self.msgbaseLists.item(i) + END msgbase + ENDFOR + self.msgbaseLists.clear() + + StrCopy(temppath,confPath) + AddPart(temppath,'MSGBASES',200) + SetStr(temppath) + val:=readToolTypeInt(temppath,'NMSGBASES') + IF val=-1 + domethod( self.lvMsgBases , [ MUIM_List_InsertSingle , 'Default' , MUIV_List_Insert_Bottom ] ) + NEW msgbase.create() + self.msgbaseLists.add(msgbase) + self.oldmsgbasecount:=0 + ELSE + FOR i:=1 TO val + StringF(tempTooltype,'NAME.\d',i) + readToolType(temppath,tempTooltype,tempStr) + domethod( self.lvMsgBases , [ MUIM_List_InsertSingle , tempStr , MUIV_List_Insert_Bottom ] ) + + NEW msgbase.create() + StringF(tempTooltype,'LOCATION.\d',i) + readToolType(temppath,tempTooltype,tempStr) + StrCopy(msgbase.location,tempStr) + + StringF(tempTooltype,'EXTSEND.\d',i) + msgbase.extSend:=checkToolTypeExists(temppath,tempTooltype) + + StringF(tempTooltype,'USERNAME.\d',i) + msgbase.username:=checkToolTypeExists(temppath,tempTooltype) + + StringF(tempTooltype,'REALNAME.\d',i) + msgbase.realname:=checkToolTypeExists(temppath,tempTooltype) + + StringF(tempTooltype,'INTERNETNAME.\d',i) + msgbase.internetname:=checkToolTypeExists(temppath,tempTooltype) + self.msgbaseLists.add(msgbase) + ENDFOR + self.oldmsgbasecount:=val + ENDIF + + + self.changed:=FALSE + set( self.btnConfSave, MUIA_Disabled , MUI_TRUE) + set( self.btnAddConf,MUIA_Disabled,FALSE) + set( self.btnCloneConf,MUIA_Disabled,FALSE) + self.newConf:=FALSE + +ENDPROC TRUE + +PROC editConfs(acpName) OF frmConfEdit + DEF count,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF bbsPath[255]:STRING + DEF msgbaseList:PTR TO stdlist + DEF msgbase:PTR TO msgbase + + NEW saveHook + installhook( saveHook, {saveChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.acpName:=acpName + + set( self.btnEditMsgbase , MUIA_Disabled , MUI_TRUE) + set( self.btnRemoveMsgbase , MUIA_Disabled , MUI_TRUE) + + set( self.btnRemoveConf, MUIA_Disabled , MUI_TRUE) + set( self.btnUlPathAdd , MUIA_Disabled , MUI_TRUE) + set( self.btnDlPathAdd , MUIA_Disabled , MUI_TRUE) + set( self.btnUlPathRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnDlPathRemove , MUIA_Disabled , MUI_TRUE) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addControls() + self.addNotifications() + + set(self.grpConfPages,MUIA_Group_ActivePage,MUIV_Group_ActivePage_First) + + self.changed:=FALSE + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + self.confConfig:=String(255) + StringF(self.confConfig,'\sCONFCONFIG',bbsPath) + self.confCount:=readToolTypeInt(self.confConfig,'NCONFS') + + NEW msgbaseList.stdlist(20) + + self.msgbaseLists:=msgbaseList + + self.loadConf(1) + + self.showModal() + + FOR i:=0 TO self.msgbaseLists.count()-1 + msgbase:=self.msgbaseLists.item(i) + END msgbase + ENDFOR + END self.msgbaseLists + + self.removeNotifications() + self.removeControls() + END saveHook + END closeHook + DisposeLink(self.confConfig) +ENDPROC diff --git a/axSetupTool/frmEditList.e b/axSetupTool/frmEditList.e new file mode 100644 index 0000000..6b969f5 --- /dev/null +++ b/axSetupTool/frmEditList.e @@ -0,0 +1,2564 @@ +OPT MODULE,LARGE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','workbench/workbench','icon','dos/dos' +MODULE 'utility/tagitem' , 'utility/hooks','tools/installhook' + +MODULE '*axedit','*frmBase','*tooltypes','*frmAddItem','*frmAddComplexItem','*/stringlist','*miscfuncs','*configobject' + +EXPORT OBJECT frmEditList OF frmBase + oldcount : INT + computersTooltype : PTR TO CHAR + namesTooltype : PTR TO CHAR + drivesTooltype : PTR TO CHAR + languagesTooltype : PTR TO CHAR + screenTypesTooltype: PTR TO CHAR + connectDefToolType : PTR TO CHAR + lvList : PTR TO LONG + lList : PTR TO LONG + strItem : PTR TO LONG + btnItemAdd : PTR TO LONG + btnItemEdit : PTR TO LONG + btnItemRemove : PTR TO LONG + btnItemsSave : PTR TO LONG + btnItemsCancel : PTR TO LONG + + acpName: PTR TO CHAR + + titles: PTR TO stringlist + extensions: PTR TO stringlist + + connectlist: PTR TO stringlist + connectbaud: PTR TO stringlist + oldconnectionstrings: PTR TO stringlist + + areaLists: PTR TO stdlist + deleteAreas:PTR TO stringlist + accessLists: PTR TO stdlist + deleteAccessLevels:PTR TO stringlist + + fCheckLists: PTR TO stdlist + deletefCheckLists:PTR TO stringlist + + protocolLists: PTR TO stdlist + deleteProtocolLists:PTR TO stringlist + + commandLists: PTR TO stdlist + deleteCommandLists:PTR TO stringlist + commandPath:PTR TO CHAR + + editCaption1: PTR TO CHAR + editCaption2: PTR TO CHAR + + bbsPath:PTR TO CHAR + + strOnChange: hook + btnAddClick: hook + btnEditClick: hook + btnRemoveClick: hook + lvChange: hook + changed +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmEditList + DEF list + SUPER self.create(app) + self.winMain:=app.wi_listEdit + self.lvList:=app.lv_list + get(self.lvList,MUIA_Listview_List,{list}) + self.lList:=list + self.strItem:=app.strListItem + self.btnItemAdd:=app.btnItemAdd + self.btnItemEdit:=app.btnItemEdit + self.btnItemRemove:=app.btnItemRemove + self.btnItemsSave:=app.btnListSave + self.btnItemsCancel:=app.btnListCancel + + set(self.lList,MUIA_List_ConstructHook,MUIV_List_ConstructHook_String) + set(self.lList,MUIA_List_DestructHook,MUIV_List_DestructHook_String) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) +ENDPROC + +PROC stringChange() OF frmEditList + DEF str + MOVE.L (A1),self + GetA4() + + get(self.strItem, MUIA_String_Contents,{str}) + set( self.btnItemAdd , MUIA_Disabled , IF StrLen(str)=0 THEN MUI_TRUE ELSE FALSE) +ENDPROC + +PROC listChange() OF frmEditList + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + set( self.btnItemRemove , MUIA_Disabled , IF entry=MUIV_List_Active_Off THEN MUI_TRUE ELSE FALSE) + set( self.btnItemEdit , MUIA_Disabled , IF entry=MUIV_List_Active_Off THEN MUI_TRUE ELSE FALSE) +ENDPROC + +PROC connectionitemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddItem: PTR TO frmAddItem + MOVE.L (A1),self + GetA4() + + NEW frmAddItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,v2:=frmAddItem.editConnectionString(str,'') + IF res + StringF(tempStr,'\s=\s',v1,v2) + domethod( self.lList , [ MUIM_List_InsertSingle , tempStr , MUIV_List_Insert_Bottom ] ) + self.connectlist.add(v1) + self.connectbaud.add(v2) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC connectionitemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddItem: PTR TO frmAddItem + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + NEW frmAddItem.create(self.app) + res,v1,v2:=frmAddItem.editConnectionString(self.connectlist.item(entry),self.connectbaud.item(entry)) + IF res + StringF(tempStr,'\s=\s',v1,v2) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + domethod( self.lList , [ MUIM_List_InsertSingle , tempStr , entry ] ) + set(self.lList,MUIA_List_Active,entry) + set(self.lList,MUIA_List_Active,entry) + self.connectlist.setItem(entry,v1) + self.connectbaud.setItem(entry,v2) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddItem +ENDPROC + +PROC connectionitemRemove() OF frmEditList + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + self.connectlist.remove(entry) + self.connectbaud.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + + self.changed:=TRUE +ENDPROC + +PROC commanditemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF command:PTR TO command + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,command:=frmAddComplexItem.editCommand(self.acpName,str,self.commandPath,NIL,self.commandLists) + IF res + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , MUIV_List_Insert_Bottom ] ) + self.commandLists.add(command) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddComplexItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC commanditemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF command:PTR TO command + DEF command2:PTR TO command + DEF i + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + domethod(self.lList,[MUIM_List_GetEntry,entry,{str}]) + + NEW frmAddComplexItem.create(self.app) + command2:=self.commandLists.item(entry) + res,v1,command:=frmAddComplexItem.editCommand(self.acpName,str,self.commandPath,command2,self.commandLists) + IF res + IF StriCmp(v1,str)=FALSE + //if we change the identifier then delete the old one + self.deleteCommandLists.add(str) + ENDIF + + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , entry+1 ] ) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + + //copy command to command2 + StrCopy(command2.name,command.name) + StrCopy(command2.location,command.location) + StrCopy(command2.access,command.access) + StrCopy(command2.internal,command.internal) + StrCopy(command2.mimicVer,command.mimicVer) + StrCopy(command2.password,command.password) + StrCopy(command2.passParams,command.passParams) + StrCopy(command2.priority,command.priority) + command2.resident:=command.resident + command2.quickMode:=command.quickMode + StrCopy(command2.stack,command.stack) + StrCopy(command2.type,command.type) + command2.trapon:=command.trapon + command2.expertMode:=command.expertMode + command2.doorSilent:=command.doorSilent + command2.logInputs:=command.logInputs + command2.scriptCheck:=command.scriptCheck + command2.multiNode:=command.multiNode + StrCopy(command2.banner,command.banner) + END command + ENDIF + END frmAddComplexItem +ENDPROC + +PROC commanditemRemove() OF frmEditList + DEF entry,v1 + DEF command:PTR TO command + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + domethod(self.lList,[MUIM_List_GetEntry,entry,{v1}]) + self.deleteCommandLists.add(v1) + + command:=self.commandLists.item(entry) + END command + self.commandLists.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC protocolitemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF protocol:PTR TO protocol + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,protocol:=frmAddComplexItem.editProtocol(self.acpName,str,NIL,self.protocolLists) + IF res + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , MUIV_List_Insert_Bottom ] ) + self.protocolLists.add(protocol) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddComplexItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC protocolitemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF protocol:PTR TO protocol + DEF protocol2:PTR TO protocol + DEF i + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + domethod(self.lList,[MUIM_List_GetEntry,entry,{str}]) + + NEW frmAddComplexItem.create(self.app) + protocol2:=self.protocolLists.item(entry) + res,v1,protocol:=frmAddComplexItem.editProtocol(self.acpName,str,protocol2,self.protocolLists) + IF res + IF StriCmp(v1,str)=FALSE + //if we change the identifier then delete the old one + self.deleteProtocolLists.add(str) + ENDIF + + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , entry+1 ] ) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + + //copy protocol to protocol2 + StrCopy(protocol2.filename,protocol.filename) + StrCopy(protocol2.options,protocol.options) + StrCopy(protocol2.httpHost,protocol.httpHost) + StrCopy(protocol2.httpTemp,protocol.httpTemp) + protocol2.ftpAuth:=protocol.ftpAuth + StrCopy(protocol2.ftpHost,protocol.ftpHost) + StrCopy(protocol2.rxWindow,protocol.rxWindow) + StrCopy(protocol2.txWindow,protocol.txWindow) + END protocol + ENDIF + END frmAddComplexItem +ENDPROC + +PROC protocolitemRemove() OF frmEditList + DEF entry,v1 + DEF protocol:PTR TO protocol + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + domethod(self.lList,[MUIM_List_GetEntry,entry,{v1}]) + self.deleteProtocolLists.add(v1) + + protocol:=self.protocolLists.item(entry) + END protocol + self.protocolLists.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC fileCheckitemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF fChecker:PTR TO fChecker + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,fChecker:=frmAddComplexItem.editFileCheck(self.acpName,str,NIL,self.fCheckLists) + IF res + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , MUIV_List_Insert_Bottom ] ) + self.fCheckLists.add(fChecker) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddComplexItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC fileCheckitemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF fChecker:PTR TO fChecker + DEF fChecker2:PTR TO fChecker + DEF i + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + domethod(self.lList,[MUIM_List_GetEntry,entry,{str}]) + + NEW frmAddComplexItem.create(self.app) + fChecker2:=self.fCheckLists.item(entry) + res,v1,fChecker:=frmAddComplexItem.editFileCheck(self.acpName,str,fChecker2,self.fCheckLists) + IF res + IF StriCmp(v1,str)=FALSE + //if we change the identifier then delete the old one + self.deletefCheckLists.add(str) + ENDIF + + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , entry+1 ] ) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + + //copy fchecker to fchecker2 + StrCopy(fChecker2.filename,fChecker.filename) + StrCopy(fChecker2.checker,fChecker.checker) + StrCopy(fChecker2.error1,fChecker.error1) + StrCopy(fChecker2.error2,fChecker.error2) + StrCopy(fChecker2.error3,fChecker.error3) + StrCopy(fChecker2.error4,fChecker.error4) + StrCopy(fChecker2.error5,fChecker.error5) + StrCopy(fChecker2.error6,fChecker.error6) + StrCopy(fChecker2.error7,fChecker.error7) + StrCopy(fChecker2.error8,fChecker.error8) + StrCopy(fChecker2.error9,fChecker.error9) + StrCopy(fChecker2.error10,fChecker.error10) + StrCopy(fChecker2.options,fChecker.options) + StrCopy(fChecker2.priority,fChecker.priority) + StrCopy(fChecker2.script,fChecker.script) + StrCopy(fChecker2.stack,fChecker.stack) + END fChecker + ENDIF + END frmAddComplexItem +ENDPROC + +PROC fileCheckitemRemove() OF frmEditList + DEF entry,v1 + DEF fChecker:PTR TO fChecker + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + domethod(self.lList,[MUIM_List_GetEntry,entry,{v1}]) + self.deletefCheckLists.add(v1) + + fChecker:=self.fCheckLists.item(entry) + END fChecker + self.fCheckLists.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC accessLevelitemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF accessLevel:PTR TO accessLevel + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,accessLevel:=frmAddComplexItem.editAccess(self.acpName,str,NIL,self.accessLists) + IF res + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , MUIV_List_Insert_Bottom ] ) + self.accessLists.add(accessLevel) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddComplexItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC accessLevelitemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF accessLevel:PTR TO accessLevel + DEF accessLevel2:PTR TO accessLevel + DEF i + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + domethod(self.lList,[MUIM_List_GetEntry,entry,{str}]) + + NEW frmAddComplexItem.create(self.app) + accessLevel2:=self.accessLists.item(entry) + res,v1,accessLevel:=frmAddComplexItem.editAccess(self.acpName,str,accessLevel2,self.accessLists) + IF res + IF StriCmp(v1,str)=FALSE + //if we change the identifier then delete the old one + self.deleteAccessLevels.add(str) + ENDIF + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , entry+1 ] ) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + StrCopy(accessLevel2.filename,accessLevel.filename) + accessLevel2.accessList.clear() + FOR i:=0 TO accessLevel.accessList.count()-1 + accessLevel2.accessList.add(accessLevel.accessList.item(i)) + ENDFOR + END accessLevel + ENDIF + END frmAddComplexItem +ENDPROC + +PROC accessLevelitemRemove() OF frmEditList + DEF entry,v1 + DEF accessLevel:PTR TO accessLevel + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + domethod(self.lList,[MUIM_List_GetEntry,entry,{v1}]) + self.deleteAccessLevels.add(v1) + + accessLevel:=self.accessLists.item(entry) + END accessLevel + self.accessLists.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC areaitemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF area:PTR TO area + MOVE.L (A1),self + GetA4() + + NEW frmAddComplexItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,area:=frmAddComplexItem.editArea(self.acpName,str,NIL,self.areaLists) + IF res + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , MUIV_List_Insert_Bottom ] ) + self.areaLists.add(area) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddComplexItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC areaitemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddComplexItem: PTR TO frmAddComplexItem + DEF area:PTR TO area + DEF area2:PTR TO area + DEF i + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + domethod(self.lList,[MUIM_List_GetEntry,entry,{str}]) + + NEW frmAddComplexItem.create(self.app) + area2:=self.areaLists.item(entry) + res,v1,area:=frmAddComplexItem.editArea(self.acpName,str,area2, self.areaLists) + IF res + IF StriCmp(v1,str)=FALSE + //if we change the identifier then delete the old one + self.deleteAreas.add(str) + ENDIF + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , entry+1 ] ) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + StrCopy(area2.filename,area.filename) + FOR i:=0 TO ListLen(area.confList)-1 + area2.confList[i]:=area.confList[i] + ENDFOR + END area + ENDIF + END frmAddComplexItem +ENDPROC + +PROC areaitemRemove() OF frmEditList + DEF entry,v1 + DEF area:PTR TO area + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + domethod(self.lList,[MUIM_List_GetEntry,entry,{v1}]) + self.deleteAreas.add(v1) + + area:=self.areaLists.item(entry) + END area + self.areaLists.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC screenitemAdd() OF frmEditList + DEF str,res,v1,v2 + DEF tempStr[255]:STRING + DEF frmAddItem: PTR TO frmAddItem + MOVE.L (A1),self + GetA4() + + NEW frmAddItem.create(self.app) + get(self.strItem, MUIA_String_Contents,{str}) + res,v1,v2:=frmAddItem.addScreen(str) + IF res + StringF(tempStr,'\s (\s)',v1,v2) + domethod( self.lList , [ MUIM_List_InsertSingle , tempStr , MUIV_List_Insert_Bottom ] ) + self.extensions.add(v2) + self.titles.add(v1) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddItem + + set(self.strItem, MUIA_String_Contents,'') +ENDPROC + +PROC screenitemEdit() OF frmEditList + DEF str,res,v1,v2,entry + DEF tempStr[255]:STRING + DEF frmAddItem: PTR TO frmAddItem + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + NEW frmAddItem.create(self.app) + res,v1,v2:=frmAddItem.editScreen(self.titles.item(entry),self.extensions.item(entry)) + IF res + StringF(tempStr,'\s (\s)',v1,v2) + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + domethod( self.lList , [ MUIM_List_InsertSingle , tempStr , entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.extensions.setItem(entry,v2) + self.titles.setItem(entry,v1) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddItem +ENDPROC + +PROC screenitemRemove() OF frmEditList + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + self.extensions.remove(entry) + self.titles.remove(entry) + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC itemAdd() OF frmEditList + DEF str + MOVE.L (A1),self + GetA4() + + get(self.strItem, MUIA_String_Contents,{str}) + domethod( self.lList , [ MUIM_List_InsertSingle , str , MUIV_List_Insert_Bottom ] ) + set(self.strItem, MUIA_String_Contents,'') + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC itemEdit() OF frmEditList + DEF str,res,v1,entry + DEF tempStr[255]:STRING + DEF frmAddItem: PTR TO frmAddItem + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + domethod(self.lList,[MUIM_List_GetEntry,entry,{v1}]) + + + NEW frmAddItem.create(self.app) + res,v1:=frmAddItem.editSingleItem(self.editCaption1,self.editCaption2,v1) + IF res + domethod( self.lList , [ MUIM_List_Remove, entry ] ) + domethod( self.lList , [ MUIM_List_InsertSingle , v1 , entry ] ) + set(self.lList,MUIA_List_Active,entry) + self.changed:=TRUE + set( self.btnItemsSave , MUIA_Disabled , FALSE) + ENDIF + END frmAddItem +ENDPROC + +PROC itemRemove() OF frmEditList + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.lList,MUIA_List_Active,{entry}) + + domethod( self.lList , [ MUIM_List_Remove, entry] ) + set( self.btnItemsSave , MUIA_Disabled , FALSE) + self.changed:=TRUE +ENDPROC + +PROC addNotifications(customAdd=FALSE) OF frmEditList + domethod( self.btnItemsCancel , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + domethod( self.btnItemsSave , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , ID_SAVE ] ) + + domethod( self.strItem , [ + MUIM_Notify , MUIA_String_Contents , MUIV_EveryTime , + self.app.app, + 3 , + MUIM_CallHook , self.strOnChange, self] ) + installhook( self.strOnChange, {stringChange}) + + + domethod( self.lList , [ + MUIM_Notify , MUIA_List_Active , MUIV_EveryTime , + self.app.app, + 3 , + MUIM_CallHook , self.lvChange, self] ) + installhook( self.lvChange, {listChange}) + + IF customAdd=FALSE + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{itemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{itemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{itemRemove}) + ENDIF +ENDPROC + +PROC removeNotifications(customAdd=FALSE) OF frmEditList + domethod(self.btnItemsCancel,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemsSave,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.strItem,[MUIM_KillNotify,MUIA_String_Contents]) + domethod(self.lList,[MUIM_KillNotify,MUIA_List_Active]) + IF (customAdd=FALSE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + ENDIF +ENDPROC + +PROC canClose() OF frmEditList + MOVE.L (A1),self + GetA4() + IF self.changed + IF self.unsavedChangesWarning()=0 THEN RETURN FALSE + ENDIF +ENDPROC TRUE + +PROC unsavedChangesWarning() OF frmEditList + IF EasyRequestArgs( NIL , [ 20 , 0 , + 'Unsaved changes' , + 'You have unsaved changes,\nif you continue you will lose them.', + '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE +ENDPROC TRUE + + +PROC saveComputersChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + DEF newCountStr[10]:STRING + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'COMPUTER.\d',i) + writeToolType(self.computersTooltype,temppath,entry) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'COMPUTER.\d',i) + deleteToolType(self.computersTooltype,temppath) + ENDFOR + StringF(newCountStr,'\d',count) + writeToolType(self.computersTooltype,'COMPUTER.NUM',newCountStr) + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editComputers(acpName) OF frmEditList + DEF count,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF bbsPath[200]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + self.changed:=FALSE + + NEW saveHook + installhook( saveHook, {saveComputersChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Computers' + self.editCaption2:='Computer' + + set(self.app.grp_arrange,MUIA_Group_Columns,1) + set(self.strItem,MUIA_ShowMe,MUI_TRUE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.computersTooltype:=String(255) + StringF(self.computersTooltype,'\sComputerList',bbsPath) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Computers') + set( self.winMain, MUIA_Window_ID, "FCPS") + + self.addNotifications() + + count:=readToolTypeInt(self.computersTooltype,'COMPUTER.NUM') + IF (count>0) + FOR i:=1 TO count + StringF(temppath,'COMPUTER.\d',i) + readToolType(self.computersTooltype,temppath,tempstr) + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + ENDFOR + ENDIF + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications() + END saveHook + END closeHook + DisposeLink(self.computersTooltype) +ENDPROC + +PROC saveNamesNotAllowedChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'NAME.\d',i) + writeToolType(self.namesTooltype,temppath,entry) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'NAME.\d',i) + deleteToolType(self.namesTooltype,temppath) + ENDFOR + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editNamesNotAllowed(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF bbsPath[200]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + self.changed:=FALSE + + NEW saveHook + installhook( saveHook, {saveNamesNotAllowedChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + readToolType(acpName,'BBS_LOCATION',bbsPath) + + self.editCaption1:='Edit Names Not Allowed' + self.editCaption2:='Name' + + set(self.app.grp_arrange,MUIA_Group_Columns,1) + set(self.strItem,MUIA_ShowMe,MUI_TRUE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) + + self.namesTooltype:=String(255) + StringF(self.namesTooltype,'\sNamesNotAllowed',bbsPath) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Names Not Allowed') + set( self.winMain, MUIA_Window_ID, "FNNS") + + self.addNotifications() + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'NAME.\d',count+1) + readToolType(self.namesTooltype,temppath,tempstr) + IF StrLen(tempstr)>0 + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications() + END saveHook + END closeHook + DisposeLink(self.namesTooltype) +ENDPROC + +PROC saveDrivesChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'DRIVE.\d',i) + writeToolType(self.drivesTooltype,temppath,entry) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'DRIVE.\d',i) + deleteToolType(self.drivesTooltype,temppath) + ENDFOR + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editDrives(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF bbsPath[200]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + self.changed:=FALSE + + NEW saveHook + installhook( saveHook, {saveDrivesChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Drives' + self.editCaption2:='Drive' + + set(self.app.grp_arrange,MUIA_Group_Columns,1) + set(self.strItem,MUIA_ShowMe,MUI_TRUE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.drivesTooltype:=String(255) + StringF(self.drivesTooltype,'\sDrives',bbsPath) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Drives') + set( self.winMain, MUIA_Window_ID, "FDRS") + + self.addNotifications() + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'DRIVE.\d',count+1) + readToolType(self.drivesTooltype,temppath,tempstr) + IF StrLen(tempstr)>0 + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + IF self.showModal() + ENDIF + self.removeNotifications() + END saveHook + END closeHook + DisposeLink(self.drivesTooltype) +ENDPROC + +PROC saveLanguagesChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'LANGUAGE.\d',i) + writeToolType(self.languagesTooltype,temppath,entry) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'LANGUAGE.\d',i) + deleteToolType(self.languagesTooltype,temppath) + ENDFOR + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editLanguages(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF bbsPath[200]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + self.changed:=FALSE + + NEW saveHook + installhook( saveHook, {saveLanguagesChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Languages' + self.editCaption2:='Language' + + set(self.app.grp_arrange,MUIA_Group_Columns,1) + set(self.strItem,MUIA_ShowMe,MUI_TRUE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.languagesTooltype:=String(255) + StringF(self.languagesTooltype,'\sLanguages',bbsPath) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Languages') + set( self.winMain, MUIA_Window_ID, "FLNS") + + self.addNotifications() + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'LANGUAGE.\d',count+1) + readToolType(self.languagesTooltype,temppath,tempstr) + IF StrLen(tempstr)>0 + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + IF self.showModal() + ENDIF + self.removeNotifications() + END saveHook + END closeHook + DisposeLink(self.languagesTooltype) +ENDPROC + +PROC saveScreenTypesChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + StringF(temppath,'TYPE.\d',i) + writeToolType(self.screenTypesTooltype,temppath,self.extensions.item(i-1)) + + StringF(temppath,'TITLE.\d',i) + writeToolType(self.screenTypesTooltype,temppath,self.titles.item(i-1)) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'TYPE.\d',i) + deleteToolType(self.screenTypesTooltype,temppath) + + StringF(temppath,'TITLE.\d',i) + deleteToolType(self.screenTypesTooltype,temppath) + ENDFOR + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editScreens(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[200]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF titles:PTR TO stringlist + DEF extensions:PTR TO stringlist + + self.changed:=FALSE + + NEW saveHook + installhook( saveHook, {saveScreenTypesChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Screentypes' + self.editCaption2:='Screentype' + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.screenTypesTooltype:=String(255) + StringF(self.screenTypesTooltype,'\sScreenTypes',bbsPath) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Screentypes') + set( self.winMain, MUIA_Window_ID, "FSTS") + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{screenitemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{screenitemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{screenitemRemove}) + self.addNotifications(TRUE) + + NEW titles.stringlist(100) + self.titles:=titles + NEW extensions.stringlist(100) + self.extensions:=extensions + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'TYPE.\d',count+1) + readToolType(self.screenTypesTooltype,temppath,tempstr) + + StringF(temppath,'TITLE.\d',count+1) + readToolType(self.screenTypesTooltype,temppath,tempstr2) + + IF StrLen(tempstr2)>0 + self.extensions.add(tempstr) + self.titles.add(tempstr2) + IF StrLen(tempstr)>0 + StringF(tempstr,'\s (\s)',tempstr2,tempstr) + ELSE + StrCopy(tempstr,'\s',tempstr2) + ENDIF + ENDIF + + IF StrLen(tempstr)>0 + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + END saveHook + END closeHook + END titles + END extensions + DisposeLink(self.screenTypesTooltype) +ENDPROC + +PROC saveAreasChanges() OF frmEditList + DEF i,j,count + DEF temppath[255]:STRING + DEF accessPath[255]:STRING + DEF areaToolType[255]:STRING + DEF area:PTR TO area + DEF confToolType[20]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + + StringF(accessPath,'\saccess/',self.bbsPath) + + FOR i:=0 TO self.deleteAreas.count()-1 + StringF(areaToolType,'\sArea.\s.info',accessPath,self.deleteAreas.item(i)) + deleteFileFromCache(areaToolType) + DeleteFile(areaToolType) + ENDFOR + self.deleteAreas.clear() + + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{area}]) + StringF(areaToolType,'\sArea.\s',accessPath,area) + + area:=self.areaLists.item(i-1) + FOR j:=1 TO ListLen(area.confList) + StringF(confToolType,'CONF.\d',j) + IF area.confList[j-1] + writeToolType(areaToolType,confToolType,-1) + ELSE + deleteToolType(areaToolType,confToolType) + ENDIF + ENDFOR + ENDFOR + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC loadAreaNames(confCount) OF frmEditList + DEF accessPath[255]:STRING + DEF areaToolType[255]:STRING + DEF confToolType[20]:STRING + DEF dir_info:PTR TO fileinfoblock + DEF pdir,r,entry,i,n + DEF area:PTR TO area + + DEF confList:PTR TO LONG + + DEF buf[255]:STRING + DEF parseBuf[100]:STRING + DEF namesList:PTR TO stringlist + + StringF(accessPath,'\saccess/',self.bbsPath) + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(accessPath,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF ParsePatternNoCase('AREA.#?.info',parseBuf,100) =-1 THEN RETURN + + domethod( self.lList , [ MUIM_List_Clear] ) + + NEW namesList.stringlist(20) + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + + IF MatchPatternNoCase(parseBuf,dir_info.filename) + StrCopy(buf,dir_info.filename+5) + stripInfo(buf) + namesList.add(buf) + ENDIF + ENDIF + ENDWHILE + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) + + namesList.sort() + FOR n:=0 TO namesList.count()-1 + + NEW area.create() + + domethod( self.lList , [ MUIM_List_InsertSingle , namesList.item(n) , MUIV_List_Insert_Bottom ] ) + + StrCopy(area.filename,namesList.item(n)) + area.confList:=List(confCount) + StringF(areaToolType,'\sArea.\s',accessPath,namesList.item(n)) + FOR i:=0 TO confCount-1 + StringF(confToolType,'CONF.\d',i+1) + ListAddItem(area.confList,IF checkToolTypeExists(areaToolType,confToolType) THEN TRUE ELSE FALSE) + ENDFOR + self.areaLists.add(area) + ENDFOR + + END namesList +ENDPROC + +PROC editAreas(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF areaLists:PTR TO stdlist + DEF deleteAreas:PTR TO stringlist + DEF area:PTR TO area + DEF confCount + + self.changed:=FALSE + + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveAreasChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Areas' + self.editCaption2:='Areas' + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.bbsPath:=bbsPath + + StringF(confConfig,'\sCONFCONFIG',bbsPath) + + confCount:=readToolTypeInt(confConfig,'NCONFS') + + NEW areaLists.stdlist(25) + self.areaLists:=areaLists + + NEW deleteAreas.stringlist(25) + self.deleteAreas:=deleteAreas + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Areas') + set( self.winMain, MUIA_Window_ID, "FARS") + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{areaitemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{areaitemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{areaitemRemove}) + self.addNotifications(TRUE) + + self.loadAreaNames(confCount) + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + END saveHook + END closeHook + FOR i:=0 TO areaLists.count()-1 + area:=areaLists.item(i) + END area + ENDFOR + END areaLists + END deleteAreas +ENDPROC + +PROC saveAccessLevelChanges() OF frmEditList + DEF i,j,count + DEF temppath[255]:STRING + DEF accessLevel:PTR TO accessLevel + DEF accessPath[255]:STRING + DEF accessToolType[255]:STRING + DEF acs + DEF confToolType[20]:STRING + DEF acsValues:PTR TO LONG + DEF tempStr[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + + StringF(accessPath,'\saccess/',self.bbsPath) + + FOR i:=0 TO self.deleteAccessLevels.count()-1 + StringF(accessToolType,'\sACS.\s.info',accessPath,self.deleteAccessLevels.item(i)) + deleteFileFromCache(accessToolType) + DeleteFile(accessToolType) + ENDFOR + self.deleteAccessLevels.clear() + + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{acs}]) + StringF(accessToolType,'\sACS.\s',accessPath,acs) + + accessLevel:=self.accessLists.item(i-1) + + acsValues:=getAccessLevels() + + FOR j:=0 TO ListLen(acsValues)-1 + IF j=0 + writeToolType(accessToolType,'ACS.MAX_PAGES',accessLevel.accessList.item(0)) + ELSE + IF accessLevel.accessList.contains(acsValues[j]) THEN writeToolType(accessToolType,acsValues[j],-1) ELSE deleteToolType(accessToolType,acsValues[j]) + ENDIF + ENDFOR + ENDFOR + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC loadAccessLevels() OF frmEditList + DEF accessPath[255]:STRING + DEF accessToolType[255]:STRING + DEF dir_info:PTR TO fileinfoblock + DEF pdir,r,entry,i,n + DEF accessLevel:PTR TO accessLevel + DEF tempStr[255]:STRING + + DEF buf[255]:STRING + DEF parseBuf[100]:STRING + DEF namesList:PTR TO stringlist + DEF acsValues:PTR TO LONG + + StringF(accessPath,'\saccess/',self.bbsPath) + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(accessPath,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF ParsePatternNoCase('ACS.#?.info',parseBuf,100) =-1 THEN RETURN + + domethod( self.lList , [ MUIM_List_Clear] ) + + NEW namesList.stringlist(100) + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + + IF MatchPatternNoCase(parseBuf,dir_info.filename) + StrCopy(buf,dir_info.filename+4) + stripInfo(buf) + namesList.add(buf) + ENDIF + ENDIF + ENDWHILE + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) + + namesList.sort() + FOR n:=0 TO namesList.count()-1 + domethod( self.lList , [ MUIM_List_InsertSingle , namesList.item(n) , MUIV_List_Insert_Bottom ] ) + NEW accessLevel.create() + + StrCopy(accessLevel.filename,namesList.item(n)) + StringF(accessToolType,'\sACS.\s',accessPath,namesList.item(n)) + + acsValues:=getAccessLevels() + + FOR i:=0 TO ListLen(acsValues)-1 + IF i=0 + readToolType(accessToolType,acsValues[0],tempStr) + accessLevel.accessList.add(tempStr) + ELSE + IF checkToolTypeExists(accessToolType,acsValues[i]) THEN accessLevel.accessList.add(acsValues[i]) + ENDIF + ENDFOR + + self.accessLists.add(accessLevel) + ENDFOR + + END namesList +ENDPROC + +PROC editAccessLevel(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF accessLists:PTR TO stdlist + DEF deleteAccessLevels:PTR TO stringlist + DEF accessList:PTR TO stringlist + + self.changed:=FALSE + + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveAccessLevelChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Access Levels' + self.editCaption2:='Access Level' + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.bbsPath:=bbsPath + + NEW accessLists.stdlist(25) + self.accessLists:=accessLists + + NEW deleteAccessLevels.stringlist(25) + self.deleteAccessLevels:=deleteAccessLevels + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Access Levels') + set( self.winMain, MUIA_Window_ID, "FALS") + + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{accessLevelitemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{accessLevelitemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{accessLevelitemRemove}) + self.addNotifications(TRUE) + + self.loadAccessLevels() + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + + END saveHook + END closeHook + + FOR i:=0 TO accessLists.count()-1 + accessList:=accessLists.item(i) + END accessList + ENDFOR + END accessLists + END deleteAccessLevels +ENDPROC + +PROC saveFCheckChanges() OF frmEditList + DEF i,count + DEF fCheckPath[255]:STRING + DEF fCheckToolType[255]:STRING + DEF fcheckName + DEF fChecker:PTR TO fChecker + DEF tempStr[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + + StringF(fCheckPath,'\sfcheck/',self.bbsPath) + + FOR i:=0 TO self.deletefCheckLists.count()-1 + StringF(fCheckToolType,'\s\s.info',fCheckPath,self.deletefCheckLists.item(i)) + deleteFileFromCache(fCheckToolType) + DeleteFile(fCheckToolType) + ENDFOR + self.deletefCheckLists.clear() + + + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{fcheckName}]) + StringF(fCheckToolType,'\s\s',fCheckPath,fcheckName) + + fChecker:=self.fCheckLists.item(i-1) + + writeToolType(fCheckToolType,'CHECKER',fChecker.checker) + writeToolType(fCheckToolType,'ERROR.1',fChecker.error1) + writeToolType(fCheckToolType,'ERROR.2',fChecker.error2) + writeToolType(fCheckToolType,'ERROR.3',fChecker.error3) + writeToolType(fCheckToolType,'ERROR.4',fChecker.error4) + writeToolType(fCheckToolType,'ERROR.5',fChecker.error5) + writeToolType(fCheckToolType,'ERROR.6',fChecker.error6) + writeToolType(fCheckToolType,'ERROR.7',fChecker.error7) + writeToolType(fCheckToolType,'ERROR.8',fChecker.error8) + writeToolType(fCheckToolType,'ERROR.9',fChecker.error9) + writeToolType(fCheckToolType,'ERROR.10',fChecker.error10) + writeToolType(fCheckToolType,'OPTIONS',fChecker.options) + writeToolType(fCheckToolType,'PRIORITY',fChecker.priority) + writeToolType(fCheckToolType,'SCRIPT',fChecker.script) + writeToolType(fCheckToolType,'STACK',fChecker.stack) + ENDFOR + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC loadFileCheckers() OF frmEditList + DEF fCheckPath[255]:STRING + DEF fCheckToolType[255]:STRING + DEF tempStr[255]:STRING + DEF dir_info:PTR TO fileinfoblock + DEF pdir,r,entry,i,n + DEF fileChecker:PTR TO fChecker + + DEF buf[255]:STRING + DEF parseBuf[100]:STRING + DEF namesList:PTR TO stringlist + + StringF(fCheckPath,'\sfcheck/',self.bbsPath) + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(fCheckPath,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF ParsePatternNoCase('#?.info',parseBuf,100) =-1 THEN RETURN + + domethod( self.lList , [ MUIM_List_Clear] ) + + NEW namesList.stringlist(20) + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + + IF MatchPatternNoCase(parseBuf,dir_info.filename) + StrCopy(buf,dir_info.filename) + stripInfo(buf) + namesList.add(buf) + ENDIF + ENDIF + ENDWHILE + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) + + namesList.sort() + FOR n:=0 TO namesList.count()-1 + domethod( self.lList , [ MUIM_List_InsertSingle , namesList.item(n) , MUIV_List_Insert_Bottom ] ) + StringF(fCheckToolType,'\s\s',fCheckPath,namesList.item(n)) + + NEW fileChecker.create() + //load fcheck details + StrCopy(fileChecker.filename,namesList.item(n)) + readToolType(fCheckToolType,'CHECKER',tempStr) + StrCopy(fileChecker.checker,tempStr) + readToolType(fCheckToolType,'OPTIONS',tempStr) + StrCopy(fileChecker.options,tempStr) + readToolType(fCheckToolType,'SCRIPT',tempStr) + StrCopy(fileChecker.script,tempStr) + readToolType(fCheckToolType,'ERROR.1',tempStr) + StrCopy(fileChecker.error1,tempStr) + readToolType(fCheckToolType,'ERROR.2',tempStr) + StrCopy(fileChecker.error2,tempStr) + readToolType(fCheckToolType,'ERROR.3',tempStr) + StrCopy(fileChecker.error3,tempStr) + readToolType(fCheckToolType,'ERROR.4',tempStr) + StrCopy(fileChecker.error4,tempStr) + readToolType(fCheckToolType,'ERROR.5',tempStr) + StrCopy(fileChecker.error5,tempStr) + readToolType(fCheckToolType,'ERROR.6',tempStr) + StrCopy(fileChecker.error6,tempStr) + readToolType(fCheckToolType,'ERROR.7',tempStr) + StrCopy(fileChecker.error7,tempStr) + readToolType(fCheckToolType,'ERROR.8',tempStr) + StrCopy(fileChecker.error8,tempStr) + readToolType(fCheckToolType,'ERROR.9',tempStr) + StrCopy(fileChecker.error9,tempStr) + readToolType(fCheckToolType,'ERROR.10',tempStr) + StrCopy(fileChecker.error10,tempStr) + readToolType(fCheckToolType,'PRIORITY',tempStr) + StrCopy(fileChecker.priority,tempStr) + readToolType(fCheckToolType,'STACK',tempStr) + StrCopy(fileChecker.stack,tempStr) + + self.fCheckLists.add(fileChecker) + ENDFOR + END namesList +ENDPROC + +PROC editFileCheckers(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF fCheckLists:PTR TO stdlist + DEF deletefCheckLists:PTR TO stringlist + DEF fileChecker:PTR TO fChecker + + self.changed:=FALSE + + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveFCheckChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit File Checkers' + self.editCaption2:='File Checker' + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.bbsPath:=bbsPath + + NEW fCheckLists.stdlist(25) + self.fCheckLists:=fCheckLists + + NEW deletefCheckLists.stringlist(25) + self.deletefCheckLists:=deletefCheckLists + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit File Checkers') + set( self.winMain, MUIA_Window_ID, "FCHK") + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{fileCheckitemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{fileCheckitemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{fileCheckitemRemove}) + self.addNotifications(TRUE) + + self.loadFileCheckers() + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + END saveHook + END closeHook + FOR i:=0 TO fCheckLists.count()-1 + fileChecker:=fCheckLists.item(i) + END fileChecker + ENDFOR + END fCheckLists + END deletefCheckLists +ENDPROC + +PROC saveProtocolChanges() OF frmEditList + DEF i,count + DEF protocolPath[255]:STRING + DEF protocolToolType[255]:STRING + DEF protocolName + DEF protocol:PTR TO protocol + DEF tempStr[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + + StringF(protocolPath,'\sprotocols/',self.bbsPath) + + FOR i:=0 TO self.deleteProtocolLists.count()-1 + StringF(protocolToolType,'\s\s.info',protocolPath,self.deleteProtocolLists.item(i)) + deleteFileFromCache(protocolToolType) + DeleteFile(protocolToolType) + ENDFOR + self.deleteProtocolLists.clear() + + + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{protocolName}]) + StringF(protocolToolType,'\s\s',protocolPath,protocolName) + + protocol:=self.protocolLists.item(i-1) + + writeToolType(protocolToolType,'OPTIONS',protocol.options) + writeToolType(protocolToolType,'HTTPHOST',protocol.httpHost) + writeToolType(protocolToolType,'HTTPTEMP',protocol.httpTemp) + writeToolType(protocolToolType,'FTPHOST',protocol.ftpHost) + IF protocol.ftpAuth THEN writeToolType(protocolToolType,'FTPAUTH',-1) ELSE deleteToolType(protocolToolType,'FTPAUTH') + writeToolType(protocolToolType,'RXWINDOW',protocol.rxWindow) + writeToolType(protocolToolType,'TXWINDOW',protocol.txWindow) + ENDFOR + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC loadProtocols() OF frmEditList + DEF protocolPath[255]:STRING + DEF protocolToolType[255]:STRING + DEF tempStr[255]:STRING + DEF dir_info:PTR TO fileinfoblock + DEF pdir,r,entry,i,n + DEF protocol:PTR TO protocol + + DEF buf[255]:STRING + DEF parseBuf[100]:STRING + DEF namesList:PTR TO stringlist + + StringF(protocolPath,'\sprotocols/',self.bbsPath) + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(protocolPath,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF ParsePatternNoCase('#?.info',parseBuf,100) =-1 THEN RETURN + + domethod( self.lList , [ MUIM_List_Clear] ) + + NEW namesList.stringlist(20) + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + + IF MatchPatternNoCase(parseBuf,dir_info.filename) + StrCopy(buf,dir_info.filename) + stripInfo(buf) + namesList.add(buf) + ENDIF + ENDIF + ENDWHILE + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) + + namesList.sort() + FOR n:=0 TO namesList.count()-1 + + domethod( self.lList , [ MUIM_List_InsertSingle , namesList.item(n) , MUIV_List_Insert_Bottom ] ) + StringF(protocolToolType,'\s\s',protocolPath,namesList.item(n)) + + NEW protocol.create() + //load protocol details + + StrCopy(protocol.filename,namesList.item(n)) + + readToolType(protocolToolType,'OPTIONS',tempStr) + StrCopy(protocol.options,tempStr) + + readToolType(protocolToolType,'HTTPHOST',tempStr) + StrCopy(protocol.httpHost,tempStr) + + readToolType(protocolToolType,'HTTPTEMP',tempStr) + StrCopy(protocol.httpTemp,tempStr) + + readToolType(protocolToolType,'FTPHOST',tempStr) + StrCopy(protocol.ftpHost,tempStr) + + protocol.ftpAuth:=checkToolTypeExists(protocolToolType,'FTPAUTH') + + readToolType(protocolToolType,'RXWINDOW',tempStr) + StrCopy(protocol.rxWindow,tempStr) + + readToolType(protocolToolType,'TXWINDOW',tempStr) + StrCopy(protocol.txWindow,tempStr) + + self.protocolLists.add(protocol) + ENDFOR + END namesList +ENDPROC + +PROC editProtocols(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF protocolLists:PTR TO stdlist + DEF deleteProtocolLists:PTR TO stringlist + DEF protocol:PTR TO protocol + + self.changed:=FALSE + + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveProtocolChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Edit Protocols' + self.editCaption2:='Protocol' + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.bbsPath:=bbsPath + + NEW protocolLists.stdlist(25) + self.protocolLists:=protocolLists + + NEW deleteProtocolLists.stringlist(25) + self.deleteProtocolLists:=deleteProtocolLists + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Protocols') + set( self.winMain, MUIA_Window_ID, "PCOL") + + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{protocolitemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{protocolitemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{protocolitemRemove}) + self.addNotifications(TRUE) + + self.loadProtocols() + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + END saveHook + END closeHook + FOR i:=0 TO protocolLists.count()-1 + protocol:=protocolLists.item(i) + END protocol + ENDFOR + END protocolLists + END deleteProtocolLists +ENDPROC + +PROC saveCommandChanges() OF frmEditList + DEF i,count,val + DEF commandPath[255]:STRING + DEF commandToolType[255]:STRING + DEF commandName + DEF command:PTR TO command + DEF tempStr[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + + StringF(commandPath,'\scommands/\s/',self.bbsPath,self.commandPath) + + FOR i:=0 TO self.deleteCommandLists.count()-1 + StringF(commandToolType,'\s\s.info',commandPath,self.deleteCommandLists.item(i)) + deleteFileFromCache(commandToolType) + DeleteFile(commandToolType) + ENDFOR + self.deleteCommandLists.clear() + + makeDir(self.commandPath) + + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{commandName}]) + StringF(commandToolType,'\s\s',commandPath,commandName) + + command:=self.commandLists.item(i-1) + + writeToolType(commandToolType,'NAME',command.name) + writeToolType(commandToolType,'LOCATION',command.location) + writeToolType(commandToolType,'ACCESS',command.access) + writeToolType(commandToolType,'INTERNAL',command.internal) + writeToolType(commandToolType,'MIMICVER',command.mimicVer) + writeToolType(commandToolType,'PASSWORD',command.password) + + writeToolType(commandToolType,'PASS_PARAMETERS',command.passParams) + writeToolType(commandToolType,'PRIORITY',command.priority) + + IF command.resident THEN writeToolType(commandToolType,'RESIDENT',-1) ELSE deleteToolType(commandToolType,'RESIDENT') + IF command.quickMode THEN writeToolType(commandToolType,'QUICKMODE',-1) ELSE deleteToolType(commandToolType,'QUICKMODE') + + writeToolType(commandToolType,'STACK',command.stack) + writeToolType(commandToolType,'TYPE',command.type) + + IF command.trapon THEN writeToolType(commandToolType,'TRAPON',-1) ELSE deleteToolType(commandToolType,'TRAPON') + IF command.expertMode THEN writeToolType(commandToolType,'EXPERT_MODE',-1) ELSE deleteToolType(commandToolType,'EXPERT_MODE') + IF command.doorSilent THEN writeToolType(commandToolType,'DOORSILENT',-1) ELSE deleteToolType(commandToolType,'DOORSILENT') + IF command.logInputs THEN writeToolType(commandToolType,'LOG_INPUTS',-1) ELSE deleteToolType(commandToolType,'LOG_INPUTS') + IF command.scriptCheck THEN writeToolType(commandToolType,'SCRIPTCHECK',-1) ELSE deleteToolType(commandToolType,'SCRIPTCHECK') + + IF command.multiNode THEN writeToolType(commandToolType,'MULTINODE','YES') + writeToolType(commandToolType,'BANNER',command.banner) + ENDFOR + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC loadCommands() OF frmEditList + DEF commandPath[255]:STRING + DEF commandToolType[255]:STRING + DEF tempStr[255]:STRING + DEF dir_info:PTR TO fileinfoblock + DEF pdir,r,entry,i,n + DEF command:PTR TO command + DEF val + DEF c=0 + + DEF buf[255]:STRING + DEF parseBuf[100]:STRING + DEF namesList:PTR TO stringlist + + StringF(commandPath,'\scommands/\s/',self.bbsPath,self.commandPath) + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(commandPath,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF ParsePatternNoCase('#?.info',parseBuf,100) =-1 THEN RETURN + + domethod( self.lList , [ MUIM_List_Clear] ) + + NEW namesList.stringlist(100) + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + + IF MatchPatternNoCase(parseBuf,dir_info.filename) + StrCopy(buf,dir_info.filename) + stripInfo(buf) + namesList.add(buf) + ENDIF + ENDIF + ENDWHILE + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) + + namesList.sort() + FOR n:=0 TO namesList.count()-1 + domethod( self.lList , [ MUIM_List_InsertSingle , namesList.item(n) , MUIV_List_Insert_Bottom ] ) + StringF(commandToolType,'\s\s',commandPath,namesList.item(n)) + + NEW command.create() + + StrCopy(command.filename,namesList.item(n)) + + //load command details + readToolType(commandToolType,'NAME',tempStr) + StrCopy(command.name,tempStr) + readToolType(commandToolType,'LOCATION',tempStr) + StrCopy(command.location,tempStr) + readToolType(commandToolType,'ACCESS',tempStr) + StrCopy(command.access,tempStr) + readToolType(commandToolType,'INTERNAL',tempStr) + StrCopy(command.internal,tempStr) + readToolType(commandToolType,'MIMICVER',tempStr) + StrCopy(command.mimicVer,tempStr) + readToolType(commandToolType,'PASSWORD',tempStr) + StrCopy(command.password,tempStr) + readToolType(commandToolType,'PASS_PARAMETERS',tempStr) + StrCopy(command.passParams,tempStr) + readToolType(commandToolType,'PRIORITY',tempStr) + StrCopy(command.priority,tempStr) + command.resident:=checkToolTypeExists(commandToolType,'RESIDENT') + command.quickMode:=checkToolTypeExists(commandToolType,'QUICKMODE') + + readToolType(commandToolType,'STACK',tempStr) + StrCopy(command.stack,tempStr) + + readToolType(commandToolType,'TYPE',tempStr) + StrCopy(command.type,tempStr) + + command.trapon:=checkToolTypeExists(commandToolType,'TRAPON') + command.expertMode:=checkToolTypeExists(commandToolType,'EXPERT_MODE') + command.doorSilent:=checkToolTypeExists(commandToolType,'DOORSILENT') + command.logInputs:=checkToolTypeExists(commandToolType,'LOG_INPUTS') + command.scriptCheck:=checkToolTypeExists(commandToolType,'SCRIPTCHECK') + + readToolType(commandToolType,'MULTINODE',tempStr) + command.multiNode:=StriCmp(tempStr,'YES') + + readToolType(commandToolType,'BANNER',tempStr) + StrCopy(command.banner,tempStr) + + self.commandLists.add(command) + ENDFOR + END namesList + +ENDPROC + +PROC editCommands(acpName,commandFolder) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF commandLists:PTR TO stdlist + DEF deleteCommandLists:PTR TO stringlist + DEF command:PTR TO command + DEF editStr[255]:STRING + + self.changed:=FALSE + + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveCommandChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + StringF(editStr,'Edit Commands (\s)',commandFolder) + self.editCaption1:=editStr + self.editCaption2:='Command' + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.bbsPath:=bbsPath + + NEW commandLists.stdlist(25) + self.commandLists:=commandLists + + NEW deleteCommandLists.stringlist(25) + self.deleteCommandLists:=deleteCommandLists + + self.commandPath:=commandFolder + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,editStr) + set( self.winMain, MUIA_Window_ID, "CMDL") + + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{commanditemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{commanditemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{commanditemRemove}) + self.addNotifications(TRUE) + + self.loadCommands() + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + END saveHook + END closeHook + FOR i:=0 TO commandLists.count()-1 + command:=commandLists.item(i) + END command + ENDFOR + END commandLists + END deleteCommandLists +ENDPROC + +PROC saveConnectionChanges() OF frmEditList + DEF i,count,entry + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + + FOR i:=0 TO self.oldconnectionstrings.count()-1 + IF self.connectlist.contains(self.oldconnectionstrings.item(i))=FALSE + deleteToolType(self.connectDefToolType,self.oldconnectionstrings.item(i)) + ENDIF + ENDFOR + self.oldconnectionstrings.clear() + FOR i:=0 TO count-1 + writeToolType(self.connectDefToolType,self.connectlist.item(i),self.connectbaud.item(i)) + self.oldconnectionstrings.add(self.connectlist.item(i)) + ENDFOR + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editConnectionStrings(acpName) OF frmEditList + DEF count,i,j,entry,temppath[255]:STRING,tempstr[255]:STRING,tempstr2[255]:STRING + DEF bbsPath[200]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF connectionstrings:PTR TO stringlist + DEF oldconnectionstrings:PTR TO stringlist + DEF baudrates:PTR TO stringlist + + self.changed:=FALSE + + NEW saveHook + installhook( saveHook, {saveConnectionChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Connection String' + self.editCaption2:='Baud' + + set(self.app.grp_arrange,MUIA_Group_Columns,2) + set(self.strItem,MUIA_ShowMe,FALSE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + + readToolType(acpName,'BBS_LOCATION',bbsPath) + self.connectDefToolType:=String(255) + StringF(self.connectDefToolType,'\sConnect.def',bbsPath) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , FALSE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Connection Strings') + set( self.winMain, MUIA_Window_ID, "CDEF") + + self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{connectionitemAdd}) + self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{connectionitemEdit}) + self.setupButtonClick(self.btnItemRemove,self.btnRemoveClick,{connectionitemRemove}) + self.addNotifications(TRUE) + + NEW connectionstrings.stringlist(100) + self.connectlist:=connectionstrings + NEW baudrates.stringlist(100) + self.connectbaud:=baudrates + + NEW oldconnectionstrings.stringlist(100) + self.oldconnectionstrings:=oldconnectionstrings + + readAllToolTypes(self.connectDefToolType,connectionstrings) + FOR j:=0 TO connectionstrings.count()-1 + domethod( self.lList , [ MUIM_List_InsertSingle , connectionstrings.item(j), MUIV_List_Insert_Bottom ] ) + + StrCopy(tempstr,connectionstrings.item(j)) + StrCopy(tempstr2,'') + i:=0 + WHILE i" " THEN StrAddChar(tempstr2,tempstr[i]) + i++ + ENDWHILE + i++ + connectionstrings.setItem(j,tempstr2) + oldconnectionstrings.add(tempstr2) + + StrCopy(tempstr2,'') + WHILE i" " THEN StrAddChar(tempstr2,tempstr[i]) + i++ + ENDWHILE + baudrates.setItem(j,tempstr2) + ENDFOR + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications(TRUE) + domethod(self.btnItemAdd,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemEdit,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnItemRemove,[MUIM_KillNotify,MUIA_Pressed]) + END saveHook + END closeHook + END connectionstrings + END oldconnectionstrings + END baudrates + DisposeLink(self.connectDefToolType) +ENDPROC + +PROC saveRestrictedChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'RESTRICT.\d',i) + writeToolType(self.acpName,temppath,entry) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'RESTRICT.\d',i) + deleteToolType(self.acpName,temppath) + ENDFOR + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editRestricted(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + self.changed:=FALSE + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveRestrictedChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Restricted files' + self.editCaption2:='File' + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Restricted Files') + set( self.winMain, MUIA_Window_ID, "FRST") + + set(self.app.grp_arrange,MUIA_Group_Columns,1) + set(self.strItem,MUIA_ShowMe,MUI_TRUE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) + + self.addNotifications() + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'RESTRICT.\d',count+1) + readToolType(acpName,temppath,tempstr) + IF StrLen(tempstr)>0 + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications() + END saveHook + END closeHook +ENDPROC + +PROC saveBackupChanges() OF frmEditList + DEF i,count,entry + DEF temppath[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + get(self.lList,MUIA_List_Entries,{count}) + FOR i:=1 TO count + domethod(self.lList,[MUIM_List_GetEntry,i-1,{entry}]) + StringF(temppath,'BACKUP.\d',i) + writeToolType(self.acpName,temppath,entry) + ENDFOR + FOR i:=count+1 TO self.oldcount + StringF(temppath,'BACKUP.\d',i) + deleteToolType(self.acpName,temppath) + ENDFOR + self.oldcount:=count + saveCachedChanges() + + set( self.btnItemsSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editBackup(acpName) OF frmEditList + DEF count,loop,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + self.changed:=FALSE + self.acpName:=acpName + + NEW saveHook + installhook( saveHook, {saveBackupChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.editCaption1:='Backup files' + self.editCaption2:='File' + + set(self.app.grp_arrange,MUIA_Group_Columns,1) + set(self.strItem,MUIA_ShowMe,MUI_TRUE) + set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) + + set( self.btnItemRemove , MUIA_Disabled , MUI_TRUE) + set( self.btnItemEdit , MUIA_Disabled , MUI_TRUE) + set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) + set(self.strItem, MUIA_String_Contents,'') + + domethod( self.lList , [ MUIM_List_Clear] ) + + set( self.winMain, MUIA_Window_Title,'Edit Backup Files') + set( self.winMain, MUIA_Window_ID, "FBAK") + + self.addNotifications() + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'BACKUP.\d',count+1) + readToolType(acpName,temppath,tempstr) + IF StrLen(tempstr)>0 + domethod( self.lList , [ MUIM_List_InsertSingle , tempstr , MUIV_List_Insert_Bottom ] ) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + self.oldcount:=count + + set( self.btnItemsSave , MUIA_Disabled , MUI_TRUE) + + self.showModal() + self.removeNotifications() + END saveHook + END closeHook +ENDPROC +/* +//hide edit +set(self.app.grp_arrange,MUIA_Group_Columns,2) +set(self.strItem,MUIA_ShowMe,FALSE) +set(self.app.grp_computers_add,MUIA_Group_Horiz,FALSE) + +//show edit +set(self.app.grp_arrange,MUIA_Group_Columns,1) +set(self.strItem,MUIA_ShowMe,MUI_TRUE) +set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) +*/ \ No newline at end of file diff --git a/axSetupTool/frmMain.e b/axSetupTool/frmMain.e new file mode 100644 index 0000000..5709296 --- /dev/null +++ b/axSetupTool/frmMain.e @@ -0,0 +1,388 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','dos/dos','libraries/asl','dos/var' +MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' +MODULE '*axedit','*frmBase','*frmEditList','*frmNodeEdit','*frmConfEdit','*frmSettingsEdit','*frmAccess','*frmCommands','*tooltypes' + +EXPORT OBJECT frmMain OF frmBase + acpConfigName: PTR TO CHAR + btnConfsClickHook: hook + btnNodesClickHook: hook + btnComputersClickHook: hook + btnCheckersClickHook: hook + btnNamesNotAllowedClickHook: hook + btnDrivesClickHook: hook + btnSystemClickHook: hook + btnScreensClickHook: hook + btnServerClickHook: hook + btnSecurityClickHook: hook + btnLanguagesClickHook: hook + btnProtocolsClickHook: hook + btnCommandsClickHook: hook + btnZoomClickHook: hook + btnConnectClickHook: hook + btnBackupClickHook: hook + btnRestrictClickHook: hook + btnExitClickHook: hook +ENDOBJECT + +PROC exitbuttonPressed() OF frmMain + MOVE.L (A1),self + GetA4() + domethod(self.app.app,[MUIM_Application_ReturnID,MUIA_Window_CloseRequest]) +ENDPROC + +PROC computersbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editComputers(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC drivesbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editDrives(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC screensbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editScreens(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC connectbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editConnectionStrings(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC namesnotallowedbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editNamesNotAllowed(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC nodesbuttonPressed() OF frmMain + DEF frmNodeEdit:PTR TO frmNodeEdit + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW frmNodeEdit.create(self.app) + frmNodeEdit.editNodes(self.acpConfigName) + END frmNodeEdit + self.wake() + +ENDPROC + +PROC confsbuttonPressed() OF frmMain + DEF frmConfEdit:PTR TO frmConfEdit + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW frmConfEdit.create(self.app) + frmConfEdit.editConfs(self.acpConfigName) + END frmConfEdit + self.wake() + +ENDPROC + +PROC zoombuttonPressed() OF frmMain + DEF frmSettingsEdit:PTR TO frmSettingsEdit + MOVE.L (A1),self + GetA4() + self.sleep() + NEW frmSettingsEdit.create(self.app) + frmSettingsEdit.editZoomSettings(self.acpConfigName) + END frmSettingsEdit + self.wake() +ENDPROC + +PROC serverbuttonPressed() OF frmMain + DEF frmSettingsEdit:PTR TO frmSettingsEdit + MOVE.L (A1),self + GetA4() + self.sleep() + NEW frmSettingsEdit.create(self.app) + frmSettingsEdit.editServerSettings(self.acpConfigName) + END frmSettingsEdit + self.wake() +ENDPROC + +PROC systembuttonPressed() OF frmMain + DEF frmSettingsEdit:PTR TO frmSettingsEdit + MOVE.L (A1),self + GetA4() + self.sleep() + NEW frmSettingsEdit.create(self.app) + frmSettingsEdit.editSystemSettings(self.acpConfigName) + END frmSettingsEdit + self.wake() +ENDPROC + +PROC securitybuttonPressed() OF frmMain + DEF frmAccess:PTR TO frmAccess + MOVE.L (A1),self + GetA4() + self.sleep() + NEW frmAccess.create(self.app) + frmAccess.editAccess(self.acpConfigName) + END frmAccess + self.wake() +ENDPROC + + +PROC backupbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editBackup(self.acpConfigName) + END listEdit + self.wake() +ENDPROC + +PROC restrictbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editRestricted(self.acpConfigName) + END listEdit + self.wake() +ENDPROC + +PROC languagesbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editLanguages(self.acpConfigName) + END listEdit + self.wake() +ENDPROC + +PROC fcheckbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editFileCheckers(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC commandsbuttonPressed() OF frmMain + DEF frmCommands:PTR TO frmCommands + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW frmCommands.create(self.app) + frmCommands.editCommands(self.acpConfigName) + END frmCommands + self.wake() + +ENDPROC + +PROC protocolsbuttonPressed() OF frmMain + DEF listEdit:PTR TO frmEditList + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW listEdit.create(self.app) + listEdit.editProtocols(self.acpConfigName) + END listEdit + self.wake() + +ENDPROC + +PROC create(app:PTR TO app_obj) OF frmMain + SUPER self.create(app) + self.winMain:=app.winMain + + set (app.mnlabel1Donotremovefolder1, MUIA_Menuitem_Exclude, 6) + set (app.mnlabel1Removefolder1, MUIA_Menuitem_Exclude, 5) + set (app.mnlabel1Ask1, MUIA_Menuitem_Exclude, 3) + + + set (app.mnlabel1Donotremovefolder2, MUIA_Menuitem_Exclude, 6) + set (app.mnlabel1Removefolder2, MUIA_Menuitem_Exclude, 5) + set (app.mnlabel1Ask2, MUIA_Menuitem_Exclude, 3) +ENDPROC + +PROC domain() OF frmMain + DEF fh,fr:PTR TO filerequester + DEF tempStr[200]:STRING + DEF v + + GetVar('axSetupEditor_prefs',tempStr,200,0) + SetStr(tempStr) + IF (EstrLen(tempStr)>0) THEN v:=tempStr[0]-48 ELSE v:=0 + SELECT v + CASE 1 + set (self.app.mnlabel1Donotremovefolder1, MUIA_Menuitem_Checked, MUI_TRUE) + CASE 2 + set (self.app.mnlabel1Removefolder1, MUIA_Menuitem_Checked, MUI_TRUE) + CASE 3 + set (self.app.mnlabel1Ask1, MUIA_Menuitem_Checked, MUI_TRUE) + DEFAULT + set (self.app.mnlabel1Donotremovefolder1, MUIA_Menuitem_Checked, MUI_TRUE) + ENDSELECT + + IF (EstrLen(tempStr)>1) THEN v:=tempStr[1]-48 ELSE v:=0 + SELECT v + CASE 1 + set (self.app.mnlabel1Donotremovefolder2, MUIA_Menuitem_Checked, MUI_TRUE) + CASE 2 + set (self.app.mnlabel1Removefolder2, MUIA_Menuitem_Checked, MUI_TRUE) + CASE 3 + set (self.app.mnlabel1Ask2, MUIA_Menuitem_Checked, MUI_TRUE) + DEFAULT + set (self.app.mnlabel1Donotremovefolder2, MUIA_Menuitem_Checked, MUI_TRUE) + ENDSELECT + + self.acpConfigName:=String(200) + + IF EstrLen(tempStr)>2 + StrCopy(self.acpConfigName,tempStr+2) + ENDIF + + StringF(tempStr,'\s.info',self.acpConfigName) + + IF (EstrLen(self.acpConfigName)=0) OR (FileLength(tempStr)<=0) + fr:=Mui_AllocAslRequest(ASL_FILEREQUEST, [ASLFR_TITLETEXT,'Select ACP file',ASLFR_INITIALDRAWER,'sys:wbstartup',ASLFR_INITIALFILE,'ACP',ASLFR_INITIALPATTERN,'ACP',0]) + IF (fr) + IF Mui_AslRequest(fr,0) + StrCopy(self.acpConfigName,fr.drawer) + AddPart(self.acpConfigName,fr.file,StrMax(self.acpConfigName)) + SetStr(self.acpConfigName) + StringF(tempStr,'\s.info',self.acpConfigName) + IF (FileLength(self.acpConfigName)<=0) OR (FileLength(tempStr)<=0) + StrCopy(self.acpConfigName,'') + ENDIF + ELSE + StrCopy(self.acpConfigName,'') + ENDIF + Mui_FreeAslRequest(fr) + ENDIF + ENDIF + IF EstrLen(self.acpConfigName)=0 + Throw("ACP","icon") + ENDIF + + self.setupButtonClick(self.app.btnComputers,self.btnComputersClickHook,{computersbuttonPressed}) + self.setupButtonClick(self.app.btnCheckers,self.btnCheckersClickHook,{fcheckbuttonPressed}) + self.setupButtonClick(self.app.btnNamesNotAllowed,self.btnNamesNotAllowedClickHook,{namesnotallowedbuttonPressed}) + self.setupButtonClick(self.app.btnDrives,self.btnDrivesClickHook,{drivesbuttonPressed}) + self.setupButtonClick(self.app.btnScreenTypes,self.btnScreensClickHook,{screensbuttonPressed}) + self.setupButtonClick(self.app.btnNodes,self.btnNodesClickHook,{nodesbuttonPressed}) + self.setupButtonClick(self.app.btnConfs,self.btnConfsClickHook,{confsbuttonPressed}) + self.setupButtonClick(self.app.btnSystem,self.btnSystemClickHook,{systembuttonPressed}) + self.setupButtonClick(self.app.btnServer,self.btnServerClickHook,{serverbuttonPressed}) + self.setupButtonClick(self.app.btnSecurity,self.btnSecurityClickHook,{securitybuttonPressed}) + self.setupButtonClick(self.app.btnLanguages,self.btnLanguagesClickHook,{languagesbuttonPressed}) + self.setupButtonClick(self.app.btnProtocols,self.btnProtocolsClickHook,{protocolsbuttonPressed}) + self.setupButtonClick(self.app.btnCommands,self.btnCommandsClickHook,{commandsbuttonPressed}) + self.setupButtonClick(self.app.btnZoom,self.btnZoomClickHook,{zoombuttonPressed}) + self.setupButtonClick(self.app.btnConnect,self.btnConnectClickHook,{connectbuttonPressed}) + self.setupButtonClick(self.app.btnExit,self.btnExitClickHook,{exitbuttonPressed}) + self.setupButtonClick(self.app.btnRestrict,self.btnRestrictClickHook,{restrictbuttonPressed}) + self.setupButtonClick(self.app.btnBackup,self.btnBackupClickHook,{backupbuttonPressed}) + + set( self.app.btnUsers, MUIA_Text_Contents,'Unused') + set( self.app.btnUsers, MUIA_Disabled , MUI_TRUE) + + initialiseCache() + self.showModal() + + get (self.app.mnlabel1Donotremovefolder1, MUIA_Menuitem_Checked,{v}) + IF v + StrCopy(tempStr,'1') + ELSE + get (self.app.mnlabel1Removefolder1, MUIA_Menuitem_Checked, {v}) + IF v + StrCopy(tempStr,'2') + ELSE + get (self.app.mnlabel1Ask1, MUIA_Menuitem_Checked, {v}) + IF v + StrCopy(tempStr,'3') + ELSE + StrCopy(tempStr,'1') + ENDIF + ENDIF + ENDIF + + get (self.app.mnlabel1Donotremovefolder2, MUIA_Menuitem_Checked,{v}) + IF v + StrAdd(tempStr,'1') + ELSE + get (self.app.mnlabel1Removefolder2, MUIA_Menuitem_Checked, {v}) + IF v + StrAdd(tempStr,'2') + ELSE + get (self.app.mnlabel1Ask2, MUIA_Menuitem_Checked, {v}) + IF v + StrAdd(tempStr,'3') + ELSE + StrAdd(tempStr,'1') + ENDIF + ENDIF + ENDIF + StrAdd(tempStr,self.acpConfigName) + SetVar('axSetupEditor_prefs',tempStr,EstrLen(tempStr),GVF_SAVE_VAR OR GVF_GLOBAL_ONLY) + + clearDiskObjectCache() + deInitialiseCache() + + DisposeLink(self.acpConfigName) + +ENDPROC diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e new file mode 100644 index 0000000..e9bc769 --- /dev/null +++ b/axSetupTool/frmNodeEdit.e @@ -0,0 +1,1362 @@ +OPT MODULE +OPT LARGE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui','dos/dos','dos/dostags','dos/dosextens' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','exec/lists','tools/installhook' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs' + +OBJECT timeItem + baudStr:PTR TO CHAR + startControl:PTR TO LONG + endControl:PTR TO LONG +ENDOBJECT + +EXPORT OBJECT frmNodeEdit OF frmBase + controlList1 : LONG + controlList2 : LONG + controlList3 : LONG + controlList4 : LONG + + grpNodePages : PTR TO LONG + + strNodeNumber : PTR TO LONG + btnFirstNode : PTR TO LONG + btnLastNode : PTR TO LONG + btnPrevNode : PTR TO LONG + btnNextNode : PTR TO LONG + btnAddNode : PTR TO LONG + btnCloneNode : PTR TO LONG + btnRemoveNode : PTR TO LONG + btnNodeSave : PTR TO LONG + btnNodeCancel : PTR TO LONG + grpNodeSettings : PTR TO LONG + grpNodeSettings2 : PTR TO LONG + grpNodeSettings3 : PTR TO LONG + grpNodeSettings4 : PTR TO LONG + + intPriority : PTR TO control + strNodeStart : PTR TO control + strSystemPassword : PTR TO control + strSystemPasswordPrompt: PTR TO control + strNewuserPassword : PTR TO control + strNamePrompt : PTR TO control + strNamePrompt2 : PTR TO control + strPasswordPrompt : PTR TO control + paScreens : PTR TO control + intAutoValPreset : PTR TO control + intAutoValDelay : PTR TO control + strAutoValPassword : PTR TO control + intFtpPort : PTR TO control + intFtpDataPort : PTR TO control + intHttpPort : PTR TO control + intKeepUlCredit : PTR TO control + intMaxMsgLen : PTR TO control + intMaxMsgQueue : PTR TO control + paPlaypen : PTR TO control + intRingCount : PTR TO control + strRemotePassword : PTR TO control + intSysopChatColour : PTR TO control + intUserChatColour : PTR TO control + fnUserDataName : PTR TO control + fnUserMiscName : PTR TO control + fnUserKeysName : PTR TO control + paLocalUlPath : PTR TO control + intOverrideTimeout : PTR TO control + //needs to be a cycle + strForceAnsi : PTR TO control + intBGFilecheckStack: PTR TO control + strConInputDev : PTR TO control + strConOutputDev : PTR TO control + strScreenPens : PTR TO control + strConfDb : PTR TO control + fnFilesNotAllowed : PTR TO control + strFirstCommand : PTR TO control + intSerialCacheSize : PTR TO control + boolCallersLog : PTR TO control + boolCapitalFilenames: PTR TO control + boolDefScreens : PTR TO control + boolDebugLog : PTR TO control + boolDoorLog : PTR TO control + boolStartLog : PTR TO control + boolUDLog : PTR TO control + boolChatOn : PTR TO control + boolDisableQuickLogon: PTR TO control + boolIdleNode : PTR TO control + boolMailscanPrompt : PTR TO control + boolNoTimeout : PTR TO control + boolQuietNode : PTR TO control + boolStealthNode : PTR TO control + boolShowPwFail : PTR TO control + boolSentByFiles : PTR TO control + boolTelnet : PTR TO control + boolFtp : PTR TO control + boolTelnetD : PTR TO control + boolTelserD : PTR TO control + boolUserNumLogin : PTR TO control + boolViewPassword : PTR TO control + boolLogHost : PTR TO control + boolLogInputs : PTR TO control + boolNoCx : PTR TO control + boolCentralAnswers : PTR TO control + boolDisableIemsi : PTR TO control + boolNoMciMsg : PTR TO control + boolNoWildcard : PTR TO control + boolOwnPartFiles : PTR TO control + boolPhoneCheck : PTR TO control + boolRamWork : PTR TO control + boolConsoleDebug : PTR TO control + boolNoEmails : PTR TO control + boolOwnDevunit : PTR TO control + boolShowCacheStats : PTR TO control + boolTrapDoor : PTR TO control + boolTrapSerial : PTR TO control + boolNoRadBoogie : PTR TO control + + //serial device settings + strSerialDevice : PTR TO control + intSerialUnit : PTR TO control + intSerialBaud : PTR TO control + boolA2232Patch : PTR TO control + boolNoPurgeLine : PTR TO control + boolRepurge : PTR TO control + boolLogoffReset : PTR TO control + boolTrueReset : PTR TO control + + //modem settings + strModemInit : PTR TO control + strModemReset : PTR TO control + strModemRing : PTR TO control + strModemAnswer : PTR TO control + strModemOffhook : PTR TO control + + strNRAMS1 : PTR TO control + strNRAMS2 : PTR TO control + strNRAMS3 : PTR TO control + strNRAMS4 : PTR TO control + + + //window settings + intNumColours : PTR TO control + intWinLeftEdge : PTR TO control + intWinTopEdge : PTR TO control + intWinWidth : PTR TO control + intWinHeight : PTR TO control + strWinPubScreen : PTR TO control + boolWinIconified : PTR TO control + boolWinInterlace : PTR TO control + boolWinStatusBar : PTR TO control + boolWinToFront : PTR TO control + strDisplayId : PTR TO control + + btnFirstNodeClick: hook + btnLastNodeClick: hook + btnNextNodeClick: hook + btnPrevNodeClick: hook + btnAddNodeClick: hook + btnCloneNodeClick: hook + btnRemoveNodeClick: hook + setChangedHook:hook + + //evo bug here + //timesList:PTR TO PTR TO timeItem + //do this instead + timesList:PTR TO LONG + + acpName:PTR TO CHAR + changed:INT + nodeCount:INT + currNode:INT + newNode:INT +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmNodeEdit + DEF group + SUPER self.create(app) + self.winMain:=app.wi_nodeEdit + + self.strNodeNumber:=app.str_Node_Number + self.btnFirstNode:=app.btnFirstNode + self.btnLastNode:=app.btnLastNode + self.btnPrevNode:=app.btnPrevNode + self.btnNextNode:=app.btnNextNode + self.btnAddNode:=app.btnAddNode + self.btnCloneNode:=app.btnNodeClone + self.btnRemoveNode:=app.btnRemoveNode + self.btnNodeSave:=app.btnNodeSave + self.btnNodeCancel:=app.btnNodeCancel + + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(75)) + + self.grpNodePages:=app.gr_node_pages + + get(app.gr_node_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpNodeSettings:=group + set(self.grpNodeSettings, MUIA_Group_Columns , 4) + + get(app.gr_node_more_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpNodeSettings2:=group + set(self.grpNodeSettings2, MUIA_Group_Columns , 4) + + get(app.gr_node_serial_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpNodeSettings3:=group + set(self.grpNodeSettings3, MUIA_Group_Columns , 4) + + get(app.gr_node_window_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpNodeSettings4:=group + set(self.grpNodeSettings4, MUIA_Group_Columns , 4) + +ENDPROC + +PROC cloneNewNode() OF frmNodeEdit + DEF tempStr[255]:STRING + MOVE.L (A1),self + GetA4() + + IF self.loadNode(self.currNode) + self.changed:=TRUE + self.newNode:=TRUE + self.nodeCount:=self.nodeCount+1 + self.currNode:=self.nodeCount-1 + + StringF(tempStr,'\d',self.currNode) + set(self.strNodeNumber, MUIA_String_Contents,tempStr) + + set( self.btnPrevNode, MUIA_Disabled , FALSE) + set( self.btnNextNode, MUIA_Disabled , MUI_TRUE) + set( self.btnRemoveNode, MUIA_Disabled , FALSE) + + set( self.btnNodeSave,MUIA_Disabled,FALSE) + set( self.btnAddNode,MUIA_Disabled,MUI_TRUE) + set( self.btnCloneNode,MUIA_Disabled,MUI_TRUE) + ENDIF +ENDPROC + +PROC createNewNode() OF frmNodeEdit + MOVE.L (A1),self + GetA4() + + IF self.loadNode(self.nodeCount) + self.changed:=TRUE + self.newNode:=TRUE + self.nodeCount:=self.nodeCount+1 + set( self.btnNodeSave,MUIA_Disabled,FALSE) + set( self.btnAddNode,MUIA_Disabled,MUI_TRUE) + set( self.btnCloneNode,MUIA_Disabled,MUI_TRUE) + ENDIF +ENDPROC + +PROC deleteNodeFolder(node) OF frmNodeEdit + DEF deleteStr[255]:STRING + DEF bbsPath[255]:STRING + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + StringF(deleteStr,'DELETE \sNode\d ALL',bbsPath,node) + Execute(deleteStr,0,0) + + StringF(deleteStr,'DELETE \sNode\d.info',bbsPath,node) + Execute(deleteStr,0,0) +ENDPROC + +PROC deleteCurrentNode() OF frmNodeEdit + DEF deleteOption + DEF nodeStr[255]:STRING + MOVE.L (A1),self + GetA4() + + get (self.app.mnlabel1Donotremovefolder2, MUIA_Menuitem_Checked, {deleteOption}) + IF deleteOption + deleteOption:=1 + ELSE + get (self.app.mnlabel1Removefolder2, MUIA_Menuitem_Checked, {deleteOption}) + IF deleteOption + deleteOption:=2 + ELSE + deleteOption:=3 + ENDIF + ENDIF + + IF self.deleteNodeWarning()=FALSE THEN RETURN + + IF self.loadNode(self.nodeCount-2) + self.nodeCount:=self.currNode+1 + + //update node count + StringF(nodeStr,'\d',self.nodeCount) + writeToolType(self.acpName,'NODES',nodeStr) + + StringF(nodeStr,'NODE\d_NAME',self.nodeCount) + deleteToolType(self.acpName,nodeStr) + StringF(nodeStr,'NODE\d_SYSOP',self.nodeCount) + deleteToolType(self.acpName,nodeStr) + StringF(nodeStr,'NODE\d_LOCATION',self.nodeCount) + deleteToolType(self.acpName,nodeStr) + + set( self.btnNextNode, MUIA_Disabled , MUI_TRUE) + set( self.btnRemoveNode, MUIA_Disabled , (self.currNode0 + timeVal:=Val(timeEntry) + IF (Mod(timeVal,100)>59) OR (timeVal>2359) OR (timeVal<0) + StringF(errorText,'You have entered an invalid time for \s baud start time',timeStr) + EasyRequestArgs( win , [ 20 , 0 , + 'Error ' , + errorText, + 'OK' ] , NIL , NIL ) + RETURN FALSE + ENDIF + ENDIF + + get(endControl, MUIA_String_Contents,{timeEntry}) + + IF StrLen(timeEntry)>0 + timeVal:=Val(timeEntry) + IF (Mod(timeVal,100)>59) OR (timeVal>2359) OR (timeVal<0) + StringF(errorText,'You have entered an invalid time for \s baud end time',timeStr) + EasyRequestArgs( win , [ 20 , 0 , + 'Error ' , + errorText, + 'OK' ] , NIL , NIL ) + RETURN FALSE + ENDIF + ENDIF + +ENDPROC TRUE + +PROC saveChanges() OF frmNodeEdit + DEF nodeStr[255]:STRING + DEF bbsPath[255]:STRING + DEF folderStr[255]:STRING + DEF tempStr[255]:STRING + DEF toolTypePath[255]:STRING + DEF windowTooltype[255]:STRING + DEF timeTooltype[255]:STRING + DEF timeItem:PTR TO timeItem + DEF window + DEF val + + MOVE.L (A1),self + GetA4() + + get(self.winMain,MUIA_Window_Window,{window}) + + fullTrim(self.strNodeStart.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( window , [ 20 , 0 , + 'Error' , + 'Express File is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + IF Exists({timeItem},self.timesList,`self.validateTime(timeItem.baudStr,timeItem.startControl,timeItem.endControl)=FALSE) THEN RETURN + + self.sleep() + StringF(nodeStr,'\d',self.nodeCount) + writeToolType(self.acpName,'NODES',nodeStr) + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + StringF(nodeStr,'\sNode\d',bbsPath,self.currNode) + + get(self.winMain,MUIA_Window_Window,{window}) + + IF (self.newNode) + //create the folder structure + makeDir(nodeStr) + StringF(folderStr,'\s/work',nodeStr) + makeDir(folderStr) + StringF(folderStr,'\s/playpen',nodeStr) + makeDir(folderStr) + StringF(folderStr,'\s/serial',nodeStr) + makeDir(folderStr) + StringF(folderStr,'\s/modem',nodeStr) + makeDir(folderStr) + StringF(folderStr,'\s/nrams',nodeStr) + makeDir(folderStr) + val:=self.paScreens.getValue() + IF StrLen(val)>0 + makeDir(val) + ENDIF + val:=self.paPlaypen.getValue() + IF StrLen(val)>0 + makeDir(val) + ENDIF + ENDIF + + writeToolType(nodeStr,'PRIORITY',self.intPriority.getValue()) + writeToolType(nodeStr,'NODESTART',self.strNodeStart.getValue()) + writeToolType(nodeStr,'SYSTEM_PASSWORD',self.strSystemPassword.getValue()) + writeToolType(nodeStr,'SYS_PWRD_PROMPT',self.strSystemPasswordPrompt.getValue()) + writeToolType(nodeStr,'NEWUSER_PASSWORD',self.strNewuserPassword.getValue()) + writeToolType(nodeStr,'NAME_PROMPT',self.strNamePrompt.getValue()) + writeToolType(nodeStr,'NAME_PROMPT2',self.strNamePrompt2.getValue()) + writeToolType(nodeStr,'PASSWORD_PROMPT',self.strPasswordPrompt.getValue()) + writeToolType(nodeStr,'SCREENS',self.paScreens.getValue()) + writeToolType(nodeStr,'AUTOVAL_PRESET',self.intAutoValPreset.getValue()) + writeToolType(nodeStr,'AUTOVAL_DELAY',self.intAutoValDelay.getValue()) + writeToolType(nodeStr,'AUTOVAL_PASSWORD',self.strAutoValPassword.getValue()) + writeToolType(nodeStr,'FTPPORT',self.intFtpPort.getValue()) + writeToolType(nodeStr,'FTPDATAPORT',self.intFtpDataPort.getValue()) + writeToolType(nodeStr,'HTTPPORT',self.intHttpPort.getValue()) + + val:=self.intKeepUlCredit.getValueIndex() + StringF(tempStr,'\d',val) + writeToolType(nodeStr,'KEEP_UPLOAD_CREDIT',tempStr) + + writeToolType(nodeStr,'MAX_MSG_LEN',self.intMaxMsgLen.getValue()) + writeToolType(nodeStr,'MAX_MSG_QU',self.intMaxMsgQueue.getValue()) + writeToolType(nodeStr,'PLAYPEN',self.paPlaypen.getValue()) + writeToolType(nodeStr,'RINGCOUNT',self.intRingCount.getValue()) + writeToolType(nodeStr,'REMOTE_PASSWORD',self.strRemotePassword.getValue()) + writeToolType(nodeStr,'SYSOP_CHAT_COLOR',self.intSysopChatColour.getValue()) + writeToolType(nodeStr,'USER_CHAT_COLOR',self.intUserChatColour.getValue()) + writeToolType(nodeStr,'USERDATA_NAME',self.fnUserDataName.getValue()) + writeToolType(nodeStr,'USERKEYS_NAME',self.fnUserMiscName.getValue()) + writeToolType(nodeStr,'USERMISC_NAME',self.fnUserKeysName.getValue()) + writeToolType(nodeStr,'LOCAL_UPLOAD_PATH',self.paLocalUlPath.getValue()) + + writeToolType(nodeStr,'OVERRIDE_TIMEOUT',self.intOverrideTimeout.getValue()) + writeToolType(nodeStr,'FORCE_ANSI',self.strForceAnsi.getValue()) + writeToolType(nodeStr,'BGFILECHECKSTACK',self.intBGFilecheckStack.getValue()) + writeToolType(nodeStr,'CONSOLE_INPUT_DEVICE',self.strConInputDev.getValue()) + writeToolType(nodeStr,'CONSOLE_OUTPUT_DEVICE',self.strConOutputDev.getValue()) + writeToolType(nodeStr,'SCREENPENS',self.strScreenPens.getValue()) + writeToolType(nodeStr,'CONF_DB',self.strConfDb.getValue()) + writeToolType(nodeStr,'FILESNOTALLOWED',self.fnFilesNotAllowed.getValue()) + writeToolType(nodeStr,'FIRSTCOMMAND',self.strFirstCommand.getValue()) + writeToolType(nodeStr,'SERIAL_CACHE_SIZE',self.intSerialCacheSize.getValue()) + + IF self.boolCallersLog.getValue() THEN writeToolType(nodeStr,'CALLERS_LOG') ELSE deleteToolType(nodeStr,'CALLERS_LOG') + IF self.boolCapitalFilenames.getValue() THEN writeToolType(nodeStr,'CAPITOL_FILES') ELSE deleteToolType(nodeStr,'CAPITOL_FILES') + IF self.boolDebugLog.getValue() THEN writeToolType(nodeStr,'DEBUG_LOG') ELSE deleteToolType(nodeStr,'DEBUG_LOG') + IF self.boolDefScreens.getValue() THEN writeToolType(nodeStr,'DEF_SCREENS') ELSE deleteToolType(nodeStr,'DEF_SCREENS') + IF self.boolDebugLog.getValue() THEN writeToolType(nodeStr,'DEBUG_LOG') ELSE deleteToolType(nodeStr,'DEBUG_LOG') + IF self.boolDoorLog.getValue() THEN writeToolType(nodeStr,'DOOR_LOG') ELSE deleteToolType(nodeStr,'DOOR_LOG') + IF self.boolStartLog.getValue() THEN writeToolType(nodeStr,'START_LOG') ELSE deleteToolType(nodeStr,'START_LOG') + IF self.boolUDLog.getValue() THEN writeToolType(nodeStr,'UD_LOG') ELSE deleteToolType(nodeStr,'UD_LOG') + IF self.boolChatOn.getValue() THEN writeToolType(nodeStr,'CHAT_ON') ELSE deleteToolType(nodeStr,'CHAT_ON') + IF self.boolDisableQuickLogon.getValue() THEN writeToolType(nodeStr,'DISABLE_QUICK_LOGONS') ELSE deleteToolType(nodeStr,'DISABLE_QUICK_LOGONS') + IF self.boolIdleNode.getValue() THEN writeToolType(nodeStr,'IDLENODE') ELSE deleteToolType(nodeStr,'IDLENODE') + IF self.boolMailscanPrompt.getValue() THEN writeToolType(nodeStr,'MAILSCAN_PROMPT') ELSE deleteToolType(nodeStr,'MAILSCAN_PROMPT') + IF self.boolNoTimeout.getValue() THEN writeToolType(nodeStr,'NO_TIMEOUT') ELSE deleteToolType(nodeStr,'NO_TIMEOUT') + IF self.boolQuietNode.getValue() THEN writeToolType(nodeStr,'QUIETNODE') ELSE deleteToolType(nodeStr,'QUIETNODE') + IF self.boolStealthNode.getValue() THEN writeToolType(nodeStr,'STEALTH_MODE') ELSE deleteToolType(nodeStr,'STEALTH_MODE') + IF self.boolShowPwFail.getValue() THEN writeToolType(nodeStr,'SHOWPWFAIL') ELSE deleteToolType(nodeStr,'SHOWPWFAIL') + IF self.boolSentByFiles.getValue() THEN writeToolType(nodeStr,'SENTBY_FILES') ELSE deleteToolType(nodeStr,'SENTBY_FILES') + IF self.boolTelnet.getValue() THEN writeToolType(nodeStr,'TELNET') ELSE deleteToolType(nodeStr,'TELNET') + IF self.boolFtp.getValue() THEN writeToolType(nodeStr,'FTP') ELSE deleteToolType(nodeStr,'FTP') + IF self.boolTelnetD.getValue() THEN writeToolType(nodeStr,'TELSERD') ELSE deleteToolType(nodeStr,'TELSERD') + IF self.boolTelserD.getValue() THEN writeToolType(nodeStr,'TELNETD') ELSE deleteToolType(nodeStr,'TELNETD') + IF self.boolUserNumLogin.getValue() THEN writeToolType(nodeStr,'USERNUMBER_LOGIN') ELSE deleteToolType(nodeStr,'USERNUMBER_LOGIN') + IF self.boolViewPassword.getValue() THEN writeToolType(nodeStr,'VIEW_PASSWORD') ELSE deleteToolType(nodeStr,'VIEW_PASSWORD') + IF self.boolLogHost.getValue() THEN writeToolType(nodeStr,'LOG_HOST') ELSE deleteToolType(nodeStr,'LOG_HOST') + IF self.boolLogInputs.getValue() THEN writeToolType(nodeStr,'LOG_INPUTS') ELSE deleteToolType(nodeStr,'LOG_INPUTS') + IF self.boolNoCx.getValue() THEN writeToolType(nodeStr,'NO_CX') ELSE deleteToolType(nodeStr,'NO_CX') + IF self.boolCentralAnswers.getValue() THEN writeToolType(nodeStr,'CENTRAL_ANSWERS') ELSE deleteToolType(nodeStr,'CENTRAL_ANSWERS') + IF self.boolDisableIemsi.getValue() THEN writeToolType(nodeStr,'DISABLE_IEMSI') ELSE deleteToolType(nodeStr,'DISABLE_IEMSI') + IF self.boolNoMciMsg.getValue() THEN writeToolType(nodeStr,'NO_MCI_MSG') ELSE deleteToolType(nodeStr,'NO_MCI_MSG') + IF self.boolNoWildcard.getValue() THEN writeToolType(nodeStr,'NO_WILDCARD_EXPANSION') ELSE deleteToolType(nodeStr,'NO_WILDCARD_EXPANSION') + IF self.boolOwnPartFiles.getValue() THEN writeToolType(nodeStr,'OWN_PARTFILES') ELSE deleteToolType(nodeStr,'OWN_PARTFILES') + IF self.boolPhoneCheck.getValue() THEN writeToolType(nodeStr,'PHONECHECK') ELSE deleteToolType(nodeStr,'PHONECHECK') + IF self.boolRamWork.getValue() THEN writeToolType(nodeStr,'RAMWORK') ELSE deleteToolType(nodeStr,'RAMWORK') + IF self.boolConsoleDebug.getValue() THEN writeToolType(nodeStr,'CONSOLE_DEBUG') ELSE deleteToolType(nodeStr,'CONSOLE_DEBUG') + IF self.boolNoEmails.getValue() THEN writeToolType(nodeStr,'NO_EMAILS') ELSE deleteToolType(nodeStr,'NO_EMAILS') + IF self.boolOwnDevunit.getValue() THEN writeToolType(nodeStr,'OWNDEVUNIT') ELSE deleteToolType(nodeStr,'OWNDEVUNIT') + IF self.boolShowCacheStats.getValue() THEN writeToolType(nodeStr,'SHOW_CACHE_STATS') ELSE deleteToolType(nodeStr,'SHOW_CACHE_STATS') + IF self.boolTrapDoor.getValue() THEN writeToolType(nodeStr,'TRAPDOOR') ELSE deleteToolType(nodeStr,'TRAPDOOR') + IF self.boolTrapSerial.getValue() THEN writeToolType(nodeStr,'TRAP_SERIAL') ELSE deleteToolType(nodeStr,'TRAP_SERIAL') + IF self.boolNoRadBoogie.getValue() THEN writeToolType(nodeStr,'NORADBOOGIE') ELSE deleteToolType(nodeStr,'NORADBOOGIE') + + //serial device settings + StringF(toolTypePath,'\sNode\d/Serial',bbsPath,self.currNode) + IF(self.getToolTypeFileName(toolTypePath,tempStr)=FALSE) + StrCopy(tempStr,'serial') + ELSE + SetStr(tempStr) + ENDIF + StringF(toolTypePath,'\sNode\d/Serial/\s',bbsPath,self.currNode,tempStr) + + writeToolType(toolTypePath,'SERIAL.DRIVER',self.strSerialDevice.getValue()) + writeToolType(toolTypePath,'SERIAL.UNIT',self.intSerialUnit.getValue()) + writeToolType(toolTypePath,'SERIAL.BAUD',self.intSerialBaud.getValue()) + + IF self.boolA2232Patch.getValue() THEN writeToolType(nodeStr,'SERIAL.A2232_PATCH') ELSE deleteToolType(nodeStr,'SERIAL.A2232_PATCH') + IF self.boolNoPurgeLine.getValue() THEN writeToolType(nodeStr,'SERIAL.NO_PURGELINE') ELSE deleteToolType(nodeStr,'SERIAL.NO_PURGELINE') + IF self.boolRepurge.getValue() THEN writeToolType(nodeStr,'SERIAL.REPURGE') ELSE deleteToolType(nodeStr,'SERIAL.REPURGE') + IF self.boolLogoffReset.getValue() THEN writeToolType(nodeStr,'SERIAL.LOGOFF_RESET') ELSE deleteToolType(nodeStr,'SERIAL.LOGOFF_RESET') + IF self.boolTrueReset.getValue() THEN writeToolType(nodeStr,'SERIAL.TRUE_RESET') ELSE deleteToolType(nodeStr,'SERIAL.TRUE_RESET') + + StringF(toolTypePath,'\sNode\d/Modem',bbsPath,self.currNode) + IF(self.getToolTypeFileName(toolTypePath,tempStr))=FALSE + StrCopy(tempStr,'modem') + ELSE + SetStr(tempStr) + ENDIF + StringF(toolTypePath,'\sNode\d/Modem/\s',bbsPath,self.currNode,tempStr) + + //modem settings + writeToolType(toolTypePath,'MODEM.INIT',self.strModemInit.getValue()) + writeToolType(toolTypePath,'MODEM.RESET',self.strModemReset.getValue()) + writeToolType(toolTypePath,'MODEM.RING',self.strModemRing.getValue()) + writeToolType(toolTypePath,'MODEM.ANSWER',self.strModemAnswer.getValue()) + writeToolType(toolTypePath,'MODEM.OFFHOOK',self.strModemOffhook.getValue()) + + StringF(toolTypePath,'\sNode\d/NRAMS',bbsPath,self.currNode) + IF(self.getToolTypeFileName(toolTypePath,tempStr))=FALSE + StrCopy(tempStr,'nrams') + ELSE + SetStr(tempStr) + ENDIF + StringF(toolTypePath,'\sNode\d/Modem/\s',bbsPath,self.currNode,tempStr) + + //NRAM settings + writeToolType(toolTypePath,'NRAM.1',self.strNRAMS1.getValue()) + writeToolType(toolTypePath,'NRAM.2',self.strNRAMS2.getValue()) + writeToolType(toolTypePath,'NRAM.3',self.strNRAMS3.getValue()) + writeToolType(toolTypePath,'NRAM.4',self.strNRAMS4.getValue()) + + + StringF(windowTooltype,'\s/WINDOW.DEF',nodeStr) + val:=self.intNumColours.getValueIndex() + SELECT val + CASE 0 + writeToolType(windowTooltype,'WINDOW.NUM_COLORS','2') + CASE 1 + writeToolType(windowTooltype,'WINDOW.NUM_COLORS','4') + CASE 2 + writeToolType(windowTooltype,'WINDOW.NUM_COLORS','8') + CASE 3 + writeToolType(windowTooltype,'WINDOW.NUM_COLORS','16') + DEFAULT + writeToolType(windowTooltype,'WINDOW.NUM_COLORS','8') + ENDSELECT + + writeToolType(windowTooltype,'WINDOW.LEFTEDGE',self.intWinLeftEdge.getValue()) + writeToolType(windowTooltype,'WINDOW.TOPEDGE',self.intWinTopEdge.getValue()) + writeToolType(windowTooltype,'WINDOW.WIDTH',self.intWinWidth.getValue()) + writeToolType(windowTooltype,'WINDOW.HEIGHT',self.intWinHeight.getValue()) + writeToolType(windowTooltype,'WINDOW.PUBSCREEN',self.strWinPubScreen.getValue()) + IF self.boolWinIconified.getValue() THEN writeToolType(windowTooltype,'WINDOW.ICONIFIED') ELSE deleteToolType(windowTooltype,'WINDOW.ICONIFIED') + IF self.boolWinInterlace.getValue() THEN writeToolType(windowTooltype,'WINDOW.INTERLACE') ELSE deleteToolType(windowTooltype,'WINDOW.INTERLACE') + IF self.boolWinStatusBar.getValue() THEN writeToolType(windowTooltype,'WINDOW.STATBAR') ELSE deleteToolType(windowTooltype,'WINDOW.STATBAR') + IF self.boolWinToFront.getValue() THEN writeToolType(windowTooltype,'WINDOW.TO_FRONT') ELSE deleteToolType(windowTooltype,'WINDOW.TO_FRONT') + writeToolType(windowTooltype,'WINDOW.DISPLAYID',self.strDisplayId.getValue()) + + StringF(timeTooltype,'\s/TIMES.DEF',nodeStr) + ForAll({timeItem},self.timesList,`self.saveTimes(timeTooltype,timeItem.baudStr,timeItem.startControl,timeItem.endControl)) + saveCachedChanges() + + + set( self.btnNodeSave,MUIA_Disabled,MUI_TRUE) + set( self.btnAddNode,MUIA_Disabled,FALSE) + set( self.btnCloneNode,MUIA_Disabled,FALSE) + self.changed:=FALSE + self.newNode:=FALSE + self.wake() +ENDPROC + +PROC getToolTypeFileName(path:PTR TO CHAR,buf:PTR TO CHAR) OF frmNodeEdit + DEF returnval=0 + DEF dir_info:PTR TO fileinfoblock + DEF pdir + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(path,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + returnval:=1 + AstrCopy(buf,dir_info.filename) + stripInfo(buf) + ENDIF + ENDIF + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) +ENDPROC returnval + +PROC saveTimes(toolType,baudStr,startControl,endControl) OF frmNodeEdit + DEF toolTypeName[255]:STRING + DEF timeVal + get(startControl, MUIA_String_Contents,{timeVal}) + StringF(toolTypeName,'START.\s',baudStr) + writeToolType(toolType,toolTypeName,timeVal) + + get(endControl, MUIA_String_Contents,{timeVal}) + StringF(toolTypeName,'END.\s',baudStr) + writeToolType(toolType,toolTypeName,timeVal) +ENDPROC + +PROC loadTimes(toolType,baudStr,startControl,endControl) OF frmNodeEdit + DEF toolTypeName[255]:STRING + DEF tempStr[255]:STRING + + StringF(toolTypeName,'START.\s',baudStr) + readToolType(toolType,toolTypeName,tempStr) + domethod(startControl,[MUIM_NoNotifySet,MUIA_String_Contents,tempStr]) + + StringF(toolTypeName,'END.\s',baudStr) + readToolType(toolType,toolTypeName,tempStr) + domethod(endControl,[MUIM_NoNotifySet,MUIA_String_Contents,tempStr]) +ENDPROC + + +PROC loadNode(node) OF frmNodeEdit + DEF nodeStr[255]:STRING,val + DEF windowTooltype[255]:STRING + DEF timeTooltype[255]:STRING + DEF bbsPath[255]:STRING + DEF tooltypeValue[255]:STRING + DEF toolTypePath[255]:STRING + DEF tempStr[255]:STRING + DEF timeItem:PTR TO timeItem + + IF self.changed + IF self.unsavedChangesWarning()=FALSE THEN RETURN FALSE + ENDIF + + IF self.newNode THEN self.nodeCount:=self.nodeCount-1 + + StringF(nodeStr,'\d',node) + self.currNode:=node + + set(self.strNodeNumber, MUIA_String_Contents,nodeStr) + set( self.btnPrevNode, MUIA_Disabled , node=0) + set( self.btnNextNode, MUIA_Disabled , node>=(self.nodeCount-1)) + set( self.btnRemoveNode, MUIA_Disabled , (node<(self.nodeCount-1)) OR (node=0)) + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + StringF(nodeStr,'\snode\d',bbsPath,node) + + val:=readToolTypeInt(nodeStr,'PRIORITY') + self.intPriority.setValue(val) + readToolType(nodeStr,'NODESTART',tooltypeValue) + self.strNodeStart.setValue(tooltypeValue) + readToolType(nodeStr,'SYSTEM_PASSWORD',tooltypeValue) + self.strSystemPassword.setValue(tooltypeValue) + readToolType(nodeStr,'SYS_PWRD_PROMPT',tooltypeValue) + self.strSystemPasswordPrompt.setValue(tooltypeValue) + readToolType(nodeStr,'NEWUSER_PASSWORD',tooltypeValue) + self.strNewuserPassword.setValue(tooltypeValue) + readToolType(nodeStr,'NAME_PROMPT',tooltypeValue) + self.strNamePrompt.setValue(tooltypeValue) + readToolType(nodeStr,'NAME_PROMPT2',tooltypeValue) + self.strNamePrompt2.setValue(tooltypeValue) + readToolType(nodeStr,'PASSWORD_PROMPT',tooltypeValue) + self.strPasswordPrompt.setValue(tooltypeValue) + readToolType(nodeStr,'SCREENS',tooltypeValue) + self.paScreens.setValue(tooltypeValue) + val:=readToolTypeInt(nodeStr,'AUTOVAL_PRESET') + self.intAutoValPreset.setValue(val) + val:=readToolTypeInt(nodeStr,'AUTOVAL_DELAY') + self.intAutoValDelay.setValue(val) + readToolType(nodeStr,'AUTOVAL_PASSWORD',tooltypeValue) + self.strAutoValPassword.setValue(tooltypeValue) + + val:=readToolTypeInt(nodeStr,'FTPPORT') + self.intFtpPort.setValue(val) + val:=readToolTypeInt(nodeStr,'FTPDATAPORT') + self.intFtpDataPort.setValue(val) + val:=readToolTypeInt(nodeStr,'HTTPPORT') + self.intHttpPort.setValue(val) + val:=readToolTypeInt(nodeStr,'KEEP_UPLOAD_CREDIT') + IF val<>1 THEN val:=0 + self.intKeepUlCredit.setValueIndex(val) + val:=readToolTypeInt(nodeStr,'MAX_MSG_LEN') + self.intMaxMsgLen.setValue(val) + val:=readToolTypeInt(nodeStr,'MAX_MSG_QU') + self.intMaxMsgQueue.setValue(val) + readToolType(nodeStr,'PLAYPEN',tooltypeValue) + self.paPlaypen.setValue(tooltypeValue) + val:=readToolTypeInt(nodeStr,'RINGCOUNT') + self.intRingCount.setValue(val) + readToolType(nodeStr,'REMOTE_PASSWORD',tooltypeValue) + self.strRemotePassword.setValue(tooltypeValue) + val:=readToolTypeInt(nodeStr,'SYSOP_CHAT_COLOR') + self.intSysopChatColour.setValue(val) + val:=readToolTypeInt(nodeStr,'USER_CHAT_COLOR') + self.intUserChatColour.setValue(val) + readToolType(nodeStr,'USERDATA_NAME',tooltypeValue) + self.fnUserDataName.setValue(tooltypeValue) + readToolType(nodeStr,'USERKEYS_NAME',tooltypeValue) + self.fnUserMiscName.setValue(tooltypeValue) + readToolType(nodeStr,'USERMISC_NAME',tooltypeValue) + self.fnUserKeysName.setValue(tooltypeValue) + readToolType(nodeStr,'LOCAL_UPLOAD_PATH',tooltypeValue) + self.paLocalUlPath.setValue(tooltypeValue) + val:=readToolTypeInt(nodeStr,'OVERRIDE_TIMEOUT') + self.intOverrideTimeout.setValue(val) + readToolType(nodeStr,'FORCE_ANSI',tooltypeValue) + self.strForceAnsi.setValue(tooltypeValue) + val:=readToolTypeInt(nodeStr,'BGFILECHECKSTACK') + self.intBGFilecheckStack.setValue(val) + readToolType(nodeStr,'CONSOLE_INPUT_DEVICE',tooltypeValue) + self.strConInputDev.setValue(tooltypeValue) + readToolType(nodeStr,'CONSOLE_OUTPUT_DEVICE',tooltypeValue) + self.strConOutputDev.setValue(tooltypeValue) + readToolType(nodeStr,'SCREENPENS',tooltypeValue) + self.strScreenPens.setValue(tooltypeValue) + readToolType(nodeStr,'CONF_DB',tooltypeValue) + self.strConfDb.setValue(tooltypeValue) + readToolType(nodeStr,'FILESNOTALLOWED',tooltypeValue) + self.fnFilesNotAllowed.setValue(tooltypeValue) + readToolType(nodeStr,'FIRSTCOMMAND',tooltypeValue) + self.strFirstCommand.setValue(tooltypeValue) + val:=readToolTypeInt(nodeStr,'SERIAL_CACHE_SIZE') + self.intSerialCacheSize.setValue(val) + self.boolCallersLog.setValue(IF checkToolTypeExists(nodeStr,'CALLERS_LOG') THEN MUI_TRUE ELSE FALSE) + self.boolCapitalFilenames.setValue(IF checkToolTypeExists(nodeStr,'CAPITOL_FILES') THEN MUI_TRUE ELSE FALSE) + self.boolDebugLog.setValue(IF checkToolTypeExists(nodeStr,'DEBUG_LOG') THEN MUI_TRUE ELSE FALSE) + self.boolDefScreens.setValue(IF checkToolTypeExists(nodeStr,'DEF_SCREENS') THEN MUI_TRUE ELSE FALSE) + self.boolDebugLog.setValue(IF checkToolTypeExists(nodeStr,'DEBUG_LOG') THEN MUI_TRUE ELSE FALSE) + self.boolDoorLog.setValue(IF checkToolTypeExists(nodeStr,'DOOR_LOG') THEN MUI_TRUE ELSE FALSE) + self.boolStartLog.setValue(IF checkToolTypeExists(nodeStr,'START_LOG') THEN MUI_TRUE ELSE FALSE) + self.boolUDLog.setValue(IF checkToolTypeExists(nodeStr,'UD_LOG') THEN MUI_TRUE ELSE FALSE) + self.boolChatOn.setValue(IF checkToolTypeExists(nodeStr,'CHAT_ON') THEN MUI_TRUE ELSE FALSE) + self.boolDisableQuickLogon.setValue(IF checkToolTypeExists(nodeStr,'DISABLE_QUICK_LOGONS') THEN MUI_TRUE ELSE FALSE) + self.boolIdleNode.setValue(IF checkToolTypeExists(nodeStr,'IDLENODE') THEN MUI_TRUE ELSE FALSE) + self.boolMailscanPrompt.setValue(IF checkToolTypeExists(nodeStr,'MAILSCAN_PROMPT') THEN MUI_TRUE ELSE FALSE) + self.boolNoTimeout.setValue(IF checkToolTypeExists(nodeStr,'NO_TIMEOUT') THEN MUI_TRUE ELSE FALSE) + self.boolQuietNode.setValue(IF checkToolTypeExists(nodeStr,'QUIETNODE') THEN MUI_TRUE ELSE FALSE) + self.boolStealthNode.setValue(IF checkToolTypeExists(nodeStr,'STEALTH_MODE') THEN MUI_TRUE ELSE FALSE) + self.boolShowPwFail.setValue(IF checkToolTypeExists(nodeStr,'SHOWPWFAIL') THEN MUI_TRUE ELSE FALSE) + self.boolSentByFiles.setValue(IF checkToolTypeExists(nodeStr,'SENTBY_FILES') THEN MUI_TRUE ELSE FALSE) + self.boolTelnet.setValue(IF checkToolTypeExists(nodeStr,'TELNET') THEN MUI_TRUE ELSE FALSE) + self.boolFtp.setValue(IF checkToolTypeExists(nodeStr,'FTP') THEN MUI_TRUE ELSE FALSE) + self.boolTelnetD.setValue(IF checkToolTypeExists(nodeStr,'TELSERD') THEN MUI_TRUE ELSE FALSE) + self.boolTelserD.setValue(IF checkToolTypeExists(nodeStr,'TELNETD') THEN MUI_TRUE ELSE FALSE) + self.boolUserNumLogin.setValue(IF checkToolTypeExists(nodeStr,'USERNUMBER_LOGIN') THEN MUI_TRUE ELSE FALSE) + self.boolViewPassword.setValue(IF checkToolTypeExists(nodeStr,'VIEW_PASSWORD') THEN MUI_TRUE ELSE FALSE) + self.boolLogHost.setValue(IF checkToolTypeExists(nodeStr,'LOG_HOST') THEN MUI_TRUE ELSE FALSE) + self.boolLogInputs.setValue(IF checkToolTypeExists(nodeStr,'LOG_INPUTS') THEN MUI_TRUE ELSE FALSE) + self.boolNoCx.setValue(IF checkToolTypeExists(nodeStr,'NO_CX') THEN MUI_TRUE ELSE FALSE) + self.boolCentralAnswers.setValue(IF checkToolTypeExists(nodeStr,'CENTRAL_ANSWERS') THEN MUI_TRUE ELSE FALSE) + self.boolDisableIemsi.setValue(IF checkToolTypeExists(nodeStr,'DISABLE_IEMSI') THEN MUI_TRUE ELSE FALSE) + self.boolNoMciMsg.setValue(IF checkToolTypeExists(nodeStr,'NO_MCI_MSG') THEN MUI_TRUE ELSE FALSE) + self.boolNoWildcard.setValue(IF checkToolTypeExists(nodeStr,'NO_WILDCARD_EXPANSION') THEN MUI_TRUE ELSE FALSE) + self.boolOwnPartFiles.setValue(IF checkToolTypeExists(nodeStr,'OWN_PARTFILES') THEN MUI_TRUE ELSE FALSE) + self.boolPhoneCheck.setValue(IF checkToolTypeExists(nodeStr,'PHONECHECK') THEN MUI_TRUE ELSE FALSE) + self.boolRamWork.setValue(IF checkToolTypeExists(nodeStr,'RAMWORK') THEN MUI_TRUE ELSE FALSE) + self.boolConsoleDebug.setValue(IF checkToolTypeExists(nodeStr,'CONSOLE_DEBUG') THEN MUI_TRUE ELSE FALSE) + self.boolNoEmails.setValue(IF checkToolTypeExists(nodeStr,'NO_EMAILS') THEN MUI_TRUE ELSE FALSE) + self.boolOwnDevunit.setValue(IF checkToolTypeExists(nodeStr,'OWNDEVUNIT') THEN MUI_TRUE ELSE FALSE) + self.boolShowCacheStats.setValue(IF checkToolTypeExists(nodeStr,'SHOW_CACHE_STATS') THEN MUI_TRUE ELSE FALSE) + self.boolTrapDoor.setValue(IF checkToolTypeExists(nodeStr,'TRAPDOOR') THEN MUI_TRUE ELSE FALSE) + self.boolTrapSerial.setValue(IF checkToolTypeExists(nodeStr,'TRAP_SERIAL') THEN MUI_TRUE ELSE FALSE) + self.boolNoRadBoogie.setValue(IF checkToolTypeExists(nodeStr,'NORADBOOGIE') THEN MUI_TRUE ELSE FALSE) + + //serial device settings + StringF(toolTypePath,'\sNode\d/Serial',bbsPath,node) + IF(self.getToolTypeFileName(toolTypePath,tempStr)=FALSE) + StrCopy(tempStr,'serial') + ELSE + SetStr(tempStr) + ENDIF + StringF(toolTypePath,'\sNode\d/Serial/\s',bbsPath,node,tempStr) + + readToolType(toolTypePath,'SERIAL.DRIVER',tooltypeValue) + self.strSerialDevice.setValue(tooltypeValue) + + val:=readToolTypeInt(toolTypePath,'SERIAL.UNIT') + self.intSerialUnit.setValue(val) + + val:=readToolTypeInt(toolTypePath,'SERIAL.BAUD') + self.intSerialBaud.setValue(val) + + self.boolA2232Patch.setValue(IF checkToolTypeExists(toolTypePath,'SERIAL.A2232_PATCH') THEN MUI_TRUE ELSE FALSE) + + self.boolNoPurgeLine.setValue(IF checkToolTypeExists(toolTypePath,'SERIAL.NO_PURGELINE') THEN MUI_TRUE ELSE FALSE) + + self.boolRepurge.setValue(IF checkToolTypeExists(toolTypePath,'SERIAL.REPURGE') THEN MUI_TRUE ELSE FALSE) + + self.boolLogoffReset.setValue(IF checkToolTypeExists(toolTypePath,'SERIAL.LOGOFF_RESET') THEN MUI_TRUE ELSE FALSE) + + self.boolTrueReset.setValue(IF checkToolTypeExists(toolTypePath,'SERIAL.TRUE_RESET') THEN MUI_TRUE ELSE FALSE) + + StringF(toolTypePath,'\sNode\d/Modem',bbsPath,node) + IF(self.getToolTypeFileName(toolTypePath,tempStr))=FALSE + StrCopy(tempStr,'modem') + ELSE + SetStr(tempStr) + ENDIF + StringF(toolTypePath,'\sNode\d/Modem/\s',bbsPath,node,tempStr) + + //modem settings + readToolType(toolTypePath,'MODEM.INIT',tooltypeValue) + self.strModemInit.setValue(tooltypeValue) + readToolType(toolTypePath,'MODEM.RESET',tooltypeValue) + self.strModemReset.setValue(tooltypeValue) + readToolType(toolTypePath,'MODEM.RING',tooltypeValue) + self.strModemRing.setValue(tooltypeValue) + readToolType(toolTypePath,'MODEM.ANSWER',tooltypeValue) + self.strModemAnswer.setValue(tooltypeValue) + readToolType(toolTypePath,'MODEM.OFFHOOK',tooltypeValue) + self.strModemOffhook.setValue(tooltypeValue) + + + StringF(windowTooltype,'\s/WINDOW.DEF',nodeStr) + val:=readToolTypeInt(windowTooltype,'WINDOW.NUM_COLORS') + SELECT val + CASE 2 + self.intNumColours.setValueIndex(0) + CASE 4 + self.intNumColours.setValueIndex(1) + CASE 8 + self.intNumColours.setValueIndex(2) + CASE 16 + self.intNumColours.setValueIndex(3) + DEFAULT + self.intNumColours.setValueIndex(8) + ENDSELECT + + val:=readToolTypeInt(windowTooltype,'WINDOW.LEFTEDGE') + self.intWinLeftEdge.setValue(val) + val:=readToolTypeInt(windowTooltype,'WINDOW.TOPEDGE') + self.intWinTopEdge.setValue(val) + val:=readToolTypeInt(windowTooltype,'WINDOW.WIDTH') + self.intWinWidth.setValue(val) + val:=readToolTypeInt(windowTooltype,'WINDOW.HEIGHT') + self.intWinHeight.setValue(val) + readToolType(windowTooltype,'WINDOW.PUBSCREEN',tooltypeValue) + self.strWinPubScreen.setValue(tooltypeValue) + self.boolWinIconified.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.ICONIFIED') THEN MUI_TRUE ELSE FALSE) + self.boolWinInterlace.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.INTERLACE') THEN MUI_TRUE ELSE FALSE) + self.boolWinStatusBar.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.STATBAR') THEN MUI_TRUE ELSE FALSE) + self.boolWinToFront.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.TO_FRONT') THEN MUI_TRUE ELSE FALSE) + readToolType(windowTooltype,'WINDOW.DISPLAYID',tooltypeValue) + self.strDisplayId.setValue(tooltypeValue) + + StringF(timeTooltype,'\s/TIMES.DEF',nodeStr) + ForAll({timeItem},self.timesList,`self.loadTimes(timeTooltype,timeItem.baudStr,timeItem.startControl,timeItem.endControl)) + + self.changed:=FALSE + set( self.btnNodeSave, MUIA_Disabled , MUI_TRUE) + set( self.btnAddNode,MUIA_Disabled,FALSE) + set( self.btnCloneNode,MUIA_Disabled,FALSE) + self.newNode:=FALSE +ENDPROC TRUE + +PROC editNodes(acpName) OF frmNodeEdit + DEF count,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + DEF timeItem:PTR TO timeItem + + NEW saveHook + installhook( saveHook, {saveChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.timesList:=[ + ['300',self.app.str300start,self.app.str300end]:timeItem, + ['1200',self.app.str1200start,self.app.str1200end]:timeItem, + ['2400',self.app.str2400start,self.app.str2400end]:timeItem, + ['4800',self.app.str4800start,self.app.str4800end]:timeItem, + ['9600',self.app.str9600start,self.app.str9600end]:timeItem, + ['12000',self.app.str12000start,self.app.str12000end]:timeItem, + ['14400',self.app.str14400start,self.app.str14400end]:timeItem, + ['16800',self.app.str16800start,self.app.str16800end]:timeItem, + ['19200',self.app.str19200start,self.app.str19200end]:timeItem, + ['21600',self.app.str21600start,self.app.str21600end]:timeItem, + ['24000',self.app.str24000start,self.app.str24000end]:timeItem, + ['26400',self.app.str26400start,self.app.str26400end]:timeItem, + ['28800',self.app.str28800start,self.app.str28800end]:timeItem, + ['31200',self.app.str31200start,self.app.str31200end]:timeItem, + ['33600',self.app.str33600start,self.app.str33600end]:timeItem, + ['38400',self.app.str38400start,self.app.str38400end]:timeItem, + ['57600',self.app.str57600start,self.app.str57600end]:timeItem, + ['115200',self.app.str115200start,self.app.str115200end]:timeItem] + + ForAll({timeItem},self.timesList,`domethod( timeItem.startControl,[MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,self.app.app,3,MUIM_CallHook,self.setChangedHook,self])) + ForAll({timeItem},self.timesList,`domethod( timeItem.endControl,[MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,self.app.app,3,MUIM_CallHook,self.setChangedHook,self])) + + self.acpName:=acpName + + set( self.btnRemoveNode, MUIA_Disabled , MUI_TRUE) + + self.nodeCount:=readToolTypeInt(acpName,'NODES') + + installhook( self.setChangedHook, {setChangedFlag}) + self.addControls() + self.addNotifications() + + set(self.grpNodePages,MUIA_Group_ActivePage,MUIV_Group_ActivePage_First) + + self.changed:=FALSE + self.loadNode(0) + + self.showModal() + self.removeNotifications() + self.removeControls() + + ForAll({timeItem},self.timesList,`domethod( timeItem.startControl,[MUIM_KillNotify,MUIA_String_Contents])) + ForAll({timeItem},self.timesList,`domethod( timeItem.endControl,[MUIM_KillNotify,MUIA_String_Contents])) + + END saveHook + END closeHook +ENDPROC + diff --git a/axSetupTool/frmPresetsEdit.e b/axSetupTool/frmPresetsEdit.e new file mode 100644 index 0000000..37fa3be --- /dev/null +++ b/axSetupTool/frmPresetsEdit.e @@ -0,0 +1,380 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists','dos/dos' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*/stringlist' + + +EXPORT OBJECT frmPresetsEdit OF frmBase + acpName : PTR TO CHAR + bbsConfigName : PTR TO CHAR + btnSave : PTR TO LONG + btnCancel : PTR TO LONG + raPreset : PTR TO LONG + grpSettings : PTR TO LONG + changed + + areaNames:PTR TO LONG + setChangedHook : hook + presetListOnChange : hook + currPreset : INT + controlList : LONG + + strAreaName : PTR TO control + intAccessLevel : PTR TO control + intConfrJoin : PTR TO control + intMsgbaserJoin : PTR TO control + intDailyBytes : PTR TO control + intRatioType : PTR TO control + intRatio : PTR TO control + intTimeLimit : PTR TO control +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmPresetsEdit + DEF group + SUPER self.create(app) + self.winMain:=app.wi_presets + + self.btnSave:=app.btnPresetSave + self.btnCancel:=app.btnPresetClose + self.raPreset:=app.ra_presets + + self.grpSettings:=app.gr_preset_settings + + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) +ENDPROC + +PROC setChangedFlag() OF frmPresetsEdit + MOVE.L (A1),self + GetA4() + IF self.changed=FALSE + self.changed:=TRUE + set( self.btnSave,MUIA_Disabled,FALSE) + ENDIF +ENDPROC + +PROC freeControl(control:PTR TO control) OF frmPresetsEdit + control.removeFromGroup(self.grpSettings) + END control +ENDPROC + +PROC addNotifications() OF frmPresetsEdit + domethod( self.btnCancel , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + domethod( self.btnSave , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , ID_SAVE ] ) + + domethod( self.raPreset , [ + MUIM_Notify , MUIA_Radio_Active , MUIV_EveryTime , + self.app.app, + 3 , + MUIM_CallHook , self.presetListOnChange, self] ) + installhook( self.presetListOnChange, {presetChange}) + +ENDPROC + +PROC removeNotifications() OF frmPresetsEdit + domethod(self.btnCancel,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnSave,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.raPreset ,[MUIM_KillNotify,MUIA_Radio_Active]) +ENDPROC + +PROC addPresetControls() OF frmPresetsEdit + DEF control: PTR TO control + + NEW control.createCycle('bArea Name','strAreaName',['',0],self.app.app,self.setChangedHook,self) + self.strAreaName:=control + + NEW control.createStringInt('bAccess Level','intAccessLevel',self.app.app,self.setChangedHook,self) + self.intAccessLevel:=control + + NEW control.createStringInt('bInitial Conf','intConfrJoin',self.app.app,self.setChangedHook,self) + self.intConfrJoin:=control + + NEW control.createStringInt('Initial Msgbase','intMsgbaserJoin',self.app.app,self.setChangedHook,self) + self.intMsgbaserJoin:=control + + NEW control.createStringInt('Daily Byte Limit','intDailyBytes',self.app.app,self.setChangedHook,self) + self.intDailyBytes:=control + + NEW control.createStringInt('Ratio Type','intRatioType',self.app.app,self.setChangedHook,self) + self.intRatioType:=control + + NEW control.createStringInt('Ratio','intRatio',self.app.app,self.setChangedHook,self) + self.intRatio:=control + + NEW control.createStringInt('Time Limit','intTimeLimit',self.app.app,self.setChangedHook,self) + self.intTimeLimit:=control + + self.controlList:=[self.strAreaName,self.intAccessLevel,self.intConfrJoin,self.intMsgbaserJoin, + self.intDailyBytes,self.intRatioType,self.intRatio,self.intTimeLimit] + + domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`control.addToGroup(self.grpSettings)) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC removePresetControls() OF frmPresetsEdit + DEF list:PTR TO lh,state,obj + DEF control: PTR TO control + + domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`self.freeControl(control)) + + get(self.grpSettings,MUIA_Group_ChildList,{list}) + state:=list.head + WHILE (obj:=NextObject({state})) + domethod(self.grpSettings,[OM_REMMEMBER,obj]) + Mui_DisposeObject(obj) + ENDWHILE + domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC presetChange() OF frmPresetsEdit + DEF entry + MOVE.L (A1),self + GetA4() + + get(self.raPreset,MUIA_Radio_Active,{entry}) + + IF self.loadPreset(entry+1)=FALSE + //restore old prest + domethod(self.raPreset,[MUIM_NoNotifySet,MUIA_Radio_Active,self.currPreset]) + ENDIF + +ENDPROC + +PROC canClose() OF frmPresetsEdit + MOVE.L (A1),self + GetA4() + IF self.changed + IF self.unsavedChangesWarning()=0 THEN RETURN FALSE + ENDIF +ENDPROC TRUE + +PROC unsavedChangesWarning() OF frmPresetsEdit + DEF win + get(self.winMain,MUIA_Window_Window,{win}) + IF EasyRequestArgs( win , [ 20 , 0 , + 'Unsaved changes' , + 'You have unsaved changes,\nif you continue you will lose them.', + '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE +ENDPROC TRUE + +PROC savePresetChanges() OF frmPresetsEdit + DEF tempStr[255]:STRING + DEF bbsPath[255]:STRING + DEF presetStr[20]:STRING + DEF win + + MOVE.L (A1),self + GetA4() + + get(self.winMain,MUIA_Window_Window,{win}) + + fullTrim(self.areaNames[self.strAreaName.getValueIndex()],tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'Area Name is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + fullTrim(self.intAccessLevel.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'Acces Level is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + fullTrim(self.intConfrJoin.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'Initial Conf is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + StringF(presetStr,'\saccess/preset.\d',bbsPath,self.currPreset) + + writeToolType(presetStr,'PRESET.AREA',self.areaNames[self.strAreaName.getValueIndex()]) + writeToolType(presetStr,'PRESET.ACCESS',self.intAccessLevel.getValue()) + writeToolType(presetStr,'PRESET.CONFRJOIN',self.intConfrJoin.getValue()) + writeToolType(presetStr,'PRESET.MSGBASERJOIN',self.intMsgbaserJoin.getValue()) + writeToolType(presetStr,'PRESET.DAILY_BYTE_LIMIT',self.intDailyBytes.getValue()) + writeToolType(presetStr,'PRESET.RATIO_TYPE',self.intRatioType.getValue()) + writeToolType(presetStr,'PRESET.RATIO',self.intRatio.getValue()) + writeToolType(presetStr,'PRESET.TIME_LIMIT',self.intTimeLimit.getValue()) + saveCachedChanges() + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE +ENDPROC + +PROC findAreaIndex(areaName:PTR TO CHAR) OF frmPresetsEdit + DEF res,i + res:=-1 + + FOR i:=0 TO ListLen(self.areaNames)-2 DO IF StriCmp(areaName,self.areaNames[i]) THEN res:=i +ENDPROC res + +PROC loadAreaNames(bbsPath:PTR TO CHAR) OF frmPresetsEdit + DEF accessPath[255]:STRING + DEF dir_info:PTR TO fileinfoblock + DEF pdir,r,entry + + DEF buf[255]:STRING + DEF parseBuf[100]:STRING + + StringF(accessPath,'\saccess/',bbsPath) + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN 0 + ENDIF + + IF ((pdir:=Lock(accessPath,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN 0 + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN 0 + ENDIF + + IF ParsePatternNoCase('AREA.#?.info',parseBuf,100) =-1 THEN RETURN + + ForAll({entry},self.areaNames,`DisposeLink(entry)) + SetList(self.areaNames,0) + + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype < 0) + + IF MatchPatternNoCase(parseBuf,dir_info.filename) + buf:=String(255) + StrCopy(buf,dir_info.filename+5) + stripInfo(buf) + ListAddItem(self.areaNames,buf) + ENDIF + ENDIF + ENDWHILE + + ListAddItem(self.areaNames,String(0)) + ListAddItem(self.areaNames,0) + + set(self.strAreaName.muiControl,MUIA_Cycle_Entries,self.areaNames) + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) + + +ENDPROC + +PROC loadPreset(presetNum) OF frmPresetsEdit + DEF bbsPath[255]:STRING + DEF presetStr[20]:STRING + DEF tempStr[255]:STRING + DEF val + + IF self.changed + IF self.unsavedChangesWarning()=FALSE THEN RETURN FALSE + ENDIF + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + StringF(presetStr,'\saccess/preset.\d',bbsPath,presetNum) + + readToolType(presetStr,'PRESET.AREA',tempStr) + IF EstrLen(tempStr)=0 THEN StrCopy(tempStr,'') + self.strAreaName.setValueIndex(self.findAreaIndex(tempStr)) + + val:=readToolTypeInt(presetStr,'PRESET.ACCESS') + self.intAccessLevel.setValue(val) + + val:=readToolTypeInt(presetStr,'PRESET.CONFRJOIN') + self.intConfrJoin.setValue(val) + + val:=readToolTypeInt(presetStr,'PRESET.MSGBASERJOIN') + self.intMsgbaserJoin.setValue(val) + + val:=readToolTypeInt(presetStr,'PRESET.DAILY_BYTE_LIMIT') + self.intDailyBytes.setValue(val) + + val:=readToolTypeInt(presetStr,'PRESET.RATIO_TYPE') + self.intRatioType.setValue(val) + + val:=readToolTypeInt(presetStr,'PRESET.RATIO') + self.intRatio.setValue(val) + + val:=readToolTypeInt(presetStr,'PRESET.TIME_LIMIT') + self.intTimeLimit.setValue(val) + + self.currPreset:=presetNum + + self.changed:=FALSE + set( self.btnSave, MUIA_Disabled , MUI_TRUE) + +ENDPROC TRUE + +PROC editPresets(acpName:PTR TO CHAR) OF frmPresetsEdit + DEF count,val,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF bbsPath[255]:STRING + + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + NEW saveHook + installhook( saveHook, {savePresetChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.acpName:=acpName + + self.areaNames:=List(100) + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + + + installhook( self.setChangedHook, {setChangedFlag}) + self.addPresetControls() + self.addNotifications() + + self.loadAreaNames(bbsPath) + + set( self.winMain, MUIA_Window_Title,'Edit Presets') + set(self.raPreset,MUIA_Radio_Active,0) + + self.changed:=FALSE + self.loadPreset(1) + + self.changed:=FALSE + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + self.showModal() + self.removeNotifications() + self.removePresetControls() + END saveHook + END closeHook + ForAll({entry},self.areaNames,`IF entry THEN DisposeLink(entry) ELSE 0) + DisposeLink(self.areaNames) +ENDPROC diff --git a/axSetupTool/frmSettingsEdit.e b/axSetupTool/frmSettingsEdit.e new file mode 100644 index 0000000..6714e03 --- /dev/null +++ b/axSetupTool/frmSettingsEdit.e @@ -0,0 +1,1149 @@ +OPT MODULE,LARGE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*/stringlist' + + +EXPORT OBJECT frmSettingsEdit OF frmBase + acpName : PTR TO CHAR + bbsConfigName : PTR TO CHAR + zoomDirPath : PTR TO CHAR + btnSave : PTR TO LONG + btnCancel : PTR TO LONG + grpSettings : PTR TO LONG + changed + setChangedHook : hook + controlList : LONG + languages : PTR TO LONG + languagesConfigName:PTR TO CHAR + nodeCount : INT + + //system settings + strBBSName : PTR TO control + strBBSLocation : PTR TO control + strSysopName : PTR TO control + strDefaultMenu : PTR TO control + paLocalULPath : PTR TO control + intAutoValPreset : PTR TO control + intAutoValDelay : PTR TO control + strAutoValPassword: PTR TO control + cyLanguage : PTR TO control + boolCreditByKb : PTR TO control + boolLongWho : PTR TO control + cyNewAccounts : PTR TO control + strRegKey : PTR TO control + boolConvertToMb : PTR TO control + boolTimeoutLc : PTR TO control + boolQuietJoin : PTR TO control + boolRelativeConfs: PTR TO control + strSmtpHost : PTR TO control + intSmtpPort : PTR TO control + strSmtpUsername : PTR TO control + strSmtpPassword : PTR TO control + boolSmtpSSL : PTR TO control + strSysopEmail : PTR TO control + strBbsEmail : PTR TO control + boolMailOnPage : PTR TO control + boolMailOnComment: PTR TO control + boolMailOnLogon : PTR TO control + boolMailOnLogoff : PTR TO control + boolMailOnNewUser: PTR TO control + boolMailOnUpload : PTR TO control + boolMailOnPwdFail: PTR TO control + paLanguageBase : PTR TO control + paHistory : PTR TO control + paUserNotes : PTR TO control + intHoldAccess : PTR TO control + strFileDizSysCmd : PTR TO control + strFtpHost : PTR TO control + strExecOnNewUser : PTR TO control + strExecAOnNewUser: PTR TO control + strExecOnPage : PTR TO control + strExecAOnPage : PTR TO control + strExecOnConnect : PTR TO control + strExecAOnConnect: PTR TO control + strExecOnLogon : PTR TO control + strExecAOnLogon : PTR TO control + strExecOnLogoff : PTR TO control + strExecAOnLogoff : PTR TO control + strExecOnComment : PTR TO control + strExecAOnComment: PTR TO control + strExecOnUpload : PTR TO control + strExecAOnUpload : PTR TO control + + //server settings + paBBSPath : PTR TO control + intStack : PTR TO control + intPriority : PTR TO control + boolIconified : PTR TO control + intIconifyLeft : PTR TO control + intIconifyTop : PTR TO control + boolDoNotMove : PTR TO control + boolMulticom : PTR TO control + boolAEShell : PTR TO control + boolNoCx : PTR TO control + boolNoSaveState: PTR TO control + intTelnetPort : PTR TO control + intFtpPort : PTR TO control + strAcpFont : PTR TO control + strExecOnStart : PTR TO control + intDosCheckTime: PTR TO control + intDosBanTime : PTR TO control + intDosCheckTrig: PTR TO control + nodeLocs : PTR TO stdlist + nodeNames : PTR TO stdlist + nodeSysops : PTR TO stdlist + buttonNames : PTR TO stdlist + buttonCommands : PTR TO stdlist + nuttonNames : PTR TO stdlist + nuttonCommands : PTR TO stdlist + + //zoom settings + strBbsNumber : PTR TO control + strBbsAddress : PTR TO control + strBbsId : PTR TO control + strQwkZip : PTR TO control + strQwkLha : PTR TO control + strAscZip : PTR TO control + strAscLha : PTR TO control +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmSettingsEdit + DEF group + SUPER self.create(app) + self.winMain:=app.wi_systemdata + + self.setChangedHook.data:=self + + self.btnSave:=app.btnSettingsSave + self.btnCancel:=app.btnSettingsCancel + + get(app.gr_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpSettings:=group + + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) +ENDPROC + +PROC setChangedFlag() OF frmSettingsEdit + MOVE.L (A1),self + GetA4() + + IF self.changed=FALSE + self.changed:=TRUE + set( self.btnSave,MUIA_Disabled,FALSE) + ENDIF +ENDPROC + +PROC freeControl(control:PTR TO control) OF frmSettingsEdit + control.removeFromGroup(self.grpSettings) + END control +ENDPROC + +PROC addNotifications() OF frmSettingsEdit + domethod( self.btnCancel , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + domethod( self.btnSave , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , ID_SAVE ] ) +ENDPROC + +PROC removeNotifications() OF frmSettingsEdit + domethod(self.btnCancel,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnSave,[MUIM_KillNotify,MUIA_Pressed]) +ENDPROC + +PROC addSystemControls() OF frmSettingsEdit + DEF control: PTR TO control + DEF languageList:PTR TO LONG + DEF i + + NEW control.createString('bBBS Name','strBBSName',self.app.app,self.setChangedHook,self) + self.strBBSName:=control + + NEW control.createString('bBBS Location','strBBSLocation',self.app.app,self.setChangedHook,self) + self.strBBSLocation:=control + + NEW control.createString('bSysop Name','strSysopName',self.app.app,self.setChangedHook,self) + self.strSysopName:=control + + NEW control.createString('Default Menu','strDefaultMenu',self.app.app,self.setChangedHook,self) + self.strDefaultMenu:=control + + NEW control.createDirSelect('Local Upload Path','paLocalULPath',self.app.app,self.setChangedHook,self) + self.paLocalULPath:=control + + NEW control.createStringInt('Auto Validate Preset','intAutoValPreset',self.app.app,self.setChangedHook,self) + self.intAutoValPreset:=control + + NEW control.createStringInt('Auto Validate Delay','intAutoValDelay',self.app.app,self.setChangedHook,self) + self.intAutoValDelay:=control + + NEW control.createString('Auto Validate Password','strAutoValPassword',self.app.app,self.setChangedHook,self) + self.strAutoValPassword:=control + + self.cyLanguage:=0 + IF ListLen(self.languages)>1 + NEW control.createCycle('Host Language','cyLanguage',self.languages,self.app.app,self.setChangedHook,self) + self.cyLanguage:=control + ENDIF + + NEW control.createCheckBox('Credit by KB','',self.app.app,self.setChangedHook,self) + self.boolCreditByKb:=control + + NEW control.createCheckBox('Long who','',self.app.app,self.setChangedHook,self) + self.boolLongWho:=control + + NEW control.createCycle('New Accounts','cyNewAccounts',['Append','Overwrite',0],self.app.app,self.setChangedHook,self) + self.cyNewAccounts:=control + + NEW control.createCycle('Timeout Recorded as','boolTimeoutLc',['Lost Carrier','Normal Logoff',0],self.app.app,self.setChangedHook,self) + self.boolTimeoutLc:=control + + NEW control.createString('Registered to','strRegKey',self.app.app,self.setChangedHook,self) + self.strRegKey:=control + + NEW control.createCheckBox('Convert to MB','',self.app.app,self.setChangedHook,self) + self.boolConvertToMb:=control + + NEW control.createCheckBox('Quiet Join','',self.app.app,self.setChangedHook,self) + self.boolQuietJoin:=control + + NEW control.createCheckBox('Relative Conferences','',self.app.app,self.setChangedHook,self) + self.boolRelativeConfs:=control + + NEW control.createString('SMTP server address','strSmtpHost',self.app.app,self.setChangedHook,self) + self.strSmtpHost:=control + NEW control.createStringInt('SMTP server port','intSmtpPort',self.app.app,self.setChangedHook,self) + self.intSmtpPort:=control + NEW control.createString('SMTP server username','strSmtpUsername',self.app.app,self.setChangedHook,self) + self.strSmtpUsername:=control + NEW control.createString('SMTP server password','strSmtpPassword',self.app.app,self.setChangedHook,self) + self.strSmtpPassword:=control + NEW control.createCheckBox('Use SSL for emails','boolSmtpSSL',self.app.app,self.setChangedHook,self) + self.boolSmtpSSL:=control + NEW control.createString('Sysops email address','strSysopEmail',self.app.app,self.setChangedHook,self) + self.strSysopEmail:=control + NEW control.createString('BBS email address','strBbsEmail',self.app.app,self.setChangedHook,self) + self.strBbsEmail:=control + NEW control.createCheckBox('Email on sysop page','boolMailOnPage',self.app.app,self.setChangedHook,self) + self.boolMailOnPage:=control + NEW control.createCheckBox('Email on comment','boolMailOnComment',self.app.app,self.setChangedHook,self) + self.boolMailOnComment:=control + NEW control.createCheckBox('Email on logon','boolMailOnLogon',self.app.app,self.setChangedHook,self) + self.boolMailOnLogon:=control + NEW control.createCheckBox('Email on logoff','boolMailOnLogoff',self.app.app,self.setChangedHook,self) + self.boolMailOnLogoff:=control + NEW control.createCheckBox('Email on new user','boolMailOnNewUser',self.app.app,self.setChangedHook,self) + self.boolMailOnNewUser:=control + NEW control.createCheckBox('Email on upload','boolMailOnUpload',self.app.app,self.setChangedHook,self) + self.boolMailOnUpload:=control + NEW control.createCheckBox('Email on password fail','boolMailOnPwdFail',self.app.app,self.setChangedHook,self) + self.boolMailOnPwdFail:=control + NEW control.createDirSelect('Language base folder','paLanguageBase',self.app.app,self.setChangedHook,self) + self.paLanguageBase:=control + NEW control.createDirSelect('History folder','paHistory',self.app.app,self.setChangedHook,self) + self.paHistory:=control + NEW control.createDirSelect('User notes folder','paUserNotes',self.app.app,self.setChangedHook,self) + self.paUserNotes:=control + NEW control.createStringInt('Hold access level','intHoldAccess',self.app.app,self.setChangedHook,self) + self.intHoldAccess:=control + NEW control.createString('File Diz Cmd','strFileDizSysCmd',self.app.app,self.setChangedHook,self) + self.strFileDizSysCmd:=control + NEW control.createString('FTP host name','strFtpHost',self.app.app,self.setChangedHook,self) + self.strFtpHost:=control + + NEW control.createString('Execute on new user','strExecOnNewUser',self.app.app,self.setChangedHook,self) + self.strExecOnNewUser:=control + NEW control.createString('Execute async on new user','strExecAOnNewUser',self.app.app,self.setChangedHook,self) + self.strExecAOnNewUser:=control + NEW control.createString('Execute on sysop page','strExecOnPage',self.app.app,self.setChangedHook,self) + self.strExecOnPage:=control + NEW control.createString('Execute async on sysop page','strExecAOnPage',self.app.app,self.setChangedHook,self) + self.strExecAOnPage:=control + NEW control.createString('Execute on connect','strExecOnConnect',self.app.app,self.setChangedHook,self) + self.strExecOnConnect:=control + NEW control.createString('Execute async on connect','strExecAOnConnect',self.app.app,self.setChangedHook,self) + self.strExecAOnConnect:=control + NEW control.createString('Execute on logon','strExecOnLogon',self.app.app,self.setChangedHook,self) + self.strExecOnLogon:=control + NEW control.createString('Execute async on logon','strExecAOnLogon',self.app.app,self.setChangedHook,self) + self.strExecAOnLogon:=control + NEW control.createString('Execute on logoff','strExecOnLogoff',self.app.app,self.setChangedHook,self) + self.strExecOnLogoff:=control + NEW control.createString('Execute async on logoff','strExecAOnLogoff',self.app.app,self.setChangedHook,self) + self.strExecAOnLogoff:=control + NEW control.createString('Execute on comment','strExecOnComment',self.app.app,self.setChangedHook,self) + self.strExecOnComment:=control + NEW control.createString('Execute async on comment','strExecAOnComment',self.app.app,self.setChangedHook,self) + self.strExecAOnComment:=control + NEW control.createString('Execute on upload','strExecOnUpload',self.app.app,self.setChangedHook,self) + self.strExecOnUpload:=control + NEW control.createString('Execute async on upload','strExecAOnUpload',self.app.app,self.setChangedHook,self) + self.strExecAOnUpload:=control + + self.controlList:=[self.strBBSName,self.strBBSLocation,self.strSysopName,self.strRegKey,self.cyNewAccounts,self.strDefaultMenu, + self.paLocalULPath,self.intAutoValPreset,self.intAutoValDelay,self.strAutoValPassword,self.cyLanguage, + self.strSmtpHost,self.intSmtpPort,self.strSmtpUsername,self.strSmtpPassword,self.boolSmtpSSL,self.strSysopEmail, + self.strBbsEmail,self.boolMailOnPage,self.boolMailOnComment,self.boolMailOnLogon,self.boolMailOnLogoff,self.boolMailOnNewUser, + self.boolMailOnUpload,self.boolMailOnPwdFail,self.paLanguageBase,self.paHistory,self.paUserNotes,self.intHoldAccess, + self.strFileDizSysCmd,self.strFtpHost,self.strExecOnNewUser,self.strExecAOnNewUser,self.strExecOnPage,self.strExecAOnPage, + self.strExecOnConnect,self.strExecAOnConnect,self.strExecOnLogon,self.strExecAOnLogon,self.strExecOnLogoff,self.strExecAOnLogoff, + self.strExecOnComment,self.strExecAOnComment,self.strExecOnUpload,self.strExecAOnUpload, + self.boolCreditByKb,self.boolLongWho,self.boolConvertToMb,self.boolQuietJoin,self.boolRelativeConfs] + + //domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`IF control THEN control.addToGroup(self.grpSettings) ELSE FALSE) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + //domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC removeSystemControls() OF frmSettingsEdit + DEF list:PTR TO lh,state,obj + DEF control: PTR TO control + + //domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`IF control THEN self.freeControl(control) ELSE FALSE) + + get(self.grpSettings,MUIA_Group_ChildList,{list}) + state:=list.head + WHILE (obj:=NextObject({state})) + domethod(self.grpSettings,[OM_REMMEMBER,obj]) + Mui_DisposeObject(obj) + ENDWHILE + //domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC addServerControls() OF frmSettingsEdit + DEF control: PTR TO control + DEF list:PTR TO stdlist + DEF sublist:PTR TO control + DEF tempStr[255]:STRING + DEF i + + NEW control.createDirSelect('bBBS Path','paBBSPath',self.app.app,self.setChangedHook,self) + self.paBBSPath:=control + + NEW control.createStringInt('Stack size','intStack',self.app.app,self.setChangedHook,self) + self.intStack:=control + + NEW control.createStringInt('Priority','intPriority',self.app.app,self.setChangedHook,self) + self.intPriority:=control + + NEW control.createCheckBox('Start Iconified','',self.app.app,self.setChangedHook,self) + self.boolIconified:=control + + NEW control.createStringInt('Iconify Left','intIconifyLeft',self.app.app,self.setChangedHook,self) + self.intIconifyLeft:=control + + NEW control.createStringInt('Iconify Top','intIconifyTop',self.app.app,self.setChangedHook,self) + self.intIconifyTop:=control + + NEW control.createCheckBox('Do not move','',self.app.app,self.setChangedHook,self) + self.boolDoNotMove:=control + + NEW control.createCheckBox('Multicom port','',self.app.app,self.setChangedHook,self) + self.boolMulticom:=control + + NEW control.createCheckBox('AE Shell','',self.app.app,self.setChangedHook,self) + self.boolAEShell:=control + + NEW control.createCheckBox('Disable commodity','',self.app.app,self.setChangedHook,self) + self.boolNoCx:=control + + NEW control.createCheckBox('Don''t save state','',self.app.app,self.setChangedHook,self) + self.boolNoSaveState:=control + + NEW control.createStringInt('Telnet Port Number','intTelnetPort',self.app.app,self.setChangedHook,self) + self.intTelnetPort:=control + + NEW control.createStringInt('FTP Port Number','intFtpPort',self.app.app,self.setChangedHook,self) + self.intFtpPort:=control + + NEW control.createString('ACP Font','strAcpFont',self.app.app,self.setChangedHook,self) + self.strAcpFont:=control + + NEW control.createString('Execute on startup','strExecOnStart',self.app.app,self.setChangedHook,self) + self.strExecOnStart:=control + + NEW control.createStringInt('DOS check time','intDosCheckTime',self.app.app,self.setChangedHook,self) + self.intDosCheckTime:=control + + NEW control.createStringInt('DOS ban time','intDosBanTime',self.app.app,self.setChangedHook,self) + self.intDosBanTime:=control + + NEW control.createStringInt('DOS check trigger','intDosCheckTrigger',self.app.app,self.setChangedHook,self) + self.intDosCheckTrig:=control + + NEW list.stdlist(self.nodeCount) + self.nodeLocs:=list + + NEW list.stdlist(self.nodeCount) + self.nodeNames:=list + + NEW list.stdlist(self.nodeCount) + self.nodeSysops:=list + + NEW list.stdlist(15) + self.buttonNames:=list + + NEW list.stdlist(15) + self.buttonCommands:=list + + NEW list.stdlist(15) + self.nuttonNames:=list + + NEW list.stdlist(15) + self.nuttonCommands:=list + + FOR i:=0 TO self.nodeCount-1 + StringF(tempStr,'Node \d Location',i) + NEW control.createString(tempStr,'strNodexLoc',self.app.app,self.setChangedHook,self) + self.nodeLocs.add(control) + StringF(tempStr,'Node \d Name',i) + NEW control.createString(tempStr,'strNodexName',self.app.app,self.setChangedHook,self) + self.nodeNames.add(control) + StringF(tempStr,'Node \d Sysop',i) + NEW control.createString(tempStr,'strNodexSysop',self.app.app,self.setChangedHook,self) + self.nodeSysops.add(control) + ENDFOR + + FOR i:=1 TO 15 + StringF(tempStr,'Button \d Name',i) + NEW control.createString(tempStr,'strButtonxName',self.app.app,self.setChangedHook,self) + self.buttonNames.add(control) + StringF(tempStr,'Button \d Command',i) + NEW control.createString(tempStr,'strButtonxCommand',self.app.app,self.setChangedHook,self) + self.buttonCommands.add(control) + + StringF(tempStr,'Nutton \d Name',i) + NEW control.createString(tempStr,'strNuttonxName',self.app.app,self.setChangedHook,self) + self.nuttonNames.add(control) + StringF(tempStr,'Nutton \d Command',i) + NEW control.createString(tempStr,'strNuttonxCommand',self.app.app,self.setChangedHook,self) + self.nuttonCommands.add(control) + ENDFOR + + self.controlList:=[self.paBBSPath,self.intStack,self.intPriority,self.intTelnetPort,self.intFtpPort, + self.boolIconified,self.intIconifyLeft,self.intIconifyTop,self.strAcpFont,self.strExecOnStart, + self.intDosCheckTime,self.intDosBanTime,self.intDosCheckTrig,self.boolDoNotMove, + self.boolMulticom,self.boolAEShell,self.boolNoCx,self.boolNoSaveState] + + domethod(self.grpSettings,[MUIM_Group_InitChange]) + + sublist:=[self.paBBSPath,self.intStack,self.intPriority,self.intTelnetPort,self.intFtpPort, + self.boolIconified,self.intIconifyLeft,self.intIconifyTop,self.strAcpFont,self.strExecOnStart, + self.intDosCheckTime,self.intDosBanTime,self.intDosCheckTrig] + + ForAll({control},sublist,`control.addToGroup(self.grpSettings)) + + FOR i:=0 TO self.nodeCount-1 + control:=self.nodeLocs.item(i) + control.addToGroup(self.grpSettings) + control:=self.nodeNames.item(i) + control.addToGroup(self.grpSettings) + control:=self.nodeSysops.item(i) + control.addToGroup(self.grpSettings) + ENDFOR + + FOR i:=0 TO 14 + control:=self.buttonNames.item(i) + control.addToGroup(self.grpSettings) + control:=self.buttonCommands.item(i) + control.addToGroup(self.grpSettings) + ENDFOR + + FOR i:=0 TO 14 + control:=self.nuttonNames.item(i) + control.addToGroup(self.grpSettings) + control:=self.nuttonCommands.item(i) + control.addToGroup(self.grpSettings) + ENDFOR + + sublist:=[self.boolDoNotMove,self.boolMulticom,self.boolAEShell,self.boolNoCx,self.boolNoSaveState] + ForAll({control},sublist,`control.addToGroup(self.grpSettings)) + + + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC removeServerControls() OF frmSettingsEdit + DEF list:PTR TO lh,state,obj,i + DEF control: PTR TO control + + domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`self.freeControl(control)) + + FOR i:=0 TO self.nodeCount-1 + control:=self.nodeLocs.item(i) + self.freeControl(control) + control:=self.nodeNames.item(i) + self.freeControl(control) + control:=self.nodeSysops.item(i) + self.freeControl(control) + ENDFOR + + FOR i:=0 TO 14 + control:=self.buttonNames.item(i) + self.freeControl(control) + control:=self.buttonCommands.item(i) + self.freeControl(control) + control:=self.nuttonNames.item(i) + self.freeControl(control) + control:=self.nuttonCommands.item(i) + self.freeControl(control) + ENDFOR + + END self.nodeLocs + END self.nodeNames + END self.nodeSysops + END self.buttonNames + END self.buttonCommands + END self.nuttonNames + END self.nuttonCommands + + get(self.grpSettings,MUIA_Group_ChildList,{list}) + state:=list.head + WHILE (obj:=NextObject({state})) + domethod(self.grpSettings,[OM_REMMEMBER,obj]) + Mui_DisposeObject(obj) + ENDWHILE + domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC addZoomControls() OF frmSettingsEdit + DEF control: PTR TO control + + NEW control.createString('BBS Number','strBbsNumber',self.app.app,self.setChangedHook,self) + self.strBbsNumber:=control + NEW control.createString('BBS Address','strBbsAddress',self.app.app,self.setChangedHook,self) + self.strBbsAddress:=control + NEW control.createString('BBS ID','strBbsId',self.app.app,self.setChangedHook,self) + self.strBbsId:=control + NEW control.createString('QWK Zip command','strQwkZip',self.app.app,self.setChangedHook,self) + self.strQwkZip:=control + NEW control.createString('QWK LHA command','strQwkLha',self.app.app,self.setChangedHook,self) + self.strQwkLha:=control + NEW control.createString('ASCII Zip command','strAscZip',self.app.app,self.setChangedHook,self) + self.strAscZip:=control + NEW control.createString('ASCII LHA command','strAscLha',self.app.app,self.setChangedHook,self) + self.strAscLha:=control + + self.controlList:=[self.strBbsNumber,self.strBbsAddress,self.strBbsId, self.strQwkZip, self.strQwkLha, self.strAscZip, self.strAscLha] + + domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`control.addToGroup(self.grpSettings)) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC removeZoomControls() OF frmSettingsEdit + DEF list:PTR TO lh,state,obj + DEF control: PTR TO control + + domethod(self.grpSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList,`self.freeControl(control)) + + get(self.grpSettings,MUIA_Group_ChildList,{list}) + state:=list.head + WHILE (obj:=NextObject({state})) + domethod(self.grpSettings,[OM_REMMEMBER,obj]) + Mui_DisposeObject(obj) + ENDWHILE + domethod(self.grpSettings,[MUIM_Group_ExitChange]) +ENDPROC + +PROC canClose() OF frmSettingsEdit + MOVE.L (A1),self + GetA4() + IF self.changed + IF self.unsavedChangesWarning()=0 THEN RETURN FALSE + ENDIF +ENDPROC TRUE + +PROC unsavedChangesWarning() OF frmSettingsEdit + DEF win + get(self.winMain,MUIA_Window_Window,{win}) + IF EasyRequestArgs( win , [ 20 , 0 , + 'Unsaved changes' , + 'You have unsaved changes,\nif you continue you will lose them.', + '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE +ENDPROC TRUE + +PROC saveSystemChanges() OF frmSettingsEdit + DEF tempStr[255]:STRING + DEF win + + MOVE.L (A1),self + GetA4() + + get(self.winMain,MUIA_Window_Window,{win}) + + fullTrim(self.strBBSName.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'BBS Name is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + fullTrim(self.strBBSLocation.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'BBS Location is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + fullTrim(self.strSysopName.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'Sysop Name is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + self.sleep() + writeToolType(self.acpName,'BBS_NAME',self.strBBSName.getValue()) + writeToolType(self.acpName,'BBS_GEOGRAPHIC',self.strBBSLocation.getValue()) + writeToolType(self.acpName,'SYSOP_NAME',self.strSysopName.getValue()) + IF self.cyNewAccounts.getValueIndex()=0 THEN writeToolType(self.acpName,'NEW_ACCOUNTS','APPEND') ELSE deleteToolType(self.acpName,'NEW_ACCOUNTS') + writeToolType(self.bbsConfigName,'REGKEY',self.strRegKey.getValue()) + writeToolType(self.bbsConfigName,'DEFAULT_MENUNAME',self.strDefaultMenu.getValue()) + writeToolType(self.bbsConfigName,'LOCAL_UPLOAD_PATH',self.paLocalULPath.getValue()) + writeToolType(self.bbsConfigName,'AUTOVAL_PRESET',self.intAutoValPreset.getValue()) + writeToolType(self.bbsConfigName,'AUTOVAL_DELAY',self.intAutoValDelay.getValue()) + writeToolType(self.acpName,'AUTOVAL_PASSWORD',self.strAutoValPassword.getValue()) + + IF self.cyLanguage + writeToolType(self.languagesConfigName,'HOSTLANGUAGE',self.languages[self.cyLanguage.getValueIndex()]) + ENDIF + + IF self.boolCreditByKb.getValue() THEN writeToolType(self.acpName,'CREDIT_BY_KBYTES') ELSE deleteToolType(self.acpName,'CREDIT_BY_KBYTES') + IF self.boolLongWho.getValue() THEN writeToolType(self.acpName,'LONG_WHO') ELSE deleteToolType(self.acpName,'LONG_WHO') + IF self.boolConvertToMb.getValue() THEN writeToolType(self.bbsConfigName,'CONVERT_TO_MB') ELSE deleteToolType(self.bbsConfigName,'CONVERT_TO_MB') + IF self.boolTimeoutLc.getValueIndex() THEN deleteToolType(self.bbsConfigName,'TIMEOUT_LC') ELSE writeToolType(self.bbsConfigName,'TIMEOUT_LC') + IF self.boolQuietJoin.getValue() THEN writeToolType(self.bbsConfigName,'QUIET_JOIN') ELSE deleteToolType(self.bbsConfigName,'QUIET_JOIN') + IF self.boolRelativeConfs.getValue() THEN writeToolType(self.bbsConfigName,'RELATIVE_CONFERENCES') ELSE deleteToolType(self.bbsConfigName,'RELATIVE_CONFERENCES') + + writeToolType(self.bbsConfigName,'SMTP_HOST',self.strSmtpHost.getValue()) + writeToolType(self.bbsConfigName,'SMTP_PORT',self.intSmtpPort.getValue()) + writeToolType(self.bbsConfigName,'SMTP_USERNAME',self.strSmtpUsername.getValue()) + writeToolType(self.bbsConfigName,'SMTP_PASSWORD',self.strSmtpPassword.getValue()) + IF self.boolSmtpSSL.getValue() THEN writeToolType(self.bbsConfigName,'SMTP_SSL') ELSE deleteToolType(self.bbsConfigName,'SMTP_SSL') + writeToolType(self.bbsConfigName,'SYSOP_EMAIL',self.strSysopEmail.getValue()) + writeToolType(self.bbsConfigName,'BBS_EMAIL',self.strBbsEmail.getValue()) + IF self.boolMailOnPage.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_SYSOP_PAGE') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_SYSOP_PAGE') + IF self.boolMailOnComment.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_SYSOP_COMMENT') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_SYSOP_COMMENT') + IF self.boolMailOnLogon.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_LOGON') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_LOGON') + IF self.boolMailOnLogoff.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_LOGOFF') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_LOGOFF') + IF self.boolMailOnNewUser.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_NEW_USER') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_NEW_USER') + IF self.boolMailOnUpload.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_UPLOAD') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_UPLOAD') + IF self.boolMailOnPwdFail.getValue() THEN writeToolType(self.bbsConfigName,'MAIL_ON_PWD_FAIL') ELSE deleteToolType(self.bbsConfigName,'MAIL_ON_PWD_FAIL') + + writeToolType(self.bbsConfigName,'LANGUAGE_BASE',self.paLanguageBase.getValue()) + writeToolType(self.bbsConfigName,'HISTORY',self.paHistory.getValue()) + writeToolType(self.bbsConfigName,'USERNOTES',self.paUserNotes.getValue()) + writeToolType(self.bbsConfigName,'HOLD_ACCESS_LEVEL',self.intHoldAccess.getValue()) + writeToolType(self.bbsConfigName,'FILEDIZ_SYSCMD',self.strFileDizSysCmd.getValue()) + writeToolType(self.bbsConfigName,'FTPHOST',self.strFtpHost.getValue()) + + writeToolType(self.bbsConfigName,'EXECUTE_ON_NEW_USER',self.strExecOnNewUser.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_NEW_USER',self.strExecAOnNewUser.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_SYSOP_PAGE',self.strExecOnPage.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_SYSOP_PAGE',self.strExecAOnPage.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_CONNECT',self.strExecOnConnect.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_CONNECT_ASYNC',self.strExecAOnConnect.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_LOGON',self.strExecOnLogon.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_LOGON',self.strExecAOnLogon.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_LOGOFF',self.strExecOnLogoff.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_LOGOFF',self.strExecAOnLogoff.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_SYSOP_COMMENT',self.strExecOnComment.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_SYSOP_COMMENT',self.strExecAOnComment.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ON_UPLOAD',self.strExecOnUpload.getValue()) + writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_UPLOAD',self.strExecAOnUpload.getValue()) + saveCachedChanges() + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC saveServerChanges() OF frmSettingsEdit + DEF tempStr[255]:STRING + DEF win,i + DEF control:PTR TO control + DEF toolName[255]:STRING + + MOVE.L (A1),self + GetA4() + + get(self.winMain,MUIA_Window_Window,{win}) + + fullTrim(self.paBBSPath.getValue(),tempStr) + IF EstrLen(tempStr)=0 + EasyRequestArgs( win , [ 20 , 0 , + 'Error' , + 'BBS Path is a mandatory field', + '_OK' ] , NIL , NIL ) + RETURN + ENDIF + + self.sleep() + writeToolType(self.acpName,'BBS_LOCATION',self.paBBSPath.getValue()) + writeToolType(self.acpName,'BBS_STACK',self.intStack.getValue()) + writeToolType(self.acpName,'PRIORITY',self.intPriority.getValue()) + IF self.boolIconified.getValue() THEN writeToolType(self.acpName,'ICONIFIED') ELSE deleteToolType(self.acpName,'ICONIFIED') + writeToolType(self.acpName,'ICONIFY.LEFTEDGE',self.intIconifyLeft.getValue()) + writeToolType(self.acpName,'ICONIFY.TOPEDGE',self.intIconifyTop.getValue()) + IF self.boolDoNotMove.getValue() THEN writeToolType(self.acpName,'SHORT_DONOTMOVE') ELSE deleteToolType(self.acpName,'SHORT_DONOTMOVE') + IF self.boolMulticom.getValue() THEN writeToolType(self.acpName,'MULTICOM_PORT') ELSE deleteToolType(self.acpName,'MULTICOM_PORT') + IF self.boolAEShell.getValue() THEN writeToolType(self.acpName,'AESHELL') ELSE deleteToolType(self.acpName,'AESHELL') + IF self.boolNoCx.getValue() THEN writeToolType(self.acpName,'NO_CX') ELSE deleteToolType(self.acpName,'NO_CX') + IF self.boolNoSaveState.getValue() THEN writeToolType(self.acpName,'NO_SAVESTATE') ELSE deleteToolType(self.acpName,'NO_SAVESTATE') + writeToolType(self.acpName,'TELNETPORT',self.intTelnetPort.getValue()) + writeToolType(self.acpName,'FTPPORT',self.intFtpPort.getValue()) + + writeToolType(self.acpName,'ACPFONT',self.strAcpFont.getValue()) + writeToolType(self.acpName,'EXECUTE_ON_STARTUP_COMPLETE',self.strExecOnStart.getValue()) + writeToolType(self.acpName,'DOSCHECKTIME',self.intDosCheckTime.getValue()) + writeToolType(self.acpName,'DOSBANTIME',self.intDosBanTime.getValue()) + writeToolType(self.acpName,'DOSCHECKTRIGGER',self.intDosCheckTrig.getValue()) + + FOR i:=0 TO self.nodeCount-1 + control:=self.nodeLocs.item(i) + StringF(toolName,'NODE\d_LOCATION',i) + writeToolType(self.acpName,toolName,control.getValue()) + + control:=self.nodeNames.item(i) + StringF(toolName,'NODE\d_NAME',i) + writeToolType(self.acpName,toolName,control.getValue()) + + control:=self.nodeSysops.item(i) + StringF(toolName,'NODE\d_SYSOP',i) + writeToolType(self.acpName,toolName,control.getValue()) + ENDFOR + + FOR i:=0 TO 14 + control:=self.buttonNames.item(i) + StringF(toolName,'BUTTON_NAME.\d',i) + writeToolType(self.acpName,toolName,control.getValue()) + + control:=self.buttonCommands.item(i) + StringF(toolName,'BUTTON_COMMAND.\d',i) + writeToolType(self.acpName,toolName,control.getValue()) + + control:=self.nuttonNames.item(i) + StringF(toolName,'NUTTON_NAME.\d',i) + writeToolType(self.acpName,toolName,control.getValue()) + + control:=self.nuttonCommands.item(i) + StringF(toolName,'NUTTON_COMMAND.\d',i) + writeToolType(self.acpName,toolName,control.getValue()) + ENDFOR + saveCachedChanges() + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC saveZoomChanges() OF frmSettingsEdit + DEF tempStr[255]:STRING + DEF zoomToolType[255]:STRING + + MOVE.L (A1),self + GetA4() + + self.sleep() + + StrCopy(zoomToolType,self.zoomDirPath) + AddPart(zoomToolType,'qwkcfg',255) + writeToolType(zoomToolType,'BBS.NUMBER',self.strBbsNumber.getValue()) + writeToolType(zoomToolType,'BBS.ADDRESS',self.strBbsAddress.getValue()) + writeToolType(zoomToolType,'BBS.ID',self.strBbsId.getValue()) + + StrCopy(zoomToolType,self.zoomDirPath) + AddPart(zoomToolType,'qwkpack',255) + writeToolType(zoomToolType,'ZIP',self.strQwkZip.getValue()) + writeToolType(zoomToolType,'LHA',self.strQwkLha.getValue()) + + StrCopy(zoomToolType,self.zoomDirPath) + AddPart(zoomToolType,'ascpack',255) + writeToolType(zoomToolType,'ZIP',self.strAscZip.getValue()) + writeToolType(zoomToolType,'LHA',self.strAscLha.getValue()) + saveCachedChanges() + + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + self.changed:=FALSE + self.wake() +ENDPROC + +PROC editSystemSettings(acpName:PTR TO CHAR) OF frmSettingsEdit + DEF loop,val,count,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF bbsPath[200]:STRING + DEF languagesTooltype[255]:STRING + DEF languages:PTR TO stringlist + + + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + NEW saveHook + installhook( saveHook, {saveSystemChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.acpName:=acpName + self.bbsConfigName:=String(255) + + readToolType(self.acpName,'BBS_LOCATION',bbsPath) + StringF(self.bbsConfigName,'\sBBSCONFIG',bbsPath) + + StringF(languagesTooltype,'\sLanguages',bbsPath) + NEW languages.stringlist(20) + + loop:=TRUE + count:=0 + WHILE (loop) + StringF(temppath,'LANGUAGE.\d',count+1) + readToolType(languagesTooltype,temppath,tempstr) + IF StrLen(tempstr)>0 + languages.add(tempstr) + count++ + ELSE + loop:=FALSE + ENDIF + ENDWHILE + + self.languages:=List(count+1) + FOR count:=0 TO languages.count()-1 DO ListAddItem(self.languages,languages.item(count)) + ListAddItem(self.languages,0) + + self.languagesConfigName:=languagesTooltype + + installhook( self.setChangedHook, {setChangedFlag}) + self.addSystemControls() + self.addNotifications() + + set( self.winMain, MUIA_Window_Title,'Edit System Settings') + set( self.winMain, MUIA_Window_ID, "FSYS") + + readToolType(self.acpName,'BBS_NAME',tempstr) + self.strBBSName.setValue(tempstr) + + readToolType(self.acpName,'BBS_GEOGRAPHIC',tempstr) + self.strBBSLocation.setValue(tempstr) + + readToolType(self.acpName,'SYSOP_NAME',tempstr) + self.strSysopName.setValue(tempstr) + + readToolType(self.acpName,'NEW_ACCOUNTS',tempstr) + self.cyNewAccounts.setValueIndex(IF StriCmp(tempstr,'APPEND') THEN 0 ELSE 1) + + readToolType(self.bbsConfigName,'REGKEY',tempstr) + self.strRegKey.setValue(tempstr) + + readToolType(self.bbsConfigName,'DEFAULT_MENUNAME',tempstr) + self.strDefaultMenu.setValue(tempstr) + + readToolType(self.bbsConfigName,'LOCAL_UPLOAD_PATH',tempstr) + self.paLocalULPath.setValue(tempstr) + + val:=readToolTypeInt(self.bbsConfigName,'AUTOVAL_PRESET') + self.intAutoValPreset.setValue(val) + + val:=readToolTypeInt(self.bbsConfigName,'AUTOVAL_DELAY') + self.intAutoValDelay.setValue(val) + + readToolType(self.acpName,'AUTOVAL_PASSWORD',tempstr) + self.strAutoValPassword.setValue(tempstr) + + IF languages.count() + readToolType(languagesTooltype,'HOSTLANGUAGE',tempstr) + FOR count:=0 TO languages.count()-1 + IF StriCmp(languages.item(count),tempstr) THEN self.cyLanguage.setValueIndex(count) + ENDFOR + ENDIF + + self.boolCreditByKb.setValue(IF checkToolTypeExists(self.acpName,'CREDIT_BY_KBYTES') THEN MUI_TRUE ELSE FALSE) + self.boolLongWho.setValue(IF checkToolTypeExists(self.acpName,'LONG_WHO') THEN MUI_TRUE ELSE FALSE) + self.boolConvertToMb.setValue(IF checkToolTypeExists(self.bbsConfigName,'CONVERT_TO_MB') THEN MUI_TRUE ELSE FALSE) + self.boolTimeoutLc.setValueIndex(IF checkToolTypeExists(self.bbsConfigName,'TIMEOUT_LC') THEN 0 ELSE 1) + self.boolQuietJoin.setValue(IF checkToolTypeExists(self.bbsConfigName,'QUIET_JOIN') THEN MUI_TRUE ELSE FALSE) + self.boolRelativeConfs.setValue(IF checkToolTypeExists(self.bbsConfigName,'RELATIVE_CONFERENCES') THEN MUI_TRUE ELSE FALSE) + + readToolType(self.bbsConfigName,'SMTP_HOST',tempstr) + self.strSmtpHost.setValue(tempstr) + val:=readToolTypeInt(self.bbsConfigName,'SMTP_PORT') + self.intSmtpPort.setValue(val) + readToolType(self.bbsConfigName,'SMTP_USERNAME',tempstr) + self.strSmtpUsername.setValue(tempstr) + readToolType(self.bbsConfigName,'SMTP_PASSWORD',tempstr) + self.strSmtpPassword.setValue(tempstr) + self.boolSmtpSSL.setValue(IF checkToolTypeExists(self.bbsConfigName,'SMTP_SSL') THEN MUI_TRUE ELSE FALSE) + readToolType(self.bbsConfigName,'SYSOP_EMAIL',tempstr) + self.strSysopEmail.setValue(tempstr) + readToolType(self.bbsConfigName,'BBS_EMAIL',tempstr) + self.strBbsEmail.setValue(tempstr) + self.boolMailOnPage.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_SYSOP_PAGE') THEN MUI_TRUE ELSE FALSE) + self.boolMailOnComment.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_SYSOP_COMMENT') THEN MUI_TRUE ELSE FALSE) + self.boolMailOnLogon.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_LOGON') THEN MUI_TRUE ELSE FALSE) + self.boolMailOnLogoff.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_LOGOFF') THEN MUI_TRUE ELSE FALSE) + self.boolMailOnNewUser.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_NEW_USER') THEN MUI_TRUE ELSE FALSE) + self.boolMailOnUpload.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_UPLOAD') THEN MUI_TRUE ELSE FALSE) + self.boolMailOnPwdFail.setValue(IF checkToolTypeExists(self.bbsConfigName,'MAIL_ON_PWD_FAIL') THEN MUI_TRUE ELSE FALSE) + readToolType(self.bbsConfigName,'LANGUAGE_BASE',tempstr) + self.paLanguageBase.setValue(tempstr) + readToolType(self.bbsConfigName,'HISTORY',tempstr) + self.paHistory.setValue(tempstr) + readToolType(self.bbsConfigName,'USERNOTES',tempstr) + self.paUserNotes.setValue(tempstr) + val:=readToolTypeInt(self.bbsConfigName,'HOLD_ACCESS_LEVEL') + self.intHoldAccess.setValue(val) + readToolType(self.bbsConfigName,'FILEDIZ_SYSCMD',tempstr) + self.strFileDizSysCmd.setValue(tempstr) + readToolType(self.bbsConfigName,'FTPHOST',tempstr) + self.strFtpHost.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_NEW_USER',tempstr) + self.strExecOnNewUser.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_NEW_USER',tempstr) + self.strExecAOnNewUser.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_SYSOP_PAGE',tempstr) + self.strExecOnPage.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_SYSOP_PAGE',tempstr) + self.strExecAOnPage.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_CONNECT',tempstr) + self.strExecOnConnect.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_CONNECT_ASYNC',tempstr) + self.strExecAOnConnect.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_LOGON',tempstr) + self.strExecOnLogon.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_LOGON',tempstr) + self.strExecAOnLogon.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_LOGOFF',tempstr) + self.strExecOnLogoff.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_LOGOFF',tempstr) + self.strExecAOnLogoff.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_SYSOP_COMMENT',tempstr) + self.strExecOnComment.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_SYSOP_COMMENT',tempstr) + self.strExecAOnComment.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ON_UPLOAD',tempstr) + self.strExecOnUpload.setValue(tempstr) + readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_UPLOAD',tempstr) + self.strExecAOnUpload.setValue(tempstr) + + self.changed:=FALSE + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + self.showModal() + + self.removeNotifications() + self.removeSystemControls() + END saveHook + END closeHook + END languages + DisposeLink(self.languages) + DisposeLink(self.bbsConfigName) +ENDPROC + +PROC editServerSettings(acpName:PTR TO CHAR) OF frmSettingsEdit + DEF count,val,i,entry,temppath[255]:STRING,tempstr[255]:STRING + DEF control:PTR TO control + DEF toolName[255]:STRING + + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + NEW saveHook + installhook( saveHook, {saveServerChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.acpName:=acpName + self.nodeCount:=readToolTypeInt(self.acpName,'NODES') + + installhook( self.setChangedHook, {setChangedFlag}) + self.addServerControls() + self.addNotifications() + + set( self.winMain, MUIA_Window_Title,'Edit Server Settings') + set( self.winMain, MUIA_Window_ID, "FSER") + + readToolType(self.acpName,'BBS_LOCATION',tempstr) + self.paBBSPath.setValue(tempstr) + + val:=readToolTypeInt(self.acpName,'BBS_STACK') + self.intStack.setValue(val) + + val:=readToolTypeInt(self.acpName,'PRIORITY') + self.intPriority.setValue(val) + + self.boolIconified.setValue(IF checkToolTypeExists(self.acpName,'ICONIFIED') THEN MUI_TRUE ELSE FALSE) + + val:=readToolTypeInt(self.acpName,'ICONIFY.LEFTEDGE') + self.intIconifyLeft.setValue(val) + + val:=readToolTypeInt(self.acpName,'ICONIFY.TOPEDGE') + self.intIconifyTop.setValue(val) + + self.boolDoNotMove.setValue(IF checkToolTypeExists(self.acpName,'SHORT_DONOTMOVE') THEN MUI_TRUE ELSE FALSE) + self.boolMulticom.setValue(IF checkToolTypeExists(self.acpName,'MULTICOM_PORT') THEN MUI_TRUE ELSE FALSE) + + self.boolAEShell.setValue(IF checkToolTypeExists(self.acpName,'AESHELL') THEN MUI_TRUE ELSE FALSE) + self.boolNoCx.setValue(IF checkToolTypeExists(self.acpName,'NO_CX') THEN MUI_TRUE ELSE FALSE) + self.boolNoSaveState.setValue(IF checkToolTypeExists(self.acpName,'NO_SAVESTATE') THEN MUI_TRUE ELSE FALSE) + + val:=readToolTypeInt(self.acpName,'TELNETPORT') + self.intTelnetPort.setValue(val) + + val:=readToolTypeInt(self.acpName,'FTPPORT') + self.intFtpPort.setValue(val) + + readToolType(self.acpName,'ACPFONT',tempstr) + self.strAcpFont.setValue(tempstr) + + readToolType(self.acpName,'EXECUTE_ON_STARTUP_COMPLETE',tempstr) + self.strExecOnStart.setValue(tempstr) + + val:=readToolTypeInt(self.acpName,'DOSCHECKTIME') + self.intDosCheckTime.setValue(val) + + val:=readToolTypeInt(self.acpName,'DOSBANTIME') + self.intDosBanTime.setValue(val) + + + val:=readToolTypeInt(self.acpName,'DOSCHECKTRIGGER') + self.intDosCheckTrig.setValue(val) + + FOR i:=0 TO self.nodeCount-1 + control:=self.nodeLocs.item(i) + StringF(toolName,'NODE\d_LOCATION',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + + control:=self.nodeNames.item(i) + StringF(toolName,'NODE\d_NAME',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + + control:=self.nodeSysops.item(i) + StringF(toolName,'NODE\d_SYSOP',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + ENDFOR + + FOR i:=0 TO 14 + control:=self.buttonNames.item(i) + StringF(toolName,'BUTTON_NAME.\d',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + + control:=self.buttonCommands.item(i) + StringF(toolName,'BUTTON_COMMAND.\d',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + + control:=self.nuttonNames.item(i) + StringF(toolName,'NUTTON_NAME.\d',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + + control:=self.nuttonCommands.item(i) + StringF(toolName,'NUTTON_COMMAND.\d',i) + readToolType(self.acpName,toolName,tempstr) + control.setValue(tempstr) + ENDFOR + + self.changed:=FALSE + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + self.showModal() + self.removeNotifications() + self.removeServerControls() + END saveHook + END closeHook +ENDPROC + +PROC editZoomSettings(acpName:PTR TO CHAR) OF frmSettingsEdit + DEF count,val,i,entry,temppath[255]:STRING,tempStr[255]:STRING + DEF zoomToolType[255]:STRING + + DEF saveHook:PTR TO hook + DEF closeHook:PTR TO hook + + NEW saveHook + installhook( saveHook, {saveZoomChanges}) + self.saveHook:=saveHook + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + + self.acpName:=acpName + self.zoomDirPath:=String(255) + + installhook( self.setChangedHook, {setChangedFlag}) + self.addZoomControls() + self.addNotifications() + + set( self.winMain, MUIA_Window_Title,'Edit Zoom Settings') + set( self.winMain, MUIA_Window_ID, "FZOM") + + readToolType(self.acpName,'BBS_LOCATION',self.zoomDirPath) + AddPart(self.zoomDirPath,'Zoom',255) + SetStr(self.zoomDirPath) + + StrCopy(zoomToolType,self.zoomDirPath) + AddPart(zoomToolType,'qwkcfg',255) + readToolType(zoomToolType,'BBS.NUMBER',tempStr) + self.strBbsNumber.setValue(tempStr) + + readToolType(zoomToolType,'BBS.ADDRESS',tempStr) + self.strBbsAddress.setValue(tempStr) + readToolType(zoomToolType,'BBS.ID',tempStr) + self.strBbsId.setValue(tempStr) + + StrCopy(zoomToolType,self.zoomDirPath) + AddPart(zoomToolType,'qwkpack',255) + readToolType(zoomToolType,'ZIP',tempStr) + self.strQwkZip.setValue(tempStr) + readToolType(zoomToolType,'LHA',tempStr) + self.strQwkLha.setValue(tempStr) + + StrCopy(zoomToolType,self.zoomDirPath) + AddPart(zoomToolType,'ascpack',255) + readToolType(zoomToolType,'ZIP',tempStr) + self.strAscZip.setValue(tempStr) + readToolType(zoomToolType,'LHA',tempStr) + self.strAscLha.setValue(tempStr) + + self.changed:=FALSE + set( self.btnSave,MUIA_Disabled,MUI_TRUE) + + self.showModal() + self.removeNotifications() + self.removeZoomControls() + END saveHook + END closeHook + DisposeLink(self.zoomDirPath) +ENDPROC diff --git a/axSetupTool/makefile b/axSetupTool/makefile new file mode 100644 index 0000000..ab50bec --- /dev/null +++ b/axSetupTool/makefile @@ -0,0 +1,65 @@ +# Compile axed + +options=DEBUG IGNORECACHE SYM SHOWFNAME ADDBUF 300 +compiler=EVO + +all: axSetupTool + +release: options = IGNORECACHE OPTI SHOWFNAME ADDBUF 300 +release: axSetupTool + +axSetupTool: axSetupTool.e frmMain.m axedit.m + $(compiler) axSetupTool $(options) + +axedit.m: axedit.e + $(compiler) axedit $(options) + +stringlist.m: ../stringlist.e + $(compiler) /stringlist $(options) + +tooltypes.m: tooltypes.e stringlist.m + $(compiler) tooltypes $(options) + +miscfuncs.m: miscfuncs.e + $(compiler) miscfuncs $(options) + +controls.m: controls.e + $(compiler) controls $(options) + +frmBase.m: frmBase.e axedit.m + $(compiler) frmBase $(options) + +frmMain.m: frmMain.e frmBase.m axedit.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m frmAccess.m frmCommands.m + $(compiler) frmMain $(options) + +frmEditList.m: frmEditList.e frmAddItem.m frmBase.m frmAddComplexItem.m tooltypes.m axedit.m stringlist.m miscfuncs.m configobject.m + $(compiler) frmEditList $(options) + +frmSettingsEdit.m: frmSettingsEdit.e frmBase.m tooltypes.m axedit.m controls.m miscfuncs.m stringlist.m + $(compiler) frmSettingsEdit $(options) + +frmPresetsEdit.m: frmPresetsEdit.e frmBase.m tooltypes.m axedit.m controls.m miscfuncs.m stringlist.m + $(compiler) frmPresetsEdit $(options) + +frmAddItem.m: frmAddItem.e frmBase.m axedit.m + $(compiler) frmAddItem $(options) + +frmAddComplexItem.m: frmAddComplexItem.e frmBase.m axedit.m controls.m stringlist.m tooltypes.m configobject.m + $(compiler) frmAddComplexItem $(options) + +frmConfEdit.m: frmConfEdit.e frmBase.m tooltypes.m axedit.m controls.m miscfuncs.m frmAddComplexItem.m configobject.m stringlist.m + $(compiler) frmConfEdit $(options) + +frmNodeEdit.m: frmNodeEdit.e frmBase.m tooltypes.m axedit.m controls.m miscfuncs.m + $(compiler) frmNodeEdit $(options) + +frmAccess.m: frmAccess.e frmBase.m frmPresetsEdit.m axedit.m frmEditList.m + $(compiler) frmAccess $(options) + +frmCommands.m: frmCommands.e frmBase.m axedit.m frmEditList.m stringlist.m tooltypes.m + $(compiler) frmCommands $(options) + +configobject.m: configobject.e stringlist.m + $(compiler) configobject $(options) +clean: + delete axSetupTool axedit.m frmAddItem.m frmBase.m frmMain.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m tooltypes.m controls.m frmAccess.m frmCommands.m miscfuncs.m /stringlist.m configobject.m diff --git a/axSetupTool/miscfuncs.e b/axSetupTool/miscfuncs.e new file mode 100644 index 0000000..0db0ed3 --- /dev/null +++ b/axSetupTool/miscfuncs.e @@ -0,0 +1,39 @@ +OPT MODULE + MODULE 'dos/dos' + +/* trim spaces from both ends of a string and puts it in the destination estring*/ +EXPORT PROC fullTrim(src:PTR TO CHAR,dest:PTR TO CHAR) + DEF n,v=0 + StrCopy(dest,TrimStr(src)) + n:=EstrLen(dest) + IF n>0 THEN v:=dest[n-1] + WHILE (n>0) AND (v=" ") + SetStr(dest,n-1) + n:=EstrLen(dest) + IF n>0 THEN v:=dest[n-1] + ENDWHILE +ENDPROC + +EXPORT PROC makeDir(folderStr) + DEF lock + + lock:=Lock(folderStr,ACCESS_READ) + IF lock=0 + lock:=CreateDir(folderStr) + ENDIF + IF lock THEN UnLock(lock) +ENDPROC + +EXPORT PROC stripInfo(y:PTR TO CHAR) + DEF x,brk=FALSE + + x:=StrLen(y)-1 + WHILE(x>-1) + IF(y[x]=".") + y[x]:=0 + brk:=TRUE + ENDIF + EXIT brk + x-- + ENDWHILE +ENDPROC x diff --git a/axSetupTool/tooltypes.e b/axSetupTool/tooltypes.e new file mode 100644 index 0000000..617184e --- /dev/null +++ b/axSetupTool/tooltypes.e @@ -0,0 +1,439 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'workbench/workbench','icon','*/stringlist','dos/dos' + +DEF diskObjectCache:PTR TO stdlist + +EXPORT OBJECT diskObjectCacheItem + fileName:PTR TO CHAR + diskObject: LONG + originalToolTypes: LONG + ownsToolTypes: CHAR + changed:CHAR +ENDOBJECT + +EXPORT PROC readToolType(toolType,key,outValue) + DEF do: PTR TO diskobject + DEF tooltypes + DEF s: PTR TO CHAR + + s:=NIL + StrCopy(outValue,'') + do:=getOrCreateCacheItem(toolType) + IF (do) + tooltypes:=do.tooltypes + IF tooltypes + IF (s:=FindToolType(tooltypes,key)) THEN StrCopy(outValue,s) + ENDIF + IF diskObjectCache=NIL THEN FreeDiskObject(do) + ENDIF +ENDPROC s<>NIL + +EXPORT PROC readAllToolTypes(toolType,outList:PTR TO stringlist) + DEF do: PTR TO diskobject + DEF tooltypes:PTR TO LONG + DEF count + + outList.clear() + do:=getOrCreateCacheItem(toolType) + IF (do) + tooltypes:=do.tooltypes + IF tooltypes + count:=0 + WHILE tooltypes[count]<>0 + outList.add(tooltypes[count]) + count++ + ENDWHILE + ENDIF + IF diskObjectCache=NIL THEN FreeDiskObject(do) + ENDIF +ENDPROC + +PROC getKeyName(tooltype,outKey) + DEF i=0 + StrCopy(outKey,'') + WHILE i" " THEN StrAddChar(outKey,tooltype[i]) + i++ + ENDWHILE +ENDPROC + +EXPORT PROC writeToolType(toolType,key,newValue=-1,force=FALSE) + DEF do: PTR TO diskobject + DEF oldtooltypes:PTR TO LONG,newToolTypes,count,i + DEF keyName[255]:STRING + DEF newItem[255]:STRING + DEF needToAdd=TRUE + DEF item + DEF s + DEF cacheObj:PTR TO diskObjectCacheItem + + + IF newValue=-1 + StringF(newItem,'\s',key) + newValue:='' + ELSEIF newValue + IF StrLen(newValue)=0 + deleteToolType(toolType,key) + RETURN + ENDIF + StringF(newItem,'\s=\s',key,newValue) + ELSEIF force=FALSE + deleteToolType(toolType,key) + RETURN + ENDIF + + do,cacheObj:=getOrCreateCacheItem(toolType,TRUE) + IF (do) + oldtooltypes:=do.tooltypes + IF oldtooltypes + IF (s:=FindToolType(oldtooltypes,key)) ANDALSO StrCmp(s,newValue) + //no changes so no need to save + RETURN + ENDIF + ENDIF + WriteF('update tooltype \s \s = \s\n',toolType,key,newValue) + + count:=0 + IF oldtooltypes + WHILE oldtooltypes[count]<>0 + count++ + ENDWHILE + ENDIF + + IF (cacheObj.originalToolTypes=oldtooltypes) + newToolTypes:=List(count+27) + + FOR i:=0 TO count-1 + ListAddItem(newToolTypes,AstrClone(oldtooltypes[i],255)) + ENDFOR + ListAddItem(newToolTypes,0) + oldtooltypes:=newToolTypes + ENDIF + + IF ListLen(oldtooltypes)=ListMax(oldtooltypes) + newToolTypes:=List(count+27) + FOR i:=0 TO count-1 + ListAddItem(newToolTypes,AstrClone(oldtooltypes[i],255)) + DisposeLink(oldtooltypes[i]) + ENDFOR + ListAdd(newToolTypes,[NIL]) + DisposeLink(oldtooltypes) + oldtooltypes:=newToolTypes + ENDIF + + FOR i:=0 TO count-1 + getKeyName(oldtooltypes[i],keyName) + IF StriCmp(keyName,key) + StrCopy(oldtooltypes[i],newItem) + cacheObj.changed:=TRUE + needToAdd:=FALSE + ENDIF + ENDFOR + IF needToAdd + WriteF('added \s\n',newItem) + cacheObj.changed:=TRUE + oldtooltypes[count]:=StrClone(newItem) + ListAddItem(oldtooltypes,0) + ENDIF + do.tooltypes:=oldtooltypes + ENDIF +ENDPROC + +EXPORT PROC deleteToolType(toolType,key) + DEF do: PTR TO diskobject + DEF oldtooltypes:PTR TO LONG,newToolTypes + DEF keyName[255]:STRING + DEF count,i,changed=FALSE,n + DEF cacheObj:PTR TO diskObjectCacheItem + + do,cacheObj:=getOrCreateCacheItem(toolType) + IF (do) + oldtooltypes:=do.tooltypes + + IF(FindToolType(oldtooltypes,key))=FALSE THEN RETURN + + count:=0 + IF oldtooltypes + WHILE oldtooltypes[count]<>0 + count++ + ENDWHILE + ENDIF + + IF (cacheObj.originalToolTypes=oldtooltypes) + newToolTypes:=List(count+27) + FOR i:=0 TO count-1 + ListAddItem(newToolTypes,AstrClone(oldtooltypes[i],255)) + ENDFOR + ListAdd(newToolTypes,[NIL]) + oldtooltypes:=newToolTypes + ENDIF + + n:=0 + FOR i:=0 TO count-1 + getKeyName(oldtooltypes[i],keyName) + IF StriCmp(keyName,key)=FALSE + IF i<>n THEN StrCopy(oldtooltypes[n],oldtooltypes[i]) + n++ + ELSE + changed:=TRUE + cacheObj.changed:=TRUE + ENDIF + ENDFOR + FOR i:=n TO count-1 + DisposeLink(oldtooltypes[i]) + oldtooltypes[i]:=NIL + ENDFOR + SetList(oldtooltypes,n+1) + do.tooltypes:=oldtooltypes + + IF changed + WriteF('delete tooltype \s \s\n',toolType,key) + ENDIF + ENDIF +ENDPROC + + +EXPORT PROC readToolTypeInt(toolType,key) + DEF value[255]:STRING + IF readToolType(toolType,key,value) + RETURN Val(value) + ENDIF +ENDPROC -1 + +EXPORT PROC checkToolTypeExists(toolType,key) + DEF nodeFile[255]:STRING + DEF do: diskobject + DEF tooltypes + DEF s: PTR TO CHAR + DEF result=FALSE + + s:=NIL + + do:=getOrCreateCacheItem(toolType) + IF (do) + tooltypes:=do.tooltypes + IF tooltypes + IF(s:=FindToolType(tooltypes,key)) THEN result:=TRUE + ENDIF + IF diskObjectCache=NIL THEN FreeDiskObject(do) + ENDIF +ENDPROC result + +EXPORT PROC initialiseCache() + diskObjectCache:=NEW diskObjectCache.stdlist(100) +ENDPROC + +EXPORT PROC deInitialiseCache() + END diskObjectCache +ENDPROC + +PROC freeCacheItem(cacheObj:PTR TO diskObjectCacheItem) + DEF newtooltypes:PTR TO LONG + DEF do:PTR TO diskobject + DEF item:PTR TO LONG + DEF mem,i + + IF cacheObj.changed + WriteF('saving file and freeing \s\n',cacheObj.fileName) + PutDiskObject(cacheObj.fileName,cacheObj.diskObject) + ENDIF + + do:=cacheObj.diskObject + IF do + IF do.tooltypes<>cacheObj.originalToolTypes + newtooltypes:=do.tooltypes + FOR i:=0 TO ListLen(newtooltypes)-1 + IF newtooltypes[i] THEN DisposeLink(newtooltypes[i]) + ENDFOR + DisposeLink(newtooltypes) + do.tooltypes:=cacheObj.originalToolTypes + ENDIF + + IF cacheObj.ownsToolTypes + IF do.tooltypes + mem:=do.tooltypes[0] -> release the file buffer (first s.tring pointer points to start of buffer) + Dispose(mem) + DisposeLink(do.tooltypes) ->our tooltypes is a list that needs to be freed + ENDIF + ENDIF + + DisposeLink(cacheObj.fileName) + FreeDiskObject(do) + ENDIF + END cacheObj + +ENDPROC + +PROC getOrCreateCacheItem(fileName:PTR TO CHAR,getDef=FALSE) + DEF i,cnt,found=FALSE + DEF cacheObj: PTR TO diskObjectCacheItem + DEF oldCacheObj: PTR TO diskObjectCacheItem + DEF do=NIL:PTR TO diskobject + DEF fn2[255]:STRING + DEF ownToolTypes + DEF toolTypes:PTR TO LONG + DEF fh,fileBuf,off,lineCount,len,item + DEF newValues:PTR TO stringlist + + IF diskObjectCache<>NIL + cnt:=diskObjectCache.count() + + i:=0 + WHILE (iLRU algorithm, move most recently used to end of list + i++ + WHILE i=0 + StringF(fn2,'\s.cfg',fileName) + IF FileLength(fn2)>=0 + do:=GetDefDiskObject(WBPROJECT) + ENDIF + ELSE + do:=GetDefDiskObject(WBPROJECT) + ENDIF + IF do<>NIL + fileBuf:=New(FileLength(fn2)+1) ->allow an extra char in case file does not end in LF + + fh:=Open(fn2,MODE_OLDFILE) + IF fh<>0 + off:=0 + lineCount:=0 + WHILE(ReadStr(fh,fn2)<>-1) OR (StrLen(fn2)>0) + len:=0 + WHILE (fn2[len]<>0) AND (fn2[len]<>";") + len++ + ENDWHILE + + ->trim trailing space + WHILE (fn2[len-1]<=32) AND (len>0) + len-- + EXIT len=0 ->this is just here to prevent the fn2[len-1] causing a buffer underrun in the absence of short circuit evaluation + ENDWHILE + SetStr(fn2,len) + + AstrCopy(fileBuf+off,fn2,len+1) + lineCount++ + off:=off+len+1 + ENDWHILE + + toolTypes:=List(lineCount+1) + off:=0 + FOR i:=1 TO lineCount + ListAddItem(toolTypes,fileBuf+off) + off:=off+StrLen(fileBuf+off)+1 + ENDFOR + ListAdd(toolTypes,[NIL]) + do.tooltypes:=toolTypes + ownToolTypes:=TRUE + Close(fh) + ELSE + Dispose(fileBuf) + FreeDiskObject(do) + do:=NIL + ENDIF + ENDIF + ENDIF + + IF (do=NIL) + IF (getDef) + do:=GetDefDiskObject(WBPROJECT) + WriteF('create new disk obj\n') + ELSE + RETURN 0,0 + ENDIF + ENDIF + + IF diskObjectCache<>NIL + NEW cacheObj + + cacheObj.fileName:=String(StrLen(fileName)) + cacheObj.ownsToolTypes:=ownToolTypes + IF do + cacheObj.originalToolTypes:=do.tooltypes + ELSE + cacheObj.originalToolTypes:=0 + ENDIF + StrCopy(cacheObj.fileName,fileName) + cacheObj.diskObject:=do + + IF diskObjectCache.count()<(diskObjectCache.maxSize()-1) + diskObjectCache.add(cacheObj) + ELSE + freeCacheItem(diskObjectCache.item(0)) + diskObjectCache.remove(0) + diskObjectCache.add(cacheObj) + ENDIF + item:=diskObjectCache.item(diskObjectCache.count()-1) + ENDIF + ENDIF +ENDPROC do,item + +EXPORT PROC clearDiskObjectCache() + DEF cacheObj: PTR TO diskObjectCacheItem + DEF i, do: PTR TO diskobject + DEF mem + + IF diskObjectCache=NIL THEN RETURN + FOR i:=0 TO diskObjectCache.count()-1 + IF (cacheObj:=diskObjectCache.item(i)) + freeCacheItem(cacheObj) + ENDIF + ENDFOR + diskObjectCache.clear() +ENDPROC + +EXPORT PROC deleteFileFromCache(filename:PTR TO CHAR) + DEF cacheObj: PTR TO diskObjectCacheItem + DEF i + + IF diskObjectCache=NIL THEN RETURN + + FOR i:=diskObjectCache.count()-1 TO 0 STEP -1 + cacheObj:=diskObjectCache.item(i) + IF StriCmp(filename,cacheObj.fileName) + freeCacheItem(cacheObj) + diskObjectCache.remove(i) + ENDIF + ENDFOR +ENDPROC + +EXPORT PROC saveCachedChanges() + DEF cacheObj: PTR TO diskObjectCacheItem + DEF i + + IF diskObjectCache=NIL THEN RETURN + FOR i:=0 TO diskObjectCache.count()-1 + cacheObj:=diskObjectCache.item(i) + IF cacheObj.changed + WriteF('saving file \s\n',cacheObj.fileName) + PutDiskObject(cacheObj.fileName,cacheObj.diskObject) + cacheObj.changed:=FALSE + ENDIF + ENDFOR +ENDPROC + From 70bbe692cfe804d383ce17f04019bf7adfa360d8 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Wed, 16 Aug 2023 14:32:35 +0100 Subject: [PATCH 09/47] setup tool: 1) initial setup for help text messages 2) fix couple of bad variable declarations --- axSetupTool/axSetupTool.e | 14 ++- axSetupTool/controls.e | 36 ++++-- axSetupTool/frmAddComplexItem.e | 100 +++++++-------- axSetupTool/frmCommands.e | 4 +- axSetupTool/frmConfEdit.e | 52 ++++---- axSetupTool/frmNodeEdit.e | 212 ++++++++++++++++---------------- axSetupTool/frmPresetsEdit.e | 18 +-- axSetupTool/frmSettingsEdit.e | 168 ++++++++++++------------- axSetupTool/helpText.e | 73 +++++++++++ axSetupTool/makefile | 19 +-- axSetupTool/tooltypes.e | 2 +- 11 files changed, 402 insertions(+), 296 deletions(-) create mode 100644 axSetupTool/helpText.e diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index 7abc5e0..710df11 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -1,4 +1,4 @@ -OPT OSVERSION = 37,STACK=60000 +OPT OSVERSION = 37,STACK=60000,LARGE OPT PREPROCESS /* @@ -22,7 +22,7 @@ MODULE 'utility/tagitem' MODULE 'tools/boopsi' MODULE 'icon' -MODULE '*frmMain','*axedit' +MODULE '*frmMain','*axedit','*helpText' PROC main() HANDLE DEF frmMain: PTR TO frmMain @@ -32,6 +32,8 @@ PROC main() HANDLE NEW app.create(NIL) + helpTextInitialise() + NEW frmMain.create(app) frmMain.domain() @@ -39,6 +41,12 @@ EXCEPT DO SELECT exception + CASE "HLP" + SELECT exceptioninfo + CASE "LIST" + error_simple( 'error: Increase help text list size' ) + ENDSELECT + CASE "LIB" SELECT exceptioninfo @@ -88,6 +96,8 @@ EXCEPT DO app.dispose() END app END frmMain + helpTextDeinitialise() + IF iconbase THEN CloseLibrary( iconbase ) IF muimasterbase THEN CloseLibrary( muimasterbase ) ENDPROC diff --git a/axSetupTool/controls.e b/axSetupTool/controls.e index 9680637..f1fd649 100644 --- a/axSetupTool/controls.e +++ b/axSetupTool/controls.e @@ -1,6 +1,7 @@ OPT MODULE MODULE 'muimaster','libraries/mui','tools/boopsi','intuition/classusr','utility/hooks','tools/installhook','libraries/asl' +MODULE '*helpText' EXPORT ENUM TYPE_STRING,TYPE_INT,TYPE_CYCLE,TYPE_CHECKBOX,TYPE_DIRSELECT,TYPE_FILESELECT,TYPE_MODESELECT EXPORT OBJECT control @@ -24,7 +25,10 @@ PROC makeLabel(caption,helpText) OF control End ENDPROC lbl -EXPORT PROC createString(labelCaption,helpText,app,changeHook, window) OF control +EXPORT PROC createString(labelCaption,helpTextId,app,changeHook, window) OF control + DEF helpText + + helpText:=getHelpText(helpTextId) self.hook:=0 self.hook2:=0 self.muiLabel:=self.makeLabel(labelCaption,helpText) @@ -44,7 +48,10 @@ EXPORT PROC createString(labelCaption,helpText,app,changeHook, window) OF contro self.type:=TYPE_STRING ENDPROC -EXPORT PROC createStringInt(labelCaption,helpText,app,changeHook, window) OF control +EXPORT PROC createStringInt(labelCaption,helpTextId,app,changeHook, window) OF control + DEF helpText + + helpText:=getHelpText(helpTextId) self.hook:=0 self.hook2:=0 self.muiLabel:=self.makeLabel(labelCaption,helpText) @@ -64,7 +71,10 @@ EXPORT PROC createStringInt(labelCaption,helpText,app,changeHook, window) OF con self.type:=TYPE_INT ENDPROC -EXPORT PROC createCycle(labelCaption,helpText,values,app,changeHook, window) OF control +EXPORT PROC createCycle(labelCaption,helpTextId,values,app,changeHook, window) OF control + DEF helpText + + helpText:=getHelpText(helpTextId) self.hook:=0 self.hook2:=0 self.muiLabel:=self.makeLabel(labelCaption,helpText) @@ -85,7 +95,10 @@ EXPORT PROC createCycle(labelCaption,helpText,values,app,changeHook, window) OF self.type:=TYPE_CYCLE ENDPROC -EXPORT PROC createCheckBox(labelCaption,helpText,app,changeHook, window) OF control +EXPORT PROC createCheckBox(labelCaption,helpTextId,app,changeHook, window) OF control + DEF helpText + + helpText:=getHelpText(helpTextId) self.hook:=0 self.hook2:=0 self.muiLabel:=self.makeLabel(labelCaption,helpText) @@ -119,8 +132,11 @@ PROC setaslflags() OF control ENDPROC TRUE -EXPORT PROC createDirSelect(labelCaption,helpText,app,changeHook, window) OF control +EXPORT PROC createDirSelect(labelCaption,helpTextId,app,changeHook, window) OF control DEF hook:PTR TO hook + DEF helpText + + helpText:=getHelpText(helpTextId) self.muiLabel:=self.makeLabel(labelCaption,helpText) self.group:=NIL NEW hook @@ -146,7 +162,10 @@ EXPORT PROC createDirSelect(labelCaption,helpText,app,changeHook, window) OF con self.type:=TYPE_DIRSELECT ENDPROC -EXPORT PROC createFileSelect(labelCaption,helpText,app,changeHook, window) OF control +EXPORT PROC createFileSelect(labelCaption,helpTextId,app,changeHook, window) OF control + DEF helpText + + helpText:=getHelpText(helpTextId) self.hook:=0 self.hook2:=0 self.muiLabel:=self.makeLabel(labelCaption,helpText) @@ -202,8 +221,11 @@ PROC getmodeid() OF control set(control,MUIA_String_Contents,str) ENDPROC -EXPORT PROC createModeSelect(labelCaption,helpText,app,changeHook, window) OF control +EXPORT PROC createModeSelect(labelCaption,helpTextId,app,changeHook, window) OF control DEF hook:PTR TO hook + DEF helpText + + helpText:=getHelpText(helpTextId) NEW hook self.hook:=hook NEW hook diff --git a/axSetupTool/frmAddComplexItem.e b/axSetupTool/frmAddComplexItem.e index af3f62b..7b8a2fa 100644 --- a/axSetupTool/frmAddComplexItem.e +++ b/axSetupTool/frmAddComplexItem.e @@ -4,7 +4,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui' MODULE 'tools/boopsi','dos/dos','libraries/asl' MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' -MODULE '*axedit','*frmBase','*controls','*/stringlist','*tooltypes','*configobject' +MODULE '*axedit','*frmBase','*controls','*/stringlist','*tooltypes','*configobject','*helpText' EXPORT OBJECT frmAddComplexItem OF frmBase lblAreaName: LONG @@ -179,7 +179,7 @@ PROC editArea(acpName,areaName,oldArea:PTR TO area, existingAreas:PTR TO stdlist StringF(tempStr,'NAME.\d',i) readToolType(self.confConfig,tempStr,confName) - NEW control.createCheckBox(confName,'',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox(confName,ACCESS_AREA_NAME,self.app.app,self.setChangedHook,self) self.confControls.add(control) control.addToGroup(self.grpAreaSettings) @@ -281,9 +281,9 @@ PROC editAccess(acpName,accessName,oldAccessLevel:PTR TO accessLevel, existingAc FOR i:=0 TO ListLen(acsValues)-1 IF i=0 - NEW control.createStringInt(acsNames[i],'',self.app.app,self.setChangedHook,self) + NEW control.createStringInt(acsNames[i],ACCESS_NAME_MAX_PAGES,self.app.app,self.setChangedHook,self) ELSE - NEW control.createCheckBox(acsNames[i],'',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox(acsNames[i],ACCESS_NAME,self.app.app,self.setChangedHook,self) ENDIF accessControls.add(control) accessControlCodes.add(acsValues[i]) @@ -402,39 +402,39 @@ PROC editFileCheck(acpName,fCheckName,oldfCheck:PTR TO fChecker,existingFchecker newfChecker:=0 - NEW controlChecker.createString('Checker','',self.app.app,self.setChangedHook,self) + NEW controlChecker.createString('Checker',CHECKER_NAME,self.app.app,self.setChangedHook,self) fCheckControls.add(controlChecker) - NEW controlError1.createString('Error 1','',self.app.app,self.setChangedHook,self) + NEW controlError1.createString('Error 1',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError1) - NEW controlError2.createString('Error 2','',self.app.app,self.setChangedHook,self) + NEW controlError2.createString('Error 2',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError2) - NEW controlError3.createString('Error 3','',self.app.app,self.setChangedHook,self) + NEW controlError3.createString('Error 3',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError3) - NEW controlError4.createString('Error 4','',self.app.app,self.setChangedHook,self) + NEW controlError4.createString('Error 4',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError4) - NEW controlError5.createString('Error 5','',self.app.app,self.setChangedHook,self) + NEW controlError5.createString('Error 5',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError5) - NEW controlError6.createString('Error 6','',self.app.app,self.setChangedHook,self) + NEW controlError6.createString('Error 6',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError6) - NEW controlError7.createString('Error 7','',self.app.app,self.setChangedHook,self) + NEW controlError7.createString('Error 7',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError7) - NEW controlError8.createString('Error 8','',self.app.app,self.setChangedHook,self) + NEW controlError8.createString('Error 8',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError8) - NEW controlError9.createString('Error 9','',self.app.app,self.setChangedHook,self) + NEW controlError9.createString('Error 9',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError9) - NEW controlError10.createString('Error 10','',self.app.app,self.setChangedHook,self) + NEW controlError10.createString('Error 10',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError10) - NEW controlOptions.createString('Options','',self.app.app,self.setChangedHook,self) + NEW controlOptions.createString('Options',CHECKER_OPTIONS,self.app.app,self.setChangedHook,self) fCheckControls.add(controlOptions) - NEW controlPriority.createStringInt('Priority','',self.app.app,self.setChangedHook,self) + NEW controlPriority.createStringInt('Priority',CHECKER_PRIORITY,self.app.app,self.setChangedHook,self) fCheckControls.add(controlPriority) - NEW controlScript.createString('Script','',self.app.app,self.setChangedHook,self) + NEW controlScript.createString('Script',CHECKER_SCRIPT,self.app.app,self.setChangedHook,self) fCheckControls.add(controlScript) - NEW controlStack.createStringInt('Stack','',self.app.app,self.setChangedHook,self) + NEW controlStack.createStringInt('Stack',CHECKER_STACK,self.app.app,self.setChangedHook,self) fCheckControls.add(controlStack) FOR i:=0 TO fCheckControls.count()-1 @@ -561,19 +561,19 @@ PROC editProtocol(acpName,protocolName,oldProtocol:PTR TO protocol,existingProto newProtocol:=0 - NEW controlOptions.createString('Options','',self.app.app,self.setChangedHook,self) + NEW controlOptions.createString('Options',PROTOCOL_OPTIONS,self.app.app,self.setChangedHook,self) protocolControls.add(controlOptions) - NEW controlRxWindow.createStringInt('Hydra Rx Window','',self.app.app,self.setChangedHook,self) + NEW controlRxWindow.createStringInt('Hydra Rx Window',HYDRA_RX_WINDOW,self.app.app,self.setChangedHook,self) protocolControls.add(controlRxWindow) - NEW controlTxWindow.createStringInt('Hydra Tx Window','',self.app.app,self.setChangedHook,self) + NEW controlTxWindow.createStringInt('Hydra Tx Window',HYDRA_TX_WINDOW,self.app.app,self.setChangedHook,self) protocolControls.add(controlTxWindow) - NEW controlHttpHost.createString('Http Host','',self.app.app,self.setChangedHook,self) + NEW controlHttpHost.createString('Http Host',HTTP_HOSTNAME,self.app.app,self.setChangedHook,self) protocolControls.add(controlHttpHost) - NEW controlHttpTemp.createDirSelect('Http TempDir','',self.app.app,self.setChangedHook,self) + NEW controlHttpTemp.createDirSelect('Http TempDir',HTTP_TEMPDIR,self.app.app,self.setChangedHook,self) protocolControls.add(controlHttpTemp) - NEW controlFtpHost.createString('Ftp Host','',self.app.app,self.setChangedHook,self) + NEW controlFtpHost.createString('Ftp Host',FTP_HOSTNAME,self.app.app,self.setChangedHook,self) protocolControls.add(controlFtpHost) - NEW controlFtpAuth.createCheckBox('Ftp Authentication','',self.app.app,self.setChangedHook,self) + NEW controlFtpAuth.createCheckBox('Ftp Authentication',FTP_AUTH,self.app.app,self.setChangedHook,self) protocolControls.add(controlFtpAuth) FOR i:=0 TO protocolControls.count()-1 @@ -703,44 +703,44 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi installhook( self.setChangedHook, {setChangedFlag}) - NEW controlName.createString('Name','',self.app.app,self.setChangedHook,self) + NEW controlName.createString('Name',COMMAND_NAME,self.app.app,self.setChangedHook,self) commandControls.add(controlName) - NEW controlLocation.createString('Location','',self.app.app,self.setChangedHook,self) + NEW controlLocation.createString('Location',COMMAND_LOCATION,self.app.app,self.setChangedHook,self) commandControls.add(controlLocation) - NEW controlAccess.createStringInt('Access','',self.app.app,self.setChangedHook,self) + NEW controlAccess.createStringInt('Access',COMMAND_ACCESS,self.app.app,self.setChangedHook,self) commandControls.add(controlAccess) - NEW controlInternal.createString('Internal','',self.app.app,self.setChangedHook,self) + NEW controlInternal.createString('Internal',COMMAND_INTERNAL,self.app.app,self.setChangedHook,self) commandControls.add(controlInternal) - NEW controlMimicVer.createString('Mimic Version','',self.app.app,self.setChangedHook,self) + NEW controlMimicVer.createString('Mimic Version',COMMAND_MIMIC_VER,self.app.app,self.setChangedHook,self) commandControls.add(controlMimicVer) - NEW controlPassword.createString('Password','',self.app.app,self.setChangedHook,self) + NEW controlPassword.createString('Password',COMMAND_PASSWORD,self.app.app,self.setChangedHook,self) commandControls.add(controlPassword) - NEW controlPassParams.createCycle('Pass Params','',['N/A','No execute','Swap and retain','Swap, retain and redo','Bypass BBSCMD',0],self.app.app,self.setChangedHook,self) + NEW controlPassParams.createCycle('Pass Params',COMMAND_PASS_PARAMS,['N/A','No execute','Swap and retain','Swap, retain and redo','Bypass BBSCMD',0],self.app.app,self.setChangedHook,self) commandControls.add(controlPassParams) - NEW controlPriority.createStringInt('Priority','',self.app.app,self.setChangedHook,self) + NEW controlPriority.createStringInt('Priority',COMMAND_PRIORITY,self.app.app,self.setChangedHook,self) commandControls.add(controlPriority) - NEW controlStack.createStringInt('Stack','',self.app.app,self.setChangedHook,self) + NEW controlStack.createStringInt('Stack',COMMAND_STACK,self.app.app,self.setChangedHook,self) commandControls.add(controlStack) - NEW controlType.createCycle('Type','',typeList,self.app.app,self.setChangedHook,self) + NEW controlType.createCycle('Type',COMMAND_TYPE,typeList,self.app.app,self.setChangedHook,self) commandControls.add(controlType) - NEW controlBanner.createString('Banner','',self.app.app,self.setChangedHook,self) + NEW controlBanner.createString('Banner',COMMAND_BANNER,self.app.app,self.setChangedHook,self) commandControls.add(controlBanner) - NEW controlResident.createCheckBox('Resident','',self.app.app,self.setChangedHook,self) + NEW controlResident.createCheckBox('Resident',COMMAND_RESIDENT,self.app.app,self.setChangedHook,self) commandControls.add(controlResident) - NEW controlQuickMode.createCheckBox('Quick Mode','',self.app.app,self.setChangedHook,self) + NEW controlQuickMode.createCheckBox('Quick Mode',COMMAND_QUICK_MODE,self.app.app,self.setChangedHook,self) commandControls.add(controlQuickMode) - NEW controlTrapon.createCheckBox('Trap On','',self.app.app,self.setChangedHook,self) + NEW controlTrapon.createCheckBox('Trap On',COMMAND_TRAP_ON,self.app.app,self.setChangedHook,self) commandControls.add(controlTrapon) - NEW controlExpertMode.createCheckBox('Expert mode','',self.app.app,self.setChangedHook,self) + NEW controlExpertMode.createCheckBox('Expert mode',COMMAND_EXPERT_MODE,self.app.app,self.setChangedHook,self) commandControls.add(controlExpertMode) - NEW controlDoorSilent.createCheckBox('Silent','',self.app.app,self.setChangedHook,self) + NEW controlDoorSilent.createCheckBox('Silent',COMMAND_SILENT,self.app.app,self.setChangedHook,self) commandControls.add(controlDoorSilent) - NEW controlLogInputs.createCheckBox('Log Inputs','',self.app.app,self.setChangedHook,self) + NEW controlLogInputs.createCheckBox('Log Inputs',COMMAND_LOG_INPUTS,self.app.app,self.setChangedHook,self) commandControls.add(controlLogInputs) - NEW controlScriptCheck.createCheckBox('Script Check','',self.app.app,self.setChangedHook,self) + NEW controlScriptCheck.createCheckBox('Script Check',COMMAND_SCRIPT_CHECK,self.app.app,self.setChangedHook,self) commandControls.add(controlScriptCheck) - NEW controlMultiNode.createCheckBox('Multinode','',self.app.app,self.setChangedHook,self) + NEW controlMultiNode.createCheckBox('Multinode',COMMAND_MULTINODE,self.app.app,self.setChangedHook,self) commandControls.add(controlMultiNode) FOR i:=0 TO commandControls.count()-1 @@ -873,15 +873,15 @@ PROC editMsgbase(acpName,msgbaseName,oldMsgbase:PTR TO msgbase) OF frmAddComplex newMsgbase:=0 - NEW controlMsgbaseLocation.createDirSelect('Location','',self.app.app,self.setChangedHook,self) + NEW controlMsgbaseLocation.createDirSelect('Location',MSGBASE_LOCATION,self.app.app,self.setChangedHook,self) msgbaseControls.add(controlMsgbaseLocation) - NEW controlExtSend.createCheckBox('Send External','',self.app.app,self.setChangedHook,self) + NEW controlExtSend.createCheckBox('Send External',MSGBASE_SEND_EXTERNAL,self.app.app,self.setChangedHook,self) msgbaseControls.add(controlExtSend) - NEW controlUserNames.createCheckBox('Uses Usernames','',self.app.app,self.setChangedHook,self) + NEW controlUserNames.createCheckBox('Uses Usernames',MSGBASE_USES_USERNAMES,self.app.app,self.setChangedHook,self) msgbaseControls.add(controlUserNames) - NEW controlRealNames.createCheckBox('Uses real names','',self.app.app,self.setChangedHook,self) + NEW controlRealNames.createCheckBox('Uses real names',MSGBASE_USES_REALNAMES,self.app.app,self.setChangedHook,self) msgbaseControls.add(controlRealNames) - NEW controlInternetNames.createCheckBox('Uses internet names','',self.app.app,self.setChangedHook,self) + NEW controlInternetNames.createCheckBox('Uses internet names',MSGBASE_USES_INETNAMES,self.app.app,self.setChangedHook,self) msgbaseControls.add(controlInternetNames) FOR i:=0 TO msgbaseControls.count()-1 diff --git a/axSetupTool/frmCommands.e b/axSetupTool/frmCommands.e index f9e752f..8c768b5 100644 --- a/axSetupTool/frmCommands.e +++ b/axSetupTool/frmCommands.e @@ -96,11 +96,11 @@ ENDPROC PROC editCommands(acpConfigName:PTR TO CHAR) OF frmCommands DEF nodeCount,confCount,i - DEF btn:PTR TO LONG DEF btnText[255]:STRING - DEF btnList:stdlist DEF bbsPath[255]:STRING DEF confConfig[255]:STRING + DEF btn:PTR TO LONG + DEF btnList:PTR TO stdlist self.acpConfigName:=acpConfigName set(self.app.grpCommands, MUIA_Group_Columns , 3) diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index 1fafcfc..381e0a4 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -4,7 +4,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui','dos' MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' -MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*frmAddComplexItem','*configObject','*/stringlist' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*frmAddComplexItem','*configObject','*/stringlist','*helpText' EXPORT OBJECT frmConfEdit OF frmBase confConfig : PTR TO CHAR @@ -519,70 +519,70 @@ ENDPROC PROC addControls() OF frmConfEdit DEF control: PTR TO control - NEW control.createString('bConference Name','strConfName2',self.app.app,self.setChangedHook,self) + NEW control.createString('bConference Name',CONF_NAME,self.app.app,self.setChangedHook,self) self.strConfName2:=control - NEW control.createDirSelect('bConference Path','paConfPath',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('bConference Path',CONF_PATH,self.app.app,self.setChangedHook,self) self.paConfPath:=control - NEW control.createCheckBox('Free Downloads','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Free Downloads',CONF_FREE_DL,self.app.app,self.setChangedHook,self) self.boolFreeDownloads:=control - NEW control.createString('Forward Systop Mail','strForwardMail',self.app.app,self.setChangedHook,self) + NEW control.createString('Forward Systop Mail',CONF_FORWARD_MAIL,self.app.app,self.setChangedHook,self) self.strForwardMail:=control - NEW control.createCheckBox('Always Do Mail Scan','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Always Do Mail Scan',CONF_FORCE_MSCAN,self.app.app,self.setChangedHook,self) self.boolForceNewscan:=control - NEW control.createCheckBox('Use Usernames','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Use Usernames',CONF_USE_USERNAMES,self.app.app,self.setChangedHook,self) self.boolUseUsernames:=control - NEW control.createCheckBox('Use Internet Names','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Use Internet Names',CONF_USE_INETNAMES,self.app.app,self.setChangedHook,self) self.boolUseInternetNames:=control - NEW control.createString('Menu Prompt','strMenuPrompt',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Use Real Names',CONF_USE_REALNAMES,self.app.app,self.setChangedHook,self) + self.boolUseRealname:=control + + NEW control.createString('Menu Prompt',CONF_MENU_PROMPT,self.app.app,self.setChangedHook,self) self.strMenuPrompt:=control - NEW control.createString('Upload Prompt','strUploadPrompt',self.app.app,self.setChangedHook,self) + NEW control.createString('Upload Prompt',CONF_UPLOAD_PROMPT,self.app.app,self.setChangedHook,self) self.strUploadPrompt:=control - NEW control.createDirSelect('Local Upload Path','paLocalULPath',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('Local Upload Path',CONF_LOCAL_UPLOAD_PATH,self.app.app,self.setChangedHook,self) self.paLocalULPath:=control - NEW control.createStringInt('FTP Dir Days','intFtpDirDays',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('FTP Dir Days',FTP_DIR_DAYS,self.app.app,self.setChangedHook,self) self.intFtpDirDays:=control - NEW control.createString('FTP Dir Name','strFtpDirName',self.app.app,self.setChangedHook,self) + NEW control.createString('FTP Dir Name',CONF_FTP_DIR_NAME,self.app.app,self.setChangedHook,self) self.strFtpDirName:=control - NEW control.createCheckBox('Custom Mail','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Custom Mail',CONF_CUSTOM_MAIL,self.app.app,self.setChangedHook,self) self.boolCustomMail:=control - NEW control.createCheckBox('Never Do Mailscan','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Never Do Mailscan',CONF_NEVER_MSCAN,self.app.app,self.setChangedHook,self) self.boolNoNewscan:=control - NEW control.createCheckBox('Default New Mailscan','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Default New Mailscan',CONF_DEFAULT_NEW_MSCAN,self.app.app,self.setChangedHook,self) self.boolDefaultNewscan:=control - NEW control.createCheckBox('Default New Filescan','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Default New Filescan',CONF_DEFAULT_NEW_FSCAN,self.app.app,self.setChangedHook,self) self.boolDefaultNewfiles:=control - NEW control.createCheckBox('Default Zoom','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Default Zoom',CONF_DEFAULT_ZOOM,self.app.app,self.setChangedHook,self) self.boolDefaultZoom:=control - - NEW control.createCheckBox('Use Real Names','',self.app.app,self.setChangedHook,self) - self.boolUseRealname:=control - - NEW control.createCheckBox('Always Show New Files','',self.app.app,self.setChangedHook,self) + + NEW control.createCheckBox('Always Show New Files',CONF_ALWAYS_NEW_FILES,self.app.app,self.setChangedHook,self) self.boolShowNewFiles:=control - NEW control.createCheckBox('Never Show New Files','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Never Show New Files',CONF_NEVER_NEW_FILES,self.app.app,self.setChangedHook,self) self.boolNoNewFiles:=control - NEW control.createCheckBox('Disable FTP Uploads','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Disable FTP Uploads',CONF_FTP_UL_DISABLE,self.app.app,self.setChangedHook,self) self.boolNoFtpUploads:=control - NEW control.createCheckBox('Ftp Dirlist','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Ftp Dirlist',CONF_FTP_DIRLIST,self.app.app,self.setChangedHook,self) self.boolFtpNoDirlist:=control self.controlList:=[self.strConfName2,self.paConfPath,self.strForwardMail,self.strMenuPrompt,self.strUploadPrompt,self.paLocalULPath, diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e index e9bc769..93433b0 100644 --- a/axSetupTool/frmNodeEdit.e +++ b/axSetupTool/frmNodeEdit.e @@ -5,7 +5,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui','dos/dos','dos/dostags','dos/dosextens' MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' MODULE 'utility/tagitem','utility/hooks','exec/lists','tools/installhook' -MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*helpText' OBJECT timeItem baudStr:PTR TO CHAR @@ -349,228 +349,226 @@ ENDPROC PROC addControls() OF frmNodeEdit DEF control: PTR TO control - NEW control.createStringInt('Node Priority','intPriority',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Node Priority',NODE_PRIORITY,self.app.app,self.setChangedHook,self) self.intPriority:=control - NEW control.createString('bExpress file','strNodeStart',self.app.app,self.setChangedHook,self) + NEW control.createString('bExpress file',NODE_EXPRESS_FILE,self.app.app,self.setChangedHook,self) self.strNodeStart:=control - NEW control.createString('System Password','strSystemPassword',self.app.app,self.setChangedHook,self) + NEW control.createString('System Password',NODE_SYSTEM_PASSWORD,self.app.app,self.setChangedHook,self) self.strSystemPassword:=control - NEW control.createString('System Password Prompt','strSystemPasswordPrompt',self.app.app,self.setChangedHook,self) + NEW control.createString('System Password Prompt',NODE_SYSTEM_PASSWORD_PROMPT,self.app.app,self.setChangedHook,self) self.strSystemPasswordPrompt:=control - NEW control.createString('New User Password','strNewuserPassword',self.app.app,self.setChangedHook,self) + NEW control.createString('New User Password',NODE_NEW_USER_PASSWORD,self.app.app,self.setChangedHook,self) self.strNewuserPassword:=control - NEW control.createString('Name Prompt','strNamePrompt',self.app.app,self.setChangedHook,self) + NEW control.createString('Name Prompt',NODE_NAME_PROMPT,self.app.app,self.setChangedHook,self) self.strNamePrompt:=control - NEW control.createString('Name Prompt2','strNamePrompt2',self.app.app,self.setChangedHook,self) + NEW control.createString('Name Prompt2',NODE_NAME_PROMPT2,self.app.app,self.setChangedHook,self) self.strNamePrompt2:=control - NEW control.createString('Password Prompt','strPasswordPrompt',self.app.app,self.setChangedHook,self) + NEW control.createString('Password Prompt',NODE_PASSWORD_PROMPT,self.app.app,self.setChangedHook,self) self.strPasswordPrompt:=control - NEW control.createString('Password Prompt','strPasswordPrompt',self.app.app,self.setChangedHook,self) - self.strPasswordPrompt:=control - NEW control.createDirSelect('Screens Path','paScreens',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('Screens Path',NODE_SCREENS_PATH,self.app.app,self.setChangedHook,self) self.paScreens:=control - NEW control.createStringInt('Auto Validate Preset','intAutoValPreset',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Auto Validate Preset',NODE_AUTO_VAL_PRESET,self.app.app,self.setChangedHook,self) self.intAutoValPreset:=control - NEW control.createStringInt('Auto Validate Delay','intAutoValDelay',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Auto Validate Delay',NODE_AUTO_VAL_DELAY,self.app.app,self.setChangedHook,self) self.intAutoValDelay:=control - NEW control.createString('Auto Validate Password','strAutoValPassword',self.app.app,self.setChangedHook,self) + NEW control.createString('Auto Validate Password',NODE_AUTO_VAL_PASSWORD,self.app.app,self.setChangedHook,self) self.strAutoValPassword:=control - NEW control.createStringInt('FTP Port','intFtpPort',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('FTP Port',NODE_FTP_PORT,self.app.app,self.setChangedHook,self) self.intFtpPort:=control - NEW control.createStringInt('FTP Data Port','intFtpDataPort',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('FTP Data Port',NODE_FTP_DATA_PORT,self.app.app,self.setChangedHook,self) self.intFtpDataPort:=control - NEW control.createStringInt('HTTP Port','intHttpPort',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('HTTP Port',NODE_HTTP_PORT,self.app.app,self.setChangedHook,self) self.intHttpPort:=control - NEW control.createCycle('UL Credit','intKeepUlCredit',['Default','Grant additional time',0],self.app.app,self.setChangedHook,self) + NEW control.createCycle('UL Credit',NODE_KEEP_UL_CREDIT,['Default','Grant additional time',0],self.app.app,self.setChangedHook,self) self.intKeepUlCredit:=control - NEW control.createStringInt('Max Message Length','intMaxMsgLen',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Max Message Length',NODE_MAX_MSG_LEN,self.app.app,self.setChangedHook,self) self.intMaxMsgLen:=control - NEW control.createStringInt('Max Message Queue','intMaxMsgQueue',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Max Message Queue',NODE_MAX_MSG_QUEUE,self.app.app,self.setChangedHook,self) self.intMaxMsgQueue:=control - NEW control.createDirSelect('Playpen Path','paPlaypen',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('Playpen Path',NODE_PLAYPEN_PATH,self.app.app,self.setChangedHook,self) self.paPlaypen:=control - NEW control.createStringInt('Ring Count','intRingCount',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Ring Count',NODE_RING_COUNT,self.app.app,self.setChangedHook,self) self.intRingCount:=control - NEW control.createString('Remote Password','strRemotePassword',self.app.app,self.setChangedHook,self) + NEW control.createString('Remote Password',NODE_REMOTE_PASSWORD,self.app.app,self.setChangedHook,self) self.strRemotePassword:=control - NEW control.createStringInt('Sysop Chat Colour','intSysopChatColour',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Sysop Chat Colour',NODE_SYSOP_CHAT_COLOUR,self.app.app,self.setChangedHook,self) self.intSysopChatColour:=control - NEW control.createStringInt('User Chat Colour','intUserChatColour',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('User Chat Colour',NODE_USER_CHAT_COLOUR,self.app.app,self.setChangedHook,self) self.intUserChatColour:=control - NEW control.createFileSelect('User Data File','fnUserDataName',self.app.app,self.setChangedHook,self) + NEW control.createFileSelect('User Data File',NODE_USER_DATA_FILE,self.app.app,self.setChangedHook,self) self.fnUserDataName:=control - NEW control.createFileSelect('User Misc file','fnUserMiscName',self.app.app,self.setChangedHook,self) + NEW control.createFileSelect('User Misc file',NODE_USER_MISC_FILE,self.app.app,self.setChangedHook,self) self.fnUserMiscName:=control - NEW control.createFileSelect('User Keys File','fnUserKeysName',self.app.app,self.setChangedHook,self) + NEW control.createFileSelect('User Keys File',NODE_USER_KEYS_FILE,self.app.app,self.setChangedHook,self) self.fnUserKeysName:=control - NEW control.createDirSelect('Local Upload Path','paLocalUlPath',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('Local Upload Path',NODE_LOCAL_UPLOAD_PATH,self.app.app,self.setChangedHook,self) self.paLocalUlPath:=control - NEW control.createStringInt('Timeout override','intOverrideTimeout',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Timeout override',NODE_OVERRIDE_TIMEOUT,self.app.app,self.setChangedHook,self) self.intOverrideTimeout:=control - NEW control.createString('Force Ansi','strForceAnsi',self.app.app,self.setChangedHook,self) + NEW control.createString('Force Ansi',NODE_FORCE_ANSI,self.app.app,self.setChangedHook,self) self.strForceAnsi:=control - NEW control.createStringInt('BG Checker Stack','intBGFilecheckStack',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('BG Checker Stack',NODE_BG_FILECHECK_STACK,self.app.app,self.setChangedHook,self) self.intBGFilecheckStack:=control - NEW control.createString('Console Input Device','strConInputDev',self.app.app,self.setChangedHook,self) + NEW control.createString('Console Input Device',NODE_CON_IN_DEVICE,self.app.app,self.setChangedHook,self) self.strConInputDev:=control - NEW control.createString('Console Output Device','strConOutputDev',self.app.app,self.setChangedHook,self) + NEW control.createString('Console Output Device',NODE_CON_OUT_DEVICE,self.app.app,self.setChangedHook,self) self.strConOutputDev:=control - NEW control.createString('Screen Pens','strScreenPens',self.app.app,self.setChangedHook,self) + NEW control.createString('Screen Pens',NODE_SCREEN_PENS,self.app.app,self.setChangedHook,self) self.strScreenPens:=control - NEW control.createString('Conf DB','strConfDb',self.app.app,self.setChangedHook,self) + NEW control.createString('Conf DB',NODE_CONF_DB_FILE,self.app.app,self.setChangedHook,self) self.strConfDb:=control - NEW control.createFileSelect('Files Not Allowed','fnFilesNotAllowed',self.app.app,self.setChangedHook,self) + NEW control.createFileSelect('Files Not Allowed',NODE_NOT_ALLOWED_FILE,self.app.app,self.setChangedHook,self) self.fnFilesNotAllowed:=control - NEW control.createString('First Command','strFirstCommand',self.app.app,self.setChangedHook,self) + NEW control.createString('First Command',NODE_FIRST_COMMAND,self.app.app,self.setChangedHook,self) self.strFirstCommand:=control - NEW control.createStringInt('Serial Cache Size','intSerialCacheSize',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Serial Cache Size',NODE_SERIAL_CACHE_SIZE,self.app.app,self.setChangedHook,self) self.intSerialCacheSize:=control - NEW control.createCheckBox('Callers Log','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Callers Log',NODE_CALLERSLOG,self.app.app,self.setChangedHook,self) self.boolCallersLog:=control - NEW control.createCheckBox('Capitalise Filenames','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Capitalise Filenames',NODE_CAPS_FILENAMES,self.app.app,self.setChangedHook,self) self.boolCapitalFilenames:=control - NEW control.createCheckBox('Def Screens','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Def Screens',NODE_DEF_SCREENS,self.app.app,self.setChangedHook,self) self.boolDefScreens:=control - NEW control.createCheckBox('Debug Logs','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Debug Logs',NODE_DEBUG_LOGS,self.app.app,self.setChangedHook,self) self.boolDebugLog:=control - NEW control.createCheckBox('Door Logs','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Door Logs',NODE_DOOR_LOGS,self.app.app,self.setChangedHook,self) self.boolDoorLog:=control - NEW control.createCheckBox('Startup Logs','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Startup Logs',NODE_STARTUP_LOGS,self.app.app,self.setChangedHook,self) self.boolStartLog:=control - NEW control.createCheckBox('UL/DL Logs','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('UL/DL Logs',NODE_UD_LOGS,self.app.app,self.setChangedHook,self) self.boolUDLog:=control - NEW control.createCheckBox('Chat on','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Chat on',NO_CHAT_ON,self.app.app,self.setChangedHook,self) self.boolChatOn:=control - NEW control.createCheckBox('No Quick Logons','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No Quick Logons',NODE_NO_QUICK_LOGON,self.app.app,self.setChangedHook,self) self.boolDisableQuickLogon:=control - NEW control.createCheckBox('Node Idle','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Node Idle',NODE_IDLE,self.app.app,self.setChangedHook,self) self.boolIdleNode:=control - NEW control.createCheckBox('Prompt For Mailscan','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Prompt For Mailscan',NODE_MSCAN_PROMPT,self.app.app,self.setChangedHook,self) self.boolMailscanPrompt:=control - NEW control.createCheckBox('Disable Timeout','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Disable Timeout',NODE_NO_TIMEOUT,self.app.app,self.setChangedHook,self) self.boolNoTimeout:=control - NEW control.createCheckBox('Quiet','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Quiet',NODE_QUIET,self.app.app,self.setChangedHook,self) self.boolQuietNode:=control - NEW control.createCheckBox('Stealth','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Stealth',NODE_STEALTH,self.app.app,self.setChangedHook,self) self.boolStealthNode:=control - NEW control.createCheckBox('Show Password Fails','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Show Password Fails',NODE_SHOW_PWFAILS,self.app.app,self.setChangedHook,self) self.boolShowPwFail:=control - NEW control.createCheckBox('Sentby Files','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Sentby Files',NODE_SENTBY_FILES,self.app.app,self.setChangedHook,self) self.boolSentByFiles:=control - NEW control.createCheckBox('Enable Native Telnet','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Enable Native Telnet',NODE_TELNET,self.app.app,self.setChangedHook,self) self.boolTelnet:=control - NEW control.createCheckBox('Enable Ftp','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Enable Ftp',NODE_FTP,self.app.app,self.setChangedHook,self) self.boolFtp:=control - NEW control.createCheckBox('Enable TelnetD','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Enable TelnetD',NODE_TELNETD,self.app.app,self.setChangedHook,self) self.boolTelnetD:=control - NEW control.createCheckBox('Enable TelserD','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Enable TelserD',NODE_TELSERD,self.app.app,self.setChangedHook,self) self.boolTelserD:=control - NEW control.createCheckBox('Usernumber Logon','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Usernumber Logon',NODE_USERNUM_LOGON,self.app.app,self.setChangedHook,self) self.boolUserNumLogin:=control - NEW control.createCheckBox('View Passwords','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('View Passwords',NODE_VIEW_PWDS,self.app.app,self.setChangedHook,self) self.boolViewPassword:=control - NEW control.createCheckBox('Log IP/Hostnames','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Log IP/Hostnames',NODE_LOG_IP,self.app.app,self.setChangedHook,self) self.boolLogHost:=control - NEW control.createCheckBox('Log Inputs','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Log Inputs',NODE_LOG_INPUTS,self.app.app,self.setChangedHook,self) self.boolLogInputs:=control - NEW control.createCheckBox('No node commodity','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No node commodity',NODE_DISABLE_COMMODITY,self.app.app,self.setChangedHook,self) self.boolNoCx:=control - NEW control.createCheckBox('Central Answers','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Central Answers',NODE_CENTRAL_ANSWERS,self.app.app,self.setChangedHook,self) self.boolCentralAnswers:=control - NEW control.createCheckBox('Disable IEMSI','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Disable IEMSI',NODE_DISABLE_IEMSI,self.app.app,self.setChangedHook,self) self.boolDisableIemsi:=control - NEW control.createCheckBox('No MCI Messages','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No MCI Messages',NODE_NO_MCI_MSG,self.app.app,self.setChangedHook,self) self.boolNoMciMsg:=control - NEW control.createCheckBox('No wildcards','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No wildcards',NODE_NO_WILDCARDS,self.app.app,self.setChangedHook,self) self.boolNoWildcard:=control - NEW control.createCheckBox('Own partuploads','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Own partuploads',NODE_OWN_PARTUPLOADS,self.app.app,self.setChangedHook,self) self.boolOwnPartFiles:=control - NEW control.createCheckBox('Phone Check','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Phone Check',NODE_PHONE_CHECK,self.app.app,self.setChangedHook,self) self.boolPhoneCheck:=control - NEW control.createCheckBox('RAM Work','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('RAM Work',NODE_RAM_WORK,self.app.app,self.setChangedHook,self) self.boolRamWork:=control - NEW control.createCheckBox('Console Debug','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Console Debug',NODE_CONSOLE_DEBUG,self.app.app,self.setChangedHook,self) self.boolConsoleDebug:=control - NEW control.createCheckBox('No Emails','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No Emails',NODE_NO_EMAILS,self.app.app,self.setChangedHook,self) self.boolNoEmails:=control - NEW control.createCheckBox('OwnDevUnit','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('OwnDevUnit',NODE_OWNDEVUNIT,self.app.app,self.setChangedHook,self) self.boolOwnDevunit:=control - NEW control.createCheckBox('Show Cache Stats','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Show Cache Stats',NODE_SHOW_CACHE_STATS,self.app.app,self.setChangedHook,self) self.boolShowCacheStats:=control - NEW control.createCheckBox('Trapdoor','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Trapdoor',NODE_TRAPDOOR,self.app.app,self.setChangedHook,self) self.boolTrapDoor:=control - NEW control.createCheckBox('Trap Serial','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Trap Serial',NODE_TRAP_SERIAL,self.app.app,self.setChangedHook,self) self.boolTrapSerial:=control - NEW control.createCheckBox('No Rad Boogie','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No Rad Boogie',NODE_NORADBOOGIE,self.app.app,self.setChangedHook,self) self.boolNoRadBoogie:=control //serial device settings - NEW control.createString('Serial Device','strSerialDevice',self.app.app,self.setChangedHook,self) + NEW control.createString('Serial Device',NODE_SERIAL_DEVICE,self.app.app,self.setChangedHook,self) self.strSerialDevice:=control - NEW control.createStringInt('Serial Device Unit','intSerialUnit',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Serial Device Unit',NODE_SERIAL_DEV_UNIT,self.app.app,self.setChangedHook,self) self.intSerialUnit:=control - NEW control.createStringInt('Serial Baud','intSerialBaud',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Serial Baud',NODE_SERIAL_BAUD,self.app.app,self.setChangedHook,self) self.intSerialBaud:=control - NEW control.createCheckBox('2232Patch','boolA2232Patch',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('2232Patch',NODE_A2232PATCH,self.app.app,self.setChangedHook,self) self.boolA2232Patch:=control - NEW control.createCheckBox('No Purge Line','boolNoPurgeLine',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('No Purge Line',NODE_NO_PURGE_LINE,self.app.app,self.setChangedHook,self) self.boolNoPurgeLine:=control - NEW control.createCheckBox('Repurge','boolRepurge',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Repurge',NODE_REPURGE,self.app.app,self.setChangedHook,self) self.boolRepurge:=control - NEW control.createCheckBox('Logoff Reset','boolLogoffReset',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Logoff Reset',NODE_LOGOFF_RESET,self.app.app,self.setChangedHook,self) self.boolLogoffReset:=control - NEW control.createCheckBox('True Reset','boolTrueReset',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('True Reset',NODE_TRUE_RESET,self.app.app,self.setChangedHook,self) self.boolTrueReset:=control //modem settings - NEW control.createString('Modem Init String','strModemInit',self.app.app,self.setChangedHook,self) + NEW control.createString('Modem Init String',NODE_MODEM_INIT,self.app.app,self.setChangedHook,self) self.strModemInit:=control - NEW control.createString('Modem Reset String','strModemReset',self.app.app,self.setChangedHook,self) + NEW control.createString('Modem Reset String',NODE_MODEM_RESET,self.app.app,self.setChangedHook,self) self.strModemReset:=control - NEW control.createString('Modem Ring String','strModemRing',self.app.app,self.setChangedHook,self) + NEW control.createString('Modem Ring String',NODE_MODEM_RING,self.app.app,self.setChangedHook,self) self.strModemRing:=control - NEW control.createString('Modem Answer String','strModemAnswer',self.app.app,self.setChangedHook,self) + NEW control.createString('Modem Answer String',NODE_MODEM_ANSWER,self.app.app,self.setChangedHook,self) self.strModemAnswer:=control - NEW control.createString('Modem Offhook String','strModemOffhook',self.app.app,self.setChangedHook,self) + NEW control.createString('Modem Offhook String',NODE_MODEM_OFFHOOK,self.app.app,self.setChangedHook,self) self.strModemOffhook:=control - NEW control.createString('NRAMS1','strNRAMS1',self.app.app,self.setChangedHook,self) + NEW control.createString('NRAMS1',NODE_MODEM_NRAMS,self.app.app,self.setChangedHook,self) self.strNRAMS1:=control - NEW control.createString('NRAMS2','strNRAMS2',self.app.app,self.setChangedHook,self) + NEW control.createString('NRAMS2',NODE_MODEM_NRAMS,self.app.app,self.setChangedHook,self) self.strNRAMS2:=control - NEW control.createString('NRAMS3','strNRAMS3',self.app.app,self.setChangedHook,self) + NEW control.createString('NRAMS3',NODE_MODEM_NRAMS,self.app.app,self.setChangedHook,self) self.strNRAMS3:=control - NEW control.createString('NRAMS4','strNRAMS4',self.app.app,self.setChangedHook,self) + NEW control.createString('NRAMS4',NODE_MODEM_NRAMS,self.app.app,self.setChangedHook,self) self.strNRAMS4:=control //window settings - NEW control.createCycle('Number of Colours','intNumColours',['2','4','8','16',0],self.app.app,self.setChangedHook,self) + NEW control.createCycle('Number of Colours',NODE_WIN_COLOURS,['2','4','8','16',0],self.app.app,self.setChangedHook,self) self.intNumColours:=control - NEW control.createStringInt('Left Edge','intWinLeftEdge',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Left Edge',NODE_WIN_LEFT,self.app.app,self.setChangedHook,self) self.intWinLeftEdge:=control - NEW control.createStringInt('Top Edge','intWinTopEdge',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Top Edge',NODE_WIN_TOP,self.app.app,self.setChangedHook,self) self.intWinTopEdge:=control - NEW control.createStringInt('Width','intWinWidth',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Width',NODE_WIN_WIDTH,self.app.app,self.setChangedHook,self) self.intWinWidth:=control - NEW control.createStringInt('Height','intWinHeight',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Height',NODE_WIN_HEIGHT,self.app.app,self.setChangedHook,self) self.intWinHeight:=control - NEW control.createString('Pubscreen','strWinPubScreen',self.app.app,self.setChangedHook,self) + NEW control.createString('Pubscreen',NODE_WIN_PUBSCREEN,self.app.app,self.setChangedHook,self) self.strWinPubScreen:=control - NEW control.createCheckBox('Iconified','boolWinIconified',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Iconified',NODE_WIN_ICONIFIED,self.app.app,self.setChangedHook,self) self.boolWinIconified:=control - NEW control.createCheckBox('Interlace','boolWinInterlace',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Interlace',NODE_WIN_INTERLACE,self.app.app,self.setChangedHook,self) self.boolWinInterlace:=control - NEW control.createCheckBox('Status bar','boolWinStatusBar',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Status bar',NODE_WIN_STATUSBAR,self.app.app,self.setChangedHook,self) self.boolWinStatusBar:=control - NEW control.createCheckBox('Bring To Front','boolWinToFront',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Bring To Front',NODE_WIN_TO_FRONT,self.app.app,self.setChangedHook,self) self.boolWinToFront:=control - NEW control.createModeSelect('DisplayId','strDisplayId',self.app.app,self.setChangedHook,self) + NEW control.createModeSelect('DisplayId',NODE_DISPLAY_ID,self.app.app,self.setChangedHook,self) self.strDisplayId:=control self.controlList1:= [self.intPriority,self.strNodeStart,self.strSystemPassword,self.strSystemPasswordPrompt,self.strNewuserPassword, diff --git a/axSetupTool/frmPresetsEdit.e b/axSetupTool/frmPresetsEdit.e index 37fa3be..d3cb3a8 100644 --- a/axSetupTool/frmPresetsEdit.e +++ b/axSetupTool/frmPresetsEdit.e @@ -4,7 +4,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui' MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists','dos/dos' -MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*/stringlist' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*/stringlist','*helpText' EXPORT OBJECT frmPresetsEdit OF frmBase @@ -91,28 +91,28 @@ ENDPROC PROC addPresetControls() OF frmPresetsEdit DEF control: PTR TO control - NEW control.createCycle('bArea Name','strAreaName',['',0],self.app.app,self.setChangedHook,self) + NEW control.createCycle('bArea Name',PRESET_AREA_NAME,['',0],self.app.app,self.setChangedHook,self) self.strAreaName:=control - NEW control.createStringInt('bAccess Level','intAccessLevel',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('bAccess Level',PRESET_ACCESS_LEVEL,self.app.app,self.setChangedHook,self) self.intAccessLevel:=control - NEW control.createStringInt('bInitial Conf','intConfrJoin',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('bInitial Conf',PRESET_CONF_RJOIN,self.app.app,self.setChangedHook,self) self.intConfrJoin:=control - NEW control.createStringInt('Initial Msgbase','intMsgbaserJoin',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Initial Msgbase',PRESET_MESSAGEBASE_RJOIN,self.app.app,self.setChangedHook,self) self.intMsgbaserJoin:=control - NEW control.createStringInt('Daily Byte Limit','intDailyBytes',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Daily Byte Limit',PRESET_DAILY_BYTES,self.app.app,self.setChangedHook,self) self.intDailyBytes:=control - NEW control.createStringInt('Ratio Type','intRatioType',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Ratio Type',PRESET_RATIO_TYPE,self.app.app,self.setChangedHook,self) self.intRatioType:=control - NEW control.createStringInt('Ratio','intRatio',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Ratio',PRESET_RATIO,self.app.app,self.setChangedHook,self) self.intRatio:=control - NEW control.createStringInt('Time Limit','intTimeLimit',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Time Limit',PRESET_TIME_LIMIT,self.app.app,self.setChangedHook,self) self.intTimeLimit:=control self.controlList:=[self.strAreaName,self.intAccessLevel,self.intConfrJoin,self.intMsgbaserJoin, diff --git a/axSetupTool/frmSettingsEdit.e b/axSetupTool/frmSettingsEdit.e index 6714e03..5a74c28 100644 --- a/axSetupTool/frmSettingsEdit.e +++ b/axSetupTool/frmSettingsEdit.e @@ -4,7 +4,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui' MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' -MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*/stringlist' +MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*/stringlist','*helpText' EXPORT OBJECT frmSettingsEdit OF frmBase @@ -166,128 +166,128 @@ PROC addSystemControls() OF frmSettingsEdit DEF languageList:PTR TO LONG DEF i - NEW control.createString('bBBS Name','strBBSName',self.app.app,self.setChangedHook,self) + NEW control.createString('bBBS Name',SYS_BBS_NAME,self.app.app,self.setChangedHook,self) self.strBBSName:=control - NEW control.createString('bBBS Location','strBBSLocation',self.app.app,self.setChangedHook,self) + NEW control.createString('bBBS Location',SYS_BBS_LOCATION,self.app.app,self.setChangedHook,self) self.strBBSLocation:=control - NEW control.createString('bSysop Name','strSysopName',self.app.app,self.setChangedHook,self) + NEW control.createString('bSysop Name',SYS_SYSOP_NAME,self.app.app,self.setChangedHook,self) self.strSysopName:=control - NEW control.createString('Default Menu','strDefaultMenu',self.app.app,self.setChangedHook,self) + NEW control.createString('Default Menu',SYS_DEFAULT_MENU,self.app.app,self.setChangedHook,self) self.strDefaultMenu:=control - NEW control.createDirSelect('Local Upload Path','paLocalULPath',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('Local Upload Path',SYS_LOCAL_UPLOAD_PATH,self.app.app,self.setChangedHook,self) self.paLocalULPath:=control - NEW control.createStringInt('Auto Validate Preset','intAutoValPreset',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Auto Validate Preset',SYS_AUTO_VAL_PRESET,self.app.app,self.setChangedHook,self) self.intAutoValPreset:=control - NEW control.createStringInt('Auto Validate Delay','intAutoValDelay',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Auto Validate Delay',SYS_AUTO_VAL_DELAY,self.app.app,self.setChangedHook,self) self.intAutoValDelay:=control - NEW control.createString('Auto Validate Password','strAutoValPassword',self.app.app,self.setChangedHook,self) + NEW control.createString('Auto Validate Password',SYS_AUTO_VAL_PASSWORD,self.app.app,self.setChangedHook,self) self.strAutoValPassword:=control self.cyLanguage:=0 IF ListLen(self.languages)>1 - NEW control.createCycle('Host Language','cyLanguage',self.languages,self.app.app,self.setChangedHook,self) + NEW control.createCycle('Host Language',SYS_LANGUAGE,self.languages,self.app.app,self.setChangedHook,self) self.cyLanguage:=control ENDIF - NEW control.createCheckBox('Credit by KB','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Credit by KB',SYS_CREDIT_BY_KB,self.app.app,self.setChangedHook,self) self.boolCreditByKb:=control - NEW control.createCheckBox('Long who','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Long who',SYS_LONG_WHO,self.app.app,self.setChangedHook,self) self.boolLongWho:=control - NEW control.createCycle('New Accounts','cyNewAccounts',['Append','Overwrite',0],self.app.app,self.setChangedHook,self) + NEW control.createCycle('New Accounts',SYS_NEW_ACCOUNTS,['Append','Overwrite',0],self.app.app,self.setChangedHook,self) self.cyNewAccounts:=control - NEW control.createCycle('Timeout Recorded as','boolTimeoutLc',['Lost Carrier','Normal Logoff',0],self.app.app,self.setChangedHook,self) + NEW control.createCycle('Timeout Recorded as',SYS_TIMEOUT_LC,['Lost Carrier','Normal Logoff',0],self.app.app,self.setChangedHook,self) self.boolTimeoutLc:=control - NEW control.createString('Registered to','strRegKey',self.app.app,self.setChangedHook,self) + NEW control.createString('Registered to',SYS_REGKEY,self.app.app,self.setChangedHook,self) self.strRegKey:=control - NEW control.createCheckBox('Convert to MB','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Convert to MB',SYS_CONVERT_TO_MB,self.app.app,self.setChangedHook,self) self.boolConvertToMb:=control - NEW control.createCheckBox('Quiet Join','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Quiet Join',SYS_QUIET_JOIN,self.app.app,self.setChangedHook,self) self.boolQuietJoin:=control - NEW control.createCheckBox('Relative Conferences','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Relative Conferences',SYS_RELATIVE_CONFS,self.app.app,self.setChangedHook,self) self.boolRelativeConfs:=control - NEW control.createString('SMTP server address','strSmtpHost',self.app.app,self.setChangedHook,self) + NEW control.createString('SMTP server address',SYS_SMTP_SERVER,self.app.app,self.setChangedHook,self) self.strSmtpHost:=control - NEW control.createStringInt('SMTP server port','intSmtpPort',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('SMTP server port',SYS_SMTP_PORT,self.app.app,self.setChangedHook,self) self.intSmtpPort:=control - NEW control.createString('SMTP server username','strSmtpUsername',self.app.app,self.setChangedHook,self) + NEW control.createString('SMTP server username',SYS_SMTP_USERNAME,self.app.app,self.setChangedHook,self) self.strSmtpUsername:=control - NEW control.createString('SMTP server password','strSmtpPassword',self.app.app,self.setChangedHook,self) + NEW control.createString('SMTP server password',SYS_SMTP_PASSWORD,self.app.app,self.setChangedHook,self) self.strSmtpPassword:=control - NEW control.createCheckBox('Use SSL for emails','boolSmtpSSL',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Use SSL for emails',SYS_SSL_EMAILS,self.app.app,self.setChangedHook,self) self.boolSmtpSSL:=control - NEW control.createString('Sysops email address','strSysopEmail',self.app.app,self.setChangedHook,self) + NEW control.createString('Sysops email address',SYS_SYSOP_EMAIL,self.app.app,self.setChangedHook,self) self.strSysopEmail:=control - NEW control.createString('BBS email address','strBbsEmail',self.app.app,self.setChangedHook,self) + NEW control.createString('BBS email address',SYS_BBS_EMAIL,self.app.app,self.setChangedHook,self) self.strBbsEmail:=control - NEW control.createCheckBox('Email on sysop page','boolMailOnPage',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on sysop page',SYS_EMAIL_ON_SYSOP_PAGE,self.app.app,self.setChangedHook,self) self.boolMailOnPage:=control - NEW control.createCheckBox('Email on comment','boolMailOnComment',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on comment',SYS_EMAIL_ON_COMMENT,self.app.app,self.setChangedHook,self) self.boolMailOnComment:=control - NEW control.createCheckBox('Email on logon','boolMailOnLogon',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on logon',SYS_EMAIL_ON_LOGON,self.app.app,self.setChangedHook,self) self.boolMailOnLogon:=control - NEW control.createCheckBox('Email on logoff','boolMailOnLogoff',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on logoff',SYS_EMAIL_ON_LOGOFF,self.app.app,self.setChangedHook,self) self.boolMailOnLogoff:=control - NEW control.createCheckBox('Email on new user','boolMailOnNewUser',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on new user',SYS_EMAIL_ON_NEW_USER,self.app.app,self.setChangedHook,self) self.boolMailOnNewUser:=control - NEW control.createCheckBox('Email on upload','boolMailOnUpload',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on upload',SYS_EMAIL_ON_UPLOAD,self.app.app,self.setChangedHook,self) self.boolMailOnUpload:=control - NEW control.createCheckBox('Email on password fail','boolMailOnPwdFail',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Email on password fail',SYS_EMAIL_ON_PW_FAIL,self.app.app,self.setChangedHook,self) self.boolMailOnPwdFail:=control - NEW control.createDirSelect('Language base folder','paLanguageBase',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('Language base folder',SYS_LANG_BASE_PATH,self.app.app,self.setChangedHook,self) self.paLanguageBase:=control - NEW control.createDirSelect('History folder','paHistory',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('History folder',SYS_HISTORY_PATH,self.app.app,self.setChangedHook,self) self.paHistory:=control - NEW control.createDirSelect('User notes folder','paUserNotes',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('User notes folder',SYS_USER_NOTES_PATH,self.app.app,self.setChangedHook,self) self.paUserNotes:=control - NEW control.createStringInt('Hold access level','intHoldAccess',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Hold access level',SYS_HOLD_ACCESS_LEVEL,self.app.app,self.setChangedHook,self) self.intHoldAccess:=control - NEW control.createString('File Diz Cmd','strFileDizSysCmd',self.app.app,self.setChangedHook,self) + NEW control.createString('File Diz Cmd',SYS_FILEDIZ_CMD,self.app.app,self.setChangedHook,self) self.strFileDizSysCmd:=control - NEW control.createString('FTP host name','strFtpHost',self.app.app,self.setChangedHook,self) + NEW control.createString('FTP host name',SYS_FTP_HOST,self.app.app,self.setChangedHook,self) self.strFtpHost:=control - NEW control.createString('Execute on new user','strExecOnNewUser',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on new user',SYS_EXEC_ON_NEW_USER,self.app.app,self.setChangedHook,self) self.strExecOnNewUser:=control - NEW control.createString('Execute async on new user','strExecAOnNewUser',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on new user',SYS_EXECA_ON_NEW_USER,self.app.app,self.setChangedHook,self) self.strExecAOnNewUser:=control - NEW control.createString('Execute on sysop page','strExecOnPage',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on sysop page',SYS_EXEC_ON_SYSOP_PAGE,self.app.app,self.setChangedHook,self) self.strExecOnPage:=control - NEW control.createString('Execute async on sysop page','strExecAOnPage',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on sysop page',SYS_EXECA_ON_SYSOP_PAGE,self.app.app,self.setChangedHook,self) self.strExecAOnPage:=control - NEW control.createString('Execute on connect','strExecOnConnect',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on connect',SYS_EXEC_ON_CONNECT,self.app.app,self.setChangedHook,self) self.strExecOnConnect:=control - NEW control.createString('Execute async on connect','strExecAOnConnect',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on connect',SYS_EXECA_ON_CONNECT,self.app.app,self.setChangedHook,self) self.strExecAOnConnect:=control - NEW control.createString('Execute on logon','strExecOnLogon',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on logon',SYS_EXEC_ON_LOGON,self.app.app,self.setChangedHook,self) self.strExecOnLogon:=control - NEW control.createString('Execute async on logon','strExecAOnLogon',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on logon',SYS_EXECA_ON_LOGON,self.app.app,self.setChangedHook,self) self.strExecAOnLogon:=control - NEW control.createString('Execute on logoff','strExecOnLogoff',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on logoff',SYS_EXEC_ON_LOGOFF,self.app.app,self.setChangedHook,self) self.strExecOnLogoff:=control - NEW control.createString('Execute async on logoff','strExecAOnLogoff',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on logoff',SYS_EXECA_ON_LOGOFF,self.app.app,self.setChangedHook,self) self.strExecAOnLogoff:=control - NEW control.createString('Execute on comment','strExecOnComment',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on comment',SYS_EXEC_ON_COMMENT,self.app.app,self.setChangedHook,self) self.strExecOnComment:=control - NEW control.createString('Execute async on comment','strExecAOnComment',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on comment',SYS_EXECA_ON_COMMENT,self.app.app,self.setChangedHook,self) self.strExecAOnComment:=control - NEW control.createString('Execute on upload','strExecOnUpload',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on upload',SYS_EXEC_ON_UPLOAD,self.app.app,self.setChangedHook,self) self.strExecOnUpload:=control - NEW control.createString('Execute async on upload','strExecAOnUpload',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute async on upload',SYS_EXECA_ON_UPLOAD,self.app.app,self.setChangedHook,self) self.strExecAOnUpload:=control self.controlList:=[self.strBBSName,self.strBBSLocation,self.strSysopName,self.strRegKey,self.cyNewAccounts,self.strDefaultMenu, @@ -330,58 +330,58 @@ PROC addServerControls() OF frmSettingsEdit DEF tempStr[255]:STRING DEF i - NEW control.createDirSelect('bBBS Path','paBBSPath',self.app.app,self.setChangedHook,self) + NEW control.createDirSelect('bBBS Path',SYS_BBS_PATH,self.app.app,self.setChangedHook,self) self.paBBSPath:=control - NEW control.createStringInt('Stack size','intStack',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Stack size',SYS_STACK,self.app.app,self.setChangedHook,self) self.intStack:=control - NEW control.createStringInt('Priority','intPriority',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Priority',SYS_PRIORITY,self.app.app,self.setChangedHook,self) self.intPriority:=control - NEW control.createCheckBox('Start Iconified','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Start Iconified',SYS_START_ICONIFIED,self.app.app,self.setChangedHook,self) self.boolIconified:=control - NEW control.createStringInt('Iconify Left','intIconifyLeft',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Iconify Left',SYS_ICONIFY_LEFT,self.app.app,self.setChangedHook,self) self.intIconifyLeft:=control - NEW control.createStringInt('Iconify Top','intIconifyTop',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Iconify Top',SYS_ICONIFY_TOP,self.app.app,self.setChangedHook,self) self.intIconifyTop:=control - NEW control.createCheckBox('Do not move','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Do not move',SYS_DO_NOT_MOVE,self.app.app,self.setChangedHook,self) self.boolDoNotMove:=control - NEW control.createCheckBox('Multicom port','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Multicom port',SYS_MULTICOM,self.app.app,self.setChangedHook,self) self.boolMulticom:=control - NEW control.createCheckBox('AE Shell','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('AE Shell',SYS_AE_SHELL,self.app.app,self.setChangedHook,self) self.boolAEShell:=control - NEW control.createCheckBox('Disable commodity','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Disable commodity',SYS_NO_COMMODITY,self.app.app,self.setChangedHook,self) self.boolNoCx:=control - NEW control.createCheckBox('Don''t save state','',self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('Don''t save state',SYS_DONT_SAVE_STATE,self.app.app,self.setChangedHook,self) self.boolNoSaveState:=control - NEW control.createStringInt('Telnet Port Number','intTelnetPort',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('Telnet Port Number',SYS_TELNET_PORT,self.app.app,self.setChangedHook,self) self.intTelnetPort:=control - NEW control.createStringInt('FTP Port Number','intFtpPort',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('FTP Port Number',SYS_FTP_PORT,self.app.app,self.setChangedHook,self) self.intFtpPort:=control - NEW control.createString('ACP Font','strAcpFont',self.app.app,self.setChangedHook,self) + NEW control.createString('ACP Font',SYS_ACP_FONT,self.app.app,self.setChangedHook,self) self.strAcpFont:=control - NEW control.createString('Execute on startup','strExecOnStart',self.app.app,self.setChangedHook,self) + NEW control.createString('Execute on startup',SYS_EXEC_ON_STARTUP,self.app.app,self.setChangedHook,self) self.strExecOnStart:=control - NEW control.createStringInt('DOS check time','intDosCheckTime',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('DOS check time',SYS_DOS_CHECK_TIME,self.app.app,self.setChangedHook,self) self.intDosCheckTime:=control - NEW control.createStringInt('DOS ban time','intDosBanTime',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('DOS ban time',SYS_DOS_BAN_TIME,self.app.app,self.setChangedHook,self) self.intDosBanTime:=control - NEW control.createStringInt('DOS check trigger','intDosCheckTrigger',self.app.app,self.setChangedHook,self) + NEW control.createStringInt('DOS check trigger',SYS_DOS_CHECK_TRIGGER,self.app.app,self.setChangedHook,self) self.intDosCheckTrig:=control NEW list.stdlist(self.nodeCount) @@ -407,29 +407,29 @@ PROC addServerControls() OF frmSettingsEdit FOR i:=0 TO self.nodeCount-1 StringF(tempStr,'Node \d Location',i) - NEW control.createString(tempStr,'strNodexLoc',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_NODE_X_LOC,self.app.app,self.setChangedHook,self) self.nodeLocs.add(control) StringF(tempStr,'Node \d Name',i) - NEW control.createString(tempStr,'strNodexName',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_NODE_X_NAME,self.app.app,self.setChangedHook,self) self.nodeNames.add(control) StringF(tempStr,'Node \d Sysop',i) - NEW control.createString(tempStr,'strNodexSysop',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_NODE_X_SYSOP,self.app.app,self.setChangedHook,self) self.nodeSysops.add(control) ENDFOR FOR i:=1 TO 15 StringF(tempStr,'Button \d Name',i) - NEW control.createString(tempStr,'strButtonxName',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_BUTTON_NAME,self.app.app,self.setChangedHook,self) self.buttonNames.add(control) StringF(tempStr,'Button \d Command',i) - NEW control.createString(tempStr,'strButtonxCommand',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_BUTTON_COMMAND,self.app.app,self.setChangedHook,self) self.buttonCommands.add(control) StringF(tempStr,'Nutton \d Name',i) - NEW control.createString(tempStr,'strNuttonxName',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_NUTTON_NAME,self.app.app,self.setChangedHook,self) self.nuttonNames.add(control) StringF(tempStr,'Nutton \d Command',i) - NEW control.createString(tempStr,'strNuttonxCommand',self.app.app,self.setChangedHook,self) + NEW control.createString(tempStr,SYS_NUTTON_COMMAND,self.app.app,self.setChangedHook,self) self.nuttonCommands.add(control) ENDFOR @@ -525,19 +525,19 @@ ENDPROC PROC addZoomControls() OF frmSettingsEdit DEF control: PTR TO control - NEW control.createString('BBS Number','strBbsNumber',self.app.app,self.setChangedHook,self) + NEW control.createString('BBS Number',SYS_QWK_BBS_NUMBER,self.app.app,self.setChangedHook,self) self.strBbsNumber:=control - NEW control.createString('BBS Address','strBbsAddress',self.app.app,self.setChangedHook,self) + NEW control.createString('BBS Address',SYS_QWK_BBS_ADDRESS,self.app.app,self.setChangedHook,self) self.strBbsAddress:=control - NEW control.createString('BBS ID','strBbsId',self.app.app,self.setChangedHook,self) + NEW control.createString('BBS ID',SYS_QWK_BBS_ID,self.app.app,self.setChangedHook,self) self.strBbsId:=control - NEW control.createString('QWK Zip command','strQwkZip',self.app.app,self.setChangedHook,self) + NEW control.createString('QWK Zip command',SYS_QWK_ZIP_COMMAND,self.app.app,self.setChangedHook,self) self.strQwkZip:=control - NEW control.createString('QWK LHA command','strQwkLha',self.app.app,self.setChangedHook,self) + NEW control.createString('QWK LHA command',SYS_QWK_LHA_COMMAND,self.app.app,self.setChangedHook,self) self.strQwkLha:=control - NEW control.createString('ASCII Zip command','strAscZip',self.app.app,self.setChangedHook,self) + NEW control.createString('ASCII Zip command',SYS_ASC_ZIP_COMMAND,self.app.app,self.setChangedHook,self) self.strAscZip:=control - NEW control.createString('ASCII LHA command','strAscLha',self.app.app,self.setChangedHook,self) + NEW control.createString('ASCII LHA command',SYS_ASC_LHA_COMMAND,self.app.app,self.setChangedHook,self) self.strAscLha:=control self.controlList:=[self.strBbsNumber,self.strBbsAddress,self.strBbsId, self.strQwkZip, self.strQwkLha, self.strAscZip, self.strAscLha] diff --git a/axSetupTool/helpText.e b/axSetupTool/helpText.e new file mode 100644 index 0000000..45ba33d --- /dev/null +++ b/axSetupTool/helpText.e @@ -0,0 +1,73 @@ +->help text definitions +OPT MODULE + +EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_NAME,CHECKER_ERROR,CHECKER_OPTIONS,CHECKER_PRIORITY,CHECKER_STACK,HYDRA_RX_WINDOW,HYDRA_TX_WINDOW,COMMAND_ACCESS, + COMMAND_PRIORITY,COMMAND_STACK,FTP_DIR_DAYS,NODE_PRIORITY,NODE_AUTO_VAL_PRESET, + NODE_AUTO_VAL_DELAY,NODE_FTP_PORT,NODE_FTP_DATA_PORT,NODE_HTTP_PORT,NODE_MAX_MSG_LEN, + NODE_MAX_MSG_QUEUE,NODE_RING_COUNT,NODE_SYSOP_CHAT_COLOUR,NODE_USER_CHAT_COLOUR,NODE_OVERRIDE_TIMEOUT, + NODE_BG_FILECHECK_STACK,NODE_SERIAL_CACHE_SIZE,NODE_SERIAL_DEV_UNIT,NODE_SERIAL_BAUD, + NODE_WIN_LEFT,NODE_WIN_TOP,NODE_WIN_WIDTH,NODE_WIN_HEIGHT,PRESET_ACCESS_LEVEL, + PRESET_CONF_RJOIN,PRESET_MESSAGEBASE_RJOIN,PRESET_DAILY_BYTES,PRESET_RATIO_TYPE,PRESET_RATIO, + PRESET_TIME_LIMIT,SYS_AUTO_VAL_PRESET,SYS_AUTO_VAL_DELAY,SYS_SMTP_PORT,SYS_HOLD_ACCESS_LEVEL, + SYS_STACK,SYS_PRIORITY,SYS_ICONIFY_LEFT,SYS_ICONIFY_TOP,SYS_TELNET_PORT,SYS_FTP_PORT, + SYS_DOS_CHECK_TIME,SYS_DOS_BAN_TIME,SYS_DOS_CHECK_TRIGGER,COMMAND_PASS_PARAMS,COMMAND_TYPE, + NODE_KEEP_UL_CREDIT,NODE_WIN_COLOURS,PRESET_AREA_NAME,SYS_LANGUAGE,SYS_NEW_ACCOUNTS, + SYS_TIMEOUT_LC,HTTP_TEMPDIR,MSGBASE_LOCATION,CONF_PATH,CONF_LOCAL_UPLOAD_PATH,NODE_SCREENS_PATH, + NODE_PLAYPEN_PATH,NODE_LOCAL_UPLOAD_PATH,SYS_LOCAL_UPLOAD_PATH,SYS_LANG_BASE_PATH,SYS_HISTORY_PATH, + SYS_USER_NOTES_PATH,SYS_BBS_PATH,NODE_USER_DATA_FILE,NODE_USER_MISC_FILE,NODE_USER_KEYS_FILE, + NODE_NOT_ALLOWED_FILE,NODE_DISPLAY_ID,ACCESS_AREA_NAME,FTP_AUTH,COMMAND_RESIDENT, + COMMAND_QUICK_MODE,COMMAND_TRAP_ON,COMMAND_EXPERT_MODE,COMMAND_SILENT,COMMAND_LOG_INPUTS, + COMMAND_SCRIPT_CHECK,COMMAND_MULTINODE,MSGBASE_SEND_EXTERNAL,MSGBASE_USES_USERNAMES,MSGBASE_USES_REALNAMES, + MSGBASE_USES_INETNAMES,CONF_FREE_DL,CONF_FORCE_MSCAN,CONF_USE_USERNAMES,CONF_USE_INETNAMES, + CONF_CUSTOM_MAIL,CONF_NEVER_MSCAN,CONF_DEFAULT_NEW_MSCAN,CONF_DEFAULT_NEW_FSCAN,CONF_DEFAULT_ZOOM, + CONF_USE_REALNAMES,CONF_ALWAYS_NEW_FILES,CONF_NEVER_NEW_FILES,CONF_FTP_UL_DISABLE,CONF_FTP_DIRLIST, + NODE_CALLERSLOG,NODE_CAPS_FILENAMES,NODE_DEF_SCREENS,NODE_DEBUG_LOGS,NODE_DOOR_LOGS,NODE_STARTUP_LOGS, + NODE_UD_LOGS,NO_CHAT_ON,NODE_NO_QUICK_LOGON,NODE_IDLE,NODE_MSCAN_PROMPT,NODE_NO_TIMEOUT,NODE_QUIET, + NODE_STEALTH,NODE_SHOW_PWFAILS,NODE_SENTBY_FILES,NODE_TELNET,NODE_FTP,NODE_TELNETD,NODE_TELSERD, + NODE_USERNUM_LOGON,NODE_VIEW_PWDS,NODE_LOG_IP,NODE_LOG_INPUTS,NODE_DISABLE_COMMODITY,NODE_CENTRAL_ANSWERS, + NODE_DISABLE_IEMSI,NODE_NO_MCI_MSG,NODE_NO_WILDCARDS,NODE_OWN_PARTUPLOADS,NODE_PHONE_CHECK,NODE_RAM_WORK, + NODE_CONSOLE_DEBUG,NODE_NO_EMAILS,NODE_OWNDEVUNIT,NODE_SHOW_CACHE_STATS,NODE_TRAPDOOR,NODE_TRAP_SERIAL, + NODE_NORADBOOGIE,NODE_A2232PATCH,NODE_NO_PURGE_LINE,NODE_REPURGE,NODE_LOGOFF_RESET,NODE_TRUE_RESET, + NODE_WIN_ICONIFIED,NODE_WIN_INTERLACE,NODE_WIN_STATUSBAR,NODE_WIN_TO_FRONT,SYS_CREDIT_BY_KB, + SYS_LONG_WHO,SYS_CONVERT_TO_MB,SYS_QUIET_JOIN,SYS_RELATIVE_CONFS,SYS_SSL_EMAILS,SYS_EMAIL_ON_SYSOP_PAGE, + SYS_EMAIL_ON_COMMENT,SYS_EMAIL_ON_LOGON,SYS_EMAIL_ON_LOGOFF,SYS_EMAIL_ON_NEW_USER,SYS_EMAIL_ON_UPLOAD, + SYS_EMAIL_ON_PW_FAIL,SYS_START_ICONIFIED,SYS_DO_NOT_MOVE,SYS_MULTICOM,SYS_AE_SHELL,SYS_NO_COMMODITY,SYS_DONT_SAVE_STATE, + CHECKER_SCRIPT,PROTOCOL_OPTIONS,HTTP_HOSTNAME,FTP_HOSTNAME,COMMAND_NAME,COMMAND_LOCATION,COMMAND_INTERNAL, + COMMAND_MIMIC_VER,COMMAND_PASSWORD,COMMAND_BANNER,CONF_NAME,CONF_FORWARD_MAIL,CONF_MENU_PROMPT,CONF_UPLOAD_PROMPT, + CONF_FTP_DIR_NAME,NODE_EXPRESS_FILE,NODE_SYSTEM_PASSWORD,NODE_SYSTEM_PASSWORD_PROMPT,NODE_NEW_USER_PASSWORD, + NODE_NAME_PROMPT,NODE_NAME_PROMPT2,NODE_PASSWORD_PROMPT,NODE_AUTO_VAL_PASSWORD,NODE_REMOTE_PASSWORD, + NODE_FORCE_ANSI,NODE_CON_IN_DEVICE,NODE_CON_OUT_DEVICE,NODE_SCREEN_PENS,NODE_CONF_DB_FILE, + NODE_FIRST_COMMAND,NODE_SERIAL_DEVICE,NODE_MODEM_INIT,NODE_MODEM_RESET,NODE_MODEM_RING,NODE_MODEM_ANSWER, + NODE_MODEM_OFFHOOK,NODE_MODEM_NRAMS,NODE_WIN_PUBSCREEN,SYS_BBS_NAME,SYS_BBS_LOCATION,SYS_SYSOP_NAME, + SYS_DEFAULT_MENU,SYS_AUTO_VAL_PASSWORD,SYS_REGKEY,SYS_SMTP_SERVER,SYS_SMTP_USERNAME,SYS_SMTP_PASSWORD, + SYS_SYSOP_EMAIL,SYS_BBS_EMAIL,SYS_FILEDIZ_CMD,SYS_FTP_HOST,SYS_EXEC_ON_NEW_USER,SYS_EXECA_ON_NEW_USER, + SYS_EXEC_ON_SYSOP_PAGE,SYS_EXECA_ON_SYSOP_PAGE,SYS_EXEC_ON_CONNECT,SYS_EXECA_ON_CONNECT, + SYS_EXEC_ON_LOGON,SYS_EXECA_ON_LOGON,SYS_EXEC_ON_LOGOFF,SYS_EXECA_ON_LOGOFF,SYS_EXEC_ON_COMMENT, + SYS_EXECA_ON_COMMENT,SYS_EXEC_ON_UPLOAD,SYS_EXECA_ON_UPLOAD,SYS_ACP_FONT,SYS_EXEC_ON_STARTUP, + SYS_NODE_X_LOC,SYS_NODE_X_NAME,SYS_NODE_X_SYSOP,SYS_BUTTON_NAME,SYS_BUTTON_COMMAND, + SYS_NUTTON_NAME,SYS_NUTTON_COMMAND,SYS_QWK_BBS_NUMBER,SYS_QWK_BBS_ADDRESS,SYS_QWK_BBS_ID, + SYS_QWK_ZIP_COMMAND,SYS_QWK_LHA_COMMAND,SYS_ASC_ZIP_COMMAND,SYS_ASC_LHA_COMMAND, + END_OF_LIST + +EXPORT DEF helpTexts:PTR TO LONG + +PROC addHelp(id,text) + IF id>=ListLen(helpTexts) THEN Throw( "HLP" , "LIST" ) + helpTexts[id]:=text +ENDPROC + +EXPORT PROC getHelpText(id) + IF id Date: Mon, 21 Aug 2023 17:34:20 +0100 Subject: [PATCH 10/47] setup tool changes --- axSetupTool/axSetupTool.e | 34 ++++ axSetupTool/frmAddComplexItem.e | 23 ++- axSetupTool/frmConfEdit.e | 2 +- axSetupTool/frmNodeEdit.e | 46 +++--- axSetupTool/helpText.e | 275 ++++++++++++++++++++++++++++++-- 5 files changed, 334 insertions(+), 46 deletions(-) diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index 710df11..23afb39 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -2,6 +2,40 @@ OPT OSVERSION = 37,STACK=60000,LARGE OPT PREPROCESS /* + ftpport ftpdataport httpport missing in bbsconfig + + backup files listview + buttons help text + restricted files listview + buttons help text + node navigation buttons help text + conf download paths listview + buttons help text + conf upload paths listview + buttons help text + messagebase paths listview + buttons help text + conf navigation buttons help text + access levels listview + buttons help text + messagebase name help text + access level help text + areas listview + buttons help text + area name help text + preset list 1-9 help text + commands listview + buttons help text + command name help text + computers listview + buttons help text + computer name help text + protocols listview + buttons help text + protocol name help text + names not allowed listview + buttons help text + name not allowed help text + screen types listview + buttons help text + screen type + extension help texts + languages listview + buttons help text + languages help text + drives listview + buttons help text + drives help text + file checkers listview + buttons help text + file checker name help text + connect strings listview + buttons help text + connect string + baud help text + about / help screens exit menu help texts diff --git a/axSetupTool/frmAddComplexItem.e b/axSetupTool/frmAddComplexItem.e index 7b8a2fa..c619d41 100644 --- a/axSetupTool/frmAddComplexItem.e +++ b/axSetupTool/frmAddComplexItem.e @@ -149,6 +149,8 @@ PROC editArea(acpName,areaName,oldArea:PTR TO area, existingAreas:PTR TO stdlist set( self.btnSave,MUIA_Disabled,MUI_TRUE) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) + NEW existingList.stringlist(existingAreas.count()) self.existingItems:=existingList FOR i:=0 TO existingAreas.count()-1 @@ -253,6 +255,8 @@ PROC editAccess(acpName,accessName,oldAccessLevel:PTR TO accessLevel, existingAc set( self.btnSave,MUIA_Disabled,MUI_TRUE) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) + NEW existingList.stringlist(existingAccessLevels.count()) self.existingItems:=existingList FOR i:=0 TO existingAccessLevels.count()-1 @@ -380,6 +384,8 @@ PROC editFileCheck(acpName,fCheckName,oldfCheck:PTR TO fChecker,existingFchecker set( self.btnSave,MUIA_Disabled,MUI_TRUE) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) + NEW existingList.stringlist(existingFcheckers.count()) self.existingItems:=existingList FOR i:=0 TO existingFcheckers.count()-1 @@ -402,7 +408,7 @@ PROC editFileCheck(acpName,fCheckName,oldfCheck:PTR TO fChecker,existingFchecker newfChecker:=0 - NEW controlChecker.createString('Checker',CHECKER_NAME,self.app.app,self.setChangedHook,self) + NEW controlChecker.createFileSelect('Checker',CHECKER_FILE,self.app.app,self.setChangedHook,self) fCheckControls.add(controlChecker) NEW controlError1.createString('Error 1',CHECKER_ERROR,self.app.app,self.setChangedHook,self) fCheckControls.add(controlError1) @@ -431,7 +437,7 @@ PROC editFileCheck(acpName,fCheckName,oldfCheck:PTR TO fChecker,existingFchecker NEW controlPriority.createStringInt('Priority',CHECKER_PRIORITY,self.app.app,self.setChangedHook,self) fCheckControls.add(controlPriority) - NEW controlScript.createString('Script',CHECKER_SCRIPT,self.app.app,self.setChangedHook,self) + NEW controlScript.createFileSelect('Script',CHECKER_SCRIPT,self.app.app,self.setChangedHook,self) fCheckControls.add(controlScript) NEW controlStack.createStringInt('Stack',CHECKER_STACK,self.app.app,self.setChangedHook,self) @@ -539,6 +545,8 @@ PROC editProtocol(acpName,protocolName,oldProtocol:PTR TO protocol,existingProto set( self.btnSave,MUIA_Disabled,MUI_TRUE) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) + NEW existingList.stringlist(existingProtocols.count()) self.existingItems:=existingList FOR i:=0 TO existingProtocols.count()-1 @@ -656,7 +664,6 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi DEF controlDoorSilent:PTR TO control DEF controlLogInputs:PTR TO control DEF controlScriptCheck:PTR TO control - DEF controlMultiNode:PTR TO control DEF controlBanner:PTR TO control DEF typeList:PTR TO LONG DEF existingList:PTR TO stringlist @@ -677,6 +684,8 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi set( self.btnSave,MUIA_Disabled,MUI_TRUE) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) + NEW existingList.stringlist(existingCommands.count()) self.existingItems:=existingList FOR i:=0 TO existingCommands.count()-1 @@ -717,7 +726,7 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi commandControls.add(controlPassword) NEW controlPassParams.createCycle('Pass Params',COMMAND_PASS_PARAMS,['N/A','No execute','Swap and retain','Swap, retain and redo','Bypass BBSCMD',0],self.app.app,self.setChangedHook,self) commandControls.add(controlPassParams) - NEW controlPriority.createStringInt('Priority',COMMAND_PRIORITY,self.app.app,self.setChangedHook,self) + NEW controlPriority.createString('Priority',COMMAND_PRIORITY,self.app.app,self.setChangedHook,self) commandControls.add(controlPriority) NEW controlStack.createStringInt('Stack',COMMAND_STACK,self.app.app,self.setChangedHook,self) commandControls.add(controlStack) @@ -740,8 +749,6 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi commandControls.add(controlLogInputs) NEW controlScriptCheck.createCheckBox('Script Check',COMMAND_SCRIPT_CHECK,self.app.app,self.setChangedHook,self) commandControls.add(controlScriptCheck) - NEW controlMultiNode.createCheckBox('Multinode',COMMAND_MULTINODE,self.app.app,self.setChangedHook,self) - commandControls.add(controlMultiNode) FOR i:=0 TO commandControls.count()-1 control:=commandControls.item(i) @@ -778,7 +785,6 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi controlDoorSilent.setValue(oldCommand.doorSilent) controlLogInputs.setValue(oldCommand.logInputs) controlScriptCheck.setValue(oldCommand.scriptCheck) - controlMultiNode.setValue(oldCommand.multiNode) controlBanner.setValue(oldCommand.banner) ENDIF self.changed:=FALSE @@ -814,7 +820,6 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi newCommand.doorSilent:=controlDoorSilent.getValue() newCommand.logInputs:=controlLogInputs.getValue() newCommand.scriptCheck:=controlScriptCheck.getValue() - newCommand.multiNode:=controlMultiNode.getValue() StrCopy(newCommand.banner,controlBanner.getValue()) ENDIF @@ -858,6 +863,8 @@ PROC editMsgbase(acpName,msgbaseName,oldMsgbase:PTR TO msgbase) OF frmAddComplex set( self.btnSave,MUIA_Disabled,MUI_TRUE) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) + self.acpName:=acpName readToolType(self.acpName,'BBS_LOCATION',bbsPath) diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index 381e0a4..1a6c15d 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -582,7 +582,7 @@ PROC addControls() OF frmConfEdit NEW control.createCheckBox('Disable FTP Uploads',CONF_FTP_UL_DISABLE,self.app.app,self.setChangedHook,self) self.boolNoFtpUploads:=control - NEW control.createCheckBox('Ftp Dirlist',CONF_FTP_DIRLIST,self.app.app,self.setChangedHook,self) + NEW control.createCheckBox('FTP No Dirlist',CONF_FTP_NO_DIRLIST,self.app.app,self.setChangedHook,self) self.boolFtpNoDirlist:=control self.controlList:=[self.strConfName2,self.paConfPath,self.strForwardMail,self.strMenuPrompt,self.strUploadPrompt,self.paLocalULPath, diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e index 93433b0..7cfd048 100644 --- a/axSetupTool/frmNodeEdit.e +++ b/axSetupTool/frmNodeEdit.e @@ -48,11 +48,10 @@ EXPORT OBJECT frmNodeEdit OF frmBase intAutoValPreset : PTR TO control intAutoValDelay : PTR TO control strAutoValPassword : PTR TO control - intFtpPort : PTR TO control - intFtpDataPort : PTR TO control - intHttpPort : PTR TO control + strFtpPort : PTR TO control + strFtpDataPort : PTR TO control + strHttpPort : PTR TO control intKeepUlCredit : PTR TO control - intMaxMsgLen : PTR TO control intMaxMsgQueue : PTR TO control paPlaypen : PTR TO control intRingCount : PTR TO control @@ -373,16 +372,14 @@ PROC addControls() OF frmNodeEdit self.intAutoValDelay:=control NEW control.createString('Auto Validate Password',NODE_AUTO_VAL_PASSWORD,self.app.app,self.setChangedHook,self) self.strAutoValPassword:=control - NEW control.createStringInt('FTP Port',NODE_FTP_PORT,self.app.app,self.setChangedHook,self) - self.intFtpPort:=control - NEW control.createStringInt('FTP Data Port',NODE_FTP_DATA_PORT,self.app.app,self.setChangedHook,self) - self.intFtpDataPort:=control - NEW control.createStringInt('HTTP Port',NODE_HTTP_PORT,self.app.app,self.setChangedHook,self) - self.intHttpPort:=control + NEW control.createString('FTP Port(s)',NODE_FTP_PORT,self.app.app,self.setChangedHook,self) + self.strFtpPort:=control + NEW control.createString('FTP Data Port(s)',NODE_FTP_DATA_PORT,self.app.app,self.setChangedHook,self) + self.strFtpDataPort:=control + NEW control.createString('HTTP Port(s)',NODE_HTTP_PORT,self.app.app,self.setChangedHook,self) + self.strHttpPort:=control NEW control.createCycle('UL Credit',NODE_KEEP_UL_CREDIT,['Default','Grant additional time',0],self.app.app,self.setChangedHook,self) self.intKeepUlCredit:=control - NEW control.createStringInt('Max Message Length',NODE_MAX_MSG_LEN,self.app.app,self.setChangedHook,self) - self.intMaxMsgLen:=control NEW control.createStringInt('Max Message Queue',NODE_MAX_MSG_QUEUE,self.app.app,self.setChangedHook,self) self.intMaxMsgQueue:=control NEW control.createDirSelect('Playpen Path',NODE_PLAYPEN_PATH,self.app.app,self.setChangedHook,self) @@ -573,7 +570,7 @@ PROC addControls() OF frmNodeEdit self.controlList1:= [self.intPriority,self.strNodeStart,self.strSystemPassword,self.strSystemPasswordPrompt,self.strNewuserPassword, self.strNamePrompt,self.strNamePrompt2,self.strPasswordPrompt,self.paScreens,self.intAutoValPreset,self.intAutoValDelay, - self.strAutoValPassword,self.intFtpPort,self.intFtpDataPort,self.intHttpPort,self.intKeepUlCredit,self.intMaxMsgLen, + self.strAutoValPassword,self.strFtpPort,self.strFtpDataPort,self.strHttpPort,self.intKeepUlCredit, self.intMaxMsgQueue,self.paPlaypen,self.intRingCount,self.strRemotePassword,self.intSysopChatColour,self.intUserChatColour, self.fnUserDataName,self.fnUserMiscName,self.fnUserKeysName,self.paLocalUlPath,self.strForceAnsi,self.intOverrideTimeout, self.intBGFilecheckStack,self.strConInputDev,self.strConOutputDev,self.strScreenPens,self.strConfDb,self.fnFilesNotAllowed, @@ -842,15 +839,14 @@ PROC saveChanges() OF frmNodeEdit writeToolType(nodeStr,'AUTOVAL_PRESET',self.intAutoValPreset.getValue()) writeToolType(nodeStr,'AUTOVAL_DELAY',self.intAutoValDelay.getValue()) writeToolType(nodeStr,'AUTOVAL_PASSWORD',self.strAutoValPassword.getValue()) - writeToolType(nodeStr,'FTPPORT',self.intFtpPort.getValue()) - writeToolType(nodeStr,'FTPDATAPORT',self.intFtpDataPort.getValue()) - writeToolType(nodeStr,'HTTPPORT',self.intHttpPort.getValue()) + writeToolType(nodeStr,'FTPPORT',self.strFtpPort.getValue()) + writeToolType(nodeStr,'FTPDATAPORT',self.strFtpDataPort.getValue()) + writeToolType(nodeStr,'HTTPPORT',self.strHttpPort.getValue()) val:=self.intKeepUlCredit.getValueIndex() StringF(tempStr,'\d',val) writeToolType(nodeStr,'KEEP_UPLOAD_CREDIT',tempStr) - writeToolType(nodeStr,'MAX_MSG_LEN',self.intMaxMsgLen.getValue()) writeToolType(nodeStr,'MAX_MSG_QU',self.intMaxMsgQueue.getValue()) writeToolType(nodeStr,'PLAYPEN',self.paPlaypen.getValue()) writeToolType(nodeStr,'RINGCOUNT',self.intRingCount.getValue()) @@ -1113,18 +1109,16 @@ PROC loadNode(node) OF frmNodeEdit readToolType(nodeStr,'AUTOVAL_PASSWORD',tooltypeValue) self.strAutoValPassword.setValue(tooltypeValue) - val:=readToolTypeInt(nodeStr,'FTPPORT') - self.intFtpPort.setValue(val) - val:=readToolTypeInt(nodeStr,'FTPDATAPORT') - self.intFtpDataPort.setValue(val) - val:=readToolTypeInt(nodeStr,'HTTPPORT') - self.intHttpPort.setValue(val) + readToolType(nodeStr,'FTPPORT',tooltypeValue) + self.strFtpPort.setValue(tooltypeValue) + readToolType(nodeStr,'FTPDATAPORT',tooltypeValue) + self.strFtpDataPort.setValue(tooltypeValue) + readToolType(nodeStr,'HTTPPORT',tooltypeValue) + self.strHttpPort.setValue(tooltypeValue) val:=readToolTypeInt(nodeStr,'KEEP_UPLOAD_CREDIT') IF val<>1 THEN val:=0 self.intKeepUlCredit.setValueIndex(val) - val:=readToolTypeInt(nodeStr,'MAX_MSG_LEN') - self.intMaxMsgLen.setValue(val) - val:=readToolTypeInt(nodeStr,'MAX_MSG_QU') + val:=readToolTypeInt(nodeStr,'MAX_MSG_QUE') self.intMaxMsgQueue.setValue(val) readToolType(nodeStr,'PLAYPEN',tooltypeValue) self.paPlaypen.setValue(tooltypeValue) diff --git a/axSetupTool/helpText.e b/axSetupTool/helpText.e index 45ba33d..eba860f 100644 --- a/axSetupTool/helpText.e +++ b/axSetupTool/helpText.e @@ -1,13 +1,13 @@ ->help text definitions OPT MODULE -EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_NAME,CHECKER_ERROR,CHECKER_OPTIONS,CHECKER_PRIORITY,CHECKER_STACK,HYDRA_RX_WINDOW,HYDRA_TX_WINDOW,COMMAND_ACCESS, +EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_FILE,CHECKER_ERROR,CHECKER_OPTIONS, + CHECKER_PRIORITY,CHECKER_STACK,HYDRA_RX_WINDOW,HYDRA_TX_WINDOW,COMMAND_ACCESS, COMMAND_PRIORITY,COMMAND_STACK,FTP_DIR_DAYS,NODE_PRIORITY,NODE_AUTO_VAL_PRESET, - NODE_AUTO_VAL_DELAY,NODE_FTP_PORT,NODE_FTP_DATA_PORT,NODE_HTTP_PORT,NODE_MAX_MSG_LEN, - NODE_MAX_MSG_QUEUE,NODE_RING_COUNT,NODE_SYSOP_CHAT_COLOUR,NODE_USER_CHAT_COLOUR,NODE_OVERRIDE_TIMEOUT, - NODE_BG_FILECHECK_STACK,NODE_SERIAL_CACHE_SIZE,NODE_SERIAL_DEV_UNIT,NODE_SERIAL_BAUD, - NODE_WIN_LEFT,NODE_WIN_TOP,NODE_WIN_WIDTH,NODE_WIN_HEIGHT,PRESET_ACCESS_LEVEL, - PRESET_CONF_RJOIN,PRESET_MESSAGEBASE_RJOIN,PRESET_DAILY_BYTES,PRESET_RATIO_TYPE,PRESET_RATIO, + NODE_AUTO_VAL_DELAY,NODE_FTP_PORT,NODE_FTP_DATA_PORT,NODE_HTTP_PORT,NODE_MAX_MSG_QUEUE,NODE_RING_COUNT, + NODE_SYSOP_CHAT_COLOUR,NODE_USER_CHAT_COLOUR,NODE_OVERRIDE_TIMEOUT,NODE_BG_FILECHECK_STACK, + NODE_SERIAL_CACHE_SIZE,NODE_SERIAL_DEV_UNIT,NODE_SERIAL_BAUD,NODE_WIN_LEFT,NODE_WIN_TOP,NODE_WIN_WIDTH,NODE_WIN_HEIGHT, + PRESET_ACCESS_LEVEL,PRESET_CONF_RJOIN,PRESET_MESSAGEBASE_RJOIN,PRESET_DAILY_BYTES,PRESET_RATIO_TYPE,PRESET_RATIO, PRESET_TIME_LIMIT,SYS_AUTO_VAL_PRESET,SYS_AUTO_VAL_DELAY,SYS_SMTP_PORT,SYS_HOLD_ACCESS_LEVEL, SYS_STACK,SYS_PRIORITY,SYS_ICONIFY_LEFT,SYS_ICONIFY_TOP,SYS_TELNET_PORT,SYS_FTP_PORT, SYS_DOS_CHECK_TIME,SYS_DOS_BAN_TIME,SYS_DOS_CHECK_TRIGGER,COMMAND_PASS_PARAMS,COMMAND_TYPE, @@ -17,10 +17,10 @@ EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_NAME,CHEC SYS_USER_NOTES_PATH,SYS_BBS_PATH,NODE_USER_DATA_FILE,NODE_USER_MISC_FILE,NODE_USER_KEYS_FILE, NODE_NOT_ALLOWED_FILE,NODE_DISPLAY_ID,ACCESS_AREA_NAME,FTP_AUTH,COMMAND_RESIDENT, COMMAND_QUICK_MODE,COMMAND_TRAP_ON,COMMAND_EXPERT_MODE,COMMAND_SILENT,COMMAND_LOG_INPUTS, - COMMAND_SCRIPT_CHECK,COMMAND_MULTINODE,MSGBASE_SEND_EXTERNAL,MSGBASE_USES_USERNAMES,MSGBASE_USES_REALNAMES, + COMMAND_SCRIPT_CHECK,MSGBASE_SEND_EXTERNAL,MSGBASE_USES_USERNAMES,MSGBASE_USES_REALNAMES, MSGBASE_USES_INETNAMES,CONF_FREE_DL,CONF_FORCE_MSCAN,CONF_USE_USERNAMES,CONF_USE_INETNAMES, CONF_CUSTOM_MAIL,CONF_NEVER_MSCAN,CONF_DEFAULT_NEW_MSCAN,CONF_DEFAULT_NEW_FSCAN,CONF_DEFAULT_ZOOM, - CONF_USE_REALNAMES,CONF_ALWAYS_NEW_FILES,CONF_NEVER_NEW_FILES,CONF_FTP_UL_DISABLE,CONF_FTP_DIRLIST, + CONF_USE_REALNAMES,CONF_ALWAYS_NEW_FILES,CONF_NEVER_NEW_FILES,CONF_FTP_UL_DISABLE,CONF_FTP_NO_DIRLIST, NODE_CALLERSLOG,NODE_CAPS_FILENAMES,NODE_DEF_SCREENS,NODE_DEBUG_LOGS,NODE_DOOR_LOGS,NODE_STARTUP_LOGS, NODE_UD_LOGS,NO_CHAT_ON,NODE_NO_QUICK_LOGON,NODE_IDLE,NODE_MSCAN_PROMPT,NODE_NO_TIMEOUT,NODE_QUIET, NODE_STEALTH,NODE_SHOW_PWFAILS,NODE_SENTBY_FILES,NODE_TELNET,NODE_FTP,NODE_TELNETD,NODE_TELSERD, @@ -52,7 +52,7 @@ EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_NAME,CHEC EXPORT DEF helpTexts:PTR TO LONG PROC addHelp(id,text) - IF id>=ListLen(helpTexts) THEN Throw( "HLP" , "LIST" ) + IF id>=END_OF_LIST THEN Throw( "HLP" , "LIST" ) helpTexts[id]:=text ENDPROC @@ -67,7 +67,260 @@ ENDPROC EXPORT PROC helpTextInitialise() helpTexts:=List(END_OF_LIST) SetList(helpTexts,END_OF_LIST) - addHelp(ACCESS_NAME_MAX_PAGES,'Maximum number of sysop pages \nallowed by the user in a session') - addHelp(ACCESS_NAME,'Grant access to the user to this item') + addHelp(ACCESS_NAME_MAX_PAGES,'Maximum number of sysop pages allowed by the user in a session') + addHelp(ACCESS_NAME,'Grant access to this function') + addHelp(ACCESS_AREA_NAME,'Grant access to this conference') + addHelp(CHECKER_FILE,'Full path to the file checker executable') + addHelp(CHECKER_ERROR,'Error string returned from checker that indicates the file is corrupt.') + addHelp(CHECKER_OPTIONS,'Additional command line options for the checker') + addHelp(CHECKER_PRIORITY,'Task priority to run the checker at') + addHelp(CHECKER_STACK,'Stack size allocated to the checker process') + addHelp(CHECKER_SCRIPT,'Script to run after testing') + addHelp(HYDRA_RX_WINDOW,'Hydra protocol receive window size') + addHelp(HYDRA_TX_WINDOW,'Hydra protocol transmit window size') + addHelp(COMMAND_ACCESS,'Access level required for this command') + addHelp(COMMAND_PRIORITY,'Task priority to run this command process at. You can also specify SAME to run this at the same priority as the node process.') + addHelp(COMMAND_STACK,'Stack space allocated to the command process') + addHelp(FTP_DIR_DAYS,'Number of days of files to be shown in the ftp server file list') + addHelp(NODE_PRIORITY,'Task priority for the node process') + addHelp(NODE_AUTO_VAL_PRESET,'Preset number to be applied when auto validation is triggered. Applies to this node only - can also be set at the system level.') + addHelp(NODE_AUTO_VAL_DELAY,'Delay (in hours) before auto validation is triggered for a new user') + addHelp(NODE_FTP_PORT,'Port number(s) that this node will use for FTP connections. You may specify a list of ports using a comma to separate. This relates to the older ftp functionality introduced in Ami-Express 5.2.0. This can also be configured in the system settings The new ftp server uses a single port managed by ACP and is managed in the server settings.') + addHelp(NODE_FTP_DATA_PORT,'Port number(s) that this node will use for FTP data connections. You may specify a list of ports using a comma to separate. This can also be configured in the system settings rather than for each node.') + addHelp(NODE_HTTP_PORT,'Port number(s) that this node will use for HTTP connections. You may specify a list of ports using a comma to separate. This can also be configured in the system settings rather than for each node.') + addHelp(NODE_MAX_MSG_QUEUE,'This determines how much memory is reserved for online messages to this node. It is not actually a hard limit to the number of messages as more memory will be allocated as needed. There is no real reason to use this setting.') + addHelp(NODE_RING_COUNT,'Number of rings after which this node will answer. If you are using native telnet or your modem is configured to auto answer this setting is not applicable') + addHelp(NODE_SYSOP_CHAT_COLOUR,'This is the colour for the sysop text in sysop chat. Valid values are 31-37 (standard ansi colours).') + addHelp(NODE_USER_CHAT_COLOUR,'This is the colour for the users text in sysop chat. Valid values are 31-37 (standard ansi colours).') + addHelp(NODE_OVERRIDE_TIMEOUT,'Override the idle timeout for this node. Specified in seconds.') + addHelp(NODE_BG_FILECHECK_STACK,'Sets the stack size used for the background process used during background file checking. Defaults to 20000 but you may need to increase this if you get crashes during background file checking.') + addHelp(NODE_SERIAL_CACHE_SIZE,'Enables serial writes to be cached until the next serial read or the cache limit is hit. Recommended to leave this disabled.') + addHelp(NODE_SERIAL_DEV_UNIT,'Serial interace unit number.') + addHelp(NODE_SERIAL_BAUD,'Serial interace baud rate.') + addHelp(NODE_WIN_LEFT,'Specifies the Left Edge of the Node Window.') + addHelp(NODE_WIN_TOP,'Specifies the Top Edge of the Node Window.') + addHelp(NODE_WIN_WIDTH,'Specifies the Width of the Node Window.') + addHelp(NODE_WIN_HEIGHT,'Specifies the Height of the Node Window.') + addHelp(PRESET_ACCESS_LEVEL,'Specifies the Access Level assigned to this preset.') + addHelp(PRESET_CONF_RJOIN,'Specifies the Default Conference assigned to this preset.') + addHelp(PRESET_MESSAGEBASE_RJOIN,'Specifies the Default Message Base assigned to this preset.') + addHelp(PRESET_DAILY_BYTES,'Specifies the Daily byte download limit for the preset.') + addHelp(PRESET_RATIO_TYPE,'Specifies the ratio type for the preset.') + addHelp(PRESET_RATIO,'Specifies the ratio for the preset.') + addHelp(PRESET_TIME_LIMIT,'Specifies the time limit (in seconds) for the preset.') + addHelp(SYS_AUTO_VAL_PRESET,'Preset number to be applied when auto validation is triggered') + addHelp(SYS_AUTO_VAL_DELAY,'Preset number to be applied when auto validation is triggered.') + addHelp(SYS_SMTP_PORT,'SMTP port number used to allow Ami-Express to send system emails.') + addHelp(SYS_HOLD_ACCESS_LEVEL,'Access level at which users can view the hold area.') + addHelp(SYS_STACK,'Stack size allocated to each node process.') + addHelp(SYS_PRIORITY,'Task priority given to each node process.') + addHelp(SYS_ICONIFY_LEFT,'Defines the left pixel position that the iconified /X image is displayed.') + addHelp(SYS_ICONIFY_TOP,'Defines the top pixel position that the iconified /X image is displayed.') + addHelp(SYS_TELNET_PORT,'Defines the port used for native telnet.') + addHelp(SYS_FTP_PORT,'Defines the port used for the newer ftp server (which was introduced in version 5.5.0).') + addHelp(SYS_DOS_CHECK_TIME,'Defines the timeframe for the denial of service protection checks (in seconds).') + addHelp(SYS_DOS_BAN_TIME,'Defines the length of the ban (in seconds) after a denial of service attack.') + addHelp(SYS_DOS_CHECK_TRIGGER,'Defines the trigger level for the denial of service protection. If a user attempts to connect a certain number of times in the given time period their ip will be banned.') + addHelp(COMMAND_PASS_PARAMS,'Controls the way the internal commands are executed.') + addHelp(COMMAND_TYPE,'Door executable type.') + addHelp(NODE_KEEP_UL_CREDIT,'Controls how upload credits are awarded.') + addHelp(NODE_WIN_COLOURS,'Controls screen pens.') + addHelp(PRESET_AREA_NAME,'Sets the area for the preset.') + addHelp(SYS_LANGUAGE,'Sets the host language for the system. This is used by the auto-translation feature.') + addHelp(SYS_NEW_ACCOUNTS,'Controls how new accounts are created.') + addHelp(SYS_TIMEOUT_LC,'Specifies if timeouts are considered as a dropped call.') + addHelp(HTTP_TEMPDIR,'Defines the temporarily folder used during http transfers.') + addHelp(MSGBASE_LOCATION,'Defines the folder used to store the messagebase.') + addHelp(CONF_PATH,'Defines the folder where the conference is located. This is mandatory for all conferences.') + addHelp(CONF_LOCAL_UPLOAD_PATH,'Defines the default path that will be used in the file requester for local uploads in this conference.') + addHelp(NODE_SCREENS_PATH,'Specifies the folder where the screens will be located for this node.') + addHelp(NODE_PLAYPEN_PATH,'Specifies an alternate playpen path for this node.') + addHelp(NODE_LOCAL_UPLOAD_PATH,'Defines the default path that will be used in the file requester for local uploads in this node.') + addHelp(SYS_LOCAL_UPLOAD_PATH,'Defines the default path that will be used in the file requester for local uploads if there are no overrides at node or conference in effect.') + addHelp(SYS_LANG_BASE_PATH,'Defines the folder where the language translation files are stored.') + addHelp(SYS_HISTORY_PATH,'Specifies the folder where the user history files are stored. These record the users command history.') + addHelp(SYS_USER_NOTES_PATH,'Specifies the folder where the user notes are stored.') + addHelp(SYS_BBS_PATH,'Defines the bbs root folder. It is recommended this should be set to BBS:') + addHelp(NODE_USER_DATA_FILE,'Overrides the user.data file - this can normally be left blank.') + addHelp(NODE_USER_MISC_FILE,'Overrides the user.misc file - this can normally be left blank.') + addHelp(NODE_USER_KEYS_FILE,'Overrides the user.keys file - this can normally be left blank.') + addHelp(NODE_NOT_ALLOWED_FILE,'Specifies a file which lists filenames you do not want to be uploaded.') + addHelp(NODE_DISPLAY_ID,'Define a display id for the node screen. Use a $ to indicate a hex value.') + addHelp(ACCESS_AREA_NAME,'Conference to be accessed.') + addHelp(FTP_AUTH,'Enables ftp authentication for the old ftp server.') + addHelp(COMMAND_RESIDENT,'This command is resident (disables checking that the file actually exists).') + addHelp(COMMAND_QUICK_MODE,'This command should not be executed if the user logged on using quick mode.') + addHelp(COMMAND_TRAP_ON,'Sends the standard output go to a log for error checking.') + addHelp(COMMAND_EXPERT_MODE,'Disables the menu immediately following the execution of this command (eg. temporarily forces expert mode).') + addHelp(COMMAND_SILENT,'Do not display any output from the command or allow any user input.') + addHelp(COMMAND_LOG_INPUTS,'Log all inputs while running this door in the callers log.') + addHelp(COMMAND_SCRIPT_CHECK,'This door is a script file so ensure it has +S flag before running it.') + addHelp(MSGBASE_SEND_EXTERNAL,'Send messages from this messagebase to the external queue (to be picked up by the QWK or FTN file processor.') + addHelp(MSGBASE_USES_USERNAMES,'This message base uses user names for messages.') + addHelp(MSGBASE_USES_REALNAMES,'This message base uses real names for messages.') + addHelp(MSGBASE_USES_INETNAMES,'This message base uses internet names for messages.') + addHelp(CONF_FREE_DL,'All files are free download in this conference.') + addHelp(CONF_FORCE_MSCAN,'Force all users to have a new mail scan for this conference at logon.') + addHelp(CONF_USE_USERNAMES,'This conference uses usernames for messaging.') + addHelp(CONF_USE_INETNAMES,'This conference uses internet names for messaging.') + addHelp(CONF_CUSTOM_MAIL,'This conference uses AmiX-NET mail.') + addHelp(CONF_NEVER_MSCAN,'New mail scanning at logon is disabled in this conference.') + addHelp(CONF_DEFAULT_NEW_MSCAN,'New mail scanning is turned on in this conference by default for all new users.') + addHelp(CONF_DEFAULT_NEW_FSCAN,'New file scanning is turned on in this conference by default for all new users.') + addHelp(CONF_DEFAULT_ZOOM,'Mail zoom is turned on in this conference for all new users.') + addHelp(CONF_USE_REALNAMES,'This conference uses real names for messaging.') + addHelp(CONF_ALWAYS_NEW_FILES,'Force all users to have a new file scan for this conference at logon.') + addHelp(CONF_NEVER_NEW_FILES,'New file scanning at logon is disabled for this conference.') + addHelp(CONF_FTP_UL_DISABLE,'Uploading via FTP is not allowed in this conference.') + addHelp(CONF_FTP_NO_DIRLIST,'When enabled the FTP directory listing will be generated by the contents of the download paths rather than using the normal Ami-Express file list.') + addHelp(NODE_CALLERSLOG,'Enable the callers log for this node.') + addHelp(NODE_CAPS_FILENAMES,'Enable all uploads to be converted to upper case file names for this node.') + addHelp(NODE_DEF_SCREENS,'Enable default security screens for this node. (eg bull.txt becomes higher priority than bullN.txt)') + addHelp(NODE_DEBUG_LOGS,'Enable debug logs for this node.') + addHelp(NODE_DOOR_LOGS,'Enable door start logs for this node.') + addHelp(NODE_STARTUP_LOGS,'Enable node startup logs for this node.') + addHelp(NODE_UD_LOGS,'Enable upload/download logs for this node.') + addHelp(NO_CHAT_ON,'Sysop chat is enabled at node startup.') + addHelp(NODE_NO_QUICK_LOGON,'Quick logons are disabled for this node.') + addHelp(NODE_IDLE,'Node should not be started by default.') + addHelp(NODE_MSCAN_PROMPT,'Prompt the user to ask if they wish to perform a mail scan at logon.') + addHelp(NODE_NO_TIMEOUT,'Input timeouts are disabled for this node. A user will never get kicked off unless they disconnect.') + addHelp(NODE_QUIET,'Node starts in quiet mode and will not be displaed in WHO list.') + addHelp(NODE_STEALTH,'The system password screen will be displaed before the Ami-Express welcome message.') + addHelp(NODE_SHOW_PWFAILS,'Incorrect passwords will be recorded in the Ami-Express callers log.') + addHelp(NODE_SENTBY_FILES,'A line will be added to each upload description with the uploaders name.') + addHelp(NODE_TELNET,'This node handles native telnet connections.') + addHelp(NODE_FTP,'This node handles FTP connection requests.') + addHelp(NODE_TELNETD,'This node is using telnet.device as its serial device.') + addHelp(NODE_TELSERD,'This node is using telserd.device as its serial device.') + addHelp(NODE_USERNUM_LOGON,'The user is allowed to log on using their user number when connecting to this node.') + addHelp(NODE_VIEW_PWDS,'Passwords are visible to the sysop on this node.') + addHelp(NODE_LOG_IP,'IP and HOSTNAME of users connecting to this node are recorded in the callers log.') + addHelp(NODE_LOG_INPUTS,'Log all inputs while running doors on this node in the callers log.') + addHelp(NODE_DISABLE_COMMODITY,'Disable the commodity for this node.') + addHelp(NODE_CENTRAL_ANSWERS,'Store all new user answers in the central folder for this node.') + addHelp(NODE_DISABLE_IEMSI,'Disable IEMSI auto logon for this node.') + addHelp(NODE_NO_MCI_MSG,'Disable the user of MCI codes in messages on this node.') + addHelp(NODE_NO_WILDCARDS,'Disable the use of wildcards when downloading on this node.') + addHelp(NODE_OWN_PARTUPLOADS,'Adds the node number to the filename for partuploads.') + addHelp(NODE_PHONE_CHECK,'User will be required to enter the last 4 digits of their phone number at logon.') + addHelp(NODE_RAM_WORK,'Disable the free space checking for the playpen area (useful if you are using RAM:).') + addHelp(NODE_CONSOLE_DEBUG,'Enable output of debug info to the standard output.') + addHelp(NODE_NO_EMAILS,'Disable all SMTP email sending for this node.') + addHelp(NODE_OWNDEVUNIT,'Use the oendevunit.library to control the serial device.') + addHelp(NODE_SHOW_CACHE_STATS,'Display tooltype cache stats in the node status window.') + addHelp(NODE_TRAPDOOR,'Start a trapdoor program instead of express.') + addHelp(NODE_TRAP_SERIAL,'Enable trapping of the A2232 error messages.') + addHelp(NODE_NORADBOOGIE,'Do not use the SERF_XDISABLED and SERF_RAD_BOOGIE when opening the serial device on this node.') + addHelp(NODE_A2232PATCH,'Turns on the A2232 multi-user serial card patch.') + addHelp(NODE_NO_PURGE_LINE,'Do not clear the serial port after a modem reset command is sent through the port.') + addHelp(NODE_REPURGE,'Enable this for A2232 cards. Manually clears the data after a modem reset since the CLEAR port command doesnt seem to work.') + addHelp(NODE_LOGOFF_RESET,'Reset the modem between each call. Should not be needed.') + addHelp(NODE_TRUE_RESET,'Forces a full modem reset after each call.') + addHelp(NODE_WIN_ICONIFIED,'This node does not open its window at startup.') + addHelp(NODE_WIN_INTERLACE,'This node runs on an interlaced screen.') + addHelp(NODE_WIN_STATUSBAR,'Enables the status bar on the node screen.') + addHelp(NODE_WIN_TO_FRONT,'If the node screen is open it will pop to the front whenever there is a connection to the node.') + addHelp(SYS_CREDIT_BY_KB,'Upload and download credits are recorded in kb rather than bytes.') + addHelp(SYS_LONG_WHO,'internal WHO command shows additional detail.') + addHelp(SYS_CONVERT_TO_MB,'File sizes in the file listings are converted to MB or GB instead of being shown in bytes if they are large.') + addHelp(SYS_QUIET_JOIN,'Joining conferences is less verbose.') + addHelp(SYS_RELATIVE_CONFS,'User will only see conference numbers for the conferences they can access.') + addHelp(SYS_SSL_EMAILS,'System emails should be sent using SSL.') + addHelp(SYS_EMAIL_ON_SYSOP_PAGE,'Enable system email when the sysop is paged.') + addHelp(SYS_EMAIL_ON_COMMENT,'Enable system email when a sysop comment is left.') + addHelp(SYS_EMAIL_ON_LOGON,'Enable system email when a user logs on.') + addHelp(SYS_EMAIL_ON_LOGOFF,'Enable system email when a user logs off.') + addHelp(SYS_EMAIL_ON_NEW_USER,'Enable system email when a new user registers.') + addHelp(SYS_EMAIL_ON_UPLOAD,'Enable system email when a user uploads.') + addHelp(SYS_EMAIL_ON_PW_FAIL,'Enable system email when a user fails the password check.') + addHelp(SYS_START_ICONIFIED,'On startup the ACP window should be iconified.') + addHelp(SYS_DO_NOT_MOVE,'Disable the ACP window resizing.') + addHelp(SYS_MULTICOM,'Enable the multicom port used for multi-node systems.') + addHelp(SYS_AE_SHELL,'Config button is replaced with the AESHELL button.') + addHelp(SYS_NO_COMMODITY,'Disable the ACP commodity.') + addHelp(SYS_DONT_SAVE_STATE,'Do not save the last callers, uploads, downloads information.') + addHelp(PROTOCOL_OPTIONS,'Additional options for the protocol.') + addHelp(HTTP_HOSTNAME,'Host name used for HTTP transfer protocol.') + addHelp(FTP_HOSTNAME,'Host name used for FTP transfer protocol.') + addHelp(COMMAND_NAME,'Command name to be displayed in ACP while this door is being executed.') + addHelp(COMMAND_LOCATION,'Path to the door executable for this command.') + addHelp(COMMAND_INTERNAL,'Run this internal command instead of an external door.') + addHelp(COMMAND_MIMIC_VER,'Ami-Express should report its version as this string while this door is being executed.') + addHelp(COMMAND_PASSWORD,'User will need to enter the password before they can use this command.') + addHelp(COMMAND_BANNER,'This banner string is displayed prior to the door being executed.') + addHelp(CONF_NAME,'The name of the conference.') + addHelp(CONF_FORWARD_MAIL,'Sysop comments in this conference will be redirected to the user specified.') + addHelp(CONF_MENU_PROMPT,'Override the menu prompt for this conference.') + addHelp(CONF_UPLOAD_PROMPT,'Display this message after the prompt to enter the file description when the user uplaods.') + addHelp(CONF_FTP_DIR_NAME,'Defines an alternative name for the conference folder for the FTP server (useful if your conference name has extended characters).') +/* +, + NODE_EXPRESS_FILE, + NODE_SYSTEM_PASSWORD, + NODE_SYSTEM_PASSWORD_PROMPT, + NODE_NEW_USER_PASSWORD, + NODE_NAME_PROMPT, + NODE_NAME_PROMPT2, + NODE_PASSWORD_PROMPT, + NODE_AUTO_VAL_PASSWORD, + NODE_REMOTE_PASSWORD, + NODE_FORCE_ANSI, + NODE_CON_IN_DEVICE, + NODE_CON_OUT_DEVICE, + NODE_SCREEN_PENS, + NODE_CONF_DB_FILE, + NODE_FIRST_COMMAND, + NODE_SERIAL_DEVICE, + NODE_MODEM_INIT, + NODE_MODEM_RESET, + NODE_MODEM_RING, + NODE_MODEM_ANSWER, + NODE_MODEM_OFFHOOK, + NODE_MODEM_NRAMS, + NODE_WIN_PUBSCREEN, + SYS_BBS_NAME, + SYS_BBS_LOCATION, + SYS_SYSOP_NAME, + SYS_DEFAULT_MENU, + SYS_AUTO_VAL_PASSWORD, + SYS_REGKEY, + SYS_SMTP_SERVER, + SYS_SMTP_USERNAME, + SYS_SMTP_PASSWORD, + SYS_SYSOP_EMAIL, + SYS_BBS_EMAIL, + SYS_FILEDIZ_CMD, + SYS_FTP_HOST, + SYS_EXEC_ON_NEW_USER, + SYS_EXECA_ON_NEW_USER, + SYS_EXEC_ON_SYSOP_PAGE, + SYS_EXECA_ON_SYSOP_PAGE, + SYS_EXEC_ON_CONNECT, + SYS_EXECA_ON_CONNECT, + SYS_EXEC_ON_LOGON, + SYS_EXECA_ON_LOGON, + SYS_EXEC_ON_LOGOFF, + SYS_EXECA_ON_LOGOFF, + SYS_EXEC_ON_COMMENT, + SYS_EXECA_ON_COMMENT, + SYS_EXEC_ON_UPLOAD, + SYS_EXECA_ON_UPLOAD, + SYS_ACP_FONT, + SYS_EXEC_ON_STARTUP, + SYS_NODE_X_LOC, + SYS_NODE_X_NAME, + SYS_NODE_X_SYSOP, + SYS_BUTTON_NAME, + SYS_BUTTON_COMMAND, + SYS_NUTTON_NAME, + SYS_NUTTON_COMMAND, + SYS_QWK_BBS_NUMBER, + SYS_QWK_BBS_ADDRESS, + SYS_QWK_BBS_ID, + SYS_QWK_ZIP_COMMAND, + SYS_QWK_LHA_COMMAND, + SYS_ASC_ZIP_COMMAND, + SYS_ASC_LHA_COMMAND,*/ ENDPROC From d6f06bef765c80aae3d1fad9e0f9813b88510c17 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 22 Aug 2023 17:23:30 +0100 Subject: [PATCH 11/47] Setup Tool Add all remaining help texts add exit menu button add about window add missing ftp port, ftp data port and http port settings --- axSetupTool/axSetupTool.e | 43 +----- axSetupTool/axedit.e | 56 +++---- axSetupTool/axsys.MUIB | Bin 20713 -> 20713 bytes axSetupTool/frmAddComplexItem.e | 13 ++ axSetupTool/frmAddItem.e | 18 ++- axSetupTool/frmConfEdit.e | 23 +++ axSetupTool/frmEditList.e | 73 ++++++++- axSetupTool/frmMain.e | 25 +++ axSetupTool/frmNodeEdit.e | 10 ++ axSetupTool/frmPresetsEdit.e | 1 + axSetupTool/frmSettingsEdit.e | 27 +++- axSetupTool/helpText.e | 263 +++++++++++++++++++++++--------- axSetupTool/makefile | 4 +- 13 files changed, 412 insertions(+), 144 deletions(-) diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index 23afb39..b1f6ec5 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -2,49 +2,16 @@ OPT OSVERSION = 37,STACK=60000,LARGE OPT PREPROCESS /* - ftpport ftpdataport httpport missing in bbsconfig - - backup files listview + buttons help text - restricted files listview + buttons help text - node navigation buttons help text - conf download paths listview + buttons help text - conf upload paths listview + buttons help text - messagebase paths listview + buttons help text - conf navigation buttons help text - access levels listview + buttons help text - messagebase name help text - access level help text - areas listview + buttons help text - area name help text - preset list 1-9 help text - commands listview + buttons help text - command name help text - computers listview + buttons help text - computer name help text - protocols listview + buttons help text - protocol name help text - names not allowed listview + buttons help text - name not allowed help text - screen types listview + buttons help text - screen type + extension help texts - languages listview + buttons help text - languages help text - drives listview + buttons help text - drives help text - file checkers listview + buttons help text - file checker name help text - connect strings listview + buttons help text - connect string + baud help text - - about / help screens - exit menu - help texts + ftpport ftpdataport httpport missing in bbsconfig + window.pubscreen can be WINDOW.PUBSCREEN or WINDOW.PUBSCREEN= + + help screens + restart bbs user editor callers log viewer msgbase viewer screens viewer - restart nodes/server */ ->///////////////////////////////////////////////////////////////////////////// diff --git a/axSetupTool/axedit.e b/axSetupTool/axedit.e index ae4e75e..b08f519 100644 --- a/axSetupTool/axedit.e +++ b/axSetupTool/axedit.e @@ -21,6 +21,9 @@ EXPORT OBJECT app_obj app : PTR TO LONG winMain : PTR TO LONG mn_label_1 : PTR TO LONG + mnlabel1Help : PTR TO LONG + mnlabel1About : PTR TO LONG + mnlabel1Exit : PTR TO LONG mnlabel1Donotremovefolder1 : PTR TO LONG mnlabel1Removefolder1 : PTR TO LONG mnlabel1Ask1 : PTR TO LONG @@ -185,27 +188,26 @@ ENDOBJECT ->///////////////////////////////////////////////////////////////////////////// PROC create( display : PTR TO app_display ) OF app_obj - DEF mnlabel1File , mnlabel1Help , mnlabel1About , mnlabel1Exit - DEF mnlabel1Settings , mnlabel1ConferenceDelete , grOUP_ROOT_0 - DEF gr_grp_1 , gr_grp_2 , im_label_2 , grOUP_ROOT_2 - DEF gr_confselect , obj_aux0 , obj_aux1 , obj_aux2 , obj_aux3 - DEF gr_grp_13 , gr_downloadpaths , gr_grp_20 , gr_uploadpaths - DEF gr_grp_22 , gr_messagebases , gr_grp_46 , gr_save - DEF grOUP_ROOT_3 , gr_nodeSelect , obj_aux4 , obj_aux5 - DEF lbl300start , lbl300end , lbl1200start , lbl1200end - DEF lbl2400start , lbl2400end , lbl4800start , lbl4800end - DEF lbl9600start , lbl9600end , lbl12000start , lbl12000end - DEF lbl14400start , lbl14400end , lbl16800start , lbl16800end - DEF lbl19200start , lbl19200end , lbl21600start , lbl21600end - DEF lbl24000start , lbl24000end , lbl26400start , lbl26400end - DEF lbl28800start , lbl28800end , lbl31200start , lbl31200end - DEF lbl33600start , lbl33600end , lbl38400start , lbl38400end - DEF lbl57600start , lbl57600end , lbl115200start , lbl115200end - DEF gr_nodesave , grp_root_listitems , space_28 , gr_grp_28 - DEF grOUP_ROOT_5 , grOUP_ROOT_6 , gr_settingsSaveCancel - DEF grOUP_ROOT_7 , gr_item_buttons , grOUP_ROOT_8 , gr_grp_39 - DEF gr_grp_36 , gr_grp_38 , grOUP_ROOT_9 , gr_grp_43 - DEF gr_area_save + DEF mnlabel1File , mnlabel1Settings , mnlabel1ConferenceDelete + DEF grOUP_ROOT_0 , gr_grp_1 , gr_grp_2 , im_label_2 + DEF grOUP_ROOT_2 , gr_confselect , obj_aux0 , obj_aux1 + DEF obj_aux2 , obj_aux3 , gr_grp_13 , gr_downloadpaths + DEF gr_grp_20 , gr_uploadpaths , gr_grp_22 , gr_messagebases + DEF gr_grp_46 , gr_save , grOUP_ROOT_3 , gr_nodeSelect + DEF obj_aux4 , obj_aux5 , lbl300start , lbl300end , lbl1200start + DEF lbl1200end , lbl2400start , lbl2400end , lbl4800start + DEF lbl4800end , lbl9600start , lbl9600end , lbl12000start + DEF lbl12000end , lbl14400start , lbl14400end , lbl16800start + DEF lbl16800end , lbl19200start , lbl19200end , lbl21600start + DEF lbl21600end , lbl24000start , lbl24000end , lbl26400start + DEF lbl26400end , lbl28800start , lbl28800end , lbl31200start + DEF lbl31200end , lbl33600start , lbl33600end , lbl38400start + DEF lbl38400end , lbl57600start , lbl57600end , lbl115200start + DEF lbl115200end , gr_nodesave , grp_root_listitems , space_28 + DEF gr_grp_28 , grOUP_ROOT_5 , grOUP_ROOT_6 + DEF gr_settingsSaveCancel , grOUP_ROOT_7 , gr_item_buttons + DEF grOUP_ROOT_8 , gr_grp_39 , gr_grp_36 , gr_grp_38 + DEF grOUP_ROOT_9 , gr_grp_43 , gr_area_save self.stR_TX_label_0 := '\ec/X\nSetup Tool' self.stR_gr_conf_pages := [ @@ -335,23 +337,23 @@ PROC create( display : PTR TO app_display ) OF app_obj Child , gr_grp_2 , End - mnlabel1Help := MenuitemObject , + self.mnlabel1Help := MenuitemObject , MUIA_Menuitem_Title , 'Help' , End - mnlabel1About := MenuitemObject , + self.mnlabel1About := MenuitemObject , MUIA_Menuitem_Title , 'About' , End - mnlabel1Exit := MenuitemObject , + self.mnlabel1Exit := MenuitemObject , MUIA_Menuitem_Title , 'Exit' , End mnlabel1File := MenuitemObject , MUIA_Menuitem_Title , 'File' , - MUIA_Family_Child , mnlabel1Help , - MUIA_Family_Child , mnlabel1About , - MUIA_Family_Child , mnlabel1Exit , + MUIA_Family_Child , self.mnlabel1Help , + MUIA_Family_Child , self.mnlabel1About , + MUIA_Family_Child , self.mnlabel1Exit , End self.mnlabel1Donotremovefolder1 := MenuitemObject , diff --git a/axSetupTool/axsys.MUIB b/axSetupTool/axsys.MUIB index 0d994838d2776571416f717b6e2196d530736afa..03b0ee54d81d175073f7dbac30df48f4c5a06d4c 100644 GIT binary patch delta 51 scmaF4kn!b0#tA`8W=0!B*qA0Wu}V&sW9FD#%_IhAZ$hvazhv?Q0FZ(X8~^|S delta 48 rcmaF4kn!b0#tA`8riL3s*qE3MxF#=jl%HJ9BnD${f-@JtWby+5gRKue diff --git a/axSetupTool/frmAddComplexItem.e b/axSetupTool/frmAddComplexItem.e index c619d41..5d8d460 100644 --- a/axSetupTool/frmAddComplexItem.e +++ b/axSetupTool/frmAddComplexItem.e @@ -146,6 +146,8 @@ PROC editArea(acpName,areaName,oldArea:PTR TO area, existingAreas:PTR TO stdlist set( self.winMain, MUIA_Window_ID, "FARE") set( self.lblAreaName, MUIA_Text_Contents,'Area Name') + set( self.lblAreaName, MUIA_ShortHelp , getHelpText(AREAS_NAME)) + set( self.txtAreaName, MUIA_ShortHelp , getHelpText(AREAS_NAME)) set( self.btnSave,MUIA_Disabled,MUI_TRUE) @@ -252,6 +254,8 @@ PROC editAccess(acpName,accessName,oldAccessLevel:PTR TO accessLevel, existingAc set( self.winMain, MUIA_Window_ID, "FACS") set( self.lblAreaName, MUIA_Text_Contents,'Access Level') + set( self.lblAreaName, MUIA_ShortHelp , getHelpText(ACS_NAME)) + set( self.txtAreaName, MUIA_ShortHelp , getHelpText(ACS_NAME)) set( self.btnSave,MUIA_Disabled,MUI_TRUE) @@ -381,6 +385,8 @@ PROC editFileCheck(acpName,fCheckName,oldfCheck:PTR TO fChecker,existingFchecker set( self.winMain, MUIA_Window_ID, "EFCH") set( self.lblAreaName, MUIA_Text_Contents,'File Type') + set( self.lblAreaName, MUIA_ShortHelp , getHelpText(FCHK_NAME)) + set( self.txtAreaName, MUIA_ShortHelp , getHelpText(FCHK_NAME)) set( self.btnSave,MUIA_Disabled,MUI_TRUE) @@ -542,6 +548,8 @@ PROC editProtocol(acpName,protocolName,oldProtocol:PTR TO protocol,existingProto set( self.winMain, MUIA_Window_ID, "EPCL") set( self.lblAreaName, MUIA_Text_Contents,'Protocol') + set( self.lblAreaName, MUIA_ShortHelp , getHelpText(PCOL_NAME)) + set( self.txtAreaName, MUIA_ShortHelp , getHelpText(PCOL_NAME)) set( self.btnSave,MUIA_Disabled,MUI_TRUE) @@ -681,6 +689,8 @@ PROC editCommand(acpName,commandName,commandFolder,oldCommand:PTR TO command,exi set( self.winMain, MUIA_Window_ID, "ECMD") set( self.lblAreaName, MUIA_Text_Contents,'Command') + set( self.lblAreaName, MUIA_ShortHelp , getHelpText(CMDS_NAME)) + set( self.txtAreaName, MUIA_ShortHelp , getHelpText(CMDS_NAME)) set( self.btnSave,MUIA_Disabled,MUI_TRUE) @@ -861,6 +871,9 @@ PROC editMsgbase(acpName,msgbaseName,oldMsgbase:PTR TO msgbase) OF frmAddComplex set( self.lblAreaName, MUIA_Text_Contents,'Name') + set( self.lblAreaName, MUIA_ShortHelp , getHelpText(MBASE_NAME)) + set( self.txtAreaName, MUIA_ShortHelp , getHelpText(MBASE_NAME)) + set( self.btnSave,MUIA_Disabled,MUI_TRUE) set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(50)) diff --git a/axSetupTool/frmAddItem.e b/axSetupTool/frmAddItem.e index 7624252..7d85798 100644 --- a/axSetupTool/frmAddItem.e +++ b/axSetupTool/frmAddItem.e @@ -4,7 +4,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui' MODULE 'tools/boopsi','dos/dos','libraries/asl' MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' -MODULE '*axedit','*frmBase' +MODULE '*axedit','*frmBase','*helpText' EXPORT OBJECT frmAddItem OF frmBase lblItemDetail1: LONG @@ -80,6 +80,11 @@ PROC addScreen(title) OF frmAddItem set( self.lblItemDetail1, MUIA_Text_Contents,'Screen Title') set( self.lblItemDetail2, MUIA_Text_Contents,'Extension') + set( self.lblItemDetail1, MUIA_ShortHelp , getHelpText(SCRN_NAME)) + set( self.txtItemDetail1, MUIA_ShortHelp , getHelpText(SCRN_NAME)) + set( self.lblItemDetail2, MUIA_ShortHelp , getHelpText(SCRN_EXT)) + set( self.txtItemDetail2, MUIA_ShortHelp , getHelpText(SCRN_EXT)) + set( self.btnSave,MUIA_Disabled,FALSE) set( self.txtItemDetail1, MUIA_String_Contents,title) @@ -102,6 +107,11 @@ PROC editScreen(title,extension) OF frmAddItem set( self.lblItemDetail1, MUIA_Text_Contents,'Screen Title') set( self.lblItemDetail2, MUIA_Text_Contents,'Extension') + set( self.lblItemDetail1, MUIA_ShortHelp , getHelpText(SCRN_NAME)) + set( self.txtItemDetail1, MUIA_ShortHelp , getHelpText(SCRN_NAME)) + set( self.lblItemDetail2, MUIA_ShortHelp , getHelpText(SCRN_EXT)) + set( self.txtItemDetail2, MUIA_ShortHelp , getHelpText(SCRN_EXT)) + set( self.btnSave,MUIA_Disabled,MUI_TRUE) set( self.txtItemDetail1, MUIA_String_Contents,title) @@ -129,6 +139,12 @@ PROC editConnectionString(connectString,baudString) OF frmAddItem set( self.txtItemDetail1, MUIA_String_Contents,connectString) set( self.txtItemDetail2, MUIA_String_Contents,baudString) + set( self.lblItemDetail1, MUIA_ShortHelp , getHelpText(CONN_TEXT)) + set( self.txtItemDetail1, MUIA_ShortHelp , getHelpText(CONN_TEXT)) + set( self.lblItemDetail2, MUIA_ShortHelp , getHelpText(CONN_BAUD)) + set( self.txtItemDetail2, MUIA_ShortHelp , getHelpText(CONN_BAUD)) + + self.addNotifications() res:=self.showModal() diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index 1a6c15d..d1c3ba6 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -1047,6 +1047,29 @@ PROC editConfs(acpName) OF frmConfEdit set( self.btnUlPathRemove , MUIA_Disabled , MUI_TRUE) set( self.btnDlPathRemove , MUIA_Disabled , MUI_TRUE) + set( self.lvDownloadPaths , MUIA_ShortHelp , getHelpText(DLPATHS_LVIEW)) + set( self.btnDlPathAdd , MUIA_ShortHelp , getHelpText(DLPATHS_ADD)) + set( self.btnDlPathRemove , MUIA_ShortHelp , getHelpText(DLPATHS_DELETE)) + set(self.strDownloadPath, MUIA_ShortHelp , getHelpText(DLPATHS_TEXT)) + + set( self.lvUploadPaths , MUIA_ShortHelp , getHelpText(ULPATHS_LVIEW)) + set( self.btnUlPathAdd , MUIA_ShortHelp , getHelpText(ULPATHS_ADD)) + set( self.btnUlPathRemove , MUIA_ShortHelp , getHelpText(ULPATHS_DELETE)) + set(self.strUploadPath, MUIA_ShortHelp , getHelpText(ULPATHS_TEXT)) + + set( self.lvMsgBases , MUIA_ShortHelp , getHelpText(MBASE_LVIEW)) + set( self.btnAddMsgbase , MUIA_ShortHelp , getHelpText(MBASE_ADD)) + set( self.btnEditMsgbase , MUIA_ShortHelp , getHelpText(MBASE_EDIT)) + set( self.btnRemoveMsgbase , MUIA_ShortHelp , getHelpText(MBASE_DELETE)) + + set( self.btnFirstConf, MUIA_ShortHelp , getHelpText(CONF_FIRST)) + set( self.btnPrevConf, MUIA_ShortHelp , getHelpText(CONF_PREV)) + set( self.btnNextConf, MUIA_ShortHelp , getHelpText(CONF_NEXT)) + set( self.btnLastConf, MUIA_ShortHelp , getHelpText(CONF_LAST)) + set( self.btnAddConf, MUIA_ShortHelp , getHelpText(CONF_ADD)) + set( self.btnCloneConf, MUIA_ShortHelp , getHelpText(CONF_CLONE)) + set( self.btnRemoveConf, MUIA_ShortHelp , getHelpText(CONF_DEL)) + installhook( self.setChangedHook, {setChangedFlag}) self.addControls() self.addNotifications() diff --git a/axSetupTool/frmEditList.e b/axSetupTool/frmEditList.e index 6b969f5..f0074c3 100644 --- a/axSetupTool/frmEditList.e +++ b/axSetupTool/frmEditList.e @@ -5,7 +5,7 @@ MODULE 'muimaster' , 'libraries/mui' MODULE 'tools/boopsi','workbench/workbench','icon','dos/dos' MODULE 'utility/tagitem' , 'utility/hooks','tools/installhook' -MODULE '*axedit','*frmBase','*tooltypes','*frmAddItem','*frmAddComplexItem','*/stringlist','*miscfuncs','*configobject' +MODULE '*axedit','*frmBase','*tooltypes','*frmAddItem','*frmAddComplexItem','*/stringlist','*miscfuncs','*configobject','*helpText' EXPORT OBJECT frmEditList OF frmBase oldcount : INT @@ -621,7 +621,6 @@ PROC screenitemEdit() OF frmEditList StringF(tempStr,'\s (\s)',v1,v2) domethod( self.lList , [ MUIM_List_Remove, entry ] ) domethod( self.lList , [ MUIM_List_InsertSingle , tempStr , entry ] ) - set(self.lList,MUIA_List_Active,entry) self.extensions.setItem(entry,v2) self.titles.setItem(entry,v1) self.changed:=TRUE @@ -813,6 +812,12 @@ PROC editComputers(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(COMPS_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(COMPS_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(COMPS_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(COMPS_DELETE)) + set(self.strItem, MUIA_ShortHelp , getHelpText(COMPS_NAME)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Computers') @@ -897,6 +902,12 @@ PROC editNamesNotAllowed(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(NNA_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(NNA_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(NNA_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(NNA_DELETE)) + set(self.strItem, MUIA_ShortHelp , getHelpText(NNA_NAME)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Names Not Allowed') @@ -984,6 +995,12 @@ PROC editDrives(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(DRV_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(DRV_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(DRV_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(DRV_DELETE)) + set(self.strItem, MUIA_ShortHelp , getHelpText(DRV_NAME)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Drives') @@ -1072,6 +1089,12 @@ PROC editLanguages(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(LANG_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(LANG_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(LANG_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(LANG_DELETE)) + set(self.strItem, MUIA_ShortHelp , getHelpText(LANG_NAME)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Languages') @@ -1167,6 +1190,11 @@ PROC editScreens(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , FALSE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(SCRN_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(SCRN_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(SCRN_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(SCRN_DELETE)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Screentypes') @@ -1386,6 +1414,11 @@ PROC editAreas(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , FALSE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(AREAS_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(AREAS_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(AREAS_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(AREAS_DELETE)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Areas') @@ -1585,6 +1618,10 @@ PROC editAccessLevel(acpName) OF frmEditList set( self.winMain, MUIA_Window_Title,'Edit Access Levels') set( self.winMain, MUIA_Window_ID, "FALS") + set( self.lvList , MUIA_ShortHelp , getHelpText(ACS_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(ACS_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(ACS_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(ACS_DELETE)) self.setupButtonClick(self.btnItemAdd,self.btnAddClick,{accessLevelitemAdd}) self.setupButtonClick(self.btnItemEdit,self.btnEditClick,{accessLevelitemEdit}) @@ -1795,6 +1832,11 @@ PROC editFileCheckers(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , FALSE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(FCHK_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(FCHK_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(FCHK_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(FCHK_DELETE)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit File Checkers') @@ -1999,6 +2041,11 @@ PROC editProtocols(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , FALSE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(PCOL_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(PCOL_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(PCOL_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(PCOL_DELETE)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Protocols') @@ -2241,6 +2288,11 @@ PROC editCommands(acpName,commandFolder) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , FALSE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(CMDS_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(CMDS_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(CMDS_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(CMDS_DELETE)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,editStr) @@ -2330,6 +2382,11 @@ PROC editConnectionStrings(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , FALSE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(CONN_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(CONN_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(CONN_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(CONN_DELETE)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Connection Strings') @@ -2442,6 +2499,12 @@ PROC editRestricted(acpName) OF frmEditList set( self.winMain, MUIA_Window_Title,'Edit Restricted Files') set( self.winMain, MUIA_Window_ID, "FRST") + set( self.lvList , MUIA_ShortHelp , getHelpText(RESTRICT_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(RESTRICT_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(RESTRICT_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(RESTRICT_DELETE)) + set(self.strItem, MUIA_ShortHelp , getHelpText(RESTRICT_TEXT)) + set(self.app.grp_arrange,MUIA_Group_Columns,1) set(self.strItem,MUIA_ShowMe,MUI_TRUE) set(self.app.grp_computers_add,MUIA_Group_Horiz,MUI_TRUE) @@ -2523,6 +2586,12 @@ PROC editBackup(acpName) OF frmEditList set( self.btnItemAdd , MUIA_Disabled , MUI_TRUE) set(self.strItem, MUIA_String_Contents,'') + set( self.lvList , MUIA_ShortHelp , getHelpText(BACKUP_LVIEW)) + set( self.btnItemAdd , MUIA_ShortHelp , getHelpText(BACKUP_ADD)) + set( self.btnItemEdit , MUIA_ShortHelp , getHelpText(BACKUP_EDIT)) + set( self.btnItemRemove , MUIA_ShortHelp , getHelpText(BACKUP_DELETE)) + set(self.strItem, MUIA_ShortHelp , getHelpText(BACKUP_TEXT)) + domethod( self.lList , [ MUIM_List_Clear] ) set( self.winMain, MUIA_Window_Title,'Edit Backup Files') diff --git a/axSetupTool/frmMain.e b/axSetupTool/frmMain.e index 5709296..5478974 100644 --- a/axSetupTool/frmMain.e +++ b/axSetupTool/frmMain.e @@ -26,6 +26,7 @@ EXPORT OBJECT frmMain OF frmBase btnBackupClickHook: hook btnRestrictClickHook: hook btnExitClickHook: hook + btnAboutClickHook: hook ENDOBJECT PROC exitbuttonPressed() OF frmMain @@ -34,6 +35,17 @@ PROC exitbuttonPressed() OF frmMain domethod(self.app.app,[MUIM_Application_ReturnID,MUIA_Window_CloseRequest]) ENDPROC +PROC aboutbuttonPressed() OF frmMain + DEF win + MOVE.L (A1),self + GetA4() + get(self.winMain,MUIA_Window_Window,{win}) + EasyRequestArgs( win , [ 20 , 0 , + 'About Ami-Express Setup Tool' , + 'This tool can assist you in configuring\nalmost every aspect of Ami-Express.\n\n(c)2023 Darren Coles.', + '_OK' ] , NIL , NIL ) +ENDPROC + PROC computersbuttonPressed() OF frmMain DEF listEdit:PTR TO frmEditList MOVE.L (A1),self @@ -337,6 +349,19 @@ PROC domain() OF frmMain self.setupButtonClick(self.app.btnExit,self.btnExitClickHook,{exitbuttonPressed}) self.setupButtonClick(self.app.btnRestrict,self.btnRestrictClickHook,{restrictbuttonPressed}) self.setupButtonClick(self.app.btnBackup,self.btnBackupClickHook,{backupbuttonPressed}) + self.setupButtonClick(self.app.btnAbout,self.btnAboutClickHook,{aboutbuttonPressed}) + + domethod( self.app.mnlabel1Exit , [ + MUIM_Notify , MUIA_Menuitem_Trigger, MUIV_EveryTime, + self.app.mnlabel1Exit, + 3, + MUIM_CallHook , self.btnExitClickHook, self ] ) + + domethod( self.app.mnlabel1About , [ + MUIM_Notify , MUIA_Menuitem_Trigger, MUIV_EveryTime, + self.app.mnlabel1About, + 3, + MUIM_CallHook , self.btnAboutClickHook, self ] ) set( self.app.btnUsers, MUIA_Text_Contents,'Unused') set( self.app.btnUsers, MUIA_Disabled , MUI_TRUE) diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e index 7cfd048..98db838 100644 --- a/axSetupTool/frmNodeEdit.e +++ b/axSetupTool/frmNodeEdit.e @@ -1303,6 +1303,14 @@ PROC editNodes(acpName) OF frmNodeEdit installhook( closeHook, {canClose}) self.closeHook:=closeHook + set( self.btnFirstNode, MUIA_ShortHelp , getHelpText(NODE_FIRST)) + set( self.btnPrevNode, MUIA_ShortHelp , getHelpText(NODE_PREV)) + set( self.btnNextNode, MUIA_ShortHelp , getHelpText(NODE_NEXT)) + set( self.btnLastNode, MUIA_ShortHelp , getHelpText(NODE_LAST)) + set( self.btnAddNode, MUIA_ShortHelp , getHelpText(NODE_ADD)) + set( self.btnCloneNode, MUIA_ShortHelp , getHelpText(NODE_CLONE)) + set( self.btnRemoveNode, MUIA_ShortHelp , getHelpText(NODE_DEL)) + self.timesList:=[ ['300',self.app.str300start,self.app.str300end]:timeItem, ['1200',self.app.str1200start,self.app.str1200end]:timeItem, @@ -1323,6 +1331,8 @@ PROC editNodes(acpName) OF frmNodeEdit ['57600',self.app.str57600start,self.app.str57600end]:timeItem, ['115200',self.app.str115200start,self.app.str115200end]:timeItem] + ForAll({timeItem},self.timesList,`set( timeItem.startControl, MUIA_ShortHelp , getHelpText(NODE_TIME_START))) + ForAll({timeItem},self.timesList,`set( timeItem.endControl, MUIA_ShortHelp , getHelpText(NODE_TIME_END))) ForAll({timeItem},self.timesList,`domethod( timeItem.startControl,[MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,self.app.app,3,MUIM_CallHook,self.setChangedHook,self])) ForAll({timeItem},self.timesList,`domethod( timeItem.endControl,[MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,self.app.app,3,MUIM_CallHook,self.setChangedHook,self])) diff --git a/axSetupTool/frmPresetsEdit.e b/axSetupTool/frmPresetsEdit.e index d3cb3a8..1eea4ec 100644 --- a/axSetupTool/frmPresetsEdit.e +++ b/axSetupTool/frmPresetsEdit.e @@ -363,6 +363,7 @@ PROC editPresets(acpName:PTR TO CHAR) OF frmPresetsEdit set( self.winMain, MUIA_Window_Title,'Edit Presets') set(self.raPreset,MUIA_Radio_Active,0) + set(self.raPreset, MUIA_ShortHelp , getHelpText(PRESET_NUMBER)) self.changed:=FALSE self.loadPreset(1) diff --git a/axSetupTool/frmSettingsEdit.e b/axSetupTool/frmSettingsEdit.e index 5a74c28..a801089 100644 --- a/axSetupTool/frmSettingsEdit.e +++ b/axSetupTool/frmSettingsEdit.e @@ -59,6 +59,9 @@ EXPORT OBJECT frmSettingsEdit OF frmBase intHoldAccess : PTR TO control strFileDizSysCmd : PTR TO control strFtpHost : PTR TO control + strFtpPort : PTR TO control + strFtpDataPort : PTR TO control + strHttpPort : PTR TO control strExecOnNewUser : PTR TO control strExecAOnNewUser: PTR TO control strExecOnPage : PTR TO control @@ -260,7 +263,12 @@ PROC addSystemControls() OF frmSettingsEdit self.strFileDizSysCmd:=control NEW control.createString('FTP host name',SYS_FTP_HOST,self.app.app,self.setChangedHook,self) self.strFtpHost:=control - + NEW control.createString('FTP port(s)',SYS_FTP_PORT,self.app.app,self.setChangedHook,self) + self.strFtpPort:=control + NEW control.createString('FTP data port(s)',SYS_FTP_DATA_PORT,self.app.app,self.setChangedHook,self) + self.strFtpDataPort:=control + NEW control.createString('HTTP port(s)',SYS_HTTP_PORT,self.app.app,self.setChangedHook,self) + self.strHttpPort:=control NEW control.createString('Execute on new user',SYS_EXEC_ON_NEW_USER,self.app.app,self.setChangedHook,self) self.strExecOnNewUser:=control NEW control.createString('Execute async on new user',SYS_EXECA_ON_NEW_USER,self.app.app,self.setChangedHook,self) @@ -295,8 +303,9 @@ PROC addSystemControls() OF frmSettingsEdit self.strSmtpHost,self.intSmtpPort,self.strSmtpUsername,self.strSmtpPassword,self.boolSmtpSSL,self.strSysopEmail, self.strBbsEmail,self.boolMailOnPage,self.boolMailOnComment,self.boolMailOnLogon,self.boolMailOnLogoff,self.boolMailOnNewUser, self.boolMailOnUpload,self.boolMailOnPwdFail,self.paLanguageBase,self.paHistory,self.paUserNotes,self.intHoldAccess, - self.strFileDizSysCmd,self.strFtpHost,self.strExecOnNewUser,self.strExecAOnNewUser,self.strExecOnPage,self.strExecAOnPage, - self.strExecOnConnect,self.strExecAOnConnect,self.strExecOnLogon,self.strExecAOnLogon,self.strExecOnLogoff,self.strExecAOnLogoff, + self.strFileDizSysCmd,self.strFtpHost,self.strFtpPort,self.strFtpDataPort,self.strHttpPort,self.strExecOnNewUser, + self.strExecAOnNewUser,self.strExecOnPage,self.strExecAOnPage,self.strExecOnConnect,self.strExecAOnConnect, + self.strExecOnLogon,self.strExecAOnLogon,self.strExecOnLogoff,self.strExecAOnLogoff, self.strExecOnComment,self.strExecAOnComment,self.strExecOnUpload,self.strExecAOnUpload, self.boolCreditByKb,self.boolLongWho,self.boolConvertToMb,self.boolQuietJoin,self.boolRelativeConfs] @@ -366,7 +375,7 @@ PROC addServerControls() OF frmSettingsEdit NEW control.createStringInt('Telnet Port Number',SYS_TELNET_PORT,self.app.app,self.setChangedHook,self) self.intTelnetPort:=control - NEW control.createStringInt('FTP Port Number',SYS_FTP_PORT,self.app.app,self.setChangedHook,self) + NEW control.createStringInt('FTP Port Number',SYS_FTP_PORT2,self.app.app,self.setChangedHook,self) self.intFtpPort:=control NEW control.createString('ACP Font',SYS_ACP_FONT,self.app.app,self.setChangedHook,self) @@ -662,7 +671,9 @@ PROC saveSystemChanges() OF frmSettingsEdit writeToolType(self.bbsConfigName,'HOLD_ACCESS_LEVEL',self.intHoldAccess.getValue()) writeToolType(self.bbsConfigName,'FILEDIZ_SYSCMD',self.strFileDizSysCmd.getValue()) writeToolType(self.bbsConfigName,'FTPHOST',self.strFtpHost.getValue()) - + writeToolType(self.bbsConfigName,'FTPPORT',self.strFtpPort.getValue()) + writeToolType(self.bbsConfigName,'FTPDATAPORT',self.strFtpDataPort.getValue()) + writeToolType(self.bbsConfigName,'HTTPPORT',self.strHttpPort.getValue()) writeToolType(self.bbsConfigName,'EXECUTE_ON_NEW_USER',self.strExecOnNewUser.getValue()) writeToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_NEW_USER',self.strExecAOnNewUser.getValue()) writeToolType(self.bbsConfigName,'EXECUTE_ON_SYSOP_PAGE',self.strExecOnPage.getValue()) @@ -922,6 +933,12 @@ PROC editSystemSettings(acpName:PTR TO CHAR) OF frmSettingsEdit self.strFileDizSysCmd.setValue(tempstr) readToolType(self.bbsConfigName,'FTPHOST',tempstr) self.strFtpHost.setValue(tempstr) + readToolType(self.bbsConfigName,'FTPPORT',tempstr) + self.strFtpPort.setValue(tempstr) + readToolType(self.bbsConfigName,'FTPDATAPORT',tempstr) + self.strFtpDataPort.setValue(tempstr) + readToolType(self.bbsConfigName,'HTTPPORT',tempstr) + self.strHttpPort.setValue(tempstr) readToolType(self.bbsConfigName,'EXECUTE_ON_NEW_USER',tempstr) self.strExecOnNewUser.setValue(tempstr) readToolType(self.bbsConfigName,'EXECUTE_ASYNC_ON_NEW_USER',tempstr) diff --git a/axSetupTool/helpText.e b/axSetupTool/helpText.e index eba860f..3df060f 100644 --- a/axSetupTool/helpText.e +++ b/axSetupTool/helpText.e @@ -47,6 +47,27 @@ EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_FILE,CHEC SYS_NODE_X_LOC,SYS_NODE_X_NAME,SYS_NODE_X_SYSOP,SYS_BUTTON_NAME,SYS_BUTTON_COMMAND, SYS_NUTTON_NAME,SYS_NUTTON_COMMAND,SYS_QWK_BBS_NUMBER,SYS_QWK_BBS_ADDRESS,SYS_QWK_BBS_ID, SYS_QWK_ZIP_COMMAND,SYS_QWK_LHA_COMMAND,SYS_ASC_ZIP_COMMAND,SYS_ASC_LHA_COMMAND, + SYS_FTP_PORT2,SYS_FTP_DATA_PORT,SYS_HTTP_PORT, + BACKUP_LVIEW,BACKUP_ADD,BACKUP_EDIT,BACKUP_DELETE,BACKUP_TEXT, + RESTRICT_LVIEW,RESTRICT_ADD,RESTRICT_EDIT,RESTRICT_DELETE,RESTRICT_TEXT, + DLPATHS_LVIEW,DLPATHS_ADD,DLPATHS_DELETE,DLPATHS_TEXT, + ULPATHS_LVIEW,ULPATHS_ADD,ULPATHS_DELETE,ULPATHS_TEXT, + MBASE_LVIEW,MBASE_ADD,MBASE_EDIT,MBASE_DELETE,MBASE_NAME, + ACS_LVIEW,ACS_ADD,ACS_EDIT,ACS_DELETE,ACS_NAME, + AREAS_LVIEW,AREAS_ADD,AREAS_EDIT,AREAS_DELETE,AREAS_NAME, + PRESET_NUMBER, + CMDS_LVIEW,CMDS_ADD,CMDS_EDIT,CMDS_DELETE,CMDS_NAME, + COMPS_LVIEW,COMPS_ADD,COMPS_EDIT,COMPS_DELETE,COMPS_NAME, + PCOL_LVIEW,PCOL_ADD,PCOL_EDIT,PCOL_DELETE,PCOL_NAME, + NNA_LVIEW,NNA_ADD,NNA_EDIT,NNA_DELETE,NNA_NAME, + SCRN_LVIEW,SCRN_ADD,SCRN_EDIT,SCRN_DELETE,SCRN_NAME,SCRN_EXT, + LANG_LVIEW,LANG_ADD,LANG_EDIT,LANG_DELETE,LANG_NAME, + DRV_LVIEW,DRV_ADD,DRV_EDIT,DRV_DELETE,DRV_NAME, + FCHK_LVIEW,FCHK_ADD,FCHK_EDIT,FCHK_DELETE,FCHK_NAME, + CONN_LVIEW,CONN_ADD,CONN_EDIT,CONN_DELETE,CONN_TEXT,CONN_BAUD, + CONF_FIRST,CONF_PREV,CONF_NEXT,CONF_LAST,CONF_ADD,CONF_DEL,CONF_CLONE, + NODE_FIRST,NODE_PREV,NODE_NEXT,NODE_LAST,NODE_ADD,NODE_DEL,NODE_CLONE, + NODE_TIME_START,NODE_TIME_END, END_OF_LIST EXPORT DEF helpTexts:PTR TO LONG @@ -117,14 +138,14 @@ EXPORT PROC helpTextInitialise() addHelp(SYS_ICONIFY_LEFT,'Defines the left pixel position that the iconified /X image is displayed.') addHelp(SYS_ICONIFY_TOP,'Defines the top pixel position that the iconified /X image is displayed.') addHelp(SYS_TELNET_PORT,'Defines the port used for native telnet.') - addHelp(SYS_FTP_PORT,'Defines the port used for the newer ftp server (which was introduced in version 5.5.0).') + addHelp(SYS_FTP_PORT2,'Defines the port used for the newer ftp server (which was introduced in version 5.5.0).') addHelp(SYS_DOS_CHECK_TIME,'Defines the timeframe for the denial of service protection checks (in seconds).') addHelp(SYS_DOS_BAN_TIME,'Defines the length of the ban (in seconds) after a denial of service attack.') addHelp(SYS_DOS_CHECK_TRIGGER,'Defines the trigger level for the denial of service protection. If a user attempts to connect a certain number of times in the given time period their ip will be banned.') addHelp(COMMAND_PASS_PARAMS,'Controls the way the internal commands are executed.') addHelp(COMMAND_TYPE,'Door executable type.') addHelp(NODE_KEEP_UL_CREDIT,'Controls how upload credits are awarded.') - addHelp(NODE_WIN_COLOURS,'Controls screen pens.') + addHelp(NODE_WIN_COLOURS,'Number of colours for the node screen.') addHelp(PRESET_AREA_NAME,'Sets the area for the preset.') addHelp(SYS_LANGUAGE,'Sets the host language for the system. This is used by the auto-translation feature.') addHelp(SYS_NEW_ACCOUNTS,'Controls how new accounts are created.') @@ -254,73 +275,177 @@ EXPORT PROC helpTextInitialise() addHelp(CONF_MENU_PROMPT,'Override the menu prompt for this conference.') addHelp(CONF_UPLOAD_PROMPT,'Display this message after the prompt to enter the file description when the user uplaods.') addHelp(CONF_FTP_DIR_NAME,'Defines an alternative name for the conference folder for the FTP server (useful if your conference name has extended characters).') + addHelp(NODE_EXPRESS_FILE,'Defines the path to the express file. This should normally be set to either BBS:EXPRESS or just EXPRESS if you have made express resident.') + addHelp(NODE_SYSTEM_PASSWORD,'Defines the system password in use on this node.') + addHelp(NODE_SYSTEM_PASSWORD_PROMPT,'Defines the prompt for the system password.') + addHelp(NODE_NEW_USER_PASSWORD,'Defines the new user password in use on this node.') + addHelp(NODE_NAME_PROMPT,'Controls the second part of the name prompt eg enter your "username".') + addHelp(NODE_NAME_PROMPT2,'Use this to completely override the name prompt with this text.') + addHelp(NODE_PASSWORD_PROMPT,'Override the password prompt. If blank it will default to "Password:".') + addHelp(NODE_AUTO_VAL_PASSWORD,'Defines an auto validation password to be used on this node.') + addHelp(NODE_REMOTE_PASSWORD,'Remote shell password. Recommended to use this if you allow shell access.') + addHelp(NODE_FORCE_ANSI,'Force ansi mode for this node. User will not be prompted and ansi mode will be set to this eg N will force no ansi.') + addHelp(NODE_CON_IN_DEVICE,'Specify the device name used for console input.') + addHelp(NODE_CON_OUT_DEVICE,'Specify the device name used for console output.') + addHelp(NODE_SCREEN_PENS,'Define the screen pens for this node which controls how the window elements are drawn.') + addHelp(NODE_CONF_DB_FILE,'Override the conf.db file.') + addHelp(NODE_FIRST_COMMAND,'Execute this AmigaDOS command at node startup. You may also include mci codes in this string.') + addHelp(NODE_SERIAL_DEVICE,'Serial device name used for this node.') + addHelp(NODE_MODEM_INIT,'String sent to the modem to initialise.') + addHelp(NODE_MODEM_RESET,'String sent to the modem to do a reset.') + addHelp(NODE_MODEM_RING,'String expected from the modem in the event of an incoming call.') + addHelp(NODE_MODEM_ANSWER,'String sent to the modem to answer an incoming call.') + addHelp(NODE_MODEM_OFFHOOK,'Command string to take teh modem off hook.') + addHelp(NODE_MODEM_NRAMS,'Command string that is used to set the defaults for your modem.') + addHelp(NODE_WIN_PUBSCREEN,'Name of the public screen used for this nodes output.') + addHelp(SYS_BBS_NAME,'Sets the name of the BBS that is shown to the user when they connect.') + addHelp(SYS_BBS_LOCATION,'Sets the bbs geographic location that is shown to the user when they connect.') + addHelp(SYS_SYSOP_NAME,'Sets the name of the sysop of the bbs.') + addHelp(SYS_DEFAULT_MENU,'Sets the default menu name (will default to MENU if left blank).') + addHelp(SYS_AUTO_VAL_PASSWORD,'Sets the auto validation password for all nodes.') + addHelp(SYS_REGKEY,'Sets the registration name. This is displayed to the user as part of the welcome message.') + addHelp(SYS_SMTP_SERVER,'Sets the smtp server used by the bbs to send notification emails.') + addHelp(SYS_SMTP_USERNAME,'Sets the user name for the smtp server used to send notification emails.') + addHelp(SYS_SMTP_PASSWORD,'Sets the password for the smtp server used to send notification emails.') + addHelp(SYS_SYSOP_EMAIL,'Sets the email address to which notification emails are sent.') + addHelp(SYS_BBS_EMAIL,'Sets the from email address for notification emails,') + addHelp(SYS_FILEDIZ_CMD,'Defines which examine door is actually the file id processor.') + addHelp(SYS_FTP_HOST,'Sets the ftp host name for the ftp server.') + addHelp(SYS_EXEC_ON_NEW_USER,'Execute this AmigaDos command when a new user registers.') + addHelp(SYS_EXECA_ON_NEW_USER,'Execute this AmigaDos command asynchronously when a new user registers.') + addHelp(SYS_EXEC_ON_SYSOP_PAGE,'Execute this AmigaDos command when a user pages the sysop.') + addHelp(SYS_EXECA_ON_SYSOP_PAGE,'Execute this AmigaDos command asynchronously when a user pages the sysop.') + addHelp(SYS_EXEC_ON_CONNECT,'Execute this AmigaDos command whenever someone connects.') + addHelp(SYS_EXECA_ON_CONNECT,'Execute this AmigaDos command asynchronously whenever someone connects.') + addHelp(SYS_EXEC_ON_LOGON,'Execute this AmigaDos command when a user sucessfully connects.') + addHelp(SYS_EXECA_ON_LOGON,'Execute this AmigaDos command asynchronously when a user sucessfully connects.') + addHelp(SYS_EXEC_ON_LOGOFF,'Execute this AmigaDos command when a user logs off.') + addHelp(SYS_EXECA_ON_LOGOFF,'Execute this AmigaDos command asynchronously when a user logs off.') + addHelp(SYS_EXEC_ON_COMMENT,'Execute this AmigaDos command when a user leaves a sysop comment.') + addHelp(SYS_EXECA_ON_COMMENT,'Execute this AmigaDos command asynchronously when a user leaves a sysop comment.') + addHelp(SYS_EXEC_ON_UPLOAD,'Execute this AmigaDos command when a user completes an upload.') + addHelp(SYS_EXECA_ON_UPLOAD,'Execute this AmigaDos command asynchronously when a user completes an upload.') + addHelp(SYS_ACP_FONT,'Set the name of the font used by ACP.') + addHelp(SYS_EXEC_ON_STARTUP,'Execute this AmigaDos command when ACP has completed startup.') + addHelp(SYS_NODE_X_LOC,'Override the geographic location of the bbs at the node level. Normally leave this blank.') + addHelp(SYS_NODE_X_NAME,'Override the name of the bbs at the node level. Normally leave this blank.') + addHelp(SYS_NODE_X_SYSOP,'Override the sysop of the bbs at the node level. Normally leave this blank.') + addHelp(SYS_BUTTON_NAME,'Set a custom button name.') + addHelp(SYS_BUTTON_COMMAND,'Set a custom button command.') + addHelp(SYS_NUTTON_NAME,'Set a custom alternative button name.') + addHelp(SYS_NUTTON_COMMAND,'Set a custom alternative button command.') + addHelp(SYS_QWK_BBS_NUMBER,'Sets the bbs number used for qwk mail packets.') + addHelp(SYS_QWK_BBS_ADDRESS,'Sets the bbs address used for qwk mail packets.') + addHelp(SYS_QWK_BBS_ID,'Sets the bbs id used for qwk mail packets.') + addHelp(SYS_QWK_ZIP_COMMAND,'Sets the zip command used for creating qwk mail packets.') + addHelp(SYS_QWK_LHA_COMMAND,'Sets the lha command used for creating qwk mail packets.') + addHelp(SYS_ASC_ZIP_COMMAND,'Sets the zip command used for creating ascii mail packets.') + addHelp(SYS_ASC_LHA_COMMAND,'Sets the lha command used for creating ascii mail packets.') + addHelp(SYS_FTP_PORT,'FTP Port used for all nodes for the old ftp protocol server.') + addHelp(SYS_FTP_DATA_PORT,'FTP Data port used for all nodes for both ftp server types.') + addHelp(SYS_HTTP_PORT,'HTTP port used for all nodes for the HTTP server.') + addHelp(BACKUP_LVIEW,'List files that are backed up at system startup.') + addHelp(BACKUP_ADD,'Add a new file to be backed up.') + addHelp(BACKUP_EDIT,'Edit the file to be backed up.') + addHelp(BACKUP_DELETE,'Remove a file from the list.') + addHelp(BACKUP_TEXT,'Enter the filename of the new file to be backed up.') + addHelp(RESTRICT_LVIEW,'List files that are restricted from all downloads.') + addHelp(RESTRICT_ADD,'Add a new restricted file.') + addHelp(RESTRICT_EDIT,'Edit the restricted file.') + addHelp(RESTRICT_DELETE,'Remove a file from the list.') + addHelp(RESTRICT_TEXT,'Enter the filename of the new restrcited file.') + addHelp(DLPATHS_LVIEW,'List of download paths for this conference.') + addHelp(DLPATHS_ADD,'Add a new downlload path.') + addHelp(DLPATHS_DELETE,'Remove the download path.') + addHelp(DLPATHS_TEXT,'Enter the new download path.') + addHelp(ULPATHS_LVIEW,'List of upload paths for this conference.') + addHelp(ULPATHS_ADD,'Add a new upload path.') + addHelp(ULPATHS_DELETE,'Remove the upload path.') + addHelp(ULPATHS_TEXT,'Enter the new upload path.') + addHelp(MBASE_LVIEW,'List of message bases in this conference.') + addHelp(MBASE_ADD,'Add a new message base.') + addHelp(MBASE_EDIT,'Edit current message base.') + addHelp(MBASE_DELETE,'Delete current message base.') + addHelp(MBASE_NAME,'Message base name.') + addHelp(ACS_LVIEW,'List of access levels.') + addHelp(ACS_ADD,'Add a new access level.') + addHelp(ACS_EDIT,'Edit existing access level.') + addHelp(ACS_DELETE,'Delete an access level.') + addHelp(ACS_NAME,'Access level.') + addHelp(AREAS_LVIEW,'List of security areas.') + addHelp(AREAS_ADD,'Add a new security area.') + addHelp(AREAS_EDIT,'Edit existing security area.') + addHelp(AREAS_DELETE,'Remove a security area.') + addHelp(AREAS_NAME,'Area name.') + addHelp(PRESET_NUMBER,'Preset number.') + addHelp(CMDS_LVIEW,'List of commands.') + addHelp(CMDS_ADD,'Add a new command.') + addHelp(CMDS_EDIT,'Edit selected command.') + addHelp(CMDS_DELETE,'Delete selected command.') + addHelp(CMDS_NAME,'Command name.') + addHelp(COMPS_LVIEW,'List of computer types.') + addHelp(COMPS_ADD,'Add new computer type.') + addHelp(COMPS_EDIT,'Edit computer type.') + addHelp(COMPS_DELETE,'Remove a computer type.') + addHelp(COMPS_NAME,'Computer name.') + addHelp(PCOL_LVIEW,'List of file transfer protocols.') + addHelp(PCOL_ADD,'Add a new transfer protocol.') + addHelp(PCOL_EDIT,'Edit file transfer protocol.') + addHelp(PCOL_DELETE,'Remove file transfer protocol.') + addHelp(PCOL_NAME,'Protocol name.') + addHelp(NNA_LVIEW,'List of names not allowed.') + addHelp(NNA_ADD,'Add new name.') + addHelp(NNA_EDIT,'Edit existing name.') + addHelp(NNA_DELETE,'Remove name.') + addHelp(NNA_NAME,'Name.') + addHelp(SCRN_LVIEW,'List of screen types.') + addHelp(SCRN_ADD,'Add new screen type.') + addHelp(SCRN_EDIT,'Edit screen type.') + addHelp(SCRN_DELETE,'Delete a screen type.') + addHelp(SCRN_NAME,'Screen type name.') + addHelp(SCRN_EXT,'Screen type file extension.') + addHelp(LANG_LVIEW,'List of system languages.') + addHelp(LANG_ADD,'Add a new system language.') + addHelp(LANG_EDIT,'Edit system language.') + addHelp(LANG_DELETE,'Remove a system language.') + addHelp(LANG_NAME,'Language name.') + addHelp(DRV_LVIEW,'List of drives used by the bbs.') + addHelp(DRV_ADD,'Add a new bbs drive.') + addHelp(DRV_EDIT,'Edit a bbs drive.') + addHelp(DRV_DELETE,'Remove a bbs drive.') + addHelp(DRV_NAME,'BBS Drive name.') + addHelp(FCHK_LVIEW,'List of file checkers.') + addHelp(FCHK_ADD,'Add a new file checker.') + addHelp(FCHK_EDIT,'Edit the file checker.') + addHelp(FCHK_DELETE,'Remove a file checker.') + addHelp(FCHK_NAME,'File checker file extension.') + addHelp(CONN_LVIEW,'List of connection strings.') + addHelp(CONN_ADD,'Add a connection string.') + addHelp(CONN_EDIT,'Edit a connection string.') + addHelp(CONN_DELETE,'Delete a connection string.') + addHelp(CONN_TEXT,'Connection string.') + addHelp(CONN_BAUD,'Equivalent baud rate.') + addHelp(CONF_FIRST,'Move to the first conference.') + addHelp(CONF_PREV,'Move to the previous conference.') + addHelp(CONF_NEXT,'Move to the next conference.') + addHelp(CONF_LAST,'Move to the last conference.') + addHelp(CONF_ADD,'Add a new conference.') + addHelp(CONF_CLONE,'Add a new conference as a clone of the current conference.') + addHelp(CONF_DEL,'Delete the conference. (can only delete the last one)') + addHelp(NODE_FIRST,'Move to the first node.') + addHelp(NODE_PREV,'Move to the previous node.') + addHelp(NODE_NEXT,'Move to the next node.') + addHelp(NODE_LAST,'Move to the last node.') + addHelp(NODE_ADD,'Add a new node.') + addHelp(NODE_CLONE,'Add a new node as a clone of the current node.') + addHelp(NODE_DEL,'Delete the node. (can only delete the last one)') + addHelp(NODE_TIME_START,'Connections (at this speed) are allowed starting from this time. Leave blank to allow at any time') + addHelp(NODE_TIME_END,'Connections (at this speed) are allowed until this time. Leave blank to allow at any time') + /* -, - NODE_EXPRESS_FILE, - NODE_SYSTEM_PASSWORD, - NODE_SYSTEM_PASSWORD_PROMPT, - NODE_NEW_USER_PASSWORD, - NODE_NAME_PROMPT, - NODE_NAME_PROMPT2, - NODE_PASSWORD_PROMPT, - NODE_AUTO_VAL_PASSWORD, - NODE_REMOTE_PASSWORD, - NODE_FORCE_ANSI, - NODE_CON_IN_DEVICE, - NODE_CON_OUT_DEVICE, - NODE_SCREEN_PENS, - NODE_CONF_DB_FILE, - NODE_FIRST_COMMAND, - NODE_SERIAL_DEVICE, - NODE_MODEM_INIT, - NODE_MODEM_RESET, - NODE_MODEM_RING, - NODE_MODEM_ANSWER, - NODE_MODEM_OFFHOOK, - NODE_MODEM_NRAMS, - NODE_WIN_PUBSCREEN, - SYS_BBS_NAME, - SYS_BBS_LOCATION, - SYS_SYSOP_NAME, - SYS_DEFAULT_MENU, - SYS_AUTO_VAL_PASSWORD, - SYS_REGKEY, - SYS_SMTP_SERVER, - SYS_SMTP_USERNAME, - SYS_SMTP_PASSWORD, - SYS_SYSOP_EMAIL, - SYS_BBS_EMAIL, - SYS_FILEDIZ_CMD, - SYS_FTP_HOST, - SYS_EXEC_ON_NEW_USER, - SYS_EXECA_ON_NEW_USER, - SYS_EXEC_ON_SYSOP_PAGE, - SYS_EXECA_ON_SYSOP_PAGE, - SYS_EXEC_ON_CONNECT, - SYS_EXECA_ON_CONNECT, - SYS_EXEC_ON_LOGON, - SYS_EXECA_ON_LOGON, - SYS_EXEC_ON_LOGOFF, - SYS_EXECA_ON_LOGOFF, - SYS_EXEC_ON_COMMENT, - SYS_EXECA_ON_COMMENT, - SYS_EXEC_ON_UPLOAD, - SYS_EXECA_ON_UPLOAD, - SYS_ACP_FONT, - SYS_EXEC_ON_STARTUP, - SYS_NODE_X_LOC, - SYS_NODE_X_NAME, - SYS_NODE_X_SYSOP, - SYS_BUTTON_NAME, - SYS_BUTTON_COMMAND, - SYS_NUTTON_NAME, - SYS_NUTTON_COMMAND, - SYS_QWK_BBS_NUMBER, - SYS_QWK_BBS_ADDRESS, - SYS_QWK_BBS_ID, - SYS_QWK_ZIP_COMMAND, - SYS_QWK_LHA_COMMAND, - SYS_ASC_ZIP_COMMAND, - SYS_ASC_LHA_COMMAND,*/ + CONF_FIRST,CONF_PREV,CONF_NEXT,CONF_LAST,CONF_ADD,CONF_DEL, + NODE_FIRST,NODE_PREV,NODE_NEXT,NODE_LAST,NODE_ADD,NODE_DEL,*/ + + ENDPROC diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 55f6011..8474475 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -32,7 +32,7 @@ frmBase.m: frmBase.e axedit.m frmMain.m: frmMain.e frmBase.m axedit.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m frmAccess.m frmCommands.m $(compiler) frmMain $(options) -frmEditList.m: frmEditList.e frmAddItem.m frmBase.m frmAddComplexItem.m tooltypes.m axedit.m stringlist.m miscfuncs.m configobject.m +frmEditList.m: frmEditList.e frmAddItem.m frmBase.m frmAddComplexItem.m tooltypes.m axedit.m stringlist.m miscfuncs.m configobject.m helpText.m $(compiler) frmEditList $(options) frmSettingsEdit.m: frmSettingsEdit.e frmBase.m tooltypes.m axedit.m controls.m miscfuncs.m stringlist.m helpText.m @@ -41,7 +41,7 @@ frmSettingsEdit.m: frmSettingsEdit.e frmBase.m tooltypes.m axedit.m controls.m m frmPresetsEdit.m: frmPresetsEdit.e frmBase.m tooltypes.m axedit.m controls.m miscfuncs.m stringlist.m helpText.m $(compiler) frmPresetsEdit $(options) -frmAddItem.m: frmAddItem.e frmBase.m axedit.m +frmAddItem.m: frmAddItem.e frmBase.m axedit.m helpText.m $(compiler) frmAddItem $(options) frmAddComplexItem.m: frmAddComplexItem.e frmBase.m axedit.m controls.m stringlist.m tooltypes.m configobject.m helpText.m From 895c73cebcb74f4084d418d6a86435b8cca158f6 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 22 Aug 2023 17:24:19 +0100 Subject: [PATCH 12/47] Add installer script --- Install Ami-Express | 317 +++++++++++++++++++++++++++++++++++++++ Install Ami-Express.info | Bin 0 -> 596 bytes 2 files changed, 317 insertions(+) create mode 100644 Install Ami-Express create mode 100644 Install Ami-Express.info diff --git a/Install Ami-Express b/Install Ami-Express new file mode 100644 index 0000000..8499ac7 --- /dev/null +++ b/Install Ami-Express @@ -0,0 +1,317 @@ +; Ami-Express +; $VER: Ami-Express 1.0 (09.08.2023) + +(set #appver "v5.6.0") +(set #appyear "2018-2023") + +(complete 0) +(set @app-name "Ami-Express") +(if (exists "BBS:" (noreq)) + (set @default-dest "bbs:") + (set @default-dest "Work:") +) +; +(welcome "Welcome to the Ami-Express installation utility.\nThis will install or upgrade your installation to AmiExpress " #appver) + + (set #muiver (/ (getversion "libs:muimaster.library" ) 65536) ) + + (set #owndevunitver (/ (getversion "libs:owndevunit.library" ) 65536) ) + + (set #fifolibver (/ (getversion "libs:fifo.library" ) 65536) ) + + (set #amissllibver (/ (getversion "libs:amisslmaster.library" ) 65536) ) + + (set #asynclibver (/ (getversion "libs:async.library" ) 65536) ) + + (if ( <> #muiver 0) + ( set #muimsg "MUI: installed\n" ) + ( set #muimsg "MUI: not installed\n" ) + ) + + (if ( <> #owndevunitver 0) + ( set #owndevunitmsg "OwnDevUnit.library: installed\n" ) + ( set #owndevunitmsg "OwnDevUnit.library: not installed\n" ) + ) + + (if ( <> #fifolibver 0) + ( set #fifolibmsg "fifo handler: installed\n" ) + ( set #fifolibmsg "fifo handler: not installed\n" ) + ) + + (if ( <> #amissllibver 0) + ( set #amissllibmsg "amissl library: installed\n" ) + ( set #amissllibmsg "amissl library: not installed\n" ) + ) + + (if ( <> #asynclibver 0) + ( set #ibmcondevmsg "async.library: installed\n" ) + ( set #ibmcondevmsg "async.library: not installed\n" ) + ) + +; +( if (exists "sys:wbstartup/acp" (noreq)) + ( set #acpname "sys:wbstartup/acp") + ( + ( if (exists "bbs:wbstartup/acp" (noreq)) + ( set #acpname "bbs:wbstartup/acp") + ( set #acpname "") + ) + ) +) +; +(set expexists + (exists "BBS:Express" (noreq)) +) + +(set expexists 0) + +; +(if (= expexists 0) +( + +; +(message "After completion of the installation you will have a bare bones functioning bbs system installed and you will be able to use the included setup tool to customise the setup according to your preferences.\n\n(C)1989-91 Mike Thomas, Synthetic Technologies\n(C)1992-95 Joe Hodge, LightSpeed Technologies Inc.\n(C)" #appyear " Darren Coles\n\nFull documentation and the latest releases are always available at:\nhttps://github.com/dmcoles/AmiExpress\n" +) + +; +(set #default-dest-installergen-temp + (askdir + (prompt "Select where you want Ami-Express installed") + (help "Select where you want Ami-Express installed.\nNo folder will be created so please ensure that you have created one if needed.") + (default @default-dest) + ) +) +(set @default-dest #default-dest-installergen-temp) + +; +( complete 20) + +(set #acpchoice (askchoice + (choices "WBStartup (for auto startup)" "BBS: (for manual startup)" "Select a different location") + (prompt "Where would you like to install the ACP program?") + (help #cpu-help) + (default 0) )) + +( if ( = #acpchoice 0) + (set #acppath "sys:wbstartup") +) + +( if ( = #acpchoice 1) + (set #acppath @default-dest) +) + +( if ( = #acpchoice 2) + ( + (set #acppath + (askdir + (prompt "Please select the destination for the ACP file") + (help #destdir-help) + (default @default-dest) ) ) + ) +) + +(copylib + (source "AmiExpress/BBS/Express") + (dest @default-dest) + (prompt "Copying Express") + (help @copylib-help) + (confirm "expert") +) + +( complete 30) + +(copylib + (source "AmiExpress/Wbstartup/ACP") + (dest #acppath) + (prompt "Copying ACP") + (help @copylib-help) + (infos) + (confirm "expert") + +) + +( complete 40) + +(copyfiles + (prompt "Copying utils") + (help @copyfiles-help) + (confirm "expert") + (source "AmiExpress/BBS/Utils") + (dest (tackon @default-dest "Utils")) + (all) +) + +( complete 50) + +(copyfiles + (prompt "Copying storage") + (help @copyfiles-help) + (confirm "expert") + (source "AmiExpress/BBS/Storage") + (dest (tackon @default-dest "Storage")) + (all) +) +( complete 60) + +; +(run (cat "LHA x AmiExpress/defaultbbs.lha " @default-dest) + (prompt "Copying default bbs configuration") + (help ) + (confirm "expert") +) + +( complete 70) + +(run (cat "setenv axsetupeditor_prefs save 11" #acppath) + (prompt "Saving configuration") + (help ) + (confirm "expert") +) + +( complete 80) + +(if (exists "BBS:" (noreq)) + (set #startup "Assign doors: bbs:doors\nPath bbs:utils add\nResident SYS:Rexxc/RX pure") + (set #startup (cat "Assign bbs: " @default-dest "\nAssign doors: bbs:doors\nPath bbs:utils add\nResident SYS:Rexxc/RX pure")) +) + + +(startup "Ami-Express" + (prompt "Add startup items") + (help @startup-help) + (command #startup) + (confirm "expert") +) +; + +) ; Else +( + +; +(set install-dest bbs:) + +; +(set #expressver (getversion "bbs:express" ) ) + + +(set #acpver (getversion #acpname ) ) + +(set #expressverMajor (/ #expressver 65536) ) +(set #expressverMinor (bitand #expressver 65535) ) +(set #expressver ("%ld.%ld" #expressverMajor #expressverMinor) ) + +(set #acpMajor (/ #expressver 65536) ) +(set #acpMinor (bitand #expressver 65535) ) +(set #acpver ("%ld.%ld" #expressverMajor #expressverMinor) ) + +(message ("An existing installation of Ami-Express was found.\n\nThe currently installed version information is \n\nACP: %s\nExpress: %s\n\nPress proceed if you wish to continue upgrading Ami-Express.\n\nThe configuration of your bbs will not be affected and only the updated\napplication files will be overwritten.\n" #expressver #acpver) +) + +( complete 10) +; + +; +( complete 20) + +(copylib + (source "AmiExpress/BBS/Express") + (dest "bbs:") + (prompt "Copying Express") + (help @copylib-help) + (confirm "expert") +) + +( complete 40) + +(set #acpdone 0) + +(set #axprefs (getenv "axsetupeditor_prefs") ) +(if (<> #axprefs "") + ( + (set #axprefs (substr #axprefs 2 (- (strlen #axprefs) 5))) + + ( if (exists (tackon #axprefs "acp") (noreq)) + ( + (copylib + (source "AmiExpress/wbstartup/acp") + (dest #axprefs) + (prompt "Copying ACP") + (help @copylib-help) + (confirm "expert") + ) + (set #acpdone 1) + ) + ) + ) +) + +( if (and (exists "sys:wbstartup/acp" (noreq)) + (<> #axprefs "sys:wbstartup") ) + ( + (copylib + (source "AmiExpress/wbstartup/acp") + (dest "sys:wbstartup") + (prompt "Copying ACP") + (help @copylib-help) + (confirm "expert") + ) + (set #acpdone 1) + ) +) + +( if (and (exists "bbs:acp" (noreq)) + (<> #axprefs "bbs:") ) + ( + (copylib + (source "AmiExpress/wbstartup/acp") + (dest "bbs:") + (prompt "Copying ACP") + (help @copylib-help) + (confirm "expert") + ) + (set #acpdone 1) + ) +) + +( if ( = #acpdone 0) + ( + (set #acppath + (askdir + (prompt "Please select the location of your ACP file") + (help #destdir-help) + (default @default-dest) ) ) + + ( if (exists (tackon #acppath "acp" ) (noreq)) + ( + (copylib + (source "AmiExpress/wbstartup/acp") + (dest #acppath) + (prompt "Copying ACP") + (help @copylib-help) + (confirm "expert") + ) + ( set #acpdone 1 ) + ) + ) + ) +) + +( complete 60) + +(copyfiles + (prompt "Copying utils") + (help @copyfiles-help) + (confirm "expert") + (source "AmiExpress/BBS/Utils") + (dest "BBS:Utils") + (pattern "~(rexxdoor)") +) + +( complete 80) +; +) +) ; End If + +( message "The MUI system is required by the Ami-Express configuration tool\nand is recommended to be installed. In addition there are optional extras that\ncan be used by Ami-Express which should be installed manually if required.\n\n" #muimsg #owndevunitmsg #fifolibmsg #amissllibmsg #ibmcondevmsg #kalacondevmsg "\nThese extras are all freely available for download on the aminet.") + +(exit) \ No newline at end of file diff --git a/Install Ami-Express.info b/Install Ami-Express.info new file mode 100644 index 0000000000000000000000000000000000000000..78d8f52169416f0a24f32068371299bf5820e894 GIT binary patch literal 596 zcmZvX!Ab&A6o&tCZaGMhix$ylZo4)S1koY{l}3;lkwR#dxfmj_5{-xmlIj6^4xge& z8R!9;awBP-&be1nqchz3?)m@2fA4+E!oj5Wu!aTh9WQ**6LF4?f>+#ycYJ^@8?vV5 z=gnSHQgA*uTx&TrG8>nEm>OyRgp1$-rL({jkkUJ~S|7;hyI!x4P5PlFrnD7aPlK()INWNvta%o%N!%ZNJ{~_PQ=vrBFzL_8AxkNE%BTe)wRPy6e z{=iZLTSTWS4_pcB3EqV#t$DI<^a){mhSC30^7%2b(g5)tB!2|ga7f>=DtZ|DW7cO_ zTE$R$4m7?{=9x268S87MWVXko# OwHs%V(e{JVoc0SyP^xAC literal 0 HcmV?d00001 From cabb8b8d5584c2afc799d65884c8cf2ba7f12625 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Wed, 23 Aug 2023 14:34:13 +0100 Subject: [PATCH 13/47] convert easyrequestargs calls to mui requesters --- axSetupTool/axSetupTool.e | 5 ++-- axSetupTool/frmAddComplexItem.e | 14 +++-------- axSetupTool/frmConfEdit.e | 34 ++++++-------------------- axSetupTool/frmEditList.e | 6 ++--- axSetupTool/frmMain.e | 8 +++--- axSetupTool/frmNodeEdit.e | 43 ++++++--------------------------- axSetupTool/frmPresetsEdit.e | 26 ++++---------------- axSetupTool/frmSettingsEdit.e | 35 ++++++--------------------- 8 files changed, 39 insertions(+), 132 deletions(-) diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index b1f6ec5..f30ef5e 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -2,10 +2,11 @@ OPT OSVERSION = 37,STACK=60000,LARGE OPT PREPROCESS /* - ftpport ftpdataport httpport missing in bbsconfig window.pubscreen can be WINDOW.PUBSCREEN or WINDOW.PUBSCREEN= - help screens + help screen + add warning about incorrect rexxdoor if nodes>10 + add warning to restart on exit if ACP running restart bbs user editor diff --git a/axSetupTool/frmAddComplexItem.e b/axSetupTool/frmAddComplexItem.e index 5d8d460..2d738a2 100644 --- a/axSetupTool/frmAddComplexItem.e +++ b/axSetupTool/frmAddComplexItem.e @@ -94,19 +94,15 @@ PROC canClose() OF frmAddComplexItem ENDPROC TRUE PROC canSave() OF frmAddComplexItem - DEF win,newName,i + DEF newName,i MOVE.L (A1),self GetA4() - get(self.winMain,MUIA_Window_Window,{win}) get(self.txtAreaName, MUIA_String_Contents,{newName}) IF self.existingItems ANDALSO self.existingItems.contains(newName) - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'An item already exists with this name.', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*Ok','An item already exists with this name.',0) RETURN FALSE ENDIF ENDPROC TRUE @@ -114,10 +110,8 @@ ENDPROC TRUE PROC unsavedChangesWarning() OF frmAddComplexItem DEF win get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Unsaved changes' , - 'You have unsaved changes,\nif you continue you will lose them.', - '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Unsaved changes','*OK|CANCEL','You have unsaved changes,\nif you continue you will lose them.',0)=0 THEN RETURN FALSE + ENDPROC TRUE PROC editArea(acpName,areaName,oldArea:PTR TO area, existingAreas:PTR TO stdlist) OF frmAddComplexItem diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index d1c3ba6..44b1357 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -654,30 +654,18 @@ PROC canClose() OF frmConfEdit ENDPROC TRUE PROC unsavedChangesWarning() OF frmConfEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Unsaved changes' , - 'You have unsaved changes,\nif you continue you will lose them.', - '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Unsaved changes', + '*OK|CANCEL','You have unsaved changes,\nif you continue you will lose them.',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC deleteConfWarning() OF frmConfEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Warning' , - 'Are you sure you wish to delete this conference?', - '_Yes|No' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Warning', + '*Yes|No','Are you sure you wish to delete this conference?',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC deleteConfFolderRequest() OF frmConfEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Warning' , - 'Do you wish to also remove the Conf folder contents?', - '_Yes|No' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Warning', + '*Yes|No','Do you wish to also remove the Conf folder contents?',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC saveChanges() OF frmConfEdit @@ -695,19 +683,13 @@ PROC saveChanges() OF frmConfEdit fullTrim(self.strConfName2.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( window , [ 20 , 0 , - 'Error' , - 'Conference Name is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Conference Name is a mandatory field',0) RETURN ENDIF fullTrim(self.paConfPath.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( window , [ 20 , 0 , - 'Error' , - 'Conference Path is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Conference Path is a mandatory field',0) RETURN ENDIF diff --git a/axSetupTool/frmEditList.e b/axSetupTool/frmEditList.e index f0074c3..05fc790 100644 --- a/axSetupTool/frmEditList.e +++ b/axSetupTool/frmEditList.e @@ -746,10 +746,8 @@ PROC canClose() OF frmEditList ENDPROC TRUE PROC unsavedChangesWarning() OF frmEditList - IF EasyRequestArgs( NIL , [ 20 , 0 , - 'Unsaved changes' , - 'You have unsaved changes,\nif you continue you will lose them.', - '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Unsaved changes', + '*OK|CANCEL','You have unsaved changes,\nif you continue you will lose them.',0)=0 THEN RETURN FALSE ENDPROC TRUE diff --git a/axSetupTool/frmMain.e b/axSetupTool/frmMain.e index 5478974..bd1703c 100644 --- a/axSetupTool/frmMain.e +++ b/axSetupTool/frmMain.e @@ -35,17 +35,15 @@ PROC exitbuttonPressed() OF frmMain domethod(self.app.app,[MUIM_Application_ReturnID,MUIA_Window_CloseRequest]) ENDPROC + PROC aboutbuttonPressed() OF frmMain DEF win MOVE.L (A1),self GetA4() - get(self.winMain,MUIA_Window_Window,{win}) - EasyRequestArgs( win , [ 20 , 0 , - 'About Ami-Express Setup Tool' , - 'This tool can assist you in configuring\nalmost every aspect of Ami-Express.\n\n(c)2023 Darren Coles.', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'About Ami-Express Setup Tool' ,'*Ok','This tool can assist you in configuring\nalmost every aspect of Ami-Express.\n\n(c)2023 Darren Coles.',0) ENDPROC + PROC computersbuttonPressed() OF frmMain DEF listEdit:PTR TO frmEditList MOVE.L (A1),self diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e index 98db838..7526f6a 100644 --- a/axSetupTool/frmNodeEdit.e +++ b/axSetupTool/frmNodeEdit.e @@ -705,48 +705,29 @@ PROC canClose() OF frmNodeEdit ENDPROC TRUE PROC unsavedChangesWarning() OF frmNodeEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Unsaved changes' , - 'You have unsaved changes,\nif you continue you will lose them.', - '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Unsaved changes', + '*OK|CANCEL','You have unsaved changes,\nif you continue you will lose them.',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC deleteNodeWarning() OF frmNodeEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Warning' , - 'Are you sure you wish to delete this node?', - '_Yes|No' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Warning','*Yes|No','Are you sure you wish to delete this node?',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC deleteNodeFolderRequest() OF frmNodeEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Warning' , - 'Do you wish to also remove the Node folder contents?', - '_Yes|No' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Warning','*Yes|No','Do you wish to also remove the Node folder contents?',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC validateTime(timeStr:PTR TO CHAR,startControl,endControl) OF frmNodeEdit - DEF win DEF timeVal,timeEntry DEF errorText[255]:STRING - get(self.winMain,MUIA_Window_Window,{win}) get(startControl, MUIA_String_Contents,{timeEntry}) IF StrLen(timeEntry)>0 timeVal:=Val(timeEntry) IF (Mod(timeVal,100)>59) OR (timeVal>2359) OR (timeVal<0) StringF(errorText,'You have entered an invalid time for \s baud start time',timeStr) - EasyRequestArgs( win , [ 20 , 0 , - 'Error ' , - errorText, - 'OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK',errorText,0) RETURN FALSE ENDIF ENDIF @@ -757,10 +738,7 @@ PROC validateTime(timeStr:PTR TO CHAR,startControl,endControl) OF frmNodeEdit timeVal:=Val(timeEntry) IF (Mod(timeVal,100)>59) OR (timeVal>2359) OR (timeVal<0) StringF(errorText,'You have entered an invalid time for \s baud end time',timeStr) - EasyRequestArgs( win , [ 20 , 0 , - 'Error ' , - errorText, - 'OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK',errorText,0) RETURN FALSE ENDIF ENDIF @@ -776,20 +754,15 @@ PROC saveChanges() OF frmNodeEdit DEF windowTooltype[255]:STRING DEF timeTooltype[255]:STRING DEF timeItem:PTR TO timeItem - DEF window DEF val MOVE.L (A1),self GetA4() - get(self.winMain,MUIA_Window_Window,{window}) fullTrim(self.strNodeStart.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( window , [ 20 , 0 , - 'Error' , - 'Express File is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Express File is a mandatory field',0) RETURN ENDIF @@ -802,8 +775,6 @@ PROC saveChanges() OF frmNodeEdit readToolType(self.acpName,'BBS_LOCATION',bbsPath) StringF(nodeStr,'\sNode\d',bbsPath,self.currNode) - get(self.winMain,MUIA_Window_Window,{window}) - IF (self.newNode) //create the folder structure makeDir(nodeStr) diff --git a/axSetupTool/frmPresetsEdit.e b/axSetupTool/frmPresetsEdit.e index 1eea4ec..dbe1496 100644 --- a/axSetupTool/frmPresetsEdit.e +++ b/axSetupTool/frmPresetsEdit.e @@ -164,49 +164,33 @@ PROC canClose() OF frmPresetsEdit ENDPROC TRUE PROC unsavedChangesWarning() OF frmPresetsEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Unsaved changes' , - 'You have unsaved changes,\nif you continue you will lose them.', - '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Unsaved changes', + '*OK|CANCEL','You have unsaved changes,\nif you continue you will lose them.',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC savePresetChanges() OF frmPresetsEdit DEF tempStr[255]:STRING DEF bbsPath[255]:STRING DEF presetStr[20]:STRING - DEF win MOVE.L (A1),self GetA4() - get(self.winMain,MUIA_Window_Window,{win}) - fullTrim(self.areaNames[self.strAreaName.getValueIndex()],tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'Area Name is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Area Name is a mandatory field',0) RETURN ENDIF fullTrim(self.intAccessLevel.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'Acces Level is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Acces Level is a mandatory field',0) RETURN ENDIF fullTrim(self.intConfrJoin.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'Initial Conf is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Initial Conf is a mandatory field',0) RETURN ENDIF diff --git a/axSetupTool/frmSettingsEdit.e b/axSetupTool/frmSettingsEdit.e index a801089..27dc92b 100644 --- a/axSetupTool/frmSettingsEdit.e +++ b/axSetupTool/frmSettingsEdit.e @@ -583,47 +583,31 @@ PROC canClose() OF frmSettingsEdit ENDPROC TRUE PROC unsavedChangesWarning() OF frmSettingsEdit - DEF win - get(self.winMain,MUIA_Window_Window,{win}) - IF EasyRequestArgs( win , [ 20 , 0 , - 'Unsaved changes' , - 'You have unsaved changes,\nif you continue you will lose them.', - '_OK|_CANCEL' ] , NIL , NIL )=0 THEN RETURN FALSE + IF Mui_RequestA(0,self.winMain,0,'Unsaved changes', + '*OK|CANCEL','You have unsaved changes,\nif you continue you will lose them.',0)=0 THEN RETURN FALSE ENDPROC TRUE PROC saveSystemChanges() OF frmSettingsEdit DEF tempStr[255]:STRING - DEF win MOVE.L (A1),self GetA4() - get(self.winMain,MUIA_Window_Window,{win}) - fullTrim(self.strBBSName.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'BBS Name is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','BBS Name is a mandatory field',0) RETURN ENDIF fullTrim(self.strBBSLocation.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'BBS Location is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','BBS Location is a mandatory field',0) RETURN ENDIF fullTrim(self.strSysopName.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'Sysop Name is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','Sysop Name is a mandatory field',0) RETURN ENDIF @@ -697,21 +681,16 @@ ENDPROC PROC saveServerChanges() OF frmSettingsEdit DEF tempStr[255]:STRING - DEF win,i + DEF i DEF control:PTR TO control DEF toolName[255]:STRING MOVE.L (A1),self GetA4() - get(self.winMain,MUIA_Window_Window,{win}) - fullTrim(self.paBBSPath.getValue(),tempStr) IF EstrLen(tempStr)=0 - EasyRequestArgs( win , [ 20 , 0 , - 'Error' , - 'BBS Path is a mandatory field', - '_OK' ] , NIL , NIL ) + Mui_RequestA(0,self.winMain,0,'Error','*OK','BBS Path is a mandatory field',0) RETURN ENDIF From d2ac1e3ea80f58a29bf209e8cb926214709f66a8 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 24 Aug 2023 12:08:37 +0100 Subject: [PATCH 14/47] add tools to setup editor (start/stop bbs) add warning requesters notify of incomplete configuration, wrong version of rexxdoor and needing a restart --- axSetupTool/axSetupTool.e | 9 +- axSetupTool/axedit.e | 127 +++++++++++++++++++++--- axSetupTool/axsys.MUIB | Bin 20713 -> 21918 bytes axSetupTool/frmCommands.e | 2 +- axSetupTool/frmMain.e | 63 +++++++++++- axSetupTool/frmNodeEdit.e | 39 ++++++-- axSetupTool/frmTools.e | 201 ++++++++++++++++++++++++++++++++++++++ axSetupTool/helpText.e | 5 +- axSetupTool/makefile | 7 +- axSetupTool/tooltypes.e | 10 ++ 10 files changed, 428 insertions(+), 35 deletions(-) create mode 100644 axSetupTool/frmTools.e diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index f30ef5e..6674dfb 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -2,13 +2,6 @@ OPT OSVERSION = 37,STACK=60000,LARGE OPT PREPROCESS /* - window.pubscreen can be WINDOW.PUBSCREEN or WINDOW.PUBSCREEN= - - help screen - add warning about incorrect rexxdoor if nodes>10 - add warning to restart on exit if ACP running - restart bbs - user editor callers log viewer msgbase viewer @@ -37,7 +30,7 @@ PROC main() HANDLE helpTextInitialise() NEW frmMain.create(app) - frmMain.domain() + frmMain.doMain() EXCEPT DO diff --git a/axSetupTool/axedit.e b/axSetupTool/axedit.e index b08f519..866d897 100644 --- a/axSetupTool/axedit.e +++ b/axSetupTool/axedit.e @@ -21,7 +21,6 @@ EXPORT OBJECT app_obj app : PTR TO LONG winMain : PTR TO LONG mn_label_1 : PTR TO LONG - mnlabel1Help : PTR TO LONG mnlabel1About : PTR TO LONG mnlabel1Exit : PTR TO LONG mnlabel1Donotremovefolder1 : PTR TO LONG @@ -51,7 +50,7 @@ EXPORT OBJECT app_obj btnUsers : PTR TO LONG tx_label_0 : PTR TO LONG btnAbout : PTR TO LONG - btnHelp : PTR TO LONG + btnTools : PTR TO LONG btnExit : PTR TO LONG wi_conf_edit : PTR TO LONG btnFirstConf : PTR TO LONG @@ -176,7 +175,24 @@ EXPORT OBJECT app_obj grpCommands : PTR TO LONG btnBBSCmd : PTR TO LONG btnSysCmd : PTR TO LONG + winTools : PTR TO LONG + tx_label_3 : PTR TO LONG + txtAcpStatus : PTR TO LONG + tx_label_4 : PTR TO LONG + txtNodeCount : PTR TO LONG + tx_label_6 : PTR TO LONG + txtConfCount : PTR TO LONG + btnShutdown : PTR TO LONG + btnStart : PTR TO LONG + btnRestart : PTR TO LONG + btnClose : PTR TO LONG stR_TX_label_0 : PTR TO CHAR + stR_TX_label_3 : PTR TO CHAR + stR_txtAcpStatus : PTR TO CHAR + stR_TX_label_4 : PTR TO CHAR + stR_txtNodeCount : PTR TO CHAR + stR_TX_label_6 : PTR TO CHAR + stR_txtConfCount : PTR TO CHAR stR_gr_conf_pages : PTR TO LONG stR_gr_node_pages : PTR TO LONG ra_presetsContent : PTR TO LONG @@ -207,9 +223,16 @@ PROC create( display : PTR TO app_display ) OF app_obj DEF gr_grp_28 , grOUP_ROOT_5 , grOUP_ROOT_6 DEF gr_settingsSaveCancel , grOUP_ROOT_7 , gr_item_buttons DEF grOUP_ROOT_8 , gr_grp_39 , gr_grp_36 , gr_grp_38 - DEF grOUP_ROOT_9 , gr_grp_43 , gr_area_save + DEF grOUP_ROOT_9 , gr_grp_43 , gr_area_save , grOUP_ROOT_11 + DEF gr_grp_48 , space_29 , gr_grp_49 , space_30 self.stR_TX_label_0 := '\ec/X\nSetup Tool' + self.stR_TX_label_3 := 'ACP Status' + self.stR_txtAcpStatus := NIL + self.stR_TX_label_4 := 'Nodes' + self.stR_txtNodeCount := NIL + self.stR_TX_label_6 := 'Conferences' + self.stR_txtConfCount := NIL self.stR_gr_conf_pages := [ 'Main' , 'Download Paths' , @@ -314,7 +337,7 @@ PROC create( display : PTR TO app_display ) OF app_obj self.btnAbout := SimpleButton( 'About' ) - self.btnHelp := SimpleButton( 'Help' ) + self.btnTools := SimpleButton( 'Tools' ) self.btnExit := SimpleButton( 'Exit' ) @@ -327,7 +350,7 @@ PROC create( display : PTR TO app_display ) OF app_obj Child , self.tx_label_0 , Child , im_label_2 , Child , self.btnAbout , - Child , self.btnHelp , + Child , self.btnTools , Child , self.btnExit , End @@ -337,10 +360,6 @@ PROC create( display : PTR TO app_display ) OF app_obj Child , gr_grp_2 , End - self.mnlabel1Help := MenuitemObject , - MUIA_Menuitem_Title , 'Help' , - End - self.mnlabel1About := MenuitemObject , MUIA_Menuitem_Title , 'About' , End @@ -351,7 +370,6 @@ PROC create( display : PTR TO app_display ) OF app_obj mnlabel1File := MenuitemObject , MUIA_Menuitem_Title , 'File' , - MUIA_Family_Child , self.mnlabel1Help , MUIA_Family_Child , self.mnlabel1About , MUIA_Family_Child , self.mnlabel1Exit , End @@ -1597,6 +1615,90 @@ PROC create( display : PTR TO app_display ) OF app_obj WindowContents , self.grpCommands , End + self.tx_label_3 := TextObject , + MUIA_Background , MUII_WindowBack , + MUIA_Text_Contents , self.stR_TX_label_3 , + MUIA_Text_SetMin , MUI_TRUE , + End + + self.txtAcpStatus := TextObject , + MUIA_Background , MUII_WindowBack , + MUIA_Frame , MUIV_Frame_Text , + MUIA_Text_Contents , self.stR_txtAcpStatus , + MUIA_Text_SetMin , MUI_TRUE , + End + + self.tx_label_4 := TextObject , + MUIA_Background , MUII_WindowBack , + MUIA_Text_Contents , self.stR_TX_label_4 , + MUIA_Text_SetMin , MUI_TRUE , + End + + self.txtNodeCount := TextObject , + MUIA_Background , MUII_WindowBack , + MUIA_Frame , MUIV_Frame_Text , + MUIA_Text_Contents , self.stR_txtNodeCount , + MUIA_Text_SetMin , MUI_TRUE , + End + + self.tx_label_6 := TextObject , + MUIA_Background , MUII_WindowBack , + MUIA_Text_Contents , self.stR_TX_label_6 , + MUIA_Text_SetMin , MUI_TRUE , + End + + self.txtConfCount := TextObject , + MUIA_Background , MUII_WindowBack , + MUIA_Frame , MUIV_Frame_Text , + MUIA_Text_Contents , self.stR_txtConfCount , + MUIA_Text_SetMin , MUI_TRUE , + End + + space_29 := VSpace( 0 ) + + gr_grp_48 := GroupObject , + MUIA_HelpNode , 'GR_grp_48' , + Child , self.tx_label_3 , + Child , self.txtAcpStatus , + Child , self.tx_label_4 , + Child , self.txtNodeCount , + Child , self.tx_label_6 , + Child , self.txtConfCount , + Child , space_29 , + End + + self.btnShutdown := SimpleButton( 'Shutdown' ) + + self.btnStart := SimpleButton( 'Start' ) + + self.btnRestart := SimpleButton( 'Restart' ) + + self.btnClose := SimpleButton( 'Close' ) + + space_30 := HVSpace + + gr_grp_49 := GroupObject , + MUIA_HelpNode , 'GR_grp_49' , + MUIA_Weight , 49 , + Child , self.btnShutdown , + Child , self.btnStart , + Child , self.btnRestart , + Child , self.btnClose , + Child , space_30 , + End + + grOUP_ROOT_11 := GroupObject , + MUIA_Group_Columns , 2 , + Child , gr_grp_48 , + Child , gr_grp_49 , + End + + self.winTools := WindowObject , + MUIA_Window_Title , 'Tools' , + MUIA_Window_ID , "10WI" , + WindowContents , grOUP_ROOT_11 , + End + self.app := ApplicationObject , //( IF icon THEN MUIA_Application_DiskObject ELSE TAG_IGNORE ) , icon , //( IF arexx THEN MUIA_Application_Commands ELSE TAG_IGNORE ) , ( IF arexx THEN arexx.commands ELSE NIL ) , @@ -1605,9 +1707,7 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Application_Author , 'Darren Coles' , MUIA_Application_Base , 'NONE' , MUIA_Application_Title , 'Ami-Express Configuration Editor' , - MUIA_Application_Version , '$VER: NONE XX.XX (XX.XX.XX)' , - MUIA_Application_Copyright , 'NOBODY' , - MUIA_Application_Description , 'NONE' , + MUIA_Application_Copyright , '(c)2023 Darren Coles' , MUIA_Application_HelpFile , 'axsys.guide' , SubWindow , self.winMain , SubWindow , self.wi_conf_edit , @@ -1619,6 +1719,7 @@ PROC create( display : PTR TO app_display ) OF app_obj SubWindow , self.wi_presets , SubWindow , self.wi_areas , SubWindow , self.wi_commands , + SubWindow , self.winTools , End ENDPROC self.app diff --git a/axSetupTool/axsys.MUIB b/axSetupTool/axsys.MUIB index 03b0ee54d81d175073f7dbac30df48f4c5a06d4c..dbf8fa5abf16adfd488ed616be24882465f482ad 100644 GIT binary patch delta 626 zcmaF4ka6B>#tGWSMqH*`rUqQ*rd&X#A(x>6kTB&k=Q855;4%P`23#f}Y-!GAYzSlk znI;qC9K^UZk~NJCjEogr5{rsb^Aw!(b5e`BHXfb8xVf8Y8y9Oxetu5z+l{PI(Po`skQVms%T z=9QqT#A%`#syc3Uu!+w3d11q3lhO*t{k#U4Y+~}5|dNojVyttfSHpQI!f~C z8UiEEJt#iCs36|N5*SpfOhD?PwaMgq3098ajM9>n{PH|d>>xOe0aDy0iA5l907Ix~ zvZ00;3z)$uDa9U?S`3l{>0pDfCj*69opbVwQ-OlE!oXw$afvY~G9fOx$S2Nizy)** G1OWiKzpv;3 delta 153 zcmbQYn(^gA#tGWShFqpxCKg=ghFr!*T!vhR20+4;%bd#y2o1p41W22h0r{3d29Rkm zG0s6o%^j4U3hIR%p&n3TYb c%@$0DxFA9gIaDAFLpI6Hj=TxZ%({kL095%UzyJUM diff --git a/axSetupTool/frmCommands.e b/axSetupTool/frmCommands.e index 8c768b5..8736414 100644 --- a/axSetupTool/frmCommands.e +++ b/axSetupTool/frmCommands.e @@ -32,6 +32,7 @@ PROC btnClick() OF frmCommands DEF btn,text MOVE.L (A1),self MOVE.L 4(A1),btn + GetA4() btn:=self.btnList.item(btn) get( btn, MUIA_Text_Contents, {text}) @@ -41,7 +42,6 @@ PROC btnClick() OF frmCommands editList.editCommands(self.acpConfigName,text+5) END editList self.wake() - GetA4() ENDPROC PROC goBBSCmd() OF frmCommands diff --git a/axSetupTool/frmMain.e b/axSetupTool/frmMain.e index bd1703c..302ef34 100644 --- a/axSetupTool/frmMain.e +++ b/axSetupTool/frmMain.e @@ -4,7 +4,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui' MODULE 'tools/boopsi','dos/dos','libraries/asl','dos/var' MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' -MODULE '*axedit','*frmBase','*frmEditList','*frmNodeEdit','*frmConfEdit','*frmSettingsEdit','*frmAccess','*frmCommands','*tooltypes' +MODULE '*axedit','*frmBase','*frmEditList','*frmNodeEdit','*frmConfEdit','*frmSettingsEdit','*frmAccess','*frmCommands','*frmTools','*tooltypes' EXPORT OBJECT frmMain OF frmBase acpConfigName: PTR TO CHAR @@ -27,6 +27,7 @@ EXPORT OBJECT frmMain OF frmBase btnRestrictClickHook: hook btnExitClickHook: hook btnAboutClickHook: hook + btnToolsClickHook: hook ENDOBJECT PROC exitbuttonPressed() OF frmMain @@ -43,6 +44,19 @@ PROC aboutbuttonPressed() OF frmMain Mui_RequestA(0,self.winMain,0,'About Ami-Express Setup Tool' ,'*Ok','This tool can assist you in configuring\nalmost every aspect of Ami-Express.\n\n(c)2023 Darren Coles.',0) ENDPROC +PROC toolsbuttonPressed() OF frmMain + DEF frmTools:PTR TO frmTools + MOVE.L (A1),self + GetA4() + + self.sleep() + NEW frmTools.create(self.app) + frmTools.tools(self.acpConfigName) + END frmTools + self.wake() + +ENDPROC + PROC computersbuttonPressed() OF frmMain DEF listEdit:PTR TO frmEditList @@ -269,11 +283,47 @@ PROC create(app:PTR TO app_obj) OF frmMain set (app.mnlabel1Ask2, MUIA_Menuitem_Exclude, 3) ENDPROC -PROC domain() OF frmMain +PROC canClose() OF frmMain + DEF tempStr[255]:STRING + DEF configOk=TRUE + + MOVE.L (A1),self + GetA4() + + readToolType(self.acpConfigName,'SYSOP_NAME',tempStr) + IF StrLen(tempStr)=0 THEN configOk:=FALSE + + readToolType(self.acpConfigName,'BBS_LOCATION',tempStr) + IF StrLen(tempStr)=0 THEN configOk:=FALSE + + readToolType(self.acpConfigName,'BBS_NAME',tempStr) + IF StrLen(tempStr)=0 THEN configOk:=FALSE + + readToolType(self.acpConfigName,'BBS_GEOGRAPHIC',tempStr) + IF StrLen(tempStr)=0 THEN configOk:=FALSE + + IF configOk=FALSE + IF Mui_RequestA(0,self.winMain,0,'Warning' ,'*Ok|Cancel','You have not cofigured the minimal settings to allow Ami-Express to start up.. Are you sure you wish to exit?',0)=0 THEN RETURN FALSE + ENDIF + + IF(FindPort('AE.Master')) AND getChangeFlag() + Mui_RequestA(0,self.winMain,0,'Warning','*OK','ACP is running and changes have been made.\nA restart of the bbs is recommended.',0) + ENDIF + +ENDPROC TRUE + +PROC doMain() OF frmMain DEF fh,fr:PTR TO filerequester DEF tempStr[200]:STRING + DEF nodeCount + DEF closeHook:PTR TO hook + DEF v + NEW closeHook + installhook( closeHook, {canClose}) + self.closeHook:=closeHook + GetVar('axSetupEditor_prefs',tempStr,200,0) SetStr(tempStr) IF (EstrLen(tempStr)>0) THEN v:=tempStr[0]-48 ELSE v:=0 @@ -348,6 +398,7 @@ PROC domain() OF frmMain self.setupButtonClick(self.app.btnRestrict,self.btnRestrictClickHook,{restrictbuttonPressed}) self.setupButtonClick(self.app.btnBackup,self.btnBackupClickHook,{backupbuttonPressed}) self.setupButtonClick(self.app.btnAbout,self.btnAboutClickHook,{aboutbuttonPressed}) + self.setupButtonClick(self.app.btnTools,self.btnToolsClickHook,{toolsbuttonPressed}) domethod( self.app.mnlabel1Exit , [ MUIM_Notify , MUIA_Menuitem_Trigger, MUIV_EveryTime, @@ -365,6 +416,12 @@ PROC domain() OF frmMain set( self.app.btnUsers, MUIA_Disabled , MUI_TRUE) initialiseCache() + + nodeCount:=readToolTypeInt(self.acpConfigName,'NODES') + IF (nodeCount>10) AND (FileLength('bbs:utils/rexxdoor')=16068) + Mui_RequestA(self.app.app,0,0,'Warning','*OK','The version of rexxdoor you are using\nis not compatible with more than 10 nodes.',0) + ENDIF + self.showModal() get (self.app.mnlabel1Donotremovefolder1, MUIA_Menuitem_Checked,{v}) @@ -407,5 +464,5 @@ PROC domain() OF frmMain deInitialiseCache() DisposeLink(self.acpConfigName) - + END closeHook ENDPROC diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e index 7526f6a..0fc5e46 100644 --- a/axSetupTool/frmNodeEdit.e +++ b/axSetupTool/frmNodeEdit.e @@ -141,7 +141,8 @@ EXPORT OBJECT frmNodeEdit OF frmBase intWinLeftEdge : PTR TO control intWinTopEdge : PTR TO control intWinWidth : PTR TO control - intWinHeight : PTR TO control + intWinHeight : PTR TO control + boolWinPubScreen : PTR TO control strWinPubScreen : PTR TO control boolWinIconified : PTR TO control boolWinInterlace : PTR TO control @@ -219,6 +220,9 @@ PROC cloneNewNode() OF frmNodeEdit self.nodeCount:=self.nodeCount+1 self.currNode:=self.nodeCount-1 + self.checkRexxDoor() + + StringF(tempStr,'\d',self.currNode) set(self.strNodeNumber, MUIA_String_Contents,tempStr) @@ -232,6 +236,12 @@ PROC cloneNewNode() OF frmNodeEdit ENDIF ENDPROC +PROC checkRexxDoor() OF frmNodeEdit + IF (self.nodeCount>10) AND (FileLength('bbs:utils/rexxdoor')=16068) + Mui_RequestA(self.app.app,0,0,'Warning','*OK','The version of rexxdoor you are using\nis not compatible with more than 10 nodes.',0) + ENDIF +ENDPROC + PROC createNewNode() OF frmNodeEdit MOVE.L (A1),self GetA4() @@ -240,6 +250,9 @@ PROC createNewNode() OF frmNodeEdit self.changed:=TRUE self.newNode:=TRUE self.nodeCount:=self.nodeCount+1 + + self.checkRexxDoor() + set( self.btnNodeSave,MUIA_Disabled,FALSE) set( self.btnAddNode,MUIA_Disabled,MUI_TRUE) set( self.btnCloneNode,MUIA_Disabled,MUI_TRUE) @@ -555,6 +568,8 @@ PROC addControls() OF frmNodeEdit self.intWinWidth:=control NEW control.createStringInt('Height',NODE_WIN_HEIGHT,self.app.app,self.setChangedHook,self) self.intWinHeight:=control + NEW control.createCheckBox('Use default pubscreen',NODE_WIN_DEFPUBSCREEN,self.app.app,self.setChangedHook,self) + self.boolWinPubScreen:=control NEW control.createString('Pubscreen',NODE_WIN_PUBSCREEN,self.app.app,self.setChangedHook,self) self.strWinPubScreen:=control NEW control.createCheckBox('Iconified',NODE_WIN_ICONIFIED,self.app.app,self.setChangedHook,self) @@ -608,8 +623,8 @@ PROC addControls() OF frmNodeEdit domethod(self.grpNodeSettings4,[MUIM_Group_InitChange]) - self.controlList4:= [self.intNumColours,self.intWinLeftEdge,self.intWinTopEdge,self.intWinWidth,self.intWinHeight,self.strWinPubScreen, - self.strDisplayId,self.boolWinIconified,self.boolWinInterlace,self.boolWinStatusBar,self.boolWinToFront] + self.controlList4:= [self.intNumColours,self.intWinLeftEdge,self.intWinTopEdge,self.intWinWidth,self.intWinHeight,self.strDisplayId, + self.boolWinPubScreen,self.strWinPubScreen,self.boolWinIconified,self.boolWinInterlace,self.boolWinStatusBar,self.boolWinToFront] ForAll({control},self.controlList4,`control.addToGroup(self.grpNodeSettings4)) domethod(self.grpNodeSettings4,[OM_ADDMEMBER,HVSpace]) @@ -949,7 +964,11 @@ PROC saveChanges() OF frmNodeEdit writeToolType(windowTooltype,'WINDOW.TOPEDGE',self.intWinTopEdge.getValue()) writeToolType(windowTooltype,'WINDOW.WIDTH',self.intWinWidth.getValue()) writeToolType(windowTooltype,'WINDOW.HEIGHT',self.intWinHeight.getValue()) - writeToolType(windowTooltype,'WINDOW.PUBSCREEN',self.strWinPubScreen.getValue()) + IF self.boolWinPubScreen.getValue() + writeToolType(windowTooltype,'WINDOW.PUBSCREEN') + ELSE + writeToolType(windowTooltype,'WINDOW.PUBSCREEN',self.strWinPubScreen.getValue()) + ENDIF IF self.boolWinIconified.getValue() THEN writeToolType(windowTooltype,'WINDOW.ICONIFIED') ELSE deleteToolType(windowTooltype,'WINDOW.ICONIFIED') IF self.boolWinInterlace.getValue() THEN writeToolType(windowTooltype,'WINDOW.INTERLACE') ELSE deleteToolType(windowTooltype,'WINDOW.INTERLACE') IF self.boolWinStatusBar.getValue() THEN writeToolType(windowTooltype,'WINDOW.STATBAR') ELSE deleteToolType(windowTooltype,'WINDOW.STATBAR') @@ -1242,8 +1261,16 @@ PROC loadNode(node) OF frmNodeEdit self.intWinWidth.setValue(val) val:=readToolTypeInt(windowTooltype,'WINDOW.HEIGHT') self.intWinHeight.setValue(val) - readToolType(windowTooltype,'WINDOW.PUBSCREEN',tooltypeValue) - self.strWinPubScreen.setValue(tooltypeValue) + IF checkToolTypeExists(windowTooltype,'WINDOW.PUBSCREEN') + readToolType(windowTooltype,'WINDOW.PUBSCREEN',tooltypeValue) + IF StrLen(tooltypeValue)=0 + self.boolWinPubScreen.setValue(-1) + self.strWinPubScreen.setValue('') + ELSE + self.boolWinPubScreen.setValue(0) + self.strWinPubScreen.setValue(tooltypeValue) + ENDIF + ENDIF self.boolWinIconified.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.ICONIFIED') THEN MUI_TRUE ELSE FALSE) self.boolWinInterlace.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.INTERLACE') THEN MUI_TRUE ELSE FALSE) self.boolWinStatusBar.setValue(IF checkToolTypeExists(windowTooltype,'WINDOW.STATBAR') THEN MUI_TRUE ELSE FALSE) diff --git a/axSetupTool/frmTools.e b/axSetupTool/frmTools.e new file mode 100644 index 0000000..778f87b --- /dev/null +++ b/axSetupTool/frmTools.e @@ -0,0 +1,201 @@ +OPT MODULE +OPT PREPROCESS + +MODULE 'muimaster' , 'libraries/mui','exec/ports','exec/nodes','amigalib/ports' +MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' +MODULE '*axedit','*frmBase','*tooltypes' + +EXPORT OBJECT acpMessage + msg: mn ->length 20 + user[50]:ARRAY OF CHAR + location[50]:ARRAY OF CHAR + action[50]:ARRAY OF CHAR + baud[10]:ARRAY OF CHAR + data:LONG + command:LONG + node:LONG + lineNum:LONG + myCmds:LONG + sopt:LONG +ENDOBJECT ->LENGTH 204 + +CONST SV_ACPSHUTDOWN=202 + +EXPORT OBJECT frmTools OF frmBase + btnShutdown : PTR TO LONG + btnStart : PTR TO LONG + btnRestart : PTR TO LONG + btnClose : PTR TO LONG + + acpConfigName : PTR TO CHAR + configOk : LONG + + btnShutdownClick: hook + btnStartupClick: hook + btnRestartClick: hook +ENDOBJECT + +PROC create(app:PTR TO app_obj) OF frmTools + DEF group + SUPER self.create(app) + self.winMain:=app.winTools + + self.btnShutdown:=app.btnShutdown + self.btnStart:=app.btnStart + self.btnRestart:=app.btnRestart + self.btnClose:=app.btnClose +ENDPROC + +PROC acpShutdown() OF frmTools + DEF port,serverRP,retry + DEF masterMsg:acpMessage + + serverRP:=createPort(0,0) + masterMsg.node:=0 + masterMsg.command:=SV_ACPSHUTDOWN + masterMsg.msg.ln.type:=NT_MESSAGE + masterMsg.msg.length:=SIZEOF acpMessage + masterMsg.msg.replyport:=serverRP + + IF(port:=FindPort('AE.Master')) + PutMsg(port,masterMsg) + WaitPort(serverRP) + GetMsg(serverRP) + ENDIF + + retry:=0 + WHILE (retry<20) AND (FindPort('AE.Master')) + Delay(30) + retry++ + ENDWHILE + IF FindPort('AE.Master') + Mui_RequestA(0,self.winMain,0,'Error' ,'*Ok','ACP did not shutdown in a timely manner.',0) + ELSE + clearChangeFlag() + ENDIF + + self.refreshAcpStatus() +ENDPROC + +PROC acpStartup() OF frmTools + DEF retry + DEF execStr[255]:STRING + + IF FindPort('AE.Master')=0 + StringF(execStr,'run >NIL: \s',self.acpConfigName) + Execute(execStr,0,0) + retry:=0 + WHILE (retry<20) AND (FindPort('AE.Master')=0) + Delay(30) + retry++ + ENDWHILE + IF FindPort('AE.Master')=0 THEN Mui_RequestA(0,self.winMain,0,'Error' ,'*Ok','ACP did not startup in a timely manner.',0) + self.refreshAcpStatus() + ENDIF +ENDPROC + +PROC doAcpStart() OF frmTools + MOVE.L (A1),self + GetA4() + + self.acpStartup() +ENDPROC + +PROC doAcpShutdown() OF frmTools + MOVE.L (A1),self + GetA4() + + self.acpShutdown() +ENDPROC + +PROC doAcpRestart() OF frmTools + MOVE.L (A1),self + GetA4() + self.acpShutdown() + self.acpStartup() +ENDPROC + +PROC refreshAcpStatus() OF frmTools + DEF tempStr[20]:STRING + IF(FindPort('AE.Master')) + StrCopy(tempStr,'Running') + set( self.btnRestart,MUIA_Disabled,FALSE) + set( self.btnStart,MUIA_Disabled,MUI_TRUE) + set( self.btnShutdown,MUIA_Disabled,FALSE) + ELSE + StrCopy(tempStr,'Not Running') + set( self.btnRestart,MUIA_Disabled,MUI_TRUE) + set( self.btnStart,MUIA_Disabled,FALSE) + set( self.btnShutdown,MUIA_Disabled,MUI_TRUE) + ENDIF + IF self.configOk=FALSE + set( self.btnRestart,MUIA_Disabled,MUI_TRUE) + set( self.btnStart,MUIA_Disabled,MUI_TRUE) + set( self.btnShutdown,MUIA_Disabled,MUI_TRUE) + ENDIF + set(self.app.txtAcpStatus, MUIA_Text_Contents,tempStr) +ENDPROC + +PROC addNotifications() OF frmTools + DEF i + self.setupButtonClick(self.btnShutdown,self.btnShutdownClick,{doAcpShutdown}) + self.setupButtonClick(self.btnStart,self.btnStartupClick,{doAcpStart}) + self.setupButtonClick(self.btnRestart,self.btnRestartClick,{doAcpRestart}) + + domethod( self.btnClose , [ + MUIM_Notify , MUIA_Pressed , FALSE , + self.app.app, + 2 , + MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + +ENDPROC + +PROC removeNotifications() OF frmTools + DEF i + domethod(self.btnShutdown,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnStart,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnRestart,[MUIM_KillNotify,MUIA_Pressed]) + domethod(self.btnClose,[MUIM_KillNotify,MUIA_Pressed]) +ENDPROC + +PROC tools(acpConfigName:PTR TO CHAR) OF frmTools + DEF nodeCount,confCount,i + DEF bbsPath[255]:STRING + DEF confConfig[255]:STRING + DEF tempStr[255]:STRING + + self.acpConfigName:=acpConfigName + + nodeCount:=readToolTypeInt(acpConfigName,'NODES') + StringF(tempStr,'\d',nodeCount) + set(self.app.txtNodeCount, MUIA_Text_Contents,tempStr) + + self.configOk:=TRUE + + readToolType(acpConfigName,'BBS_LOCATION',bbsPath) + IF StrLen(bbsPath)=0 THEN self.configOk:=FALSE + + StringF(confConfig,'\sCONFCONFIG',bbsPath) + confCount:=readToolTypeInt(confConfig,'NCONFS') + StringF(tempStr,'\d',confCount) + set(self.app.txtConfCount, MUIA_Text_Contents,tempStr) + + IF (nodeCount<0) OR (confCount<0) THEN self.configOk:=FALSE + + readToolType(acpConfigName,'SYSOP_NAME',tempStr) + IF StrLen(tempStr)=0 THEN self.configOk:=FALSE + + readToolType(acpConfigName,'BBS_NAME',tempStr) + IF StrLen(tempStr)=0 THEN self.configOk:=FALSE + + readToolType(acpConfigName,'BBS_GEOGRAPHIC',tempStr) + IF StrLen(tempStr)=0 THEN self.configOk:=FALSE + self.addNotifications() + + self.refreshAcpStatus() + self.showModal() + + self.removeNotifications() + +ENDPROC diff --git a/axSetupTool/helpText.e b/axSetupTool/helpText.e index 3df060f..8517432 100644 --- a/axSetupTool/helpText.e +++ b/axSetupTool/helpText.e @@ -38,7 +38,7 @@ EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_FILE,CHEC NODE_NAME_PROMPT,NODE_NAME_PROMPT2,NODE_PASSWORD_PROMPT,NODE_AUTO_VAL_PASSWORD,NODE_REMOTE_PASSWORD, NODE_FORCE_ANSI,NODE_CON_IN_DEVICE,NODE_CON_OUT_DEVICE,NODE_SCREEN_PENS,NODE_CONF_DB_FILE, NODE_FIRST_COMMAND,NODE_SERIAL_DEVICE,NODE_MODEM_INIT,NODE_MODEM_RESET,NODE_MODEM_RING,NODE_MODEM_ANSWER, - NODE_MODEM_OFFHOOK,NODE_MODEM_NRAMS,NODE_WIN_PUBSCREEN,SYS_BBS_NAME,SYS_BBS_LOCATION,SYS_SYSOP_NAME, + NODE_MODEM_OFFHOOK,NODE_MODEM_NRAMS,NODE_WIN_DEFPUBSCREEN,NODE_WIN_PUBSCREEN,SYS_BBS_NAME,SYS_BBS_LOCATION,SYS_SYSOP_NAME, SYS_DEFAULT_MENU,SYS_AUTO_VAL_PASSWORD,SYS_REGKEY,SYS_SMTP_SERVER,SYS_SMTP_USERNAME,SYS_SMTP_PASSWORD, SYS_SYSOP_EMAIL,SYS_BBS_EMAIL,SYS_FILEDIZ_CMD,SYS_FTP_HOST,SYS_EXEC_ON_NEW_USER,SYS_EXECA_ON_NEW_USER, SYS_EXEC_ON_SYSOP_PAGE,SYS_EXECA_ON_SYSOP_PAGE,SYS_EXEC_ON_CONNECT,SYS_EXECA_ON_CONNECT, @@ -297,7 +297,8 @@ EXPORT PROC helpTextInitialise() addHelp(NODE_MODEM_ANSWER,'String sent to the modem to answer an incoming call.') addHelp(NODE_MODEM_OFFHOOK,'Command string to take teh modem off hook.') addHelp(NODE_MODEM_NRAMS,'Command string that is used to set the defaults for your modem.') - addHelp(NODE_WIN_PUBSCREEN,'Name of the public screen used for this nodes output.') + addHelp(NODE_WIN_DEFPUBSCREEN,'Use the default pubscreen for thois nodes window.') + addHelp(NODE_WIN_PUBSCREEN,'Name of the public screen used for this nodes window.') addHelp(SYS_BBS_NAME,'Sets the name of the BBS that is shown to the user when they connect.') addHelp(SYS_BBS_LOCATION,'Sets the bbs geographic location that is shown to the user when they connect.') addHelp(SYS_SYSOP_NAME,'Sets the name of the sysop of the bbs.') diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 8474475..00db67d 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -29,9 +29,12 @@ controls.m: controls.e helpText.m frmBase.m: frmBase.e axedit.m $(compiler) frmBase $(options) -frmMain.m: frmMain.e frmBase.m axedit.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m frmAccess.m frmCommands.m +frmMain.m: frmMain.e frmBase.m axedit.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m frmAccess.m frmCommands.m frmTools.m $(compiler) frmMain $(options) +frmTools.m: frmTools.e frmBAse.m axedit.m tooltypes.m + $(compiler) frmTools $(options) + frmEditList.m: frmEditList.e frmAddItem.m frmBase.m frmAddComplexItem.m tooltypes.m axedit.m stringlist.m miscfuncs.m configobject.m helpText.m $(compiler) frmEditList $(options) @@ -65,4 +68,4 @@ helpText.m: helpText.e configobject.m: configobject.e stringlist.m $(compiler) configobject $(options) clean: - delete axSetupTool axedit.m frmAddItem.m frmPresetsEdit.m frmBase.m frmMain.m frmAddComplexItem.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m tooltypes.m controls.m frmAccess.m frmCommands.m miscfuncs.m /stringlist.m configobject.m helpText.m + delete axSetupTool axedit.m frmAddItem.m frmPresetsEdit.m frmBase.m frmMain.m frmAddComplexItem.m frmEditList.m frmNodeEdit.m frmConfEdit.m frmSettingsEdit.m tooltypes.m controls.m frmAccess.m frmCommands.m miscfuncs.m /stringlist.m configobject.m helpText.m frmTools.m diff --git a/axSetupTool/tooltypes.e b/axSetupTool/tooltypes.e index 5d9126e..f60ce37 100644 --- a/axSetupTool/tooltypes.e +++ b/axSetupTool/tooltypes.e @@ -4,6 +4,7 @@ OPT PREPROCESS MODULE 'workbench/workbench','icon','*/stringlist','dos/dos' DEF diskObjectCache:PTR TO stdlist +DEF changesMade EXPORT OBJECT diskObjectCacheItem fileName:PTR TO CHAR @@ -95,6 +96,7 @@ EXPORT PROC writeToolType(toolType,key,newValue=-1,force=FALSE) ENDIF ENDIF WriteF('update tooltype \s \s = \s\n',toolType,key,newValue) + changesMade:=TRUE count:=0 IF oldtooltypes @@ -134,6 +136,7 @@ EXPORT PROC writeToolType(toolType,key,newValue=-1,force=FALSE) ENDFOR IF needToAdd WriteF('added \s\n',newItem) + changesMade:=TRUE cacheObj.changed:=TRUE oldtooltypes[count]:=StrClone(newItem) ListAddItem(oldtooltypes,0) @@ -191,6 +194,7 @@ EXPORT PROC deleteToolType(toolType,key) IF changed WriteF('delete tooltype \s \s\n',toolType,key) + changesMade:=TRUE ENDIF ENDIF ENDPROC @@ -224,6 +228,7 @@ ENDPROC result EXPORT PROC initialiseCache() diskObjectCache:=NEW diskObjectCache.stdlist(100) + changesMade:=FALSE ENDPROC EXPORT PROC deInitialiseCache() @@ -437,3 +442,8 @@ EXPORT PROC saveCachedChanges() ENDFOR ENDPROC +EXPORT PROC clearChangeFlag() + changesMade:=FALSE +ENDPROC + +EXPORT PROC getChangeFlag() IS changesMade From 01e36e4062414198c5e2dca8989fae9d0014e8b3 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Wed, 30 Aug 2023 11:23:14 +0100 Subject: [PATCH 15/47] add checks for initial install to display settings page set as runbg add new tabs for conf and nodes pages add about mui window add checks for missing critical settings --- axSetupTool/axSetupTool.e | 50 +++++++++++++++++++---- axSetupTool/axSetupTool.info | Bin 790 -> 790 bytes axSetupTool/axedit.e | 74 +++++++++++++++++++++++++--------- axSetupTool/axsys.MUIB | Bin 21918 -> 22294 bytes axSetupTool/frmBase.e | 7 +++- axSetupTool/frmConfEdit.e | 40 +++++++++++++----- axSetupTool/frmMain.e | 66 +++++++++++++++++++++++++++++- axSetupTool/frmNodeEdit.e | 33 +++++++++++---- axSetupTool/frmSettingsEdit.e | 61 +++++++++++++++++----------- 9 files changed, 260 insertions(+), 71 deletions(-) diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index 6674dfb..bb688c7 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -1,4 +1,4 @@ -OPT OSVERSION = 37,STACK=60000,LARGE +OPT OSVERSION = 37,STACK=60000,LARGE,RUNBG OPT PREPROCESS /* @@ -15,21 +15,53 @@ MODULE 'locale' MODULE 'muimaster' , 'libraries/mui' MODULE 'utility/tagitem' MODULE 'tools/boopsi' -MODULE 'icon' +MODULE 'icon','intuition/classusr' MODULE '*frmMain','*axedit','*helpText' PROC main() HANDLE - DEF frmMain: PTR TO frmMain - DEF app: PTR TO app_obj + DEF frmMain=NIL: PTR TO frmMain + DEF app=NIL: PTR TO app_obj + IF ( muimasterbase := OpenLibrary( 'muimaster.library' , MUIMASTER_VMIN ) ) = NIL THEN Throw( "LIB" , "muim" ) IF (iconbase := OpenLibrary( 'icon.library' , 0 )) = NIL THEN Throw( "LIB" , "icon" ) NEW app.create(NIL) - helpTextInitialise() + + domethod(app.gr_ax_image,[OM_ADDMEMBER,BodychunkObject, + MUIA_Frame , MUIV_Frame_ImageButton , + MUIA_Bodychunk_Body, + [$FF,$00,$03,$FE,$03,$F8,$00,$FB,$00,$05,$00,$01,$FF,$07,$FC, + $00,$FB,$00,$05,$00,$03,$F1,$8F,$C6,$00,$FF,$00,$03,$0E,$00, + $38,$00,$05,$00,$07,$E0,$DF,$8C,$00,$FF,$00,$03,$1F,$00,$70, + $00,$05,$00,$0F,$C4,$7F,$18,$00,$FF,$00,$03,$3B,$80,$E0,$00, + $05,$00,$1F,$8E,$3E,$30,$00,$FF,$00,$03,$71,$C1,$C0,$00,$05, + $00,$3F,$1F,$1C,$60,$00,$FF,$00,$03,$E0,$E3,$80,$00,$05,$00, + $7E,$3F,$88,$C0,$00,$05,$00,$01,$C0,$77,$00,$00,$05,$00,$FC, + $6F,$C1,$80,$00,$05,$00,$03,$80,$3E,$00,$00,$05,$01,$F8,$C7, + $E3,$00,$00,$05,$00,$07,$00,$1C,$00,$00,$05,$03,$F1,$8F,$C1, + $80,$00,$05,$00,$0E,$00,$3E,$00,$00,$05,$07,$E3,$1F,$88,$C0, + $00,$05,$00,$1C,$00,$77,$00,$00,$05,$0F,$C6,$3F,$1C,$60,$00, + $05,$00,$38,$00,$E3,$80,$00,$05,$1F,$8C,$7E,$3E,$30,$00,$05, + $00,$70,$01,$C1,$C0,$00,$05,$3F,$18,$FC,$7F,$18,$00,$05,$00, + $E0,$03,$80,$E0,$00,$05,$7E,$31,$F8,$DF,$8C,$00,$05,$01,$C0, + $07,$00,$70,$00,$05,$FC,$63,$F1,$8F,$C6,$00,$05,$03,$80,$0E, + $00,$38,$00,$05,$FC,$C3,$F3,$07,$E6,$00,$05,$03,$00,$0C,$00, + $18,$00,$05,$FF,$83,$FE,$03,$FE,$00,$FB,$00,$05,$7F,$01,$FC, + $01,$FC,$00,$FB,$00,$FB,$00,$FB,$00]:CHAR, + MUIA_Bodychunk_Masking, 2, + MUIA_Bodychunk_Compression, 1, + MUIA_Bodychunk_Depth, 2, + MUIA_Bitmap_Height, 21, + MUIA_Bitmap_Width, 40, + MUIA_FixHeight, 21, + MUIA_FixWidth, 40, + End]) + NEW frmMain.create(app) + frmMain.doMain() EXCEPT DO @@ -88,9 +120,11 @@ EXCEPT DO ENDSELECT - app.dispose() - END app - END frmMain + IF app + app.dispose() + END app + ENDIF + IF frmMain THEN END frmMain helpTextDeinitialise() IF iconbase THEN CloseLibrary( iconbase ) diff --git a/axSetupTool/axSetupTool.info b/axSetupTool/axSetupTool.info index 8f8c23c8e6e3a772517c6649daf83aa870ae9202..3c6b7b5865cb534e2cc72fa882dbbf52a8a345ad 100644 GIT binary patch delta 66 zcmbQnHjQn9n6!gRzk`G7n;i_uAO*-_WS(fK!OXheWAg#VFh)MGv^s+f0}})5h8bWn E0JNM8y#N3J delta 66 zcmbQnHjQn9m^8=fDI!38h5;F*06B~-6Ad+(nNIB4e1I{Gkq<1b&LG3U#K3g!30MpO D-jxm^ diff --git a/axSetupTool/axedit.e b/axSetupTool/axedit.e index 866d897..f1dd6d4 100644 --- a/axSetupTool/axedit.e +++ b/axSetupTool/axedit.e @@ -22,6 +22,7 @@ EXPORT OBJECT app_obj winMain : PTR TO LONG mn_label_1 : PTR TO LONG mnlabel1About : PTR TO LONG + mnlabel1AboutMui : PTR TO LONG mnlabel1Exit : PTR TO LONG mnlabel1Donotremovefolder1 : PTR TO LONG mnlabel1Removefolder1 : PTR TO LONG @@ -49,6 +50,7 @@ EXPORT OBJECT app_obj btnZoom : PTR TO LONG btnUsers : PTR TO LONG tx_label_0 : PTR TO LONG + gr_ax_image : PTR TO LONG btnAbout : PTR TO LONG btnTools : PTR TO LONG btnExit : PTR TO LONG @@ -64,6 +66,7 @@ EXPORT OBJECT app_obj btnRemoveConf : PTR TO LONG gr_conf_pages : PTR TO LONG gr_conf_settings : PTR TO LONG + gr_conf_more : PTR TO LONG lv_download_paths : PTR TO LONG pa_downloadpath : PTR TO LONG stR_PA_downloadpath : PTR TO LONG @@ -91,6 +94,7 @@ EXPORT OBJECT app_obj btnRemoveNode : PTR TO LONG gr_node_pages : PTR TO LONG gr_node_settings : PTR TO LONG + gr_node_second_settings : PTR TO LONG gr_node_more_settings : PTR TO LONG gr_node_serial_settings : PTR TO LONG gr_node_window_settings : PTR TO LONG @@ -205,12 +209,12 @@ ENDOBJECT PROC create( display : PTR TO app_display ) OF app_obj DEF mnlabel1File , mnlabel1Settings , mnlabel1ConferenceDelete - DEF grOUP_ROOT_0 , gr_grp_1 , gr_grp_2 , im_label_2 - DEF grOUP_ROOT_2 , gr_confselect , obj_aux0 , obj_aux1 - DEF obj_aux2 , obj_aux3 , gr_grp_13 , gr_downloadpaths - DEF gr_grp_20 , gr_uploadpaths , gr_grp_22 , gr_messagebases - DEF gr_grp_46 , gr_save , grOUP_ROOT_3 , gr_nodeSelect - DEF obj_aux4 , obj_aux5 , lbl300start , lbl300end , lbl1200start + DEF grOUP_ROOT_0 , gr_grp_1 , gr_grp_2 , grOUP_ROOT_2 + DEF gr_confselect , obj_aux0 , obj_aux1 , obj_aux2 , obj_aux3 + DEF gr_grp_13 , gr_downloadpaths , gr_grp_20 , gr_uploadpaths + DEF gr_grp_22 , gr_messagebases , gr_grp_46 , gr_save + DEF grOUP_ROOT_3 , gr_nodeSelect , obj_aux4 , obj_aux5 + DEF gr_grp_50 , lbl300start , lbl300end , lbl1200start DEF lbl1200end , lbl2400start , lbl2400end , lbl4800start DEF lbl4800end , lbl9600start , lbl9600end , lbl12000start DEF lbl12000end , lbl14400start , lbl14400end , lbl16800start @@ -235,15 +239,17 @@ PROC create( display : PTR TO app_display ) OF app_obj self.stR_txtConfCount := NIL self.stR_gr_conf_pages := [ 'Main' , + 'More' , 'Download Paths' , 'Upload Paths' , 'Message bases' , NIL ] self.stR_gr_node_pages := [ - 'Node Settings' , - 'More Settings' , + 'Main' , + 'Second' , + 'More' , 'Serial/Modem' , - 'Window Settings' , + 'Window' , 'Time restrictions' , NIL ] self.ra_presetsContent := [ @@ -326,13 +332,8 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Text_SetMin , MUI_TRUE , End - im_label_2 := ImageObject , - MUIA_Image_Spec , '5:bbs:Storage/Icons/ICONIFIED.info' , - MUIA_Frame , MUIV_Frame_ImageButton , - MUIA_Image_FreeVert , MUI_TRUE , - MUIA_Image_FreeHoriz , MUI_TRUE , - MUIA_FixHeight , 21 , - MUIA_FixWidth , 38 , + self.gr_ax_image := GroupObject , + MUIA_HelpNode , 'GR_ax_image' , End self.btnAbout := SimpleButton( 'About' ) @@ -348,7 +349,7 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Group_SameWidth , MUI_TRUE , MUIA_Group_VertSpacing , 5 , Child , self.tx_label_0 , - Child , im_label_2 , + Child , self.gr_ax_image , Child , self.btnAbout , Child , self.btnTools , Child , self.btnExit , @@ -364,6 +365,10 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Menuitem_Title , 'About' , End + self.mnlabel1AboutMui := MenuitemObject , + MUIA_Menuitem_Title , 'About Mui...' , + End + self.mnlabel1Exit := MenuitemObject , MUIA_Menuitem_Title , 'Exit' , End @@ -371,6 +376,7 @@ PROC create( display : PTR TO app_display ) OF app_obj mnlabel1File := MenuitemObject , MUIA_Menuitem_Title , 'File' , MUIA_Family_Child , self.mnlabel1About , + MUIA_Family_Child , self.mnlabel1AboutMui , MUIA_Family_Child , self.mnlabel1Exit , End @@ -563,6 +569,17 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Scrollgroup_Contents , self.gr_conf_settings , End + self.gr_conf_more := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_conf_more' , + MUIA_Group_Columns , 4 , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_conf_more := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_conf_more , + End + self.lv_download_paths := ListObject , MUIA_Frame , MUIV_Frame_InputList , End @@ -707,6 +724,7 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Register_Titles , self.stR_gr_conf_pages , MUIA_HelpNode , 'gr_conf_pages' , Child , self.gr_conf_settings , + Child , self.gr_conf_more , Child , gr_downloadpaths , Child , gr_uploadpaths , Child , gr_messagebases , @@ -843,7 +861,7 @@ PROC create( display : PTR TO app_display ) OF app_obj self.gr_node_settings := VirtgroupObject , VirtualFrame , MUIA_HelpNode , 'GR_node_settings' , - MUIA_Group_Columns , 2 , + MUIA_Group_Columns , 4 , MUIA_Group_HorizSpacing , 4 , End @@ -851,6 +869,17 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Scrollgroup_Contents , self.gr_node_settings , End + self.gr_node_second_settings := VirtgroupObject , + VirtualFrame , + MUIA_HelpNode , 'GR_node_second_settings' , + MUIA_Group_Columns , 2 , + MUIA_Group_HorizSpacing , 4 , + End + + self.gr_node_second_settings := ScrollgroupObject , + MUIA_Scrollgroup_Contents , self.gr_node_second_settings , + End + self.gr_node_more_settings := VirtgroupObject , VirtualFrame , MUIA_HelpNode , 'GR_node_more_settings' , @@ -1294,12 +1323,19 @@ PROC create( display : PTR TO app_display ) OF app_obj MUIA_Register_Titles , self.stR_gr_node_pages , MUIA_HelpNode , 'gr_node_pages' , Child , self.gr_node_settings , + Child , self.gr_node_second_settings , Child , self.gr_node_more_settings , Child , self.gr_node_serial_settings , Child , self.gr_node_window_settings , Child , self.gr_node_time_settings , End + gr_grp_50 := GroupObject , + MUIA_HelpNode , 'GR_grp_50' , + MUIA_Group_Horiz , MUI_TRUE , + Child , self.gr_node_pages , + End + self.btnNodeSave := SimpleButton( 'Save' ) self.btnNodeCancel := SimpleButton( 'Close' ) @@ -1313,7 +1349,7 @@ PROC create( display : PTR TO app_display ) OF app_obj grOUP_ROOT_3 := GroupObject , Child , gr_nodeSelect , - Child , self.gr_node_pages , + Child , gr_grp_50 , Child , gr_nodesave , End diff --git a/axSetupTool/axsys.MUIB b/axSetupTool/axsys.MUIB index dbf8fa5abf16adfd488ed616be24882465f482ad..5ba044f498db12a375ce6a2ad29c6bd8b0fd928f 100644 GIT binary patch delta 216 zcmbQYnsM4X#t86ldpJc6jk!F1<8u;|Qgh;s zfO4L>iRr169r$D>3&`_18gVgjap@Xz!Jv^Lm$3y`Qc|&1a7lgBnI(#gs4)sxRCC~vM*aFg16$SOnz E03jAfqyPW_ diff --git a/axSetupTool/frmBase.e b/axSetupTool/frmBase.e index 5656b5d..5fae612 100644 --- a/axSetupTool/frmBase.e +++ b/axSetupTool/frmBase.e @@ -10,14 +10,16 @@ EXPORT CONST ID_SAVE=1 EXPORT OBJECT frmBase app : PTR TO app_obj winMain : PTR TO LONG + showHook : PTR TO hook saveHook : PTR TO hook - canSaveHook : PTR TO hook + canSaveHook : PTR TO hook closeHook : PTR TO hook ENDOBJECT PROC create(app:PTR TO app_obj) OF frmBase self.app:=app self.saveHook:=NIL + self.showHook:=NIL self.canSaveHook:=NIL self.closeHook:=NIL ENDPROC @@ -51,13 +53,14 @@ PROC showModal() OF frmBase DEF running = TRUE , result_domethod , signal,result = FALSE self.show() - domethod( self.winMain , [ MUIM_Notify , MUIA_Window_CloseRequest , MUI_TRUE , self.app.app, 2 , MUIM_Application_ReturnID , MUIA_Window_CloseRequest ] ) + + IF self.showHook THEN callHookA(self.showHook,0,{self}) WHILE running diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index 44b1357..f1000f2 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -9,10 +9,12 @@ MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*frmAddComple EXPORT OBJECT frmConfEdit OF frmBase confConfig : PTR TO CHAR controlList : LONG + controlList2 : LONG strConfNumber : PTR TO LONG strConfName : PTR TO LONG grpConfSettings : PTR TO LONG + grpConfMore : PTR TO LONG grpConfPages : PTR TO LONG strConfName2 : PTR TO control paConfPath : PTR TO control @@ -297,7 +299,12 @@ PROC create(app:PTR TO app_obj) OF frmConfEdit get(app.gr_conf_settings,MUIA_Scrollgroup_Contents,{group}) self.grpConfSettings:=group - set(self.grpConfSettings, MUIA_Group_Columns , 4) + get(app.gr_conf_more,MUIA_Scrollgroup_Contents,{group}) + self.grpConfMore:=group + + set(self.grpConfSettings, MUIA_Group_Columns , 2) + set(self.grpConfMore, MUIA_Group_Columns , 2) + set(self.winMain,MUIA_Window_Width,MUIV_Window_Width_Screen(75)) get(self.lvDownloadPaths,MUIA_Listview_List,{list}) @@ -586,22 +593,27 @@ PROC addControls() OF frmConfEdit self.boolFtpNoDirlist:=control self.controlList:=[self.strConfName2,self.paConfPath,self.strForwardMail,self.strMenuPrompt,self.strUploadPrompt,self.paLocalULPath, - self.intFtpDirDays,self.strFtpDirName,self.boolFreeDownloads,self.boolUseUsernames,self.boolUseRealname,self.boolUseInternetNames, + self.intFtpDirDays,self.strFtpDirName] + + self.controlList2:=[self.boolFreeDownloads,self.boolUseUsernames,self.boolUseRealname,self.boolUseInternetNames, self.boolCustomMail,self.boolDefaultNewscan,self.boolDefaultNewfiles,self.boolDefaultZoom,self.boolForceNewscan, self.boolShowNewFiles,self.boolNoNewscan,self.boolNoNewFiles,self.boolNoFtpUploads,self.boolFtpNoDirlist] - domethod(self.grpConfSettings,[MUIM_Group_InitChange]) ForAll({control},self.controlList,`control.addToGroup(self.grpConfSettings)) domethod(self.grpConfSettings,[OM_ADDMEMBER,HVSpace]) domethod(self.grpConfSettings,[OM_ADDMEMBER,HVSpace]) - domethod(self.grpConfSettings,[OM_ADDMEMBER,HVSpace]) - domethod(self.grpConfSettings,[OM_ADDMEMBER,HVSpace]) domethod(self.grpConfSettings,[MUIM_Group_ExitChange]) + + domethod(self.grpConfMore,[MUIM_Group_InitChange]) + ForAll({control},self.controlList2,`control.addToGroup(self.grpConfMore)) + domethod(self.grpConfMore,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpConfMore,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpConfMore,[MUIM_Group_ExitChange]) ENDPROC -PROC freeControl(control:PTR TO control) OF frmConfEdit - control.removeFromGroup(self.grpConfSettings) +PROC freeControl(control:PTR TO control,group) OF frmConfEdit + control.removeFromGroup(group) END control ENDPROC @@ -610,8 +622,7 @@ PROC removeControls() OF frmConfEdit DEF control:PTR TO control domethod(self.grpConfSettings,[MUIM_Group_InitChange]) - ForAll({control},self.controlList,`self.freeControl(control)) - + ForAll({control},self.controlList,`self.freeControl(control,self.grpConfSettings)) get(self.grpConfSettings,MUIA_Group_ChildList,{list}) state:=list.head WHILE (obj:=NextObject({state})) @@ -619,6 +630,16 @@ PROC removeControls() OF frmConfEdit Mui_DisposeObject(obj) ENDWHILE domethod(self.grpConfSettings,[MUIM_Group_ExitChange]) + + + ForAll({control},self.controlList2,`self.freeControl(control,self.grpConfMore)) + get(self.grpConfMore,MUIA_Group_ChildList,{list}) + state:=list.head + WHILE (obj:=NextObject({state})) + domethod(self.grpConfMore,[OM_REMMEMBER,obj]) + Mui_DisposeObject(obj) + ENDWHILE + domethod(self.grpConfMore,[MUIM_Group_ExitChange]) ENDPROC PROC firstConf() OF frmConfEdit @@ -693,7 +714,6 @@ PROC saveChanges() OF frmConfEdit RETURN ENDIF - self.sleep() StringF(tempStr,'\d',self.confCount) writeToolType(self.confConfig,'NCONFS',tempStr) diff --git a/axSetupTool/frmMain.e b/axSetupTool/frmMain.e index 302ef34..426f4b3 100644 --- a/axSetupTool/frmMain.e +++ b/axSetupTool/frmMain.e @@ -7,6 +7,8 @@ MODULE 'utility/tagitem' , 'utility/hooks', 'tools/installhook' MODULE '*axedit','*frmBase','*frmEditList','*frmNodeEdit','*frmConfEdit','*frmSettingsEdit','*frmAccess','*frmCommands','*frmTools','*tooltypes' EXPORT OBJECT frmMain OF frmBase + aboutwin:LONG + missingMandatory:INT acpConfigName: PTR TO CHAR btnConfsClickHook: hook btnNodesClickHook: hook @@ -28,8 +30,21 @@ EXPORT OBJECT frmMain OF frmBase btnExitClickHook: hook btnAboutClickHook: hook btnToolsClickHook: hook + mnuAboutMuiClickHook: hook ENDOBJECT +PROC aboutMui() OF frmMain + MOVE.L (A1),self + GetA4() + IF (self.aboutwin=0) + self.aboutwin:=AboutmuiObject, + MUIA_Window_RefWindow, self.winMain, + MUIA_Aboutmui_Application, self.app.app, + End + ENDIF + IF (self.aboutwin) THEN set(self.aboutwin,MUIA_Window_Open,TRUE) +ENDPROC + PROC exitbuttonPressed() OF frmMain MOVE.L (A1),self GetA4() @@ -38,7 +53,6 @@ ENDPROC PROC aboutbuttonPressed() OF frmMain - DEF win MOVE.L (A1),self GetA4() Mui_RequestA(0,self.winMain,0,'About Ami-Express Setup Tool' ,'*Ok','This tool can assist you in configuring\nalmost every aspect of Ami-Express.\n\n(c)2023 Darren Coles.',0) @@ -269,6 +283,19 @@ PROC protocolsbuttonPressed() OF frmMain ENDPROC +PROC formShow() OF frmMain + DEF frmSettingsEdit:PTR TO frmSettingsEdit + MOVE.L (A1),self + GetA4() + IF self.missingMandatory + NEW frmSettingsEdit.create(self.app) + frmSettingsEdit.editSystemSettings(self.acpConfigName,TRUE) + END frmSettingsEdit + + ENDIF +ENDPROC + + PROC create(app:PTR TO app_obj) OF frmMain SUPER self.create(app) self.winMain:=app.winMain @@ -317,13 +344,19 @@ PROC doMain() OF frmMain DEF tempStr[200]:STRING DEF nodeCount DEF closeHook:PTR TO hook + DEF showHook:PTR TO hook DEF v NEW closeHook + NEW showHook + installhook( closeHook, {canClose}) self.closeHook:=closeHook + installhook( showHook, {formShow}) + self.showHook:=showHook + GetVar('axSetupEditor_prefs',tempStr,200,0) SetStr(tempStr) IF (EstrLen(tempStr)>0) THEN v:=tempStr[0]-48 ELSE v:=0 @@ -376,9 +409,12 @@ PROC doMain() OF frmMain ENDIF ENDIF IF EstrLen(self.acpConfigName)=0 + Mui_RequestA(0,self.winMain,0,'Error' ,'*Ok','Ami-Express setup tool is unable to proceed\nbecause we cannot find the acp.info file',0) Throw("ACP","icon") ENDIF + self.aboutwin:=0 + self.setupButtonClick(self.app.btnComputers,self.btnComputersClickHook,{computersbuttonPressed}) self.setupButtonClick(self.app.btnCheckers,self.btnCheckersClickHook,{fcheckbuttonPressed}) self.setupButtonClick(self.app.btnNamesNotAllowed,self.btnNamesNotAllowedClickHook,{namesnotallowedbuttonPressed}) @@ -400,6 +436,14 @@ PROC doMain() OF frmMain self.setupButtonClick(self.app.btnAbout,self.btnAboutClickHook,{aboutbuttonPressed}) self.setupButtonClick(self.app.btnTools,self.btnToolsClickHook,{toolsbuttonPressed}) + installhook( self.mnuAboutMuiClickHook, {aboutMui}) + + domethod( self.app.mnlabel1AboutMui, [ + MUIM_Notify , MUIA_Menuitem_Trigger, MUIV_EveryTime, + self.app.mnlabel1AboutMui, + 3, + MUIM_CallHook , self.mnuAboutMuiClickHook, self ] ) + domethod( self.app.mnlabel1Exit , [ MUIM_Notify , MUIA_Menuitem_Trigger, MUIV_EveryTime, self.app.mnlabel1Exit, @@ -418,6 +462,21 @@ PROC doMain() OF frmMain initialiseCache() nodeCount:=readToolTypeInt(self.acpConfigName,'NODES') + IF nodeCount=-1 + Mui_RequestA(0,self.winMain,0,'Error' ,'*Ok','Ami-Express setup tool is unable to proceed\nbecause the number of nodes is not defined in the acp.info file',0) + Throw("ACP","icon") + ENDIF + + self.missingMandatory:=FALSE + readToolType(self.acpConfigName,'BBS_LOCATION',tempStr) + IF EstrLen(tempStr)=0 THEN self.missingMandatory:=TRUE + readToolType(self.acpConfigName,'BBS_NAME',tempStr) + IF EstrLen(tempStr)=0 THEN self.missingMandatory:=TRUE + readToolType(self.acpConfigName,'BBS_GEOGRAPHIC',tempStr) + IF EstrLen(tempStr)=0 THEN self.missingMandatory:=TRUE + readToolType(self.acpConfigName,'SYSOP_NAME',tempStr) + IF EstrLen(tempStr)=0 THEN self.missingMandatory:=TRUE + IF (nodeCount>10) AND (FileLength('bbs:utils/rexxdoor')=16068) Mui_RequestA(self.app.app,0,0,'Warning','*OK','The version of rexxdoor you are using\nis not compatible with more than 10 nodes.',0) ENDIF @@ -458,11 +517,14 @@ PROC doMain() OF frmMain ENDIF ENDIF StrAdd(tempStr,self.acpConfigName) - SetVar('axSetupEditor_prefs',tempStr,EstrLen(tempStr),GVF_SAVE_VAR OR GVF_GLOBAL_ONLY) + + SetVar('axSetupEditor_prefs',tempStr,-1,GVF_SAVE_VAR OR GVF_GLOBAL_ONLY) + IF KickVersion(39)=FALSE THEN Execute('Copy env:axSetupEditor_prefs envarc:',0,0) clearDiskObjectCache() deInitialiseCache() DisposeLink(self.acpConfigName) END closeHook + END showHook ENDPROC diff --git a/axSetupTool/frmNodeEdit.e b/axSetupTool/frmNodeEdit.e index 0fc5e46..cd3a507 100644 --- a/axSetupTool/frmNodeEdit.e +++ b/axSetupTool/frmNodeEdit.e @@ -14,7 +14,8 @@ OBJECT timeItem ENDOBJECT EXPORT OBJECT frmNodeEdit OF frmBase - controlList1 : LONG + controlList1a : LONG + controlList1b : LONG controlList2 : LONG controlList3 : LONG controlList4 : LONG @@ -32,6 +33,7 @@ EXPORT OBJECT frmNodeEdit OF frmBase btnNodeSave : PTR TO LONG btnNodeCancel : PTR TO LONG grpNodeSettings : PTR TO LONG + grpNodeMoreSettings: PTR TO LONG grpNodeSettings2 : PTR TO LONG grpNodeSettings3 : PTR TO LONG grpNodeSettings4 : PTR TO LONG @@ -193,7 +195,11 @@ PROC create(app:PTR TO app_obj) OF frmNodeEdit get(app.gr_node_settings,MUIA_Scrollgroup_Contents,{group}) self.grpNodeSettings:=group - set(self.grpNodeSettings, MUIA_Group_Columns , 4) + set(self.grpNodeSettings, MUIA_Group_Columns , 2) + + get(app.gr_node_second_settings,MUIA_Scrollgroup_Contents,{group}) + self.grpNodeMoreSettings:=group + set(self.grpNodeMoreSettings, MUIA_Group_Columns , 2) get(app.gr_node_more_settings,MUIA_Scrollgroup_Contents,{group}) self.grpNodeSettings2:=group @@ -391,7 +397,7 @@ PROC addControls() OF frmNodeEdit self.strFtpDataPort:=control NEW control.createString('HTTP Port(s)',NODE_HTTP_PORT,self.app.app,self.setChangedHook,self) self.strHttpPort:=control - NEW control.createCycle('UL Credit',NODE_KEEP_UL_CREDIT,['Default','Grant additional time',0],self.app.app,self.setChangedHook,self) + NEW control.createCycle('UL Credit',NODE_KEEP_UL_CREDIT,['Default','Give extra time',0],self.app.app,self.setChangedHook,self) self.intKeepUlCredit:=control NEW control.createStringInt('Max Message Queue',NODE_MAX_MSG_QUEUE,self.app.app,self.setChangedHook,self) self.intMaxMsgQueue:=control @@ -583,19 +589,27 @@ PROC addControls() OF frmNodeEdit NEW control.createModeSelect('DisplayId',NODE_DISPLAY_ID,self.app.app,self.setChangedHook,self) self.strDisplayId:=control - self.controlList1:= [self.intPriority,self.strNodeStart,self.strSystemPassword,self.strSystemPasswordPrompt,self.strNewuserPassword, + self.controlList1a:= [self.intPriority,self.strNodeStart,self.strSystemPassword,self.strSystemPasswordPrompt,self.strNewuserPassword, self.strNamePrompt,self.strNamePrompt2,self.strPasswordPrompt,self.paScreens,self.intAutoValPreset,self.intAutoValDelay, self.strAutoValPassword,self.strFtpPort,self.strFtpDataPort,self.strHttpPort,self.intKeepUlCredit, - self.intMaxMsgQueue,self.paPlaypen,self.intRingCount,self.strRemotePassword,self.intSysopChatColour,self.intUserChatColour, + self.intMaxMsgQueue] + + self.controlList1b:= [self.paPlaypen,self.intRingCount,self.strRemotePassword,self.intSysopChatColour,self.intUserChatColour, self.fnUserDataName,self.fnUserMiscName,self.fnUserKeysName,self.paLocalUlPath,self.strForceAnsi,self.intOverrideTimeout, self.intBGFilecheckStack,self.strConInputDev,self.strConOutputDev,self.strScreenPens,self.strConfDb,self.fnFilesNotAllowed, self.strFirstCommand,self.intSerialCacheSize] domethod(self.grpNodeSettings,[MUIM_Group_InitChange]) - ForAll({control},self.controlList1,`control.addToGroup(self.grpNodeSettings)) + ForAll({control},self.controlList1a,`control.addToGroup(self.grpNodeSettings)) domethod(self.grpNodeSettings,[OM_ADDMEMBER,HVSpace]) domethod(self.grpNodeSettings,[OM_ADDMEMBER,HVSpace]) domethod(self.grpNodeSettings,[MUIM_Group_ExitChange]) + + domethod(self.grpNodeMoreSettings,[MUIM_Group_InitChange]) + ForAll({control},self.controlList1b,`control.addToGroup(self.grpNodeMoreSettings)) + domethod(self.grpNodeMoreSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpNodeMoreSettings,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpNodeMoreSettings,[MUIM_Group_ExitChange]) self.controlList2:= [self.boolCallersLog,self.boolCapitalFilenames,self.boolDefScreens,self.boolDebugLog,self.boolDoorLog,self.boolStartLog, self.boolUDLog,self.boolChatOn,self.boolDisableQuickLogon,self.boolIdleNode,self.boolMailscanPrompt,self.boolNoTimeout, @@ -608,6 +622,8 @@ PROC addControls() OF frmNodeEdit ForAll({control},self.controlList2,`control.addToGroup(self.grpNodeSettings2)) domethod(self.grpNodeSettings2,[OM_ADDMEMBER,HVSpace]) domethod(self.grpNodeSettings2,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpNodeSettings2,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpNodeSettings2,[OM_ADDMEMBER,HVSpace]) domethod(self.grpNodeSettings2,[MUIM_Group_ExitChange]) self.controlList3:=[self.strSerialDevice,self.intSerialUnit,self.intSerialBaud,0,0,self.boolA2232Patch,self.boolNoPurgeLine,self.boolRepurge, @@ -619,6 +635,8 @@ PROC addControls() OF frmNodeEdit ForAll({control},self.controlList3,`IF control THEN control.addToGroup(self.grpNodeSettings3) ELSE domethod(self.grpNodeSettings3,[OM_ADDMEMBER,HVSpace])) domethod(self.grpNodeSettings3,[OM_ADDMEMBER,HVSpace]) domethod(self.grpNodeSettings3,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpNodeSettings3,[OM_ADDMEMBER,HVSpace]) + domethod(self.grpNodeSettings3,[OM_ADDMEMBER,HVSpace]) domethod(self.grpNodeSettings3,[MUIM_Group_ExitChange]) domethod(self.grpNodeSettings4,[MUIM_Group_InitChange]) @@ -645,7 +663,8 @@ PROC removeControls() OF frmNodeEdit DEF list:PTR TO lh,state,obj DEF control:PTR TO control - ForAll({control},self.controlList1,`self.freeControl(control,self.grpNodeSettings)) + ForAll({control},self.controlList1a,`self.freeControl(control,self.grpNodeSettings)) + ForAll({control},self.controlList1b,`self.freeControl(control,self.grpNodeMoreSettings)) ForAll({control},self.controlList2,`self.freeControl(control,self.grpNodeSettings2)) ForAll({control},self.controlList3,`self.freeControl(control,self.grpNodeSettings3)) ForAll({control},self.controlList4,`self.freeControl(control,self.grpNodeSettings4)) diff --git a/axSetupTool/frmSettingsEdit.e b/axSetupTool/frmSettingsEdit.e index 27dc92b..e61bd40 100644 --- a/axSetupTool/frmSettingsEdit.e +++ b/axSetupTool/frmSettingsEdit.e @@ -169,6 +169,9 @@ PROC addSystemControls() OF frmSettingsEdit DEF languageList:PTR TO LONG DEF i + NEW control.createDirSelect('bBBS Path',SYS_BBS_PATH,self.app.app,self.setChangedHook,self) + self.paBBSPath:=control + NEW control.createString('bBBS Name',SYS_BBS_NAME,self.app.app,self.setChangedHook,self) self.strBBSName:=control @@ -298,16 +301,17 @@ PROC addSystemControls() OF frmSettingsEdit NEW control.createString('Execute async on upload',SYS_EXECA_ON_UPLOAD,self.app.app,self.setChangedHook,self) self.strExecAOnUpload:=control - self.controlList:=[self.strBBSName,self.strBBSLocation,self.strSysopName,self.strRegKey,self.cyNewAccounts,self.strDefaultMenu, + self.controlList:=[self.paBBSPath,self.strBBSName,self.strBBSLocation,self.strSysopName,self.strRegKey,self.cyNewAccounts,self.strDefaultMenu, self.paLocalULPath,self.intAutoValPreset,self.intAutoValDelay,self.strAutoValPassword,self.cyLanguage, self.strSmtpHost,self.intSmtpPort,self.strSmtpUsername,self.strSmtpPassword,self.boolSmtpSSL,self.strSysopEmail, - self.strBbsEmail,self.boolMailOnPage,self.boolMailOnComment,self.boolMailOnLogon,self.boolMailOnLogoff,self.boolMailOnNewUser, - self.boolMailOnUpload,self.boolMailOnPwdFail,self.paLanguageBase,self.paHistory,self.paUserNotes,self.intHoldAccess, + self.strBbsEmail,self.paLanguageBase,self.paHistory,self.paUserNotes,self.intHoldAccess, self.strFileDizSysCmd,self.strFtpHost,self.strFtpPort,self.strFtpDataPort,self.strHttpPort,self.strExecOnNewUser, self.strExecAOnNewUser,self.strExecOnPage,self.strExecAOnPage,self.strExecOnConnect,self.strExecAOnConnect, self.strExecOnLogon,self.strExecAOnLogon,self.strExecOnLogoff,self.strExecAOnLogoff, self.strExecOnComment,self.strExecAOnComment,self.strExecOnUpload,self.strExecAOnUpload, - self.boolCreditByKb,self.boolLongWho,self.boolConvertToMb,self.boolQuietJoin,self.boolRelativeConfs] + self.boolCreditByKb,self.boolLongWho,self.boolConvertToMb,self.boolQuietJoin,self.boolRelativeConfs, + self.boolMailOnPage,self.boolMailOnComment,self.boolMailOnLogon,self.boolMailOnLogoff,self.boolMailOnNewUser, + self.boolMailOnUpload,self.boolMailOnPwdFail] //domethod(self.grpSettings,[MUIM_Group_InitChange]) ForAll({control},self.controlList,`IF control THEN control.addToGroup(self.grpSettings) ELSE FALSE) @@ -339,9 +343,6 @@ PROC addServerControls() OF frmSettingsEdit DEF tempStr[255]:STRING DEF i - NEW control.createDirSelect('bBBS Path',SYS_BBS_PATH,self.app.app,self.setChangedHook,self) - self.paBBSPath:=control - NEW control.createStringInt('Stack size',SYS_STACK,self.app.app,self.setChangedHook,self) self.intStack:=control @@ -442,15 +443,15 @@ PROC addServerControls() OF frmSettingsEdit self.nuttonCommands.add(control) ENDFOR - self.controlList:=[self.paBBSPath,self.intStack,self.intPriority,self.intTelnetPort,self.intFtpPort, + self.controlList:=[self.intStack,self.intPriority,self.intTelnetPort,self.intFtpPort, self.boolIconified,self.intIconifyLeft,self.intIconifyTop,self.strAcpFont,self.strExecOnStart, self.intDosCheckTime,self.intDosBanTime,self.intDosCheckTrig,self.boolDoNotMove, self.boolMulticom,self.boolAEShell,self.boolNoCx,self.boolNoSaveState] domethod(self.grpSettings,[MUIM_Group_InitChange]) - sublist:=[self.paBBSPath,self.intStack,self.intPriority,self.intTelnetPort,self.intFtpPort, - self.boolIconified,self.intIconifyLeft,self.intIconifyTop,self.strAcpFont,self.strExecOnStart, + sublist:=[self.intStack,self.intPriority,self.intTelnetPort,self.intFtpPort, + self.strAcpFont,self.strExecOnStart, self.intDosCheckTime,self.intDosBanTime,self.intDosCheckTrig] ForAll({control},sublist,`control.addToGroup(self.grpSettings)) @@ -478,7 +479,7 @@ PROC addServerControls() OF frmSettingsEdit control.addToGroup(self.grpSettings) ENDFOR - sublist:=[self.boolDoNotMove,self.boolMulticom,self.boolAEShell,self.boolNoCx,self.boolNoSaveState] + sublist:=[self.intIconifyLeft,self.intIconifyTop,self.boolIconified,self.boolDoNotMove,self.boolMulticom,self.boolAEShell,self.boolNoCx,self.boolNoSaveState] ForAll({control},sublist,`control.addToGroup(self.grpSettings)) @@ -593,6 +594,12 @@ PROC saveSystemChanges() OF frmSettingsEdit MOVE.L (A1),self GetA4() + fullTrim(self.paBBSPath.getValue(),tempStr) + IF EstrLen(tempStr)=0 + Mui_RequestA(0,self.winMain,0,'Error','*OK','BBS Path is a mandatory field',0) + RETURN + ENDIF + fullTrim(self.strBBSName.getValue(),tempStr) IF EstrLen(tempStr)=0 Mui_RequestA(0,self.winMain,0,'Error','*OK','BBS Name is a mandatory field',0) @@ -612,6 +619,7 @@ PROC saveSystemChanges() OF frmSettingsEdit ENDIF self.sleep() + writeToolType(self.acpName,'BBS_LOCATION',self.paBBSPath.getValue()) writeToolType(self.acpName,'BBS_NAME',self.strBBSName.getValue()) writeToolType(self.acpName,'BBS_GEOGRAPHIC',self.strBBSLocation.getValue()) writeToolType(self.acpName,'SYSOP_NAME',self.strSysopName.getValue()) @@ -688,14 +696,7 @@ PROC saveServerChanges() OF frmSettingsEdit MOVE.L (A1),self GetA4() - fullTrim(self.paBBSPath.getValue(),tempStr) - IF EstrLen(tempStr)=0 - Mui_RequestA(0,self.winMain,0,'Error','*OK','BBS Path is a mandatory field',0) - RETURN - ENDIF - self.sleep() - writeToolType(self.acpName,'BBS_LOCATION',self.paBBSPath.getValue()) writeToolType(self.acpName,'BBS_STACK',self.intStack.getValue()) writeToolType(self.acpName,'PRIORITY',self.intPriority.getValue()) IF self.boolIconified.getValue() THEN writeToolType(self.acpName,'ICONIFIED') ELSE deleteToolType(self.acpName,'ICONIFIED') @@ -784,14 +785,20 @@ PROC saveZoomChanges() OF frmSettingsEdit self.wake() ENDPROC -PROC editSystemSettings(acpName:PTR TO CHAR) OF frmSettingsEdit +PROC formShow() OF frmSettingsEdit + MOVE.L (A1),self + GetA4() + Mui_RequestA(0,self.winMain,0,'Information','*OK','For the initial setup please fill in the mandatory fields on this page.',0) +ENDPROC + +PROC editSystemSettings(acpName:PTR TO CHAR, initialSetup=FALSE) OF frmSettingsEdit DEF loop,val,count,i,entry,temppath[255]:STRING,tempstr[255]:STRING DEF bbsPath[200]:STRING DEF languagesTooltype[255]:STRING DEF languages:PTR TO stringlist - DEF saveHook:PTR TO hook + DEF formShowHook:PTR TO hook DEF closeHook:PTR TO hook NEW saveHook @@ -800,6 +807,13 @@ PROC editSystemSettings(acpName:PTR TO CHAR) OF frmSettingsEdit NEW closeHook installhook( closeHook, {canClose}) self.closeHook:=closeHook + + IF initialSetup + NEW formShowHook + installhook( formShowHook, {formShow}) + self.showHook:=formShowHook + ENDIF + self.acpName:=acpName self.bbsConfigName:=String(255) @@ -839,6 +853,9 @@ PROC editSystemSettings(acpName:PTR TO CHAR) OF frmSettingsEdit readToolType(self.acpName,'BBS_NAME',tempstr) self.strBBSName.setValue(tempstr) + readToolType(self.acpName,'BBS_LOCATION',tempstr) + self.paBBSPath.setValue(tempstr) + readToolType(self.acpName,'BBS_GEOGRAPHIC',tempstr) self.strBBSLocation.setValue(tempstr) @@ -957,6 +974,7 @@ PROC editSystemSettings(acpName:PTR TO CHAR) OF frmSettingsEdit END saveHook END closeHook END languages + IF initialSetup THEN END formShowHook DisposeLink(self.languages) DisposeLink(self.bbsConfigName) ENDPROC @@ -986,9 +1004,6 @@ PROC editServerSettings(acpName:PTR TO CHAR) OF frmSettingsEdit set( self.winMain, MUIA_Window_Title,'Edit Server Settings') set( self.winMain, MUIA_Window_ID, "FSER") - readToolType(self.acpName,'BBS_LOCATION',tempstr) - self.paBBSPath.setValue(tempstr) - val:=readToolTypeInt(self.acpName,'BBS_STACK') self.intStack.setValue(val) From d2f6b7bc16af013baae5ab3aeda1e55704817112 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 1 Sep 2023 10:52:46 +0100 Subject: [PATCH 16/47] setup editor 1) set file selector to only show folders for conf upload/download paths 2) give user option to add all sub folders when adding conf download path --- axSetupTool/axSetupTool.e | 2 +- axSetupTool/frmConfEdit.e | 65 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/axSetupTool/axSetupTool.e b/axSetupTool/axSetupTool.e index bb688c7..69e34bf 100644 --- a/axSetupTool/axSetupTool.e +++ b/axSetupTool/axSetupTool.e @@ -1,4 +1,4 @@ -OPT OSVERSION = 37,STACK=60000,LARGE,RUNBG +OPT OSVERSION = 37,LARGE,RUNBG OPT PREPROCESS /* diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index f1000f2..05b4d36 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -3,7 +3,7 @@ OPT PREPROCESS MODULE 'muimaster' , 'libraries/mui','dos' MODULE 'tools/boopsi','workbench/workbench','icon','intuition/classusr' -MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists' +MODULE 'utility/tagitem','utility/hooks','tools/installhook','exec/lists','libraries/asl','dos/dos' MODULE '*axedit','*frmBase','*tooltypes','*controls','*miscfuncs','*frmAddComplexItem','*configObject','*/stringlist','*helpText' EXPORT OBJECT frmConfEdit OF frmBase @@ -95,6 +95,18 @@ EXPORT OBJECT frmConfEdit OF frmBase msgbaseLists: PTR TO stdlist ENDOBJECT +PROC setasldrawerflags() OF frmConfEdit + DEF tags:PTR TO LONG + MOVE.L A1,tags + + WHILE tags[]<>0 DO tags++ + tags[]:=ASLFR_DRAWERSONLY + tags++ + tags[]:=-1 + tags++ + tags[]:=0 +ENDPROC TRUE + PROC dlPathChange() OF frmConfEdit DEF str MOVE.L (A1),self @@ -163,6 +175,41 @@ PROC ulpathItemRemove() OF frmConfEdit self.changed:=TRUE ENDPROC +PROC addDlPathSubDirs(path) OF frmConfEdit + DEF dir_info:PTR TO fileinfoblock + DEF pdir + DEF subdir[255]:STRING + + IF ((dir_info:=AllocDosObject(DOS_FIB,NIL)) = NIL) + RETURN + ENDIF + + IF ((pdir:=Lock(path,ACCESS_READ)))=FALSE + FreeDosObject(DOS_FIB,dir_info) + RETURN + ENDIF + + IF(Examine(pdir, dir_info))=FALSE + FreeDosObject(DOS_FIB,dir_info) + UnLock(pdir) + RETURN + ENDIF + + WHILE(ExNext(pdir,dir_info)) + IF(dir_info.direntrytype >= 0) + StrCopy(subdir,path) + AddPart(subdir,dir_info.filename,255) + SetStr(subdir) + StrAdd(subdir,'/') + domethod( self.lvDownloadPaths , [ MUIM_List_InsertSingle , subdir , MUIV_List_Insert_Bottom ] ) + self.addDlPathSubDirs(subdir) + ENDIF + ENDWHILE + + UnLock(pdir) + FreeDosObject(DOS_FIB,dir_info) +ENDPROC + PROC dlpathItemAdd() OF frmConfEdit DEF str MOVE.L (A1),self @@ -170,6 +217,14 @@ PROC dlpathItemAdd() OF frmConfEdit get(self.strDownloadPath, MUIA_String_Contents,{str}) domethod( self.lvDownloadPaths , [ MUIM_List_InsertSingle , str , MUIV_List_Insert_Bottom ] ) + + IF Mui_RequestA(0,self.winMain,0,'Query', + '*Yes|No','Should we also scan for and add any sub-folders of this path?',0) + self.addDlPathSubDirs(str) + ENDIF + + + get (self.strDownloadPath,MUIA_Popstring_String,{str}) set(str, MUIA_String_Contents,'') @@ -1027,6 +1082,7 @@ PROC editConfs(acpName) OF frmConfEdit DEF count,i,entry,temppath[255]:STRING,tempstr[255]:STRING DEF saveHook:PTR TO hook DEF closeHook:PTR TO hook + DEF aslflagsHook:PTR TO hook DEF bbsPath[255]:STRING DEF msgbaseList:PTR TO stdlist DEF msgbase:PTR TO msgbase @@ -1038,6 +1094,9 @@ PROC editConfs(acpName) OF frmConfEdit installhook( closeHook, {canClose}) self.closeHook:=closeHook + NEW aslflagsHook + installhook( aslflagsHook, {setasldrawerflags}) + self.acpName:=acpName set( self.btnEditMsgbase , MUIA_Disabled , MUI_TRUE) @@ -1049,6 +1108,9 @@ PROC editConfs(acpName) OF frmConfEdit set( self.btnUlPathRemove , MUIA_Disabled , MUI_TRUE) set( self.btnDlPathRemove , MUIA_Disabled , MUI_TRUE) + set (self.strUploadPath,MUIA_Popasl_StartHook,aslflagsHook) + set (self.strDownloadPath,MUIA_Popasl_StartHook,aslflagsHook) + set( self.lvDownloadPaths , MUIA_ShortHelp , getHelpText(DLPATHS_LVIEW)) set( self.btnDlPathAdd , MUIA_ShortHelp , getHelpText(DLPATHS_ADD)) set( self.btnDlPathRemove , MUIA_ShortHelp , getHelpText(DLPATHS_DELETE)) @@ -1102,5 +1164,6 @@ PROC editConfs(acpName) OF frmConfEdit self.removeControls() END saveHook END closeHook + END aslflagsHook DisposeLink(self.confConfig) ENDPROC From 5106d18cea3152353673c7d8a5904db997a226ce Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 1 Sep 2023 10:56:44 +0100 Subject: [PATCH 17/47] ACP 1) Add options to start config tool 2) add a shutdown command so config tool can restart ACP Express 1) add install script 2) remove file size check from ftp dir scanning as it was causing some issues 3) update (c) dates to 2023 4) fix memory corruption bug in tooltype cache --- ACP.e | 60 ++++++++++++---- Install Ami-Express | 170 +++++++++++++++++++++++++++----------------- axcommon.e | 1 + express.e | 18 +++-- stringlist.e | 41 ++++++++++- tooltypes.e | 7 +- 6 files changed, 201 insertions(+), 96 deletions(-) diff --git a/ACP.e b/ACP.e index 18dc532..7ebc05d 100644 --- a/ACP.e +++ b/ACP.e @@ -46,6 +46,8 @@ ENUM ERR_NONE,ERR_ALREADY_RUNNING,ERR_STARTUP, ERR_VALIDATE,ERR_NO_DISKFONT,ERR_FDS_RANGE +CONST AX_SETUP_TOOL='BBS:Utils/axSetupTool' + CONST LISTENQ=100 CONST EINTR=4 CONST MAX_LINE=255 @@ -297,6 +299,7 @@ DEF nodeIdle[MAX_NODES]:ARRAY OF CHAR DEF startUp=FALSE/*** Set startup scripts to none ***/ DEF zipOn=FALSE/*** Turn ZIPPED window off ***/ DEF notDone=1 +DEF shuttingDown=0 DEF down[MAX_NODES]:ARRAY OF CHAR DEF activeNodes[MAX_NODES]:ARRAY OF CHAR DEF publicName[200]:STRING @@ -329,6 +332,8 @@ DEF dosCheckTime=60 DEF dosCheckTrigger=5 DEF dosBanTime=60 +DEF menuSelect=FALSE + DEF masterPort[100]:STRING DEF cmds[MAX_NODES]:ARRAY OF LONG @@ -1036,10 +1041,8 @@ PROC createCustomMenus(nodes) maddNodes(nodes) maddItem( NM_ITEM, 'Instant Login',0, 0, 0, 0) maddNodes(nodes) - IF shellMode - maddItem( NM_ITEM, 'AEShell',0, 0, 0, 0) - maddNodes(nodes) - ENDIF + maddItem( NM_ITEM, 'Shell',0, 0, 0, 0) + maddNodes(nodes) maddItem( NM_ITEM, 'Toggle Chat',0, 0, 0, 0) maddNodes(nodes) maddItem( NM_ITEM, 'Exit Node',0, 0, 0, 0) @@ -1062,6 +1065,7 @@ PROC createCustomMenus(nodes) maddNodes(nodes) maddItem( NM_ITEM,'Set NRAMS',0,0,0,0) maddNodes(nodes) + maddItem( NM_ITEM,'Config Editor',0,IF FileLength(AX_SETUP_TOOL)>=0 THEN 0 ELSE ITEMENABLED,0,0) maddItem( NM_TITLE, 'Custom Control',0,0,0,0) @@ -1280,12 +1284,10 @@ PROC doControl(node) DisplayBeep(scr) ENDIF CASE SV_AESHELL - IF shellMode - IF(users[node].actionVal=ENV_AWAITCONNECT) - callNode(node,SV_AESHELL) - ELSE - DisplayBeep(scr) - ENDIF + IF(users[node].actionVal=ENV_AWAITCONNECT) + callNode(node,SV_AESHELL) + ELSE + DisplayBeep(scr) ENDIF CASE SV_CHATTOGGLE cd:=users[node].actionVal @@ -1443,10 +1445,14 @@ PROC handleEditGadget(im:PTR TO intuimessage,ig) IF(button) IF(nutton(2)=FALSE) THEN doButton(2,0) ELSE - IF shellMode + IF shellMode OR menuSelect IF(control) THEN control:=0 ELSE control:=SV_AESHELL ELSE - selectAndRunConfig('','','') + IF FileLength(AX_SETUP_TOOL)>=0 + Execute(AX_SETUP_TOOL,0,0) + ELSE + selectAndRunConfig('','','') + ENDIF ENDIF ENDIF CASE GAD_TOGGLECHAT @@ -1586,6 +1592,8 @@ PROC updateNode(name:PTR TO CHAR,location:PTR TO CHAR,action:PTR TO CHAR,baud:PT StrCopy(action2,'Node Inactive ') IF activeNodes[node] THEN activeNodeCount-- activeNodes[node]:=FALSE + down[node]:=TRUE + IF (activeNodeCount=0) AND (shuttingDown) THEN notDone:=0 /*if(ActiveNodeCount==0) notDone=0;*/ CASE ENV_MULTICHAT StrCopy(action2,'MultiNode Chat ') @@ -2026,6 +2034,9 @@ PROC checkMasterSig(signals) ELSEIF(cpymsg.command=SV_ACPALERT) myrequest(cpymsg.user) ReplyMsg(cpymsg) + ELSEIF(cpymsg.command=SV_ACPSHUTDOWN) + attemptShutdown() + ReplyMsg(cpymsg) ELSEIF(cpymsg.command=SV_STARTNODE) StringF(temp,'AmiExpress_Node.\d',cpymsg.node) IF(FindPort(temp))=FALSE @@ -2747,6 +2758,18 @@ PROC readStartUp(s:PTR TO CHAR) dobj,cfg:=getToolTypes(s) IF (dobj=NIL) + acpError:=1 + ELSEIF(FindToolType(dobj.tooltypes,'SYSOP_NAME')=0) OR (FindToolType(dobj.tooltypes,'BBS_NAME')=0) OR + (FindToolType(dobj.tooltypes,'BBS_LOCATION')=0) OR (FindToolType(dobj.tooltypes,'BBS_GEOGRAPHIC')=0) + acpError:=1 + ENDIF + + IF acpError + IF FileLength(AX_SETUP_TOOL)>=0 + Execute(AX_SETUP_TOOL,0,0) + RETURN + ENDIF + acpError:=0 selectAndRunConfig('','s:','aeicon.json') dobj,cfg:=getToolTypes(s) @@ -2757,7 +2780,7 @@ PROC readStartUp(s:PTR TO CHAR) ENDIF ENDIF oldtooltypes:=dobj.tooltypes - + IF(t:=FindToolType(oldtooltypes,'ACPFONT')) StrCopy(fontName,t) ENDIF @@ -3229,7 +3252,8 @@ ENDPROC PROC attemptShutdown() DEF i - + + shuttingDown:=TRUE IF(activeNodeCount=0) notDone:=0 ELSE @@ -3237,7 +3261,7 @@ PROC attemptShutdown() IF(StrLen(startNode[i])>0) IF((users[i].actionVal=ENV_AWAITCONNECT) AND (down[i])=FALSE) control:=SV_NODEOFFHOOK - down[i]:=TRUE + ->down[i]:=TRUE doControl(i) ENDIF ELSE @@ -4155,13 +4179,19 @@ PROC main() HANDLE CASE MENUPICK ->quit menu item IF(menunum(im.code)=0) AND (itemnum(im.code)=5) THEN attemptShutdown() + + IF(menunum(im.code)=1) AND (itemnum(im.code)=14) + IF FileLength(AX_SETUP_TOOL)>=0 THEN Execute(AX_SETUP_TOOL,0,0) + ENDIF IF(menunum(im.code)=1) i:=button button:=0 + menuSelect:=TRUE handleEditGadget(NIL,GAD_SYSOPLOGIN+itemnum(im.code)) handleEditGadget(NIL,GAD_NODES+subnum(im.code)) button:=i + menuSelect:=FALSE ENDIF IF(menunum(im.code)=2) num:=itemnum(im.code) diff --git a/Install Ami-Express b/Install Ami-Express index 8499ac7..673d97c 100644 --- a/Install Ami-Express +++ b/Install Ami-Express @@ -8,19 +8,26 @@ (set @app-name "Ami-Express") (if (exists "BBS:" (noreq)) (set @default-dest "bbs:") - (set @default-dest "Work:") + (set @default-dest "sys:bbs") ) ; + +(if (< (getversion) (* 37 65536)) + (abort (cat + "Ami-Express requires operating system " + "version 2.04 or higher to work." + )) +) + (welcome "Welcome to the Ami-Express installation utility.\nThis will install or upgrade your installation to AmiExpress " #appver) - (set #muiver (/ (getversion "libs:muimaster.library" ) 65536) ) + (set #muiver (/ (getversion "mui:mui" ) 65536) ) (set #owndevunitver (/ (getversion "libs:owndevunit.library" ) 65536) ) (set #fifolibver (/ (getversion "libs:fifo.library" ) 65536) ) (set #amissllibver (/ (getversion "libs:amisslmaster.library" ) 65536) ) - (set #asynclibver (/ (getversion "libs:async.library" ) 65536) ) (if ( <> #muiver 0) @@ -34,8 +41,8 @@ ) (if ( <> #fifolibver 0) - ( set #fifolibmsg "fifo handler: installed\n" ) - ( set #fifolibmsg "fifo handler: not installed\n" ) + ( set #fifolibmsg "fifo library: installed\n" ) + ( set #fifolibmsg "fifo library: not installed\n" ) ) (if ( <> #amissllibver 0) @@ -44,16 +51,16 @@ ) (if ( <> #asynclibver 0) - ( set #ibmcondevmsg "async.library: installed\n" ) - ( set #ibmcondevmsg "async.library: not installed\n" ) + ( set #asynclibmsg "async.library: installed\n" ) + ( set #asynclibmsg "async.library: not installed\n" ) ) ; -( if (exists "sys:wbstartup/acp" (noreq)) - ( set #acpname "sys:wbstartup/acp") +( if (exists "sys:wbstartup/ACP" (noreq)) + ( set #acpname "sys:wbstartup/ACP") ( - ( if (exists "bbs:wbstartup/acp" (noreq)) - ( set #acpname "bbs:wbstartup/acp") + ( if (exists "bbs:wbstartup/ACP" (noreq)) + ( set #acpname "bbs:wbstartup/ACP") ( set #acpname "") ) ) @@ -63,8 +70,6 @@ (exists "BBS:Express" (noreq)) ) -(set expexists 0) - ; (if (= expexists 0) ( @@ -76,7 +81,7 @@ ; (set #default-dest-installergen-temp (askdir - (prompt "Select where you want Ami-Express installed") + (prompt "Select where you want Ami-Express installed (create a folder if you need one)") (help "Select where you want Ami-Express installed.\nNo folder will be created so please ensure that you have created one if needed.") (default @default-dest) ) @@ -89,7 +94,7 @@ (set #acpchoice (askchoice (choices "WBStartup (for auto startup)" "BBS: (for manual startup)" "Select a different location") (prompt "Where would you like to install the ACP program?") - (help #cpu-help) + (help "") (default 0) )) ( if ( = #acpchoice 0) @@ -110,21 +115,20 @@ ) ) -(copylib +(copyfiles + (prompt "Copying Express") + (help @copyfiles-help) (source "AmiExpress/BBS/Express") (dest @default-dest) - (prompt "Copying Express") - (help @copylib-help) - (confirm "expert") + (confirm ) ) - ( complete 30) -(copylib - (source "AmiExpress/Wbstartup/ACP") +(copyfiles + (source "AmiExpress/ACP") (dest #acppath) (prompt "Copying ACP") - (help @copylib-help) + (help @copyfiles-help) (infos) (confirm "expert") @@ -141,8 +145,39 @@ (all) ) +( complete 45) + +(copyfiles + (prompt "Copying aedoor library") + (help @copyfiles-help) + (confirm "expert") + (source "AmiExpress/libs") + (dest "libs:") + (all) +) + ( complete 50) +(copyfiles + (prompt "Copying extras") + (help @copyfiles-help) + (confirm "expert") + (source "AmiExpress/c") + (dest "c:") + (all) +) + +(copyfiles + (prompt "Copying extras") + (help @copyfiles-help) + (confirm "expert") + (source "AmiExpress/l") + (dest "l:") + (all) +) + +( complete 55) + (copyfiles (prompt "Copying storage") (help @copyfiles-help) @@ -154,18 +189,24 @@ ( complete 60) ; -(run (cat "LHA x AmiExpress/defaultbbs.lha " @default-dest) +(copyfiles (prompt "Copying default bbs configuration") - (help ) + (help @copyfiles-help) (confirm "expert") + (source "AmiExpress/defaultbbs") + (dest @default-dest) + (all) ) - ( complete 70) -(run (cat "setenv axsetupeditor_prefs save 11" #acppath) +(run (cat "setenv axsetupeditor_prefs 11" (tackon #acppath "acp")) + (prompt "Saving configuration") + (help ) +) + +(run (cat "copy env:axsetupeditor_prefs envarc:") (prompt "Saving configuration") (help ) - (confirm "expert") ) ( complete 80) @@ -180,7 +221,6 @@ (prompt "Add startup items") (help @startup-help) (command #startup) - (confirm "expert") ) ; @@ -190,21 +230,19 @@ ; (set install-dest bbs:) -; -(set #expressver (getversion "bbs:express" ) ) - - -(set #acpver (getversion #acpname ) ) - -(set #expressverMajor (/ #expressver 65536) ) -(set #expressverMinor (bitand #expressver 65535) ) -(set #expressver ("%ld.%ld" #expressverMajor #expressverMinor) ) +(run (cat "version full >env:tmpver " #acpname)) +(set #acpver (getenv "tmpver") ) +(if (= (substr #acpver 0 4) "ACP ") + (set #acpver (substr #acpver 4 (- (strlen #acpver) 4))) +) -(set #acpMajor (/ #expressver 65536) ) -(set #acpMinor (bitand #expressver 65535) ) -(set #acpver ("%ld.%ld" #expressverMajor #expressverMinor) ) +(run (cat "version full >env:tmpver bbs:express")) +(set #expressver (getenv "tmpver") ) +(if (= (substr #expressver 0 13) "Ami-Express ") + (set #expressver (substr #expressver 13 (- (strlen #expressver) 13))) +) -(message ("An existing installation of Ami-Express was found.\n\nThe currently installed version information is \n\nACP: %s\nExpress: %s\n\nPress proceed if you wish to continue upgrading Ami-Express.\n\nThe configuration of your bbs will not be affected and only the updated\napplication files will be overwritten.\n" #expressver #acpver) +(message ("An existing installation of Ami-Express was found.\n\nThe currently installed version information is \n\nACP: %sExpress: %s\nPress proceed if you wish to continue upgrading Ami-Express.\n\nThe configuration of your bbs will not be affected and only the updated\napplication files will be overwritten.\n" #acpver #expressver) ) ( complete 10) @@ -213,11 +251,11 @@ ; ( complete 20) -(copylib +(copyfiles (source "AmiExpress/BBS/Express") (dest "bbs:") - (prompt "Copying Express") - (help @copylib-help) + (prompt "Upgrading Express") + (help @copyfiles-help) (confirm "expert") ) @@ -232,11 +270,11 @@ ( if (exists (tackon #axprefs "acp") (noreq)) ( - (copylib - (source "AmiExpress/wbstartup/acp") + (copyfiles + (source "AmiExpress/ACP") (dest #axprefs) - (prompt "Copying ACP") - (help @copylib-help) + (prompt "Upgrading ACP") + (help @copyfiles-help) (confirm "expert") ) (set #acpdone 1) @@ -244,15 +282,15 @@ ) ) ) - -( if (and (exists "sys:wbstartup/acp" (noreq)) - (<> #axprefs "sys:wbstartup") ) +(message #axprefs) +( if (and (exists "sys:wbstartup/ACP" (noreq)) + (<> #axprefs "sys:wbstartup/") ) ( - (copylib - (source "AmiExpress/wbstartup/acp") + (copyfiles + (source "AmiExpress/ACP") (dest "sys:wbstartup") - (prompt "Copying ACP") - (help @copylib-help) + (prompt "Upgrading ACP") + (help @copyfiles-help) (confirm "expert") ) (set #acpdone 1) @@ -262,11 +300,11 @@ ( if (and (exists "bbs:acp" (noreq)) (<> #axprefs "bbs:") ) ( - (copylib - (source "AmiExpress/wbstartup/acp") + (copyfiles + (source "AmiExpress/ACP") (dest "bbs:") - (prompt "Copying ACP") - (help @copylib-help) + (prompt "Upgrading ACP") + (help @copyfiles-help) (confirm "expert") ) (set #acpdone 1) @@ -283,11 +321,11 @@ ( if (exists (tackon #acppath "acp" ) (noreq)) ( - (copylib - (source "AmiExpress/wbstartup/acp") + (copyfiles + (source "AmiExpress/ACP") (dest #acppath) - (prompt "Copying ACP") - (help @copylib-help) + (prompt "Upgrading ACP") + (help @copyfiles-help) (confirm "expert") ) ( set #acpdone 1 ) @@ -299,7 +337,7 @@ ( complete 60) (copyfiles - (prompt "Copying utils") + (prompt "Upgrading utils") (help @copyfiles-help) (confirm "expert") (source "AmiExpress/BBS/Utils") @@ -312,6 +350,6 @@ ) ) ; End If -( message "The MUI system is required by the Ami-Express configuration tool\nand is recommended to be installed. In addition there are optional extras that\ncan be used by Ami-Express which should be installed manually if required.\n\n" #muimsg #owndevunitmsg #fifolibmsg #amissllibmsg #ibmcondevmsg #kalacondevmsg "\nThese extras are all freely available for download on the aminet.") +( message "The MUI system is required by the Ami-Express configuration tool and is recommended to be installed. In addition there are optional extras that can be used by Ami-Express which should be installed manually if required.\n\n" #muimsg #owndevunitmsg #fifolibmsg #amissllibmsg #asynclibmsg "\nThese extras are all freely available for download on the aminet.") (exit) \ No newline at end of file diff --git a/axcommon.e b/axcommon.e index f1396c9..da49048 100644 --- a/axcommon.e +++ b/axcommon.e @@ -174,6 +174,7 @@ EXPORT CONST SV_STARTNODE=185 EXPORT CONST SV_INFO=199 EXPORT CONST INCOMING_TELNET=200 EXPORT CONST INCOMING_FTP=201 +EXPORT CONST SV_ACPSHUTDOWN=202 EXPORT CONST GETKEY=500 diff --git a/express.e b/express.e index fec5b05..5b86f95 100644 --- a/express.e +++ b/express.e @@ -22476,12 +22476,10 @@ PROC makeFtpDirCache(confLoc:PTR TO CHAR, confnum, dirnum, dlpath:PTR TO CHAR, s t:=dateStampToDateTime(f_info.datestamp) s:=f_info.size IF (f_info.direntrytype>0) - IF s=0 - StringF(tempstr,'\s\s/',dlpath,f_info.filename) - StringF(tempstr2,'\s\s\s',subdir,IF StrLen(subdir)>0 THEN '_' ELSE '',f_info.filename) - makeFtpDirCache(confLoc,confnum,dirnum,tempstr,tempstr2) - s:=-1 - ENDIF + StringF(tempstr,'\s\s/',dlpath,f_info.filename) + StringF(tempstr2,'\s\s\s',subdir,IF StrLen(subdir)>0 THEN '_' ELSE '',f_info.filename) + makeFtpDirCache(confLoc,confnum,dirnum,tempstr,tempstr2) + s:=-1 ENDIF StringF(tempstr,'\z\h[8] \z\h[8] \s\n',t,s,f_info.filename) WriteF(tempstr) @@ -25501,7 +25499,7 @@ ENDPROC RESULT_SUCCESS PROC internalCommandVER() DEF tempStr[255]:STRING - StringF(tempStr,'\b\nAmiExpress \s (\s) Copyright ©2018-2022 Darren Coles\b\n\b\n',expressVer,expressDate) + StringF(tempStr,'\b\nAmiExpress \s (\s) Copyright ©2018-2023 Darren Coles\b\n\b\n',expressVer,expressDate) aePuts(tempStr) aePuts('Original Version:\b\n') aePuts(' (C)1989-91 Mike Thomas, Synthetic Technologies\b\n') @@ -28554,7 +28552,7 @@ PROC processFtpLogon() ENDIF telnetSend(sendStr,EstrLen(sendStr)) - StringF(sendStr,'230-\b\n230-Running AmiExpress \s Copyright ©2018-2022 Darren Coles\b\n',expressVer) + StringF(sendStr,'230-\b\n230-Running AmiExpress \s Copyright ©2018-2023 Darren Coles\b\n',expressVer) telnetSend(sendStr,EstrLen(sendStr)) StringF(sendStr,'230-Registration \s. You are connected to Node \d\b\n',regKey,node) telnetSend(sendStr,EstrLen(sendStr)) @@ -29284,7 +29282,7 @@ PROC processLogon() ENDIF aePuts(tempStr) - StringF(tempStr,'\b\n\b\nRunning AmiExpress \s Copyright ©2018-2022 Darren Coles\b\n',expressVer) + StringF(tempStr,'\b\n\b\nRunning AmiExpress \s Copyright ©2018-2023 Darren Coles\b\n',expressVer) aePuts(tempStr) StringF(tempStr,'Registration \s. You are connected to Node \d at \d baud',regKey,node,onlineBaud) aePuts(tempStr) @@ -29684,7 +29682,7 @@ PROC processAwait() send017() sendCLS() - StringF(tempstr,'\b\n ©2018-2022 AmiExpress by Darren Coles\b\n\b\n') + StringF(tempstr,'\b\n ©2018-2023 AmiExpress by Darren Coles\b\n\b\n') aePuts(tempstr) StringF(tempstr,'  Original Version:\b\n\b\n') diff --git a/stringlist.e b/stringlist.e index 1dcafb1..e2005f9 100644 --- a/stringlist.e +++ b/stringlist.e @@ -11,7 +11,7 @@ EXPORT OBJECT stringlist PRIVATE initialMax:LONG ENDOBJECT -EXPORT PROC end() OF stringlist -> destructor +EXPORT PROC end() OF stringlist -> destructor self.clear() DisposeLink(self.items) ENDPROC @@ -66,6 +66,12 @@ EXPORT PROC insert(pos,stringVal:PTR TO CHAR) OF stringlist self.items[pos]:=s ENDPROC +EXPORT PROC contains(stringVal:PTR TO CHAR) OF stringlist + DEF i + FOR i:=0 TO ListLen(self.items)-1 + IF StriCmp(self.items[i],stringVal) THEN RETURN TRUE + ENDFOR +ENDPROC FALSE EXPORT PROC add(stringVal:PTR TO CHAR) OF stringlist DEF s,c @@ -110,6 +116,37 @@ EXPORT PROC count() OF stringlist IS ListLen(self.items) EXPORT PROC maxSize() OF stringlist IS ListMax(self.items) +PROC partition(first, last) OF stringlist + DEF splitv, up, down, i + splitv:=self.items[first] + up:=first + down:=last + REPEAT + WHILE (StrCompare(self.items[up],splitv)<=0) AND (up0) AND (down>first) DO down-- + IF up=down + i:=self.items[first] + self.items[first]:=self.items[down] + self.items[down]:=i +ENDPROC down + +PROC quicksort(first, last) OF stringlist + DEF index + IF first destructor +EXPORT PROC end() OF stdlist -> destructor DisposeLink(self.items) ENDPROC diff --git a/tooltypes.e b/tooltypes.e index 1ca7aeb..7de6f6f 100644 --- a/tooltypes.e +++ b/tooltypes.e @@ -223,6 +223,7 @@ ENDPROC result EXPORT PROC getOrCreateCacheItem(fileName:PTR TO CHAR) DEF i,cnt,found=FALSE DEF cacheObj: PTR TO diskObjectCacheItem + DEF oldCacheObj: PTR TO diskObjectCacheItem DEF do=NIL:PTR TO diskobject DEF fn2[255]:STRING DEF ownToolTypes @@ -319,9 +320,9 @@ EXPORT PROC getOrCreateCacheItem(fileName:PTR TO CHAR) IF diskObjectCache.count()<(diskObjectCache.maxSize()-1) diskObjectCache.add(cacheObj) ELSE - cacheObj:=diskObjectCache.item(0) - DisposeLink(cacheObj.fileName) - FreeDiskObject(cacheObj.diskObject) + oldCacheObj:=diskObjectCache.item(0) + DisposeLink(oldCacheObj.fileName) + FreeDiskObject(oldCacheObj.diskObject) diskObjectCache.remove(0) diskObjectCache.add(cacheObj) ENDIF From 4e04f82d543055605ca1d1d8ad17ff20633009d9 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 1 Sep 2023 11:00:42 +0100 Subject: [PATCH 18/47] Express 1) for ftp filter out download paths that are sub-folders so that files are not duplicated in the root as well as in the folders --- ftpd.e | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/ftpd.e b/ftpd.e index 3dd6ccc..7ab5bce 100644 --- a/ftpd.e +++ b/ftpd.e @@ -1000,28 +1000,51 @@ PROC makeFtpListFromDlDirs(ftpData:PTR TO ftpData, startDate, cmdType, sb, data_ DEF path[255]:STRING DEF dirCache[255]:STRING DEF fib:PTR TO fileinfoblock - DEF dirNum,i + DEF dirNum,i,j,add + DEF dlDirList:PTR TO stringlist IF((fib:=AllocDosObject(DOS_FIB,NIL)))=NIL RETURN FALSE ENDIF + NEW dlDirList.stringlist(20) + dirNum:=1 StringF(path,'DLPATH.\d',dirNum++) WHILE(readToolType(TOOLTYPE_CONF,ftpData.confNums.item(ftpData.currentConf-1),path,path)) checkPathSlash(path) - IF StrLen(ftpData.subDirPath) - StrAdd(path,ftpData.subDirPath) - checkPathSlash(path) - ENDIF - - StringF(dirCache,'RAM:DirCaches/Conf\dDir\d\s\s',ftpData.currentConf,dirNum-1,IF StrLen(ftpData.subDirPath)>0 THEN '_' ELSE '', ftpData.subDirPath) - FOR i:=14 TO StrLen(dirCache)-1 DO IF dirCache[i]="/" THEN dirCache[i]:="_" - - makeList(path,dirCache,fib,startDate,cmdType,sb,data_c) + dlDirList.add(path) StringF(path,'DLPATH.\d',dirNum++) ENDWHILE + FOR i:=0 TO dlDirList.count()-1 + add:=TRUE + FOR j:=0 TO dlDirList.count()-1 + IF (i<>j) + IF EstrLen(dlDirList.item(i))>=EstrLen(dlDirList.item(j)) + IF StriCmp(dlDirList.item(i),dlDirList.item(j),EstrLen(dlDirList.item(j))) THEN add:=FALSE + ENDIF + ENDIF + ENDFOR + IF add=FALSE THEN dlDirList.setItem(i,'') + ENDFOR + + FOR j:=0 TO dlDirList.count()-1 + IF EstrLen(dlDirList.item(j))>0 + StrCopy(path,dlDirList.item(j)) + IF StrLen(ftpData.subDirPath) + StrAdd(path,ftpData.subDirPath) + checkPathSlash(path) + ENDIF + + StringF(dirCache,'RAM:DirCaches/Conf\dDir\d\s\s',ftpData.currentConf,j,IF StrLen(ftpData.subDirPath)>0 THEN '_' ELSE '', ftpData.subDirPath) + FOR i:=14 TO StrLen(dirCache)-1 DO IF dirCache[i]="/" THEN dirCache[i]:="_" + + makeList(path,dirCache,fib,startDate,cmdType,sb,data_c) + ENDIF + ENDFOR + END dlDirList + FreeDosObject(DOS_FIB,fib) ENDPROC From c1b2b7499a820a8dd096ae301a42647163b1d72f Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 7 Sep 2023 15:11:09 +0100 Subject: [PATCH 19/47] setup tool 1) make conf numbers always two digits on conf selector 2) fix path in makefile to stringlist.e --- axSetupTool/frmConfEdit.e | 4 ++-- axSetupTool/makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/axSetupTool/frmConfEdit.e b/axSetupTool/frmConfEdit.e index 05b4d36..366f454 100644 --- a/axSetupTool/frmConfEdit.e +++ b/axSetupTool/frmConfEdit.e @@ -390,7 +390,7 @@ PROC cloneNewConf() OF frmConfEdit self.confCount:=self.confCount+1 self.currConf:=self.confCount - StringF(tempStr,'\d',self.currConf) + StringF(tempStr,'\r\z\d[2]',self.currConf) set(self.strConfNumber, MUIA_String_Contents,tempStr) set( self.btnPrevConf, MUIA_Disabled , FALSE) @@ -956,7 +956,7 @@ PROC loadConf(conf) OF frmConfEdit StringF(tempStr,'LOCATION.\d',conf) readToolType(self.confConfig,tempStr,confPath) - StringF(tempStr,'\d',conf) + StringF(tempStr,'\r\z\d[2]',conf) set(self.strConfNumber, MUIA_String_Contents,tempStr) set(self.strConfName, MUIA_String_Contents,confName) self.strConfName2.setValue(confName) diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 00db67d..5fdcfef 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -14,7 +14,7 @@ axSetupTool: axSetupTool.e frmMain.m axedit.m helpText.m axedit.m: axedit.e $(compiler) axedit $(options) -stringlist.m: ../stringlist.e +stringlist.m: /stringlist.e $(compiler) /stringlist $(options) tooltypes.m: tooltypes.e stringlist.m From df0930943eeb927e8ce6101a3cb8135509123814 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 7 Sep 2023 15:17:05 +0100 Subject: [PATCH 20/47] 1) Fix line terminators in makefile 2) add iconify menu option in ACP 3) add system stats and session stats in ACP 4) add intuition menus on node screen in express 5) rework install script --- ACP.e | 153 ++++++++++++++++++-- Install Ami-Express | 76 ++++++---- axcommon.e | 10 +- express.e | 341 +++++++++++++++++++++++++++++++++++++++----- makefile | 218 ++++++++++++++-------------- 5 files changed, 611 insertions(+), 187 deletions(-) diff --git a/ACP.e b/ACP.e index 7ebc05d..2c6cf6d 100644 --- a/ACP.e +++ b/ACP.e @@ -61,9 +61,11 @@ CONST TAG_END=0 CONST NODECONFIG=1 CONST RUNMCP=2 +CONST LAST_CALLERS=0 CONST LAST_UPLOADS=1 CONST LAST_DOWNLOADS=2 -CONST LAST_CALLERS=0 +CONST SYSTEM_STATS=3 +CONST SESSION_STATS=4 CONST CHAT_ENTER=5 CONST CHAT_EXIT=4 @@ -314,6 +316,10 @@ DEF telnetNode[MAX_NODES]:ARRAY OF INT DEF ftpNode[MAX_NODES]:ARRAY OF INT DEF bbsStack +DEF startTime:datestamp +DEF startCalls +DEF ulCount=0,dlCount=0 + DEF nodes[MAX_NODES]:ARRAY OF INT DEF suspend[MAX_NODES]:ARRAY OF INT DEF showAbout=0 @@ -540,6 +546,25 @@ PROC getSystemTime() startds:=DateStamp(currDate) ENDPROC Mul(Mul(startds.days,1440),60)+(startds.minute*60)+(startds.tick/50) +PROC formatLongDateTime(dt:PTR TO datetime,outDateStr) + DEF datestr[10]:STRING + DEF daystr[10]:STRING + DEF timestr[10]:STRING + DEF dateVal + + + dt.format:=FORMAT_DOS + dt.flags:=0 + dt.strday:=0 + dt.strdate:=datestr + dt.strtime:=timestr + + IF DateToStr(dt) + StringF(outDateStr,'\s[7]\d\s \s',datestr,IF dt.stamp.days>=8035 THEN 20 ELSE 19,datestr+7,timestr) + RETURN TRUE + ENDIF +ENDPROC FALSE + PROC trimStr(src:PTR TO CHAR, dest:PTR TO CHAR) DEF i StrCopy(dest,TrimStr(src)) @@ -564,14 +589,11 @@ PROC myrequest(s:PTR TO CHAR) END myES[5] ENDPROC -PROC menunum(n) -ENDPROC ((n) AND $1F) +PROC menunum(n) IS ((n) AND $1F) -PROC itemnum(n) -ENDPROC (Shr((n),5) AND $3F) +PROC itemnum(n) IS (Shr((n),5) AND $3F) -PROC subnum(n) -ENDPROC (Shr((n),11) AND $1F) +PROC subnum(n) IS (Shr((n),11) AND $1F) ->/* ***** Free the Gadlist and return ***** */ PROC freeGads() @@ -914,6 +936,16 @@ PROC findClose() dir_info:=NIL ENDPROC +EXPORT PROC readIntFromFile(filename: PTR TO CHAR) + DEF fh + DEF v[100]:STRING + IF((fh:=Open(filename,MODE_OLDFILE)))<>0 + ReadStr(fh,v) + Close(fh) + RETURN Val(v) + ENDIF +ENDPROC -1 + /* ***** Do BevelBorders ***** */ PROC drawborders() /* *** Stats *** */ @@ -1034,6 +1066,7 @@ PROC createCustomMenus(nodes) maddItem( NM_SUB,' Stephan Schiemann ',0,0,0,0) maddItem( NM_SUB,' Eddie Oniel ',0,0,0,0) + maddItem( NM_ITEM, 'Iconify',0,0,0,0) maddItem( NM_ITEM, 'Quit',0,0,0,0) maddItem( NM_TITLE, 'Master Control',0,0,0,0) @@ -1184,7 +1217,7 @@ PROC initGads(scr:PTR TO screen) IF (gad = NIL) THEN RETURN 0 ->IF(initGadsagain=FALSE) THEN ngAry[GAD_TOPS].topedge:=ngAry[GAD_TOPS].topedge+(-110+(theight*11)) - gad:= CreateGadgetA(CYCLE_KIND, gad, ngAry [GAD_TOPS], [GTCY_LABELS,['Last Five Callers','Last Five Uploads','Last Five Downloads',NIL],GTCY_ACTIVE,topOption,TAG_END]) + gad:= CreateGadgetA(CYCLE_KIND, gad, ngAry [GAD_TOPS], [GTCY_LABELS,['Last Five Callers','Last Five Uploads','Last Five Downloads','System Stats','Session Stats',NIL],GTCY_ACTIVE,topOption,TAG_END]) IF (gad = NIL) THEN RETURN 0 ->IF(initGadsagain=FALSE) THEN ngAry[GAD_TOPSBOX].topedge:=ngAry[GAD_TOPSBOX].topedge+(-110+(theight*11)) @@ -1322,6 +1355,10 @@ PROC doControl(node) showNdLastUploads(eWin,node) CASE LAST_DOWNLOADS showNdLastDownloads(eWin,node) + CASE SYSTEM_STATS + showSystemStats(eWin) + CASE SESSION_STATS + showSessionStats(eWin) ENDSELECT ENDSELECT control:=0 @@ -1463,7 +1500,7 @@ PROC handleEditGadget(im:PTR TO intuimessage,ig) ENDIF CASE GAD_TOPS topOption++ - IF(topOption>2) THEN topOption:=0 + IF(topOption>SESSION_STATS) THEN topOption:=0 SELECT topOption CASE LAST_CALLERS showLastUser(eWin) @@ -1471,6 +1508,10 @@ PROC handleEditGadget(im:PTR TO intuimessage,ig) showLastDownloads(eWin) CASE LAST_UPLOADS showLastUploads(eWin) + CASE SYSTEM_STATS + showSystemStats(eWin) + CASE SESSION_STATS + showSessionStats(eWin) ENDSELECT CASE GAD_TOPSBOX IF(control) @@ -1482,6 +1523,10 @@ PROC handleEditGadget(im:PTR TO intuimessage,ig) showLastUploads(eWin) CASE LAST_DOWNLOADS showLastDownloads(eWin) + CASE SYSTEM_STATS + showSystemStats(eWin) + CASE SESSION_STATS + showSessionStats(eWin) ENDSELECT ELSE control:=SV_TOPS @@ -1666,6 +1711,10 @@ PROC updateNode(name:PTR TO CHAR,location:PTR TO CHAR,action:PTR TO CHAR,baud:PT showLastUploads(eWin) CASE LAST_DOWNLOADS showLastDownloads(eWin) + CASE SYSTEM_STATS + showSystemStats(eWin) + CASE SESSION_STATS + showSessionStats(eWin) ENDSELECT saveState() ENDIF @@ -1838,6 +1887,77 @@ PROC regNodeUser(name:PTR TO CHAR,dateStr:PTR TO CHAR, node) list.add(name,dateStr) ENDPROC +PROC showSystemStats(win:PTR TO window) + DEF i=0 + DEF rowTop + DEF tempStr[255]:STRING + DEF systemCalls + rowTop:=topOffset+(theight*11)+BTOP_TOPSBOX + SetAPen(win.rport,0) + RectFill(win.rport,BLEF_TOPSBOX+5,rowTop+1,BLEF_TOPSBOX+BWID_TOPSBOX-10,rowTop+BHEI_TOPSBOX-2) + SetAPen(win.rport,1) + + StringF(tempStr,'\sSystemStats',bbsPath) + systemCalls:=readIntFromFile(tempStr) + + StringF(tempStr,'System Calls: \d',systemCalls) + rowTop:=topOffset+155-110+(theight*11) + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + StringF(tempStr,'Number of users: \d',Div(FileLength('bbs:user.data'),$e8 )) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + formatLongDateTime(startTime,tempStr) + StringF(tempStr,'Startup: \s',tempStr) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + StringF(tempStr,'Available memory: \d',AvailMem(0)) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) +ENDPROC + +PROC showSessionStats(win:PTR TO window) + DEF i=0 + DEF rowTop + DEF tempStr[255]:STRING + DEF systemCalls,uptime + DEF systemTime:datestamp + rowTop:=topOffset+(theight*11)+BTOP_TOPSBOX + SetAPen(win.rport,0) + RectFill(win.rport,BLEF_TOPSBOX+5,rowTop+1,BLEF_TOPSBOX+BWID_TOPSBOX-10,rowTop+BHEI_TOPSBOX-2) + SetAPen(win.rport,1) + + DateStamp(systemTime) + uptime:=Mul(systemTime.days-startTime.days,1440)+systemTime.minute-startTime.minute + + formatLongDateTime(startTime,tempStr) + StringF(tempStr,'Startup: \s',tempStr) + rowTop:=topOffset+155-110+(theight*11) + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + StringF(tempStr,'Uptime: \d days \r\z\d[2]:\r\z\d[2]',Div(uptime,1440),Div(Mod(uptime,1440),60),Mod(uptime,60)) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + StringF(tempStr,'\sSystemStats',bbsPath) + systemCalls:=readIntFromFile(tempStr) + + StringF(tempStr,'System calls: \d',systemCalls-startCalls) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + + StringF(tempStr,'Uploads: \d',ulCount) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) + + StringF(tempStr,'Downloads: \d',dlCount) + rowTop+=10 + printMyText(win.rport,tempStr,GLEF_TOPS+5,rowTop) +ENDPROC + PROC showLastUser(win:PTR TO window) DEF i=0 DEF rowTop @@ -2066,8 +2186,10 @@ PROC checkMasterSig(signals) getSystemDate(datestr) regLastDownloads(tempstr2,datestr,msg.node) + dlCount++ saveState() IF topOption = LAST_DOWNLOADS THEN showLastDownloads(eWin) + IF topOption = SESSION_STATS THEN showSessionStats(eWin) StringF(temp,'DL: \s',msg.user) StringF(temp1,'\d',SV_NEWMSG) updateNode(temp,msg.location,temp1,msg.baud,msg.node) @@ -2081,8 +2203,10 @@ PROC checkMasterSig(signals) getSystemDate(datestr) regLastUploads(tempstr2,datestr,msg.node) + ulCount++ saveState() IF topOption = LAST_UPLOADS THEN showLastUploads(eWin) + IF topOption = SESSION_STATS THEN showSessionStats(eWin) StringF(temp,'UL: \s',msg.user) StringF(temp1,'\d',SV_NEWMSG) updateNode(temp,msg.location,temp1,msg.baud,msg.node) @@ -3804,6 +3928,8 @@ PROC main() HANDLE KickVersion(37) -> E-Note: requires V37 + DateStamp(startTime) + updateVersion(myVerStr,myBuildStr) FOR i:=0 TO MAX_NODES-1 @@ -3937,6 +4063,9 @@ PROC main() HANDLE readStartUp(iconStartName) IF acpError THEN Raise(ERR_STARTUP) + StringF(tempstr,'\sSystemStats',bbsPath) + startCalls:=readIntFromFile(tempstr) + loadConnectionList(connectionList) IF commodityEnabled @@ -4165,6 +4294,8 @@ PROC main() HANDLE showLastUploads(eWin) CASE LAST_DOWNLOADS showLastDownloads(eWin) + CASE SYSTEM_STATS + showSystemStats(eWin) ENDSELECT FOR i:=0 TO MAX_NODES-1 IF(StrLen(startNode[i])>0) @@ -4177,8 +4308,10 @@ PROC main() HANDLE CASE GADGETUP handleEditGadget(im,0) CASE MENUPICK + ->iconify + IF(menunum(im.code)=0) AND (itemnum(im.code)=5) THEN ZipWindow(eWin) ->quit menu item - IF(menunum(im.code)=0) AND (itemnum(im.code)=5) THEN attemptShutdown() + IF(menunum(im.code)=0) AND (itemnum(im.code)=6) THEN attemptShutdown() IF(menunum(im.code)=1) AND (itemnum(im.code)=14) IF FileLength(AX_SETUP_TOOL)>=0 THEN Execute(AX_SETUP_TOOL,0,0) diff --git a/Install Ami-Express b/Install Ami-Express index 673d97c..d121602 100644 --- a/Install Ami-Express +++ b/Install Ami-Express @@ -118,17 +118,19 @@ (copyfiles (prompt "Copying Express") (help @copyfiles-help) - (source "AmiExpress/BBS/Express") + (source "AmiExpress/AmiExpress") + (choices "Express") (dest @default-dest) - (confirm ) + (confirm "expert") ) ( complete 30) (copyfiles - (source "AmiExpress/ACP") + (source "AmiExpress/AmiExpress") (dest #acppath) (prompt "Copying ACP") (help @copyfiles-help) + (choices "ACP") (infos) (confirm "expert") @@ -140,7 +142,7 @@ (prompt "Copying utils") (help @copyfiles-help) (confirm "expert") - (source "AmiExpress/BBS/Utils") + (source "AmiExpress/AmiExpress/Utils") (dest (tackon @default-dest "Utils")) (all) ) @@ -148,45 +150,59 @@ ( complete 45) (copyfiles - (prompt "Copying aedoor library") + (prompt "Copying icons") (help @copyfiles-help) (confirm "expert") - (source "AmiExpress/libs") - (dest "libs:") + (source "AmiExpress/AmiExpress/Storage") + (dest (tackon @default-dest "Storage")) (all) ) + ( complete 50) +(copylib + (prompt "Copying aedoor library") + (help @copylib-help) + (confirm "average") + (source "AmiExpress/libs/aedoor.library") + (dest "libs:") +) + +( complete 55) + (copyfiles - (prompt "Copying extras") + (prompt "Copying archive tools") (help @copyfiles-help) - (confirm "expert") + (confirm "average") (source "AmiExpress/c") (dest "c:") - (all) + (choices "LHA" "LZX" "ZIP" "UNZIP") ) +( complete 60) + (copyfiles - (prompt "Copying extras") + (prompt "Copying LZX registration key") (help @copyfiles-help) - (confirm "expert") + (confirm "average") (source "AmiExpress/l") (dest "l:") - (all) + (choices "LZX.keyfile") ) -( complete 55) +( complete 65) (copyfiles - (prompt "Copying storage") + (prompt "Copying file id tools") (help @copyfiles-help) (confirm "expert") - (source "AmiExpress/BBS/Storage") - (dest (tackon @default-dest "Storage")) - (all) + (source "AmiExpress/fileid") + (dest "c:") + (choices "Textract" "DMSDescript" "EXEDescript" "GIFDesc") ) -( complete 60) + +( complete 70) ; (copyfiles @@ -197,7 +213,7 @@ (dest @default-dest) (all) ) -( complete 70) +( complete 90) (run (cat "setenv axsetupeditor_prefs 11" (tackon #acppath "acp")) (prompt "Saving configuration") @@ -209,7 +225,7 @@ (help ) ) -( complete 80) +( complete 95) (if (exists "BBS:" (noreq)) (set #startup "Assign doors: bbs:doors\nPath bbs:utils add\nResident SYS:Rexxc/RX pure") @@ -252,9 +268,10 @@ ( complete 20) (copyfiles - (source "AmiExpress/BBS/Express") + (source "AmiExpress/AmiExpress") (dest "bbs:") (prompt "Upgrading Express") + (choices "Express") (help @copyfiles-help) (confirm "expert") ) @@ -271,8 +288,9 @@ ( if (exists (tackon #axprefs "acp") (noreq)) ( (copyfiles - (source "AmiExpress/ACP") + (source "AmiExpress/AmiExpress") (dest #axprefs) + (choices "ACP") (prompt "Upgrading ACP") (help @copyfiles-help) (confirm "expert") @@ -282,15 +300,15 @@ ) ) ) -(message #axprefs) ( if (and (exists "sys:wbstartup/ACP" (noreq)) (<> #axprefs "sys:wbstartup/") ) ( (copyfiles - (source "AmiExpress/ACP") + (source "AmiExpress/AmiExpress") (dest "sys:wbstartup") (prompt "Upgrading ACP") (help @copyfiles-help) + (choices "ACP") (confirm "expert") ) (set #acpdone 1) @@ -301,10 +319,11 @@ (<> #axprefs "bbs:") ) ( (copyfiles - (source "AmiExpress/ACP") + (source "AmiExpress/AmiExpress") (dest "bbs:") (prompt "Upgrading ACP") (help @copyfiles-help) + (choices "ACP") (confirm "expert") ) (set #acpdone 1) @@ -322,10 +341,11 @@ ( if (exists (tackon #acppath "acp" ) (noreq)) ( (copyfiles - (source "AmiExpress/ACP") + (source "AmiExpress/AmiExpress") (dest #acppath) (prompt "Upgrading ACP") (help @copyfiles-help) + (choices "ACP") (confirm "expert") ) ( set #acpdone 1 ) @@ -340,7 +360,7 @@ (prompt "Upgrading utils") (help @copyfiles-help) (confirm "expert") - (source "AmiExpress/BBS/Utils") + (source "AmiExpress/AmiExpress/Utils") (dest "BBS:Utils") (pattern "~(rexxdoor)") ) diff --git a/axcommon.e b/axcommon.e index da49048..4e82fb4 100644 --- a/axcommon.e +++ b/axcommon.e @@ -175,8 +175,14 @@ EXPORT CONST SV_INFO=199 EXPORT CONST INCOMING_TELNET=200 EXPORT CONST INCOMING_FTP=201 EXPORT CONST SV_ACPSHUTDOWN=202 - - +EXPORT CONST SV_CONFMAINT=203 +EXPORT CONST SV_VIEWLOGS=204 +EXPORT CONST SV_TOGGLESTATUS=205 +EXPORT CONST SV_TIMEINCREASE=206 +EXPORT CONST SV_TIMEDECREASE=207 +EXPORT CONST SV_CAPTURE=208 +EXPORT CONST SV_DISPLAYFILE=209 +EXPORT CONST SV_GRANTTEMP=210 EXPORT CONST GETKEY=500 EXPORT CONST RAWARROW=501 EXPORT CONST CHAIN=502 diff --git a/express.e b/express.e index 5b86f95..3efc25c 100644 --- a/express.e +++ b/express.e @@ -51,6 +51,7 @@ DEF state=-1, stateData, reqState,instantLogon=FALSE DEF windowClose=NIL:PTR TO window DEF windowStat=NIL:PTR TO window DEF windowZmodem=NIL:PTR TO window +DEF expMenu:PTR TO menu DEF consoleReadMP=NIL: PTR TO mp DEF titlebar[255]:STRING DEF ititlebar[255]:STRING @@ -1393,9 +1394,9 @@ PROC checkDoorMsg(mode) CASE SV_INSTANT servercmd:=SV_INSTANT CASE SV_CHATTOGGLE - sysopAvail:=Not(sysopAvail) - updateTitle(NIL) - statChatFlag() + servercmd:=SV_CHATTOGGLE + CASE SV_TOGGLESTATUS + servercmd:=SV_TOGGLESTATUS CASE SV_ACCOUNTS servercmd:=SV_ACCOUNTS CASE SV_QUIETNODE @@ -1431,6 +1432,16 @@ PROC checkDoorMsg(mode) servercmd:=SV_AESHELL CASE SV_KICKUSER servercmd:=SV_KICKUSER + CASE SV_TIMEINCREASE + servercmd:=SV_TIMEINCREASE + CASE SV_TIMEDECREASE + servercmd:=SV_TIMEDECREASE + CASE SV_CAPTURE + servercmd:=SV_CAPTURE + CASE SV_DISPLAYFILE + servercmd:=SV_DISPLAYFILE + CASE SV_GRANTTEMP + servercmd:=SV_GRANTTEMP CASE SV_RESERVENODE StrCopy(reservedName,servermsg.string) IF(StrLen(reservedName)>0) @@ -1476,6 +1487,10 @@ PROC checkDoorMsg(mode) acceptIncomingConnection(servermsg.data,FALSE) CASE INCOMING_FTP acceptIncomingConnection(servermsg.data,TRUE) + CASE SV_CONFMAINT + servercmd:=SV_CONFMAINT + CASE SV_VIEWLOGS + servercmd:=SV_VIEWLOGS ENDSELECT IF servermsg<>NIL ReplyMsg(servermsg) @@ -6952,12 +6967,25 @@ PROC processCommodityMessage(signals) ENDIF ENDPROC +PROC processWinMessage2(win:PTR TO window) + DEF winmsg:PTR TO intuimessage + DEF msgclass + WHILE winmsg:=GetMsg(win.userport) + msgclass:=winmsg.class + ReplyMsg(winmsg) + SELECT msgclass + CASE IDCMP_CLOSEWINDOW + closeExpressScreen() + CASE IDCMP_MENUPICK + handleMenuPick(winmsg.code) + ENDSELECT + EXIT window=NIL + ENDWHILE +ENDPROC + PROC processWindowMessage(signals) -> If IDCMP messages received, handle them - DEF winmsg:PTR TO intuimessage DEF windowsig - DEF msgclass - DEF win:PTR TO window IF screen AND (scropen=FALSE) IF CloseScreen(screen) THEN screen:=NIL @@ -6965,25 +6993,17 @@ PROC processWindowMessage(signals) IF windowClose<>NIL windowsig:=Shl(1, windowClose.userport.sigbit) - win:=windowClose - ELSEIF window<>NIL + IF signals AND windowsig THEN processWinMessage2(windowClose) + ENDIF + + IF window<>NIL windowsig:=Shl(1, window.userport.sigbit) - win:=window - ELSE - windowsig:=0 + IF signals AND windowsig THEN processWinMessage2(window) ENDIF - IF signals AND windowsig - -> We have to ReplyMsg these when done with them - WHILE winmsg:=GetMsg(win.userport) - msgclass:=winmsg.class - ReplyMsg(winmsg) - SELECT msgclass - CASE IDCMP_CLOSEWINDOW - closeExpressScreen() - ENDSELECT - EXIT window=NIL - ENDWHILE + IF windowStat<>NIL + windowsig:=Shl(1, windowStat.userport.sigbit) + IF signals AND windowsig THEN processWinMessage2(windowStat) ENDIF ENDPROC @@ -7031,7 +7051,10 @@ PROC closeAEStats() statWriteMP:=NIL ENDIF - IF(windowStat<>NIL) THEN CloseWindow(windowStat) + IF(windowStat<>NIL) + ClearMenuStrip(windowStat) + CloseWindow(windowStat) + ENDIF windowStat:=NIL ENDPROC @@ -7099,6 +7122,8 @@ PROC toggleStatusDisplay() WA_HEIGHT,sz, WA_DETAILPEN,dp, WA_BLOCKPEN,bp, + WA_IDCMP,IDCMP_MENUPICK, + WA_NEWLOOKMENUS,1, WA_FLAGS,WFLG_SIMPLE_REFRESH, TAG_DONE] ELSE @@ -7109,9 +7134,12 @@ PROC toggleStatusDisplay() WA_HEIGHT,sz, WA_DETAILPEN,dp, WA_BLOCKPEN,bp, + WA_IDCMP,IDCMP_MENUPICK, + WA_NEWLOOKMENUS,1, WA_FLAGS,WFLG_SIMPLE_REFRESH, TAG_DONE] ENDIF + IF(( windowStat:=OpenWindowTagList(NIL,tags))<>NIL) dStatBar:=1 @@ -7121,6 +7149,8 @@ PROC toggleStatusDisplay() initStatCon() clearStatusPane() SetWindowTitles(window,titlebar,titlebar) + SetMenuStrip(windowStat,expMenu) + IF pub THEN SetWindowTitles(windowStat,titlebar,titlebar) IF (loggedOnUser<>NIL) IF (StrLen(loggedOnUser.name)>0) THEN statPrintUser(loggedOnUser,loggedOnUserKeys,loggedOnUserMisc) @@ -7130,6 +7160,7 @@ PROC toggleStatusDisplay() FastDisposeList(tags) IF pubLock THEN UnlockPubScreen(NIL,pubLock) ENDIF + updateMenus() ENDPROC PROC doFax() @@ -7372,10 +7403,15 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) IF windowClose<>NIL windowsig:=Shl(1, windowClose.userport.sigbit) - ELSEIF window<>NIL - windowsig:=Shl(1, window.userport.sigbit) + ENDIF + + IF window<>NIL + windowsig:=windowsig OR Shl(1, window.userport.sigbit) ENDIF + IF windowStat<>NIL + windowsig:=windowsig OR Shl(1, windowStat.userport.sigbit) + ENDIF IF resmp<>NIL THEN doorsig:=Shl(1, resmp.sigbit) IF rexxmp<>NIL THEN rexxsig:=Shl(1, rexxmp.sigbit) @@ -7555,6 +7591,8 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) servercmd:=-1 debugLog(LOG_DEBUG,'SYSOP LOGON') statClearTime() + disableNodeMenus(TRUE) + disableOnlineMenus(FALSE) StrCopy(connectString,'SYSOP_LOCAL') IF (scropen) THEN expressToFront() ELSE openExpressScreen() ioFlags[IOFLAG_SER_IN]:=0 @@ -7572,6 +7610,8 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) servercmd:=-1 debugLog(LOG_DEBUG,'LOCAL LOGON') statClearTime() + disableNodeMenus(TRUE) + disableOnlineMenus(FALSE) StrCopy(connectString,'F2_LOCAL') IF (scropen) THEN expressToFront() ELSE openExpressScreen() ioFlags[IOFLAG_SER_IN]:=0 @@ -7597,6 +7637,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) IF(StrLen(reservedName)>0) StrCopy(reservedName,'') ELSE + disableNodeMenus(TRUE) ioFlags[IOFLAG_SER_IN]:=0 ioFlags[IOFLAG_SER_OUT]:=0 ioFlags[IOFLAG_SCR_OUT]:=-1 @@ -7607,6 +7648,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) conCLS() reserveForUser() resetSystem() + disableNodeMenus(FALSE) ioFlags[IOFLAG_SER_IN]:=-1 ioFlags[IOFLAG_SCR_OUT]:=0 setEnvStat(ENV_RESERVE) @@ -7615,7 +7657,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->F5 - IF ((wasControl=1) AND (ch="4")) + IF (servercmd=SV_CONFMAINT) OR ((wasControl=1) AND (ch="4")) servercmd:=-1 ioFlags[IOFLAG_SER_IN]:=0 ioFlags[IOFLAG_SCR_OUT]:=-1 @@ -7625,6 +7667,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) onlineBaud:=cmds.openingBaud onlineBaudR:=cmds.openingBaud timeLimit:=3600 + disableNodeMenus(TRUE) logonType:=LOGON_TYPE_LOCAL logonTime:=getSystemTime() lastTimeUpdate:=logonTime @@ -7644,6 +7687,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ioFlags[IOFLAG_SER_IN]:=-1 ioFlags[IOFLAG_SCR_OUT]:=0 IF(ioFlags[IOFLAG_FIL_IN]) THEN ioFlags[IOFLAG_FIL_IN]:=0 + disableNodeMenus(FALSE) IF reqState=REQ_STATE_NONE THEN statePtr.redrawScreen:=TRUE ENDIF @@ -7653,11 +7697,13 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ioFlags[IOFLAG_SER_IN]:=0 ioFlags[IOFLAG_SCR_OUT]:=-1 intDoReset(sopt.offHook) + disableNodeMenus(TRUE) IF (scropen) THEN expressToFront() ELSE openExpressScreen() setEnvStat(ENV_SHELL) sendCLS() remoteShell() resetSystem() + disableNodeMenus(FALSE) ioFlags[IOFLAG_SER_IN]:=-1 ioFlags[IOFLAG_SCR_OUT]:=0 IF(ioFlags[IOFLAG_FIL_IN]) THEN ioFlags[IOFLAG_FIL_IN]:=0 @@ -7670,6 +7716,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ioFlags[IOFLAG_SER_IN]:=0 ioFlags[IOFLAG_SCR_OUT]:=-1 intDoReset(sopt.offHook) + disableNodeMenus(TRUE) IF (scropen) THEN expressToFront() ELSE openExpressScreen() conCursorOn() sendCLS() @@ -7694,6 +7741,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) loggedOnUserMisc:=NIL loggedOnUserKeys:=NIL resetSystem() + disableNodeMenus(FALSE) ioFlags[IOFLAG_SER_IN]:=-1 ioFlags[IOFLAG_SCR_OUT]:=0 IF(ioFlags[IOFLAG_FIL_IN]) THEN ioFlags[IOFLAG_FIL_IN]:=0 @@ -7701,11 +7749,12 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->Shift F6 - IF ((wasControl=2) AND (ch="5")) + IF (servercmd=SV_VIEWLOGS) OR ((wasControl=2) AND (ch="5")) servercmd:=-1 ioFlags[IOFLAG_SER_IN]:=0 ioFlags[IOFLAG_SCR_OUT]:=-1 intDoReset(sopt.offHook) + disableNodeMenus(TRUE) IF (scropen) THEN expressToFront() ELSE openExpressScreen() sendCLS() StringF(temp,'\sNode\d/Callerslog',cmds.bbsLoc,node) @@ -7726,6 +7775,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) loggedOnUserMisc:=NIL loggedOnUserKeys:=NIL resetSystem() + disableNodeMenus(FALSE) ioFlags[IOFLAG_SER_IN]:=-1 ioFlags[IOFLAG_SCR_OUT]:=0 IF(ioFlags[IOFLAG_FIL_IN]) THEN ioFlags[IOFLAG_FIL_IN]:=0 @@ -7733,9 +7783,10 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->F7 - IF ((wasControl=1) AND (ch="6")) + IF (servercmd=SV_CHATTOGGLE) OR ((wasControl=1) AND (ch="6")) servercmd:=-1 sysopAvail:=Not(sysopAvail) + updateMenus() updateTitle(NIL) statChatFlag() ENDIF @@ -7765,7 +7816,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) clearDiskObjectCache() ENDIF - IF ((wasControl=1) AND (ch="?")) + IF (servercmd=SV_TOGGLESTATUS) OR ((wasControl=1) AND (ch="?")) toggleStatusDisplay() ENDIF ENDIF @@ -7796,27 +7847,27 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->F2 - increase time limit - IF ((wasControl=1) AND (ch="1") AND (loggedOnUser<>NIL)) + IF (servercmd=SV_TIMEINCREASE) OR ((wasControl=1) AND (ch="1") AND (loggedOnUser<>NIL)) servercmd:=-1 timeLimit:=timeLimit+600 loggedOnUser.timeTotal:=loggedOnUser.timeTotal+600 ENDIF ->F3 - decrease time limit - IF ((wasControl=1) AND (ch="2") AND (loggedOnUser<>NIL)) + IF (servercmd=SV_TIMEDECREASE) OR ((wasControl=1) AND (ch="2") AND (loggedOnUser<>NIL)) servercmd:=-1 timeLimit:=timeLimit-600 loggedOnUser.timeTotal:=loggedOnUser.timeTotal-600 ENDIF ->F4 - capture - IF ((wasControl=1) AND (ch="3")) + IF (servercmd=SV_CAPTURE) OR ((wasControl=1) AND (ch="3")) servercmd:=-1 startCapture() ENDIF ->Shift F4 - display file to user - IF ((wasControl=2) AND (ch="3")) + IF (servercmd=SV_DISPLAYFILE) OR ((wasControl=2) AND (ch="3")) servercmd:=-1 startASend() RETURN TRUE,RESULT_SUCCESS @@ -7831,7 +7882,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->Shift F6 - grant/remove temporary access - IF ((wasControl=2) AND (ch="5") AND (loggedOnUser<>NIL)) + IF (servercmd=SV_GRANTTEMP) OR ((wasControl=2) AND (ch="5") AND (loggedOnUser<>NIL)) servercmd:=-1 IF(tempAccessGranted) loggedOnUser.secStatus:=tempAccess.accessLevel; @@ -7855,9 +7906,10 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->F7 - IF ((wasControl=1) AND (ch="6")) + IF (servercmd=SV_CHATTOGGLE) OR ((wasControl=1) AND (ch="6")) servercmd:=-1 sysopAvail:=Not(sysopAvail) + updateMenus() updateTitle(NIL) statChatFlag() ENDIF @@ -7893,7 +7945,7 @@ PROC processInputMessage(timeout, extsig = 0,rawMode=FALSE, allowSer=TRUE) ENDIF ->HELP - IF ((wasControl=1) AND (ch="?")) + IF (servercmd=SV_TOGGLESTATUS) OR ((wasControl=1) AND (ch="?")) servercmd:=-1 toggleStatusDisplay() ENDIF @@ -8194,6 +8246,8 @@ PROC processLoggingOff() Delay(50) stateData:=0 writeLogoffLog('logging off 22',FALSE) + disableNodeMenus(FALSE) + disableOnlineMenus(TRUE) StrCopy(telnetUsername,'') StrCopy(telnetPassword,'') @@ -29739,7 +29793,9 @@ PROC processAwait() ENDIF IF (checkSer()) OR (sopt.trapDoor) OR (instantLogon) OR (checkTelnetConnection()) AND (reqState=REQ_STATE_NONE) - + disableNodeMenus(TRUE) + disableOnlineMenus(FALSE) + IF checkIncomingCall()=RESULT_CONNECT debugLog(LOG_DEBUG,'REMOTE LOGON') ioFlags[IOFLAG_SCR_OUT]:=-1 @@ -30646,6 +30702,138 @@ PROC openZmodemStat() ENDPROC +PROC disableNodeMenus(flag) + DEF item:PTR TO menuitem + IF windowStat THEN ClearMenuStrip(windowStat) + IF window THEN ClearMenuStrip(window) + item:=expMenu.firstitem + WHILE item + IF (item.flags AND CHECKIT)=0 + IF flag THEN item.flags:=item.flags AND $FFEF ELSE item.flags:=item.flags OR $10 + ENDIF + item:=item.nextitem + ENDWHILE + + IF windowStat THEN ResetMenuStrip(windowStat,expMenu) + IF window THEN ResetMenuStrip(window,expMenu) + +ENDPROC + +PROC disableOnlineMenus(flag) + DEF item:PTR TO menuitem + IF windowStat THEN ClearMenuStrip(windowStat) + IF window THEN ClearMenuStrip(window) + + item:=expMenu.nextmenu.firstitem + WHILE item + IF flag THEN item.flags:=item.flags AND $FFEF ELSE item.flags:=item.flags OR $10 + item:=item.nextitem + ENDWHILE + + IF windowStat THEN ResetMenuStrip(windowStat,expMenu) + IF window THEN ResetMenuStrip(window,expMenu) +ENDPROC + +PROC updateMenus() + DEF item:PTR TO menuitem + IF windowStat THEN ClearMenuStrip(windowStat) + IF window THEN ClearMenuStrip(window) + item:=expMenu.firstitem + WHILE item + IF GTMENUITEM_USERDATA(item)=-1 + IF sysopAvail THEN item.flags:=item.flags OR $100 ELSE item.flags:=item.flags AND $FEFF + ENDIF + IF GTMENUITEM_USERDATA(item)=-2 + IF dStatBar THEN item.flags:=item.flags OR $100 ELSE item.flags:=item.flags AND $FEFF + ENDIF + item:=item.nextitem + ENDWHILE + + IF windowStat THEN ResetMenuStrip(windowStat,expMenu) + IF window THEN ResetMenuStrip(window,expMenu) + +ENDPROC + +PROC createMenus() + DEF eWinMenu:PTR TO newmenu + DEF n=0 + + eWinMenu:=NEW eWinMenu[28] + eWinMenu[n].type:=NM_TITLE + eWinMenu[n++].label:='Node' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Sysop logon F1' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Local logon F2' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Instant logon F3' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Reserve node F4' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Conference maintenance F5' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Shell Sh-F5' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Account editor F6' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='View callerslog Sh-F6' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n].flags:=CHECKIT + eWinMenu[n].mutualexclude:=0 + eWinMenu[n].userdata:=-1 + eWinMenu[n++].label:='Sysop available F7' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n].flags:=CHECKIT + eWinMenu[n].mutualexclude:=0 + eWinMenu[n].userdata:=-2 + eWinMenu[n++].label:='Toggle status Help' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Init modem F8' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Exit node F9' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Exit node (offhook) F10' + eWinMenu[n].type:=NM_TITLE + eWinMenu[n++].label:='Online' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Chat F1' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Time limit' + eWinMenu[n].type:=NM_SUB + eWinMenu[n++].label:='Increase F2' + eWinMenu[n].type:=NM_SUB + eWinMenu[n++].label:='Decrease F3' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Capture F4' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Show file F5' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Account edit F6' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Grant temporary access F7' + eWinMenu[n].type:=NM_ITEM + eWinMenu[n++].label:='Disconnect F10' + eWinMenu[n].type:=NM_END + + IF (gadtoolsbase:=OpenLibrary('gadtools.library',0))<>NIL + expMenu:=CreateMenusA(eWinMenu,[TAG_END]) + disableNodeMenus(FALSE) + disableOnlineMenus(TRUE) + CloseLibrary(gadtoolsbase) + ENDIF + END eWinMenu[28] + +ENDPROC + +PROC freeMenus() + IF expMenu + IF (gadtoolsbase:=OpenLibrary('gadtools.library',0))<>NIL + FreeMenus(expMenu) + CloseLibrary(gadtoolsbase) + ENDIF + ENDIF +ENDPROC + PROC openExpressScreen() DEF width,height,top,left,dispId DEF pubScreen[255]:STRING @@ -30654,6 +30842,7 @@ PROC openExpressScreen() DEF pub=FALSE DEF pubLock=NIL DEF opentags:PTR TO LONG,temp + DEF vi DEF pens: PTR TO INT, cols:PTR TO INT DEF pensize,colsize DEF statePtr:PTR TO awaitState @@ -30794,6 +30983,8 @@ PROC openExpressScreen() IF screen=NIL THEN RETURN ERR_SCREEN + vi:=GetVisualInfoA(screen, [NIL]) + IF windowClose=NIL opentags:=NEW [WA_CLOSEGADGET,1,WA_CUSTOMSCREEN,screen, WA_TOP,0, @@ -30828,7 +31019,8 @@ PROC openExpressScreen() WA_MAXHEIGHT,-1, ->WA_DETAILPEN,0, ->WA_BLOCKPEN,blockpen, - WA_IDCMP,IDCMP_CLOSEWINDOW, + WA_NEWLOOKMENUS,1, + WA_IDCMP,IDCMP_CLOSEWINDOW OR IDCMP_MENUPICK, WA_FLAGS,WFLG_ACTIVATE, TAG_DONE] window:=OpenWindowTagList(NIL,opentags) @@ -30842,6 +31034,8 @@ PROC openExpressScreen() WA_HEIGHT,height-(screen.wbortop+screen.font.ysize+1), ->WA_DETAILPEN,0, ->WA_BLOCKPEN,blockpen, + WA_NEWLOOKMENUS,1, + WA_IDCMP,IDCMP_MENUPICK, WA_FLAGS,WFLG_ACTIVATE, TAG_DONE] window:=OpenWindowTagList(NIL,opentags) @@ -30849,9 +31043,15 @@ PROC openExpressScreen() ENDIF ENDIF + IF pubLock THEN UnlockPubScreen(NIL,pubLock) IF window=NIL THEN RETURN ERR_WINDOW + updateMenus() + LayoutMenusA(expMenu,vi,[GTMN_NEWLOOKMENUS,1,TAG_DONE]) + FreeVisualInfo(vi) + SetMenuStrip(window,expMenu) + IF state=STATE_AWAIT statePtr:=stateData statePtr.redrawScreen:=TRUE @@ -30907,6 +31107,66 @@ PROC openExpressScreen() IF((sopt.statBar<>FALSE) AND (pub=FALSE)) THEN toggleStatusDisplay() ENDPROC ERR_NONE +PROC handleMenuPick(menucode) + DEF menu,item,subitem + menu:=menucode AND $1F + item:=(Shr((menucode),5) AND $3F) + subitem:=(Shr((menucode),11) AND $1F) + + SELECT menu + CASE 0 + SELECT item + CASE 0 + servercmd:=SV_SYSOPLOG + CASE 1 + servercmd:=SV_LOCALLOG + CASE 2 + servercmd:=SV_INSTANT + CASE 3 + servercmd:=SV_RESERVE + CASE 4 + servercmd:=SV_CONFMAINT + CASE 5 + servercmd:=SV_AESHELL + CASE 6 + servercmd:=SV_ACCOUNTS + CASE 7 + servercmd:=SV_VIEWLOGS + CASE 8 + servercmd:=SV_CHATTOGGLE + CASE 9 + servercmd:=SV_TOGGLESTATUS + CASE 10 + servercmd:=SV_INITMODEM + CASE 11 + servercmd:=SV_EXITNODE + CASE 12 + servercmd:=SV_NODEOFFHOOK + ENDSELECT + CASE 1 + SELECT item + CASE 0 + servercmd:=SV_CHAT + CASE 1 + IF subitem=0 + servercmd:=SV_TIMEINCREASE + ELSE + servercmd:=SV_TIMEDECREASE + ENDIF + CASE 2 + servercmd:=SV_CAPTURE + CASE 3 + servercmd:=SV_DISPLAYFILE + CASE 4 + servercmd:=SV_ACCOUNTS + CASE 5 + servercmd:=SV_GRANTTEMP + CASE 6 + servercmd:=SV_KICKUSER + ENDSELECT + ENDSELECT +ENDPROC + PROC closeExpressScreen() closeAEStats() @@ -30947,6 +31207,7 @@ PROC closeExpressScreen() ENDIF IF window + ClearMenuStrip(window) CloseWindow(window) window:=NIL ENDIF @@ -31563,6 +31824,7 @@ PROC main() HANDLE SetTaskPri(FindTask(0),cmds.taskPri) ENDIF + createMenus() IF (sopt.iconify=FALSE) THEN openExpressScreen() formatLongDateTime(getSystemTime(),tempstr) @@ -31687,6 +31949,8 @@ PROC main() HANDLE socketbase:=NIL closeExpressScreen() + freeMenus() + IF iconbase THEN CloseLibrary(iconbase) IF diskfontbase THEN CloseLibrary(diskfontbase) @@ -31745,6 +32009,7 @@ PROC main() HANDLE CASE "NIL" StringF(tempstr,'NIL pointer error at line \d',exceptioninfo) debugLog(LOG_ERROR,tempstr) + WriteF('Error: NIL pointer exception') DEFAULT IF exception<>0 StringF(tempstr,'Unknown exception \d',exception) diff --git a/makefile b/makefile index 824ff6e..a648e55 100644 --- a/makefile +++ b/makefile @@ -1,110 +1,110 @@ -# Compile ACP and EXPRESS and any dependencies - -options=DEBUG IGNORECACHE NILCHECK OPTI SYM SHOWFNAME -compiler=EVO -expprogramname=AmiExpress -acpprogramname=ACP -version=5.6.0-dev - -all: acp express5 jsonimport icon2cfg qwk ftn - -release: options = IGNORECACHE OPTI SHOWFNAME -release: acp express5 jsonimport icon2cfg qwk ftn - -acp: acp.e acpversion.m axcommon.m jsonparser.m jsoncreate.m stringlist.m - $(compiler) acp $(options) - -express5: express.e expversion.m axcommon.m axconsts.m miscfuncs.m axobjects.m axenums.m stringlist.m errors.m mailssl.m ftpd.m httpd.m xymodem.m zmodem.m hydra.m tooltypes.m pwdhash.m bcd.m sha256.m - $(compiler) express $(options) - copy express express5 - delete express - -verinfogen: verinfogen.e - $(compiler) verinfogen $(options) - -ftn: ftn.e stringlist.m - $(compiler) ftn $(options) - -qwk: qwk.e stringlist.m - $(compiler) qwk $(options) - -icon2cfg: icon2cfg.e miscfuncs.m - $(compiler) icon2cfg $(options) - -jsonimport: jsonimport.e jsonparser.m jsoncreate.m - $(compiler) jsonimport $(options) - -jsonparser.m: jsonparser.e miscfuncs.m - $(compiler) jsonparser $(options) - -jsoncreate.m: jsoncreate.e miscfuncs.m jsonparser.m - $(compiler) jsoncreate $(options) - -zmodem.m: zmodem.e bcd.m - $(compiler) zmodem $(options) - -xymodem.m: xymodem.e bcd.m - $(compiler) xymodem $(options) - -hydra.m: hydra.e - $(compiler) hydra $(options) - -stringlist.m: stringlist.e - $(compiler) stringlist $(options) - -miscfuncs.m: miscfuncs.e axconsts.m axenums.m axobjects.m errors.m - $(compiler) miscfuncs $(options) - -errors.m: errors.e - $(compiler) errors $(options) - -mailssl.m: mailssl.e - $(compiler) mailssl $(options) - -tooltypes.m: tooltypes.e - $(compiler) tooltypes $(options) - -pwdhash.m: pwdhash.e - $(compiler) pwdhash $(options) - -axcommon.m: axcommon.e stringlist.m - $(compiler) axcommon $(options) - -axconsts.m: axconsts.e - $(compiler) axconsts $(options) - -axobjects.m: axobjects.e axconsts.m - $(compiler) axobjects $(options) - -axenums.m: axenums.e - $(compiler) axenums $(options) - -expversion.m: expversion.e - $(compiler) expversion $(options) - -expversion.e: verinfogen - verinfogen expversion.e $(expprogramname) $(version) usedate - -acpversion.m: acpversion.e - $(compiler) acpversion $(options) - -acpversion.e: verinfogen - verinfogen acpversion.e $(acpprogramname) $(version) usedate - -bcd.m: bcd.e axobjects.m - $(compiler) bcd $(options) - -sha256.m: sha256.e - $(compiler) sha256 $(options) - -ftpd.m: ftpd.e tooltypes.m stringlist.m axobjects.m axenums.m miscfuncs.m bcd.m - $(compiler) ftpd $(options) - -httpd.m: httpd.e axcommon.m stringlist.m - $(compiler) httpd $(options) - -clean: - delete expversion.e acpversion.e delete express verinfogen express5 acp qwk ftn jsonimport icon2cfg miscfuncs.m stringlist.m errors.m mailssl.m jsoncreate.m jsonparser.m axcommon.m ftpd.m httpd.m axconsts.m axobjects.m axenums.m zmodem.m xymodem.m hydra.m bcd.m expversion.m acpversion.m pwdhash.m tooltypes.m sha256.m - -.PHONY: expversion.e +# Compile ACP and EXPRESS and any dependencies + +options=DEBUG IGNORECACHE NILCHECK OPTI SYM SHOWFNAME +compiler=EVO +expprogramname=AmiExpress +acpprogramname=ACP +version=5.6.0-dev + +all: acp express5 jsonimport icon2cfg qwk ftn + +release: options = IGNORECACHE OPTI SHOWFNAME +release: acp express5 jsonimport icon2cfg qwk ftn + +acp: acp.e acpversion.m axcommon.m jsonparser.m jsoncreate.m stringlist.m + $(compiler) acp $(options) + +express5: express.e expversion.m axcommon.m axconsts.m miscfuncs.m axobjects.m axenums.m stringlist.m errors.m mailssl.m ftpd.m httpd.m xymodem.m zmodem.m hydra.m tooltypes.m pwdhash.m bcd.m sha256.m + $(compiler) express $(options) + copy express express5 + delete express + +verinfogen: verinfogen.e + $(compiler) verinfogen $(options) + +ftn: ftn.e stringlist.m + $(compiler) ftn $(options) + +qwk: qwk.e stringlist.m + $(compiler) qwk $(options) + +icon2cfg: icon2cfg.e miscfuncs.m + $(compiler) icon2cfg $(options) + +jsonimport: jsonimport.e jsonparser.m jsoncreate.m + $(compiler) jsonimport $(options) + +jsonparser.m: jsonparser.e miscfuncs.m + $(compiler) jsonparser $(options) + +jsoncreate.m: jsoncreate.e miscfuncs.m jsonparser.m + $(compiler) jsoncreate $(options) + +zmodem.m: zmodem.e bcd.m + $(compiler) zmodem $(options) + +xymodem.m: xymodem.e bcd.m + $(compiler) xymodem $(options) + +hydra.m: hydra.e + $(compiler) hydra $(options) + +stringlist.m: stringlist.e + $(compiler) stringlist $(options) + +miscfuncs.m: miscfuncs.e axconsts.m axenums.m axobjects.m errors.m + $(compiler) miscfuncs $(options) + +errors.m: errors.e + $(compiler) errors $(options) + +mailssl.m: mailssl.e + $(compiler) mailssl $(options) + +tooltypes.m: tooltypes.e + $(compiler) tooltypes $(options) + +pwdhash.m: pwdhash.e + $(compiler) pwdhash $(options) + +axcommon.m: axcommon.e stringlist.m + $(compiler) axcommon $(options) + +axconsts.m: axconsts.e + $(compiler) axconsts $(options) + +axobjects.m: axobjects.e axconsts.m + $(compiler) axobjects $(options) + +axenums.m: axenums.e + $(compiler) axenums $(options) + +expversion.m: expversion.e + $(compiler) expversion $(options) + +expversion.e: verinfogen + verinfogen expversion.e $(expprogramname) $(version) usedate + +acpversion.m: acpversion.e + $(compiler) acpversion $(options) + +acpversion.e: verinfogen + verinfogen acpversion.e $(acpprogramname) $(version) usedate + +bcd.m: bcd.e axobjects.m + $(compiler) bcd $(options) + +sha256.m: sha256.e + $(compiler) sha256 $(options) + +ftpd.m: ftpd.e tooltypes.m stringlist.m axobjects.m axenums.m miscfuncs.m bcd.m + $(compiler) ftpd $(options) + +httpd.m: httpd.e axcommon.m stringlist.m + $(compiler) httpd $(options) + +clean: + delete expversion.e acpversion.e delete express verinfogen express5 acp qwk ftn jsonimport icon2cfg miscfuncs.m stringlist.m errors.m mailssl.m jsoncreate.m jsonparser.m axcommon.m ftpd.m httpd.m axconsts.m axobjects.m axenums.m zmodem.m xymodem.m hydra.m bcd.m expversion.m acpversion.m pwdhash.m tooltypes.m sha256.m + +.PHONY: expversion.e \ No newline at end of file From 9fd85ec1e5d2a7dd7ab8e25a3b23ea77a786caaa Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 8 Sep 2023 14:41:08 +0100 Subject: [PATCH 21/47] setup tool 1) fix add buffers in makefile. each buffer is 100k so it should be 3 not 300 --- axSetupTool/makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 5fdcfef..82bea8a 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -1,11 +1,11 @@ # Compile axed -options=DEBUG IGNORECACHE SYM SHOWFNAME ADDBUF 300 +options=DEBUG IGNORECACHE SYM SHOWFNAME ADDBUF 3 compiler=EVO all: axSetupTool -release: options = IGNORECACHE OPTI SHOWFNAME ADDBUF 300 +release: options = IGNORECACHE OPTI SHOWFNAME ADDBUF 3 release: axSetupTool axSetupTool: axSetupTool.e frmMain.m axedit.m helpText.m @@ -15,7 +15,7 @@ axedit.m: axedit.e $(compiler) axedit $(options) stringlist.m: /stringlist.e - $(compiler) /stringlist $(options) + $(compiler)/stringlist $(options) tooltypes.m: tooltypes.e stringlist.m $(compiler) tooltypes $(options) From d2925829290005ffb35e5bdf93b8f3cbd9d74273 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 8 Sep 2023 16:59:43 +0100 Subject: [PATCH 22/47] makefile again --- axSetupTool/makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 82bea8a..63f80dd 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -14,8 +14,8 @@ axSetupTool: axSetupTool.e frmMain.m axedit.m helpText.m axedit.m: axedit.e $(compiler) axedit $(options) -stringlist.m: /stringlist.e - $(compiler)/stringlist $(options) +stringlist.m: ../stringlist.e + $(compiler) /stringlist $(options) tooltypes.m: tooltypes.e stringlist.m $(compiler) tooltypes $(options) From 377e7f1ce811b15374dcbe44adba7acf9fabef31 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Fri, 8 Sep 2023 17:17:54 +0100 Subject: [PATCH 23/47] Setup Editor - fix button typo --- axSetupTool/axedit.e | 2 +- axSetupTool/axsys.MUIB | Bin 22294 -> 22293 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/axSetupTool/axedit.e b/axSetupTool/axedit.e index f1dd6d4..c718bbe 100644 --- a/axSetupTool/axedit.e +++ b/axSetupTool/axedit.e @@ -702,7 +702,7 @@ PROC create( display : PTR TO app_display ) OF app_obj self.btnMsgbaseAdd := SimpleButton( 'Add' ) - self.btnMsgbaseEdit := SimpleButton( 'Ediit' ) + self.btnMsgbaseEdit := SimpleButton( 'Edit' ) self.btnMsgbaseDelete := SimpleButton( 'Remove' ) diff --git a/axSetupTool/axsys.MUIB b/axSetupTool/axsys.MUIB index 5ba044f498db12a375ce6a2ad29c6bd8b0fd928f..4389395217f4ed6b05a547ec76789a0cf0d13c69 100644 GIT binary patch delta 39 xcmV+?0NDSQt^t*<0gzGxHaW3WF#-WGlK}%Dv!(*S7L(mR3X=*65VL?8mOTSS47&gT delta 35 rcmbQbj&a&L#tA`8CZ-!h44Eb|D{fxKv|o%Vvt%+Or{v~($!WF#+GGo; From 41fde0e36c1064ee6ccea51f3c6fae2f323738c5 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 10:38:51 +0100 Subject: [PATCH 24/47] prepare makefile for automated builds --- axSetupTool/makefile | 11 +++++++++-- makefile | 17 ++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 63f80dd..4a787c8 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -1,11 +1,18 @@ # Compile axed -options=DEBUG IGNORECACHE SYM SHOWFNAME ADDBUF 3 +debugoptions=DEBUG IGNORECACHE LARGE NILCHECK OPTI SYM SHOWFNAME ADDBUF 5 +releaseoptions=IGNORECACHE OPTI SHOWFNAME ADDBUF 5 compiler=EVO +ifeq ($(build),release) +options=$(releaseoptions) +else +options=$(debugoptions) +endif + all: axSetupTool -release: options = IGNORECACHE OPTI SHOWFNAME ADDBUF 3 +release: options=$(releaseoptions) release: axSetupTool axSetupTool: axSetupTool.e frmMain.m axedit.m helpText.m diff --git a/makefile b/makefile index a648e55..730482b 100644 --- a/makefile +++ b/makefile @@ -1,14 +1,21 @@ # Compile ACP and EXPRESS and any dependencies -options=DEBUG IGNORECACHE NILCHECK OPTI SYM SHOWFNAME +debugoptions=DEBUG IGNORECACHE NILCHECK OPTI SYM SHOWFNAME +releaseoptions=IGNORECACHE OPTI SHOWFNAME compiler=EVO expprogramname=AmiExpress acpprogramname=ACP version=5.6.0-dev +ifeq ($(build),release) +options=$(releaseoptions) +else +options=$(debugoptions) +endif + all: acp express5 jsonimport icon2cfg qwk ftn -release: options = IGNORECACHE OPTI SHOWFNAME +release: options=$(releaseoptions) release: acp express5 jsonimport icon2cfg qwk ftn acp: acp.e acpversion.m axcommon.m jsonparser.m jsoncreate.m stringlist.m @@ -22,10 +29,10 @@ express5: express.e expversion.m axcommon.m axconsts.m miscfuncs.m axobjects.m verinfogen: verinfogen.e $(compiler) verinfogen $(options) -ftn: ftn.e stringlist.m +ftn: ftn.e stringlist.m axobjects.m $(compiler) ftn $(options) -qwk: qwk.e stringlist.m +qwk: qwk.e stringlist.m axobjects.m $(compiler) qwk $(options) icon2cfg: icon2cfg.e miscfuncs.m @@ -73,7 +80,7 @@ axcommon.m: axcommon.e stringlist.m axconsts.m: axconsts.e $(compiler) axconsts $(options) -axobjects.m: axobjects.e axconsts.m +axobjects.m: axobjects.e axconsts.m stringlist.m $(compiler) axobjects $(options) axenums.m: axenums.e From c95741c46f177cd40b9e2927f7e3c6c5cec56a53 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 11:43:57 +0100 Subject: [PATCH 25/47] Update makefile.yml update dev-build release on every commit --- .github/workflows/makefile.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 6c90e2b..4e7dec9 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -32,10 +32,24 @@ jobs: cp $GITHUB_WORKSPACE/icon2cfg downloads/utils cp $GITHUB_WORKSPACE/qwk downloads/utils cp $GITHUB_WORKSPACE/ftn downloads/utils - cp $GITHUB_WORKSPACE/axSetupTool/axSetupTool downloads/utils - + cp $GITHUB_WORKSPACE/axSetupTool/axSetupTool downloads/utils + - name: Use the Upload Artifact GitHub Action uses: actions/upload-artifact@v2 with: name: amiExpress-nightly${{ github.sha }} path: downloads + + - name: Grab the uploaded artifact + uses: actions/download-artifact@v3 + with: + name: amiExpress-nightly${{ github.sha }} + path: ~/ + + - name: Update nightly release + uses: eine/tip@master + with: + tag: dev-build + rm: true + token: ${{ secrets.GITHUB_TOKEN }} + files: ~/*.* From 81b215ede591dcbfe49521b85c64c047fbb42212 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 11:48:33 +0100 Subject: [PATCH 26/47] Update makefile.yml deploy build artifact --- .github/workflows/makefile.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 4e7dec9..1b1149a 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -45,11 +45,15 @@ jobs: with: name: amiExpress-nightly${{ github.sha }} path: ~/ - + + - name: add zip file extension to artifact + run: | + mv ~/amiExpress-nightly${{ github.sha }} ~/amiExpress-nightly${{ github.sha }}.zip + - name: Update nightly release uses: eine/tip@master with: tag: dev-build rm: true token: ${{ secrets.GITHUB_TOKEN }} - files: ~/*.* + files: ~/amiExpress-nightly${{ github.sha }}.zip From 4bc014aed3a362e3df516235a2e37c8b6d3fd0a7 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 11:52:20 +0100 Subject: [PATCH 27/47] Update makefile.yml --- .github/workflows/makefile.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 1b1149a..98efea0 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -48,6 +48,7 @@ jobs: - name: add zip file extension to artifact run: | + ls ~/ mv ~/amiExpress-nightly${{ github.sha }} ~/amiExpress-nightly${{ github.sha }}.zip - name: Update nightly release From cbf472a29dcb4e14ef5b58c4339e4d9d2cbbaa16 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 12:09:00 +0100 Subject: [PATCH 28/47] Update makefile.yml create release artifcact (lha) --- .github/workflows/makefile.yml | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 98efea0..8f71177 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -24,6 +24,7 @@ jobs: - name: add build artifacts to publish run: | + apk add lha mkdir downloads mkdir downloads/utils cp $GITHUB_WORKSPACE/express5 downloads @@ -32,24 +33,9 @@ jobs: cp $GITHUB_WORKSPACE/icon2cfg downloads/utils cp $GITHUB_WORKSPACE/qwk downloads/utils cp $GITHUB_WORKSPACE/ftn downloads/utils - cp $GITHUB_WORKSPACE/axSetupTool/axSetupTool downloads/utils - - - name: Use the Upload Artifact GitHub Action - uses: actions/upload-artifact@v2 - with: - name: amiExpress-nightly${{ github.sha }} - path: downloads - - - name: Grab the uploaded artifact - uses: actions/download-artifact@v3 - with: - name: amiExpress-nightly${{ github.sha }} - path: ~/ - - - name: add zip file extension to artifact - run: | - ls ~/ - mv ~/amiExpress-nightly${{ github.sha }} ~/amiExpress-nightly${{ github.sha }}.zip + cp $GITHUB_WORKSPACE/axSetupTool/axSetupTool downloads/utils + cd downloads + lha a ~/amiExpress-nightly${{ github.sha }}.lha * - name: Update nightly release uses: eine/tip@master @@ -57,4 +43,4 @@ jobs: tag: dev-build rm: true token: ${{ secrets.GITHUB_TOKEN }} - files: ~/amiExpress-nightly${{ github.sha }}.zip + files: ~/amiExpress-nightly${{ github.sha }}.lha From 8d5aaf80dc13aacd8ffe55f5ca49b1e298aaa4c2 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 12:14:07 +0100 Subject: [PATCH 29/47] Update makefile.yml --- .github/workflows/makefile.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 8f71177..c5332e6 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -36,6 +36,7 @@ jobs: cp $GITHUB_WORKSPACE/axSetupTool/axSetupTool downloads/utils cd downloads lha a ~/amiExpress-nightly${{ github.sha }}.lha * + ls ~/ - name: Update nightly release uses: eine/tip@master From 099569feba99a75447305cb1c61b030641b14475 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 12:20:24 +0100 Subject: [PATCH 30/47] Update makefile.yml --- .github/workflows/makefile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index c5332e6..03a0444 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -37,9 +37,9 @@ jobs: cd downloads lha a ~/amiExpress-nightly${{ github.sha }}.lha * ls ~/ - + - name: Update nightly release - uses: eine/tip@master + uses: pyTooling/Actions/releaser@main with: tag: dev-build rm: true From f24dfc57f952c7eccb9166b8ea19316151cfca5c Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 13:08:51 +0100 Subject: [PATCH 31/47] Update makefile.yml --- .github/workflows/makefile.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 03a0444..edfddd6 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -35,8 +35,8 @@ jobs: cp $GITHUB_WORKSPACE/ftn downloads/utils cp $GITHUB_WORKSPACE/axSetupTool/axSetupTool downloads/utils cd downloads - lha a ~/amiExpress-nightly${{ github.sha }}.lha * - ls ~/ + lha a ../amiExpress-nightly${{ github.sha }}.lha * + ls ../ - name: Update nightly release uses: pyTooling/Actions/releaser@main @@ -44,4 +44,4 @@ jobs: tag: dev-build rm: true token: ${{ secrets.GITHUB_TOKEN }} - files: ~/amiExpress-nightly${{ github.sha }}.lha + files: amiExpress-nightly${{ github.sha }}.lha From ae7b5f5f0ec2ace424e7872c831d2cc6059ab6a7 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Tue, 12 Sep 2023 13:14:19 +0100 Subject: [PATCH 32/47] Update makefile.yml change make to use release build --- .github/workflows/makefile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index edfddd6..b32bff4 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -19,8 +19,8 @@ jobs: - uses: actions/checkout@v4 - name: run build run: | - vamos -c /usr/amiga/.vamosrc --cwd esource: -V system:/usr/amiga -V esource:$GITHUB_WORKSPACE make - vamos -c /usr/amiga/.vamosrc --cwd esource:axSetupTool -V system:/usr/amiga -V esource:$GITHUB_WORKSPACE make + vamos -c /usr/amiga/.vamosrc --cwd esource: -V system:/usr/amiga -V esource:$GITHUB_WORKSPACE make build=release + vamos -c /usr/amiga/.vamosrc --cwd esource:axSetupTool -V system:/usr/amiga -V esource:$GITHUB_WORKSPACE make build=release - name: add build artifacts to publish run: | From 5dd31d0825430726c7df839ec2bf67f10dcfd2c5 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Wed, 13 Sep 2023 10:32:50 +0100 Subject: [PATCH 33/47] update makefile to be able to prepare a dist folder and add necessary extra files --- deployment/File_Id.Diz | 10 +++ .../Install Ami-Express | 0 .../Install Ami-Express.info | Bin deployment/binaries.lha | Bin 0 -> 637486 bytes deployment/read_me.txt | 83 ++++++++++++++++++ makefile | 74 ++++++++++------ 6 files changed, 142 insertions(+), 25 deletions(-) create mode 100644 deployment/File_Id.Diz rename Install Ami-Express => deployment/Install Ami-Express (100%) rename Install Ami-Express.info => deployment/Install Ami-Express.info (100%) create mode 100644 deployment/binaries.lha create mode 100644 deployment/read_me.txt diff --git a/deployment/File_Id.Diz b/deployment/File_Id.Diz new file mode 100644 index 0000000..c0a6f16 --- /dev/null +++ b/deployment/File_Id.Diz @@ -0,0 +1,10 @@ + ______________________________________ +A \_ __ __/ | / _ / _ / __/_ __/_ + / ___/__ _/ ____/_____/___ \___ \ +M_/ ___/ / \ \ \___/ \/ \ + \________/__| \__/______/________/______/ +I-----------|____/------[Version 5!]-------. +! IEMSI support for auto-login, XMODEM and| +| HYDRA support, FTP Direct Server for | +| fast transfers. | +`----[v5.5.0]----------------[05.06.2022]--' \ No newline at end of file diff --git a/Install Ami-Express b/deployment/Install Ami-Express similarity index 100% rename from Install Ami-Express rename to deployment/Install Ami-Express diff --git a/Install Ami-Express.info b/deployment/Install Ami-Express.info similarity index 100% rename from Install Ami-Express.info rename to deployment/Install Ami-Express.info diff --git a/deployment/binaries.lha b/deployment/binaries.lha new file mode 100644 index 0000000000000000000000000000000000000000..0797a7ab30e6a73db523471538d486787da7ef51 GIT binary patch literal 637486 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�L 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%0D5&mP!{2K}3X~x`kEh(<*TUz41!6+xMedY* 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 |ZK%!s*_# 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�~kT;0V8OZ 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 literal 0 HcmV?d00001 diff --git a/deployment/read_me.txt b/deployment/read_me.txt new file mode 100644 index 0000000..ebc5cbc --- /dev/null +++ b/deployment/read_me.txt @@ -0,0 +1,83 @@ +[sof] ____ + ___________ __\ /________ ________________________________ + \_ _ ¬\ ¬\/ ¬\\/¡ ___/ ¬Y / __ /__ ¬\ ___/ ___/ ___/C +.--/----¡ ¬ \ \/ \ | __/__> ' < ¬__/ ¬ _/_ __/_____ ¬\___ ¬\-----\--. +|// l__¡ \\_¡¡ \\!___ ¬\_. \ ¡ l__¡ ¯¬\__ ¬\ \\ \\ \\| +/ ¬l____/¬'l____/: ¬l___/ l___\ ! ¬l____/¬l___/_____/_____/ \ +| · · | +| Ami-Express was a BBS System that ran on the Commodore Amiga series of | +| computers and was developed by Lightspeed Technologies in the 1990s. | +| | +| Version 5.5.0 | +| | +| This is a rewrite of that system written in Amiga E. It is open source | +| and has new features and bug fixes in addition to aiming for near 100% | +| backwards compatibility with the version 4.x releases. | +| | +| I contacted Joe Hodge/LightSpeed Technologies the owner of /X product | +| in December 2018 and he has given his full approval for me to take over | +| this software and to continue using the Ami-Express name. | +| | +| I have also updated the documentation for Ami-Express as many existing | +| features were not properly documented. Some new features included in this | +| release are: | +| * XMODEM and HYDRA protocol support | +| * IEMSI support for auto-login if your client supports it. | +| * FTP Direct Server - you can now log onto FTP directly and upload or | +| download without having to log on via telnet. | +| * Improved CPS info in ACP during transfers | +| | +| With the inclusion of the HYDRA protocol support in this release we have | +| achieved full feature parity with the old V4.x Releases of Ami-Express. | +| There may still be some small differences between this version and the | +| older releases but all features are now covered. | +| | +| All source code is publicly available at: | +| https://github.com/dmcoles/AmiExpress along with the documentation. | +| | +| Included in this archive are several sample bbs configurations using | +| tooltype (.info) and config file (.cfg) format. These are aimed at users | +| wanting to set up a bbs for the first time. There is also a file called | +| aeicon.json which can be imported using the json import tool or by | +| selecting the file the first time you start /X with no configuration in | +| place. This file will create a basic structure similar to the ones | +| included in the archive. | +| | +| This verison of /X comes with both rexxdoor 1.3 and 2.2 - If you have 10 | +| nodes or more you *MUST* use 2.2 (rename it to rexxdoor) - however this | +| version requires that you make RX resident otherwise it won't work. If | +| you have less than 10 nodes you can use either version. | +| | +| If you are a pre-existing /X4 user, the ACP and Express files can just | +| replace the old versions and should be as close to fully backwards | +| compatible as possible. Plesae do contact me or raise issues in github if | +| you encounter any problems. | +| | +|---------------------------------------------------------------------------| +| This release is dedicated to my partner Traci who was taken ill | +| unexpectedly at the end of 2018 and passed away after suffering | +| lung damage caused by Influenza. RIP Traci xx. | +|---------------------------------------------------------------------------| +| | +| Version History | +| | +| 5.5.0 05 Jun 2022 (Feature parity release) | +| * XMODEM and Hydra support, FTP Direct Server, IEMSI auto login | +| 5.4.0 17 May 2021 | +| * YModem and ZModem 8k support, FTP authentication, shortcut mode | +| 5.3.2 01 September 2020 | +| * Minor bugfix release | +| 5.3.1 07 August 2020 | +| * Minor bugfix release | +| 5.3.0 04 July 2020 | +| * Internal Zmodem, HTTP File Transfers, connect to QWK & FTN | +| 5.2.0 02 Jan 2020 | +| * Native Telnet, FTP File Transfers, some bugfixes. | +| 5.1.0 03 June 2019 | +| * New features and bugfixes. | +| 5.0.0 23 December 2018 | +| * First release of this project | +\ / +|\\ //| +`--\---------------------------------------------------------------------/--' + [eof] diff --git a/makefile b/makefile index 730482b..7f42bc3 100644 --- a/makefile +++ b/makefile @@ -13,21 +13,24 @@ else options=$(debugoptions) endif -all: acp express5 jsonimport icon2cfg qwk ftn +all: ACP express5 jsonImport icon2cfg qwk ftn release: options=$(releaseoptions) -release: acp express5 jsonimport icon2cfg qwk ftn +release: ACP express5 jsonImport icon2cfg qwk ftn -acp: acp.e acpversion.m axcommon.m jsonparser.m jsoncreate.m stringlist.m - $(compiler) acp $(options) +axSetupTool: + make -B -C axSetupTool build=$(build) -express5: express.e expversion.m axcommon.m axconsts.m miscfuncs.m axobjects.m axenums.m stringlist.m errors.m mailssl.m ftpd.m httpd.m xymodem.m zmodem.m hydra.m tooltypes.m pwdhash.m bcd.m sha256.m +ACP: ACP.e acpversion.m axcommon.m jsonParser.m jsonCreate.m stringlist.m + $(compiler) ACP $(options) + +express5: express.e expversion.m axcommon.m axconsts.m MiscFuncs.m axobjects.m axenums.m stringlist.m errors.m mailssl.m ftpd.m httpd.m xymodem.m zmodem.m hydra.m tooltypes.m pwdhash.m bcd.m sha256.m $(compiler) express $(options) copy express express5 delete express -verinfogen: verinfogen.e - $(compiler) verinfogen $(options) +VerInfoGen: VerInfoGen.e + $(compiler) VerInfoGen $(options) ftn: ftn.e stringlist.m axobjects.m $(compiler) ftn $(options) @@ -35,17 +38,17 @@ ftn: ftn.e stringlist.m axobjects.m qwk: qwk.e stringlist.m axobjects.m $(compiler) qwk $(options) -icon2cfg: icon2cfg.e miscfuncs.m +icon2cfg: icon2cfg.e MiscFuncs.m $(compiler) icon2cfg $(options) -jsonimport: jsonimport.e jsonparser.m jsoncreate.m - $(compiler) jsonimport $(options) +jsonImport: jsonImport.e jsonParser.m jsonCreate.m + $(compiler) jsonImport $(options) -jsonparser.m: jsonparser.e miscfuncs.m - $(compiler) jsonparser $(options) +jsonParser.m: jsonParser.e MiscFuncs.m + $(compiler) jsonParser $(options) -jsoncreate.m: jsoncreate.e miscfuncs.m jsonparser.m - $(compiler) jsoncreate $(options) +jsonCreate.m: jsonCreate.e MiscFuncs.m jsonParser.m + $(compiler) jsonCreate $(options) zmodem.m: zmodem.e bcd.m $(compiler) zmodem $(options) @@ -59,8 +62,8 @@ hydra.m: hydra.e stringlist.m: stringlist.e $(compiler) stringlist $(options) -miscfuncs.m: miscfuncs.e axconsts.m axenums.m axobjects.m errors.m - $(compiler) miscfuncs $(options) +MiscFuncs.m: MiscFuncs.e axconsts.m axenums.m axobjects.m errors.m + $(compiler) MiscFuncs $(options) errors.m: errors.e $(compiler) errors $(options) @@ -89,14 +92,14 @@ axenums.m: axenums.e expversion.m: expversion.e $(compiler) expversion $(options) -expversion.e: verinfogen - verinfogen expversion.e $(expprogramname) $(version) usedate +expversion.e: VerInfoGen + VerInfoGen expversion.e $(expprogramname) $(version) usedate acpversion.m: acpversion.e $(compiler) acpversion $(options) -acpversion.e: verinfogen - verinfogen acpversion.e $(acpprogramname) $(version) usedate +acpversion.e: VerInfoGen + VerInfoGen acpversion.e $(acpprogramname) $(version) usedate bcd.m: bcd.e axobjects.m $(compiler) bcd $(options) @@ -104,14 +107,35 @@ bcd.m: bcd.e axobjects.m sha256.m: sha256.e $(compiler) sha256 $(options) -ftpd.m: ftpd.e tooltypes.m stringlist.m axobjects.m axenums.m miscfuncs.m bcd.m +ftpd.m: ftpd.e tooltypes.m stringlist.m axobjects.m axenums.m MiscFuncs.m bcd.m $(compiler) ftpd $(options) httpd.m: httpd.e axcommon.m stringlist.m $(compiler) httpd $(options) clean: - delete expversion.e acpversion.e delete express verinfogen express5 acp qwk ftn jsonimport icon2cfg miscfuncs.m stringlist.m errors.m mailssl.m jsoncreate.m jsonparser.m axcommon.m ftpd.m httpd.m axconsts.m axobjects.m axenums.m zmodem.m xymodem.m hydra.m bcd.m expversion.m acpversion.m pwdhash.m tooltypes.m sha256.m - -.PHONY: expversion.e - \ No newline at end of file + delete expversion.e acpversion.e delete express VerInfoGen express5 acp qwk ftn jsonImport icon2cfg MiscFuncs.m stringlist.m errors.m mailssl.m jsonCreate.m jsonParser.m axcommon.m ftpd.m httpd.m axconsts.m axobjects.m axenums.m zmodem.m xymodem.m hydra.m bcd.m expversion.m acpversion.m pwdhash.m tooltypes.m sha256.m + +dist: options=$(releaseoptions) +dist: build=release +dist: ACP express5 jsonImport icon2cfg qwk ftn axSetupTool + -delete Rel ALL FORCE + makedir Rel + makedir Rel/AmiExpress + makedir Rel/AmiExpress/AmiExpress + makedir Rel/AmiExpress/AmiExpress/Utils + lha x deployment/binaries.lha Rel/AmiExpress/ + Copy acp Rel/AmiExpress/AmiExpress/ + Copy express5 Rel/AmiExpress/AmiExpress/express + Copy jsonImport Rel/AmiExpress/AmiExpress/Utils/ + Copy icon2cfg Rel/AmiExpress/AmiExpress/Utils/ + Copy icon2cfg Rel/AmiExpress/AmiExpress/Utils/ + Copy axSetupTool/axSetupTool Rel/AmiExpress/AmiExpress/Utils/ + Copy qwk Rel/AmiExpress/AmiExpress/Utils/ + Copy ftn Rel/AmiExpress/AmiExpress/Utils/ + Copy deployment/Install\ Ami-Express Rel/ + Copy deployment/Install\ Ami-Express.info Rel/ + Copy deployment/File_Id.Diz Rel/ + Copy deployment/read_me.txt Rel/ + +.PHONY: expversion.e axSetupTool From 071b86c0b78dceba141b0a1b9c7b47a46c37d8e3 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Wed, 13 Sep 2023 10:44:14 +0100 Subject: [PATCH 34/47] Update makefile.yml fix casing in github build action --- .github/workflows/makefile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index b32bff4..3c130fe 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -28,8 +28,8 @@ jobs: mkdir downloads mkdir downloads/utils cp $GITHUB_WORKSPACE/express5 downloads - cp $GITHUB_WORKSPACE/acp downloads - cp $GITHUB_WORKSPACE/jsonimport downloads/utils + cp $GITHUB_WORKSPACE/ACP downloads + cp $GITHUB_WORKSPACE/jsonImport downloads/utils cp $GITHUB_WORKSPACE/icon2cfg downloads/utils cp $GITHUB_WORKSPACE/qwk downloads/utils cp $GITHUB_WORKSPACE/ftn downloads/utils From 50956ccb7b6b03cd329dde2f224ca99d391fdd0c Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 12 Oct 2023 13:58:55 +0100 Subject: [PATCH 35/47] Add in the v5.6.0 password security settings to the config editor --- axSetupTool/frmSettingsEdit.e | 87 ++++++++++++++++++++++++++++++++++- axSetupTool/helpText.e | 7 +++ axSetupTool/makefile | 2 +- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/axSetupTool/frmSettingsEdit.e b/axSetupTool/frmSettingsEdit.e index e61bd40..71a365b 100644 --- a/axSetupTool/frmSettingsEdit.e +++ b/axSetupTool/frmSettingsEdit.e @@ -26,6 +26,12 @@ EXPORT OBJECT frmSettingsEdit OF frmBase strBBSLocation : PTR TO control strSysopName : PTR TO control strDefaultMenu : PTR TO control + intMinPasswordLen: PTR TO control + cycMinPasswordStrength: PTR TO control + cycPasswordEncryption: PTR TO control + intMaxPasswordFails: PTR TO control + intPasswordExpiry: PTR TO control + cycStrictPasswordPolicy: PTR TO control paLocalULPath : PTR TO control intAutoValPreset : PTR TO control intAutoValDelay : PTR TO control @@ -181,6 +187,24 @@ PROC addSystemControls() OF frmSettingsEdit NEW control.createString('bSysop Name',SYS_SYSOP_NAME,self.app.app,self.setChangedHook,self) self.strSysopName:=control + NEW control.createStringInt('Min Password Length',SYS_MIN_PASSWORD_LEN,self.app.app,self.setChangedHook,self) + self.intMinPasswordLen:=control + + NEW control.createCycle('Min Password Strength',SYS_MIN_PASSWORD_STRENGTH,['No restriction','2 character types','3 character types','All 4 character types',0],self.app.app,self.setChangedHook,self) + self.cycMinPasswordStrength:=control + + NEW control.createCycle('Password Encryption',SYS_PASSWORD_ENCRYPTION,['Legacy /X Encryption','PBKDF2 (5 rounds)','PBKDF2 (50 rounds)','PBKDF2 (100 rounds)','PBKDF2 (1000 rounds)','PBKDF2 (10000 rounds)',0],self.app.app,self.setChangedHook,self) + self.cycPasswordEncryption:=control + + NEW control.createStringInt('Max Password Fails',SYS_MAX_PASSWORD_FAILS,self.app.app,self.setChangedHook,self) + self.intMaxPasswordFails:=control + + NEW control.createStringInt('Password Expiry',SYS_PASSWORD_EXPIRY,self.app.app,self.setChangedHook,self) + self.intPasswordExpiry:=control + + NEW control.createCycle('Strict Password Policy',SYS_STRICT_PASSWORD_POLICY,['No','Yes',0],self.app.app,self.setChangedHook,self) + self.cycStrictPasswordPolicy:=control + NEW control.createString('Default Menu',SYS_DEFAULT_MENU,self.app.app,self.setChangedHook,self) self.strDefaultMenu:=control @@ -301,7 +325,9 @@ PROC addSystemControls() OF frmSettingsEdit NEW control.createString('Execute async on upload',SYS_EXECA_ON_UPLOAD,self.app.app,self.setChangedHook,self) self.strExecAOnUpload:=control - self.controlList:=[self.paBBSPath,self.strBBSName,self.strBBSLocation,self.strSysopName,self.strRegKey,self.cyNewAccounts,self.strDefaultMenu, + self.controlList:=[self.paBBSPath,self.strBBSName,self.strBBSLocation,self.strSysopName,self.intMinPasswordLen, + self.cycMinPasswordStrength,self.cycPasswordEncryption,self.intMaxPasswordFails,self.intPasswordExpiry, + self.cycStrictPasswordPolicy,self.strRegKey,self.cyNewAccounts,self.strDefaultMenu, self.paLocalULPath,self.intAutoValPreset,self.intAutoValDelay,self.strAutoValPassword,self.cyLanguage, self.strSmtpHost,self.intSmtpPort,self.strSmtpUsername,self.strSmtpPassword,self.boolSmtpSSL,self.strSysopEmail, self.strBbsEmail,self.paLanguageBase,self.paHistory,self.paUserNotes,self.intHoldAccess, @@ -623,6 +649,33 @@ PROC saveSystemChanges() OF frmSettingsEdit writeToolType(self.acpName,'BBS_NAME',self.strBBSName.getValue()) writeToolType(self.acpName,'BBS_GEOGRAPHIC',self.strBBSLocation.getValue()) writeToolType(self.acpName,'SYSOP_NAME',self.strSysopName.getValue()) + + writeToolType(self.bbsConfigName,'MIN_PASSWORD_LENGTH',self.intMinPasswordLen.getValue()) + IF self.cycMinPasswordStrength.getValueIndex()=0 + writeToolType(self.bbsConfigName,'MIN_PASSWORD_STRENGTH','') + ELSE + StringF(tempStr,'\d',self.cycMinPasswordStrength.getValueIndex()+1) + writeToolType(self.bbsConfigName,'MIN_PASSWORD_STRENGTH',tempStr) + ENDIF + SELECT self.cycPasswordEncryption.getValueIndex() + CASE 0 + writeToolType(self.bbsConfigName,'PASSWORD_SECURITY','LEGACY') + CASE 1 + writeToolType(self.bbsConfigName,'PASSWORD_SECURITY','PBKDF2_5') + CASE 2 + writeToolType(self.bbsConfigName,'PASSWORD_SECURITY','PBKDF2_50') + CASE 3 + writeToolType(self.bbsConfigName,'PASSWORD_SECURITY','PBKDF2_100') + CASE 4 + writeToolType(self.bbsConfigName,'PASSWORD_SECURITY','PBKDF2_1000') + CASE 5 + writeToolType(self.bbsConfigName,'PASSWORD_SECURITY','PBKDF2_10000') + ENDSELECT + + writeToolType(self.bbsConfigName,'MAX_PASSWORD_FAILS',self.intMaxPasswordFails.getValue()) + writeToolType(self.bbsConfigName,'PASSWORD_EXPIRY_DAYS',self.intPasswordExpiry.getValue()) + IF self.cycStrictPasswordPolicy.getValueIndex() THEN writeToolType(self.bbsConfigName,'STRICT_PASSWORD_POLICY') ELSE deleteToolType(self.bbsConfigName,'STRICT_PASSWORD_POLICY') + IF self.cyNewAccounts.getValueIndex()=0 THEN writeToolType(self.acpName,'NEW_ACCOUNTS','APPEND') ELSE deleteToolType(self.acpName,'NEW_ACCOUNTS') writeToolType(self.bbsConfigName,'REGKEY',self.strRegKey.getValue()) writeToolType(self.bbsConfigName,'DEFAULT_MENUNAME',self.strDefaultMenu.getValue()) @@ -862,6 +915,38 @@ PROC editSystemSettings(acpName:PTR TO CHAR, initialSetup=FALSE) OF frmSettingsE readToolType(self.acpName,'SYSOP_NAME',tempstr) self.strSysopName.setValue(tempstr) + val:=readToolTypeInt(self.bbsConfigName,'MIN_PASSWORD_LENGTH') + self.intMinPasswordLen.setValue(val) + + val:=readToolTypeInt(self.bbsConfigName,'MIN_PASSWORD_STRENGTH') + IF val<1 THEN val:=1 + self.cycMinPasswordStrength.setValueIndex(val-1) + + readToolType(self.bbsConfigName,'PASSWORD_SECURITY',tempstr) + IF StriCmp(tempstr,'LEGACY') + self.cycPasswordEncryption.setValueIndex(0) + ELSEIF StriCmp(tempstr,'PBKDF2_5') + self.cycPasswordEncryption.setValueIndex(1) + ELSEIF StriCmp(tempstr,'PBKDF2_50') + self.cycPasswordEncryption.setValueIndex(2) + ELSEIF StriCmp(tempstr,'PBKDF2_100') + self.cycPasswordEncryption.setValueIndex(3) + ELSEIF StriCmp(tempstr,'PBKDF2_1000') + self.cycPasswordEncryption.setValueIndex(4) + ELSEIF StriCmp(tempstr,'PBKDF2_10000') + self.cycPasswordEncryption.setValueIndex(5) + ELSE + self.cycPasswordEncryption.setValueIndex(0) + ENDIF + + val:=readToolTypeInt(self.bbsConfigName,'MAX_PASSWORD_FAILS') + self.intMaxPasswordFails.setValue(val) + + val:=readToolTypeInt(self.bbsConfigName,'PASSWORD_EXPIRY_DAYS') + self.intPasswordExpiry.setValue(val) + + self.cycStrictPasswordPolicy.setValueIndex(IF checkToolTypeExists(self.bbsConfigName,'STRICT_PASSWORD_POLICY') THEN 1 ELSE 0) + readToolType(self.acpName,'NEW_ACCOUNTS',tempstr) self.cyNewAccounts.setValueIndex(IF StriCmp(tempstr,'APPEND') THEN 0 ELSE 1) diff --git a/axSetupTool/helpText.e b/axSetupTool/helpText.e index 8517432..6676a0b 100644 --- a/axSetupTool/helpText.e +++ b/axSetupTool/helpText.e @@ -39,6 +39,7 @@ EXPORT ENUM ACCESS_NAME_MAX_PAGES,ACCESS_NAME,ACCESS_AREA_NAME,CHECKER_FILE,CHEC NODE_FORCE_ANSI,NODE_CON_IN_DEVICE,NODE_CON_OUT_DEVICE,NODE_SCREEN_PENS,NODE_CONF_DB_FILE, NODE_FIRST_COMMAND,NODE_SERIAL_DEVICE,NODE_MODEM_INIT,NODE_MODEM_RESET,NODE_MODEM_RING,NODE_MODEM_ANSWER, NODE_MODEM_OFFHOOK,NODE_MODEM_NRAMS,NODE_WIN_DEFPUBSCREEN,NODE_WIN_PUBSCREEN,SYS_BBS_NAME,SYS_BBS_LOCATION,SYS_SYSOP_NAME, + SYS_MIN_PASSWORD_LEN,SYS_MIN_PASSWORD_STRENGTH,SYS_PASSWORD_ENCRYPTION,SYS_MAX_PASSWORD_FAILS,SYS_PASSWORD_EXPIRY,SYS_STRICT_PASSWORD_POLICY, SYS_DEFAULT_MENU,SYS_AUTO_VAL_PASSWORD,SYS_REGKEY,SYS_SMTP_SERVER,SYS_SMTP_USERNAME,SYS_SMTP_PASSWORD, SYS_SYSOP_EMAIL,SYS_BBS_EMAIL,SYS_FILEDIZ_CMD,SYS_FTP_HOST,SYS_EXEC_ON_NEW_USER,SYS_EXECA_ON_NEW_USER, SYS_EXEC_ON_SYSOP_PAGE,SYS_EXECA_ON_SYSOP_PAGE,SYS_EXEC_ON_CONNECT,SYS_EXECA_ON_CONNECT, @@ -302,6 +303,12 @@ EXPORT PROC helpTextInitialise() addHelp(SYS_BBS_NAME,'Sets the name of the BBS that is shown to the user when they connect.') addHelp(SYS_BBS_LOCATION,'Sets the bbs geographic location that is shown to the user when they connect.') addHelp(SYS_SYSOP_NAME,'Sets the name of the sysop of the bbs.') + addHelp(SYS_MIN_PASSWORD_LEN,'Sets the minimum number of characters allowed for a users password.') + addHelp(SYS_MIN_PASSWORD_STRENGTH,'Sets the minimum complexity of a users password. The character types are Upper, Lower, Numeric, Symbol') + addHelp(SYS_PASSWORD_ENCRYPTION,'Sets the encryption used to store the users passwords. The legacy /X encryption is very weak and can be broken in seconds.') + addHelp(SYS_MAX_PASSWORD_FAILS,'Controls the maximum number of incorrect password attempts before a users account is locked out.') + addHelp(SYS_PASSWORD_EXPIRY,'Sets the number of days after which the user will be forced to change their password.') + addHelp(SYS_STRICT_PASSWORD_POLICY,'If strict password policy is enabled then users will be forced to change their existing password if it does not comply with the settings.') addHelp(SYS_DEFAULT_MENU,'Sets the default menu name (will default to MENU if left blank).') addHelp(SYS_AUTO_VAL_PASSWORD,'Sets the auto validation password for all nodes.') addHelp(SYS_REGKEY,'Sets the registration name. This is displayed to the user as part of the welcome message.') diff --git a/axSetupTool/makefile b/axSetupTool/makefile index 4a787c8..b8cf782 100644 --- a/axSetupTool/makefile +++ b/axSetupTool/makefile @@ -21,7 +21,7 @@ axSetupTool: axSetupTool.e frmMain.m axedit.m helpText.m axedit.m: axedit.e $(compiler) axedit $(options) -stringlist.m: ../stringlist.e +stringlist.m: $(compiler) /stringlist $(options) tooltypes.m: tooltypes.e stringlist.m From 894837f226494034c8e97cac3fa5ce2f0cf35816 Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Thu, 12 Oct 2023 14:03:50 +0100 Subject: [PATCH 36/47] ACP 1) System stats and session stats are single page only 2) Enable new look menus 3) SessionStats were not refreshed after deiconify 4) Menu's were not freed correctly --- ACP.e | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ACP.e b/ACP.e index 2c6cf6d..a207dda 100644 --- a/ACP.e +++ b/ACP.e @@ -1514,7 +1514,7 @@ PROC handleEditGadget(im:PTR TO intuimessage,ig) showSessionStats(eWin) ENDSELECT CASE GAD_TOPSBOX - IF(control) + IF(control) OR (topOption>=SYSTEM_STATS) control:=0 SELECT topOption CASE LAST_CALLERS @@ -4200,6 +4200,7 @@ PROC main() HANDLE WA_MAXHEIGHT, -1, WA_ZOOM, dim, WA_AUTOADJUST, 1, + WA_NEWLOOKMENUS, 1, WA_PUBSCREEN, IF EstrLen(publicName)=0 THEN NIL ELSE scr, WA_PUBSCREENFALLBACK, 1, WA_GADGETS, gadgets, @@ -4296,6 +4297,8 @@ PROC main() HANDLE showLastDownloads(eWin) CASE SYSTEM_STATS showSystemStats(eWin) + CASE SESSION_STATS + showSessionStats(eWin) ENDSELECT FOR i:=0 TO MAX_NODES-1 IF(StrLen(startNode[i])>0) @@ -4368,6 +4371,7 @@ EXCEPT DO Permit() ENDIF ENDIF + FreeMenus(eWinM) IF msg THEN FreeMem(msg,SIZEOF acpMessage) From b8c658b81ff0e4b77da0233936f5667f6c040eac Mon Sep 17 00:00:00 2001 From: phantasm4489 Date: Sat, 4 Nov 2023 19:17:48 +0000 Subject: [PATCH 37/47] Express 1) Incorrect conf num recorded in callers log when rejoining conf after login --- express.e | 56 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/express.e b/express.e index 3efc25c..00cbefb 100644 --- a/express.e +++ b/express.e @@ -2961,40 +2961,40 @@ PROC checkUserOnLine(check) loop:=0 error:=1 REPEAT - IF(loop=node) THEN loop++ + IF(loop=node) THEN loop++ - IF sopt.toggles[TOGGLES_MULTICOM] - status:=-1 + IF sopt.toggles[TOGGLES_MULTICOM] + status:=-1 ObtainSemaphore(masterNode) - sp:=(masterNode.myNode[loop].s) + sp:=(masterNode.myNode[loop].s) ReleaseSemaphore(masterNode) - IF sp - ObtainSemaphore(sp) - status:=sp.status - ReleaseSemaphore(sp) + IF sp + ObtainSemaphore(sp) + status:=sp.status + ReleaseSemaphore(sp) + ENDIF + ELSE + status:=0 ENDIF - ELSE - status:=0 - ENDIF - - IF (status>=0) AND (status<>ENV_NOTACTIVE) AND (status<>ENV_SHUTDOWN) - StringF(tempStr,'\snode\d',cmds.bbsLoc,loop) - IF(lock:=Lock(tempStr,ACCESS_READ)) - UnLock(lock) - StringF(tempStr,'\snode\d.user',cmds.bbsLoc,loop) - IF(fh:=Open(tempStr,MODE_OLDFILE))<>0 - IF(Read(fh,tuser,SIZEOF user)) - IF(stringCompare(tuser.name,loggedOnUser.name)=RESULT_SUCCESS) - error:=0 - lock:=NIL + + IF (status>=0) AND (status<>ENV_NOTACTIVE) AND (status<>ENV_SHUTDOWN) + StringF(tempStr,'\snode\d',cmds.bbsLoc,loop) + IF(lock:=Lock(tempStr,ACCESS_READ)) + UnLock(lock) + StringF(tempStr,'\snode\d.user',cmds.bbsLoc,loop) + IF(fh:=Open(tempStr,MODE_OLDFILE))<>0 + IF(Read(fh,tuser,SIZEOF user)) + IF(stringCompare(tuser.name,loggedOnUser.name)=RESULT_SUCCESS) + error:=0 + lock:=NIL + ENDIF ENDIF ENDIF + Close(fh) ENDIF - Close(fh) ENDIF - ENDIF - loop++ + loop++ UNTIL (lock=NIL) OR (loop=MAX_NODES) ELSE error:=1 @@ -5053,9 +5053,9 @@ PROC joinConf(conf, msgBaseNum,confScan, auto, forceMailScan=FORCE_MAILSCAN_NOFO processSysCommand('S') IF getConfMsgBaseCount(conf)>1 getMsgBaseName(conf,msgBaseNum,tempstr) - StringF(string,'Conference \d: \s [\s] Auto-ReJoined',relConfNum,currentConfName,tempstr) + StringF(string,'Conference \d: \s [\s] Auto-ReJoined',conf,currentConfName,tempstr) ELSE - StringF(string,'Conference \d: \s Auto-ReJoined',relConfNum,currentConfName) + StringF(string,'Conference \d: \s Auto-ReJoined',conf,currentConfName) ENDIF IF quietJoin=FALSE THEN aePuts(string) ELSE @@ -18273,7 +18273,7 @@ ENDPROC RESULT_SUCCESS PROC checkForFile(fn: PTR TO CHAR) DEF path[255]:STRING,final[255]:STRING - DEF x + DEF x IF((InStr(fn,'%')>=0) OR ((InStr(fn,'#'))>=0) OR ((InStr(fn,'?'))>=0) OR ((InStr(fn,' '))>=0) OR ((InStr(fn,'/'))>=0) OR ((InStr(fn,'('))>=0) OR ((InStr(fn,')'))>=0) OR ((InStr(fn,':'))>=0) OR ((InStr(fn,'*'))>=0)) THEN RETURN RESULT_FAILURE From f860c8d6dd72f8fda3b8308d9fb7949b9bba90cd Mon Sep 17 00:00:00 2001 From: dmcoles Date: Mon, 27 Nov 2023 11:25:55 +0000 Subject: [PATCH 38/47] extra checking to prevent users from logging onto mode than 1 node at the same time --- express.e | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/express.e b/express.e index 00cbefb..0c0c7e8 100644 --- a/express.e +++ b/express.e @@ -2960,19 +2960,30 @@ PROC checkUserOnLine(check) IF(check) loop:=0 error:=1 + + IF sopt.toggles[TOGGLES_MULTICOM] + ObtainSemaphore(masterNode) + ENDIF + REPEAT IF(loop=node) THEN loop++ IF sopt.toggles[TOGGLES_MULTICOM] status:=-1 - ObtainSemaphore(masterNode) sp:=(masterNode.myNode[loop].s) - ReleaseSemaphore(masterNode) IF sp ObtainSemaphore(sp) status:=sp.status ReleaseSemaphore(sp) + lock:=-1 + IF (status>=0) AND (status<>ENV_NOTACTIVE) AND (status<>ENV_SHUTDOWN) + IF(stringCompare(sp.handle,loggedOnUser.name)=RESULT_SUCCESS) + lock:=0 + error:=0 + ENDIF + ENDIF + status:=-1 ENDIF ELSE status:=0 @@ -2996,6 +3007,10 @@ PROC checkUserOnLine(check) ENDIF loop++ UNTIL (lock=NIL) OR (loop=MAX_NODES) + + IF sopt.toggles[TOGGLES_MULTICOM] + ReleaseSemaphore(masterNode) + ENDIF ELSE error:=1 ENDIF From 7278ad683c5b5b5996dc0a64da10f74aab88e71a Mon Sep 17 00:00:00 2001 From: dmcoles Date: Tue, 12 Dec 2023 15:53:20 +0000 Subject: [PATCH 39/47] remove debug messages from setup tool --- axSetupTool/tooltypes.e | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/axSetupTool/tooltypes.e b/axSetupTool/tooltypes.e index f60ce37..8e0d6a6 100644 --- a/axSetupTool/tooltypes.e +++ b/axSetupTool/tooltypes.e @@ -95,7 +95,7 @@ EXPORT PROC writeToolType(toolType,key,newValue=-1,force=FALSE) RETURN ENDIF ENDIF - WriteF('update tooltype \s \s = \s\n',toolType,key,newValue) + ->WriteF('update tooltype \s \s = \s\n',toolType,key,newValue) changesMade:=TRUE count:=0 @@ -135,7 +135,7 @@ EXPORT PROC writeToolType(toolType,key,newValue=-1,force=FALSE) ENDIF ENDFOR IF needToAdd - WriteF('added \s\n',newItem) + ->WriteF('added \s\n',newItem) changesMade:=TRUE cacheObj.changed:=TRUE oldtooltypes[count]:=StrClone(newItem) @@ -193,7 +193,7 @@ EXPORT PROC deleteToolType(toolType,key) do.tooltypes:=oldtooltypes IF changed - WriteF('delete tooltype \s \s\n',toolType,key) + ->WriteF('delete tooltype \s \s\n',toolType,key) changesMade:=TRUE ENDIF ENDIF @@ -242,7 +242,7 @@ PROC freeCacheItem(cacheObj:PTR TO diskObjectCacheItem) DEF mem,i IF cacheObj.changed - WriteF('saving file and freeing \s\n',cacheObj.fileName) + ->WriteF('saving file and freeing \s\n',cacheObj.fileName) PutDiskObject(cacheObj.fileName,cacheObj.diskObject) ENDIF @@ -367,7 +367,7 @@ PROC getOrCreateCacheItem(fileName:PTR TO CHAR,getDef=FALSE) IF (do=NIL) IF (getDef) do:=GetDefDiskObject(WBPROJECT) - WriteF('create new disk obj\n') + ->WriteF('create new disk obj\n') ELSE RETURN 0,0 ENDIF @@ -435,7 +435,7 @@ EXPORT PROC saveCachedChanges() FOR i:=0 TO diskObjectCache.count()-1 cacheObj:=diskObjectCache.item(i) IF cacheObj.changed - WriteF('saving file \s\n',cacheObj.fileName) + ->WriteF('saving file \s\n',cacheObj.fileName) PutDiskObject(cacheObj.fileName,cacheObj.diskObject) cacheObj.changed:=FALSE ENDIF From d660a2c516a9f29d631e1fb1be8f16e6a16e52e6 Mon Sep 17 00:00:00 2001 From: dmcoles Date: Fri, 29 Dec 2023 12:41:14 +0000 Subject: [PATCH 40/47] update installer with options to set encryption set script bit on logoff scripts in the default bbs archive --- deployment/Install Ami-Express | 27 +++++++++++++++++++++++++++ deployment/binaries.lha | Bin 637486 -> 639493 bytes 2 files changed, 27 insertions(+) diff --git a/deployment/Install Ami-Express b/deployment/Install Ami-Express index d121602..5c97b54 100644 --- a/deployment/Install Ami-Express +++ b/deployment/Install Ami-Express @@ -238,6 +238,9 @@ (help @startup-help) (command #startup) ) + +( message "The user password encryption used by Ami-Express prior to this release is extremely weak and easily hackable using brute force.\n\nThis release introduces password encryption using PKBDF2. The number of rounds of PKBDF2 has been set to 100 which is a compromise between security and the processing capability of the Amiga. If you have a powerful CPU you should consider changing the settings to make it more secure.") + ; ) ; Else @@ -366,6 +369,30 @@ ) ( complete 80) + +(set #currsecurity "") +(iconinfo (dest "bbs:bbsconfig") (gettooltype "PASSWORD_SECURITY" "#currsecurity" )) + +( if ( = #currsecurity "") +( + (set #securitychoice (askchoice + (choices "Enable the new encryption" "Keep the legacy encryption" + (prompt "This release of Ami-Express includes a new password encryption system.\nThe old system was extremely weak and easily hacked using brute force.\nIf you have to downgrade Ami-Express for any reason, new users created with the new password security will not be able to log into the BBS.") + (help "") + (default 0) )) + ) + + + ( if ( = #securitychoice 0) + (tooltype (dest "bbs:bbsconfig") (settooltype "PASSWORD_SECURITY" "PKBDF2_100")) + (tooltype (dest "bbs:bbsconfig") (settooltype "PASSWORD_SECURITY" "LEGACY")) + ) + ) +) + + +( complete 90) + ; ) ) ; End If diff --git a/deployment/binaries.lha b/deployment/binaries.lha index 0797a7ab30e6a73db523471538d486787da7ef51..282d9e7261c097c23c7a6119f3d9bf5e647c2a3f 100644 GIT binary patch delta 13169 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 q)GLHIEf5~zK)F9d>>O*gK Date: Sat, 30 Dec 2023 21:13:12 +0000 Subject: [PATCH 41/47] update file id and read_me for v5.6.0 --- deployment/File_Id.Diz | 20 ++++++++++---------- deployment/read_me.txt | 20 +++++++------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/deployment/File_Id.Diz b/deployment/File_Id.Diz index c0a6f16..d51e547 100644 --- a/deployment/File_Id.Diz +++ b/deployment/File_Id.Diz @@ -1,10 +1,10 @@ - ______________________________________ -A \_ __ __/ | / _ / _ / __/_ __/_ - / ___/__ _/ ____/_____/___ \___ \ -M_/ ___/ / \ \ \___/ \/ \ - \________/__| \__/______/________/______/ -I-----------|____/------[Version 5!]-------. -! IEMSI support for auto-login, XMODEM and| -| HYDRA support, FTP Direct Server for | -| fast transfers. | -`----[v5.5.0]----------------[05.06.2022]--' \ No newline at end of file + ____ _____ A M I +.:::\ \| /:::. :::::. .:::: .:::: .:::: +::../ /::..' ::..' ::.. ::... ::... +::./ | \: :: `: ::... ...:: ...:: +.--\____|\____\-----------------------. +| /X v5.6.0 Released on 31-Dec-2023 | +| Written By Darren Coles | +| This update introduces a full MUI based | +| setup editor and a standard installer | +`------------------------------------------' diff --git a/deployment/read_me.txt b/deployment/read_me.txt index ebc5cbc..a6c483f 100644 --- a/deployment/read_me.txt +++ b/deployment/read_me.txt @@ -8,7 +8,7 @@ | Ami-Express was a BBS System that ran on the Commodore Amiga series of | | computers and was developed by Lightspeed Technologies in the 1990s. | | | -| Version 5.5.0 | +| Version 5.6.0 | | | | This is a rewrite of that system written in Amiga E. It is open source | | and has new features and bug fixes in addition to aiming for near 100% | @@ -21,16 +21,9 @@ | I have also updated the documentation for Ami-Express as many existing | | features were not properly documented. Some new features included in this | | release are: | -| * XMODEM and HYDRA protocol support | -| * IEMSI support for auto-login if your client supports it. | +| * Full MUI Based Configuration / Setup Edit | +| * Installer Script that allows upgrading and initial BBS setup | | * FTP Direct Server - you can now log onto FTP directly and upload or | -| download without having to log on via telnet. | -| * Improved CPS info in ACP during transfers | -| | -| With the inclusion of the HYDRA protocol support in this release we have | -| achieved full feature parity with the old V4.x Releases of Ami-Express. | -| There may still be some small differences between this version and the | -| older releases but all features are now covered. | | | | All source code is publicly available at: | | https://github.com/dmcoles/AmiExpress along with the documentation. | @@ -44,9 +37,8 @@ | included in the archive. | | | | This verison of /X comes with both rexxdoor 1.3 and 2.2 - If you have 10 | -| nodes or more you *MUST* use 2.2 (rename it to rexxdoor) - however this | -| version requires that you make RX resident otherwise it won't work. If | -| you have less than 10 nodes you can use either version. | +| nodes or more you *MUST* use 2.2 - the installer will prompt you to make | +| a decision on which version you prefer. | | | | If you are a pre-existing /X4 user, the ACP and Express files can just | | replace the old versions and should be as close to fully backwards | @@ -61,6 +53,8 @@ | | | Version History | | | +| 5.6.0 31 Dec 2023 | +| * Improved password encryption, Full Setup Editor, Installer | | 5.5.0 05 Jun 2022 (Feature parity release) | | * XMODEM and Hydra support, FTP Direct Server, IEMSI auto login | | 5.4.0 17 May 2021 | From 16cd0cdd1fcbbcb472f54375ad4115103eb016c0 Mon Sep 17 00:00:00 2001 From: dmcoles Date: Sat, 30 Dec 2023 21:31:03 +0000 Subject: [PATCH 42/47] makefile: update version info and create lha archive --- makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 7f42bc3..3860ea8 100644 --- a/makefile +++ b/makefile @@ -5,7 +5,7 @@ releaseoptions=IGNORECACHE OPTI SHOWFNAME compiler=EVO expprogramname=AmiExpress acpprogramname=ACP -version=5.6.0-dev +version=5.6.0 ifeq ($(build),release) options=$(releaseoptions) @@ -137,5 +137,8 @@ dist: ACP express5 jsonImport icon2cfg qwk ftn axSetupTool Copy deployment/Install\ Ami-Express.info Rel/ Copy deployment/File_Id.Diz Rel/ Copy deployment/read_me.txt Rel/ + Lha -r a t:Amix560.lha Rel/ + Copy t:Amix560.lha Rel/ + -delete t:Amix560.lha .PHONY: expversion.e axSetupTool From 059be0a64abffb1407736fede7c707fce337ebf3 Mon Sep 17 00:00:00 2001 From: dmcoles Date: Tue, 2 Jan 2024 07:09:49 +0000 Subject: [PATCH 43/47] updates to installer script --- deployment/Install Ami-Express | 147 +++++++++++++++++---------------- 1 file changed, 77 insertions(+), 70 deletions(-) diff --git a/deployment/Install Ami-Express b/deployment/Install Ami-Express index 5c97b54..0b9fe6d 100644 --- a/deployment/Install Ami-Express +++ b/deployment/Install Ami-Express @@ -249,25 +249,66 @@ ; (set install-dest bbs:) -(run (cat "version full >env:tmpver " #acpname)) -(set #acpver (getenv "tmpver") ) -(if (= (substr #acpver 0 4) "ACP ") - (set #acpver (substr #acpver 4 (- (strlen #acpver) 4))) +(if (exists "env:axsetupeditor_prefs" (noreq)) + (set #axprefs (getenv "axsetupeditor_prefs") ) + (set #axprefs "") +) + +(set #acppath "") +(if (<> #axprefs "") + ( + (set #axprefs (substr #axprefs 2 (- (strlen #axprefs) 5))) + + ( if (exists (tackon #axprefs "acp") (noreq)) + (set #acppath #axprefs) + ) + ) +) +(if (= #acppath "") + (if (exists "sys:wbstartup/ACP" (noreq)) + (set #acppath "sys:wbstartup") + ) +) +(if (= #acppath "") + (if (exists "bbs:ACP" (noreq)) + (set #acppath "bbs:") + ) +) + +(if (= #acppath "") + (set #acppath + (askdir + (prompt "Please select the location of your ACP file") + (help #destdir-help) + (default @default-dest) ) ) +) + + +( complete 10) + +(set #acpname (tackon #acppath "acp")) + +(if (= #acpname "") + (set #acpver "Unknown\n") + ( + (run (cat "echo >ram:out " #acpname)) + (run (cat "version full >env:tmpver \"" #acpname "\"")) + (set #acpver (getenv "tmpver") ) + (if (= (substr #acpver 0 4) "ACP ") + (set #acpver (substr #acpver 4 (- (strlen #acpver) 4))) + ) + ) ) (run (cat "version full >env:tmpver bbs:express")) (set #expressver (getenv "tmpver") ) -(if (= (substr #expressver 0 13) "Ami-Express ") - (set #expressver (substr #expressver 13 (- (strlen #expressver) 13))) +(if (= (substr #expressver 0 11) "AmiExpress ") + (set #expressver (substr #expressver 11 (- (strlen #expressver) 11))) ) (message ("An existing installation of Ami-Express was found.\n\nThe currently installed version information is \n\nACP: %sExpress: %s\nPress proceed if you wish to continue upgrading Ami-Express.\n\nThe configuration of your bbs will not be affected and only the updated\napplication files will be overwritten.\n" #acpver #expressver) ) -( complete 10) -; - -; ( complete 20) (copyfiles @@ -281,78 +322,29 @@ ( complete 40) -(set #acpdone 0) - -(set #axprefs (getenv "axsetupeditor_prefs") ) -(if (<> #axprefs "") - ( - (set #axprefs (substr #axprefs 2 (- (strlen #axprefs) 5))) - - ( if (exists (tackon #axprefs "acp") (noreq)) - ( - (copyfiles - (source "AmiExpress/AmiExpress") - (dest #axprefs) - (choices "ACP") - (prompt "Upgrading ACP") - (help @copyfiles-help) - (confirm "expert") - ) - (set #acpdone 1) - ) - ) - ) -) -( if (and (exists "sys:wbstartup/ACP" (noreq)) - (<> #axprefs "sys:wbstartup/") ) - ( +( if (exists (tackon #acppath "ACP" (noreq))) (copyfiles (source "AmiExpress/AmiExpress") - (dest "sys:wbstartup") + (dest #acppath) (prompt "Upgrading ACP") (help @copyfiles-help) (choices "ACP") (confirm "expert") ) - (set #acpdone 1) - ) ) -( if (and (exists "bbs:acp" (noreq)) - (<> #axprefs "bbs:") ) - ( - (copyfiles - (source "AmiExpress/AmiExpress") - (dest "bbs:") - (prompt "Upgrading ACP") - (help @copyfiles-help) - (choices "ACP") - (confirm "expert") - ) - (set #acpdone 1) - ) -) +( complete 50) -( if ( = #acpdone 0) +(if (= (exists "env:axsetupeditor_prefs" (noreq)) 0) ( - (set #acppath - (askdir - (prompt "Please select the location of your ACP file") - (help #destdir-help) - (default @default-dest) ) ) + (run (cat "setenv axsetupeditor_prefs 11" (tackon #acppath "acp")) + (prompt "Saving configuration") + (help ) + ) - ( if (exists (tackon #acppath "acp" ) (noreq)) - ( - (copyfiles - (source "AmiExpress/AmiExpress") - (dest #acppath) - (prompt "Upgrading ACP") - (help @copyfiles-help) - (choices "ACP") - (confirm "expert") - ) - ( set #acpdone 1 ) - ) + (run (cat "copy env:axsetupeditor_prefs envarc:") + (prompt "Saving configuration") + (help ) ) ) ) @@ -382,6 +374,21 @@ (default 0) )) ) + (if (= (exists "bbs:bbsconfig.info" (noreq)) 0) + ( + (copyfiles + (prompt "Creating bbsconfig.info") + (help @copyfiles-help) + (source "AmiExpress/defaultbbs/bbsconfig.info") + (dest "BBS:") + ) + + (tooltype (dest "bbs:bbsconfig") (settooltype "HISTORY")) + (tooltype (dest "bbs:bbsconfig") (settooltype "CONVERT_TO_MB")) + ) + + ) + ( if ( = #securitychoice 0) (tooltype (dest "bbs:bbsconfig") (settooltype "PASSWORD_SECURITY" "PKBDF2_100")) From c821890f0c36c4b37c04c409af2a239a657110b9 Mon Sep 17 00:00:00 2001 From: dmcoles Date: Tue, 2 Jan 2024 07:50:04 +0000 Subject: [PATCH 44/47] update version of lha in default bbs install, include installer binary update file_id and readme dates --- deployment/File_Id.Diz | 2 +- deployment/binaries.lha | Bin 639493 -> 709735 bytes deployment/read_me.txt | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/File_Id.Diz b/deployment/File_Id.Diz index d51e547..662dd14 100644 --- a/deployment/File_Id.Diz +++ b/deployment/File_Id.Diz @@ -3,7 +3,7 @@ ::../ /::..' ::..' ::.. ::... ::... ::./ | \: :: `: ::... ...:: ...:: .--\____|\____\-----------------------. -| /X v5.6.0 Released on 31-Dec-2023 | +| /X v5.6.0 Released on 02-Jan-2024 | | Written By Darren Coles | | This update introduces a full MUI based | | setup editor and a standard installer | diff --git a/deployment/binaries.lha b/deployment/binaries.lha index 282d9e7261c097c23c7a6119f3d9bf5e647c2a3f..a8999c28c0d4b6ca22d5784e01343f09a26b66b1 100644 GIT binary patch delta 105254 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𗊘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 CXWFL# diff --git a/deployment/read_me.txt b/deployment/read_me.txt index a6c483f..692ee07 100644 --- a/deployment/read_me.txt +++ b/deployment/read_me.txt @@ -53,7 +53,7 @@ | | | Version History | | | -| 5.6.0 31 Dec 2023 | +| 5.6.0 02 Jan 2024 | | * Improved password encryption, Full Setup Editor, Installer | | 5.5.0 05 Jun 2022 (Feature parity release) | | * XMODEM and Hydra support, FTP Direct Server, IEMSI auto login | From d787e0efdd7251e11d159a182dde197a73ac2a8f Mon Sep 17 00:00:00 2001 From: dmcoles Date: Tue, 2 Jan 2024 10:47:56 +0000 Subject: [PATCH 45/47] installer: exclude qwk.cfg when upgrading --- deployment/Install Ami-Express | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/Install Ami-Express b/deployment/Install Ami-Express index 0b9fe6d..e94a154 100644 --- a/deployment/Install Ami-Express +++ b/deployment/Install Ami-Express @@ -357,7 +357,7 @@ (confirm "expert") (source "AmiExpress/AmiExpress/Utils") (dest "BBS:Utils") - (pattern "~(rexxdoor)") + (pattern "~(rexxdoor|qwk.cfg)") ) ( complete 80) From 7396361eede6f907bb75dcacfc2203a701d03705 Mon Sep 17 00:00:00 2001 From: dmcoles Date: Tue, 2 Jan 2024 15:19:12 +0000 Subject: [PATCH 46/47] add license info to README.md update readme.txt add aminet header file copy installer into dist archive update lha version in dist archive update acp.info icon --- README.md | 30 +++++++++++++++++++++++ deployment/binaries.lha | Bin 709735 -> 708828 bytes deployment/read_me.hdr | 10 ++++++++ deployment/read_me.txt | 52 ++++++++++++++++++++++++++++++---------- makefile | 7 ++++-- 5 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 deployment/read_me.hdr diff --git a/README.md b/README.md index 43f9405..a20da12 100644 --- a/README.md +++ b/README.md @@ -31,3 +31,33 @@ I have also updated the documentation for AmiExpress as many existing features w ### Want to help out? I am currently the sole developer on this project. If you are experienced with running /X on the Amiga platform and wish to help out, please feel free to contact me. I am always looking for ideas on how to improve this product. + +### License + +Copyright (c)2024 Darren Coles + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Installer and Installer project icon +(c) Copyright 1995-96 Escom AG. All Rights Reserved. +Reproduced and distributed under license from Escom AG. + +INSTALLER SOFTWARE IS PROVIDED "AS-IS" AND SUBJECT TO CHANGE; +NO WARRANTIES ARE MADE. ALL USE IS AT YOUR OWN RISK. NO LIABILITY +OR RESPONSIBILITY IS ASSUMED. \ No newline at end of file diff --git a/deployment/binaries.lha b/deployment/binaries.lha index a8999c28c0d4b6ca22d5784e01343f09a26b66b1..ce965f6edaba31002f492f1c1cee9382aa6f49dc 100644 GIT binary patch delta 971 zcmaF9Li^4_?Rv#P-JA?l-KmTW435kU48CDX5e$qRiOB_enR#jXdCHD_3`~x>nXVND zMXANb|5+Ir41^dM82yu~FK$hSw zcHmHfj=xIR8iGYa-&jk}8W{9ly+w!e%Y_YNFIzlgfp1 zH`^SNW7Ly*>o>}F^xUrBKQV5O{UckqM7dK+HhLMEf^Rl+eBHD2x4c!1jG$ZCYr%EZ z+kd`_-d-DDucqUkdrocp%=E$uam$!3Zr(SH61nda8*+4&bLhG|`gV_FYOe3!vt6qw z_SvrWr0Em?RB5Z=!f7}2zJ84|QC#Mk3GMPaR00Kd6 zX+?N&a%FRK{{;X5nBM>Z0aId|)wJe6)s(JKWgUZHQK&rVirvAD?g+`|UktwYi#kt_JbR|q9e;~%cXe>64EJDc1)%x^ zg7qt9s*t1A9S+&XQB4+&Y`b`+o)4F+&-G|NVW1UxwlryxDCI{j`&#IZtj zCJP?J`e@`4WrzhgeuGVje}-r&8CpNUa%sAo4SA;0a*@j5W(R+(@L-O1!u!_09OE!M zvK2B0&$x|n&n9EW<@Nz;cPPSy+< z+yD8IV^h!Zlj~;A{g9@nBtG(tgOF3~$hz!{2~iEllW5PAlcS&W_~qKghocK8X&n$2 zGH^F39r)0h^_V&Fw^68@hDF0F`8Sx_a3JVa=ZvPQpIkxB#A3k3_|CWYA}sSOZeQUN4-A*BAOIm~Eo^8tEv5kg z06_x)0BU;S00039VPkMEX>Mk3LZ6e71R#HYH~;_vO=4rVH0D07p>D{%M_|x0TV*0E zSP8!ap1*qhdjI@)eJNp4qd|nwwZWiJ)>g4JO(R9na3uCK6@tXEDm8!a|GVgv9RY`d zhRL-@V%we9L?#0L{S9!gA0V7BGJo^)P$l%o1EN91DK&#XtM}82NIqVpC(`h`K{tO> zvTI~w9H`~K>Q*&oQk9@^gP6cFg+D?2Fmed4!~wT{V%re^j$ADqQ?71=5$vKP!sUjsq2mmC-hX`u z_gjB{J7;#mNzZo&JxiA`Gyn49#+QFy;U?``yLCaeFd^qsWE_H<%Zu||SIURtb{gh* zoOkbidATZb-M@8ns2vrH88;b}j?`#|O=Zj28K~2SBO)Uv(KeRe`p7yHWz!{!XOMGn z7`2wa2^QAG1>i|*K2lZB87PKGyDN>WV~PZfs}|uzOve09TQ=Q!egh!MA3QB=Xf-YWAOHZwJ^%oZrD_}i0SHn>SXe|)Pf{8Smw*ca7y_vq xvvum}AcHyThdJs2hdJs3hdJs4hdJs5hdJs6hdJs7hdJs8hdJs9w>jzwqvqup#~}a! diff --git a/deployment/read_me.hdr b/deployment/read_me.hdr new file mode 100644 index 0000000..76d23ec --- /dev/null +++ b/deployment/read_me.hdr @@ -0,0 +1,10 @@ +Short: AmiExpress BBS system redeveloped in E +Author: darren_m_coles@yahoo.co.uk (Darren Coles) +Uploader: darren_m_coles@yahoo.co.uk (Darren Coles) +Type: comm/amiex +Version: 5.6.0 +Replaces: comm/amiex/Amix550.lha +Architecture: m68k-amigaos >= 2.0.4 +Distribution: Aminet +Kurz: AmiExpress BBS entwickelt in E + diff --git a/deployment/read_me.txt b/deployment/read_me.txt index 692ee07..1b17f82 100644 --- a/deployment/read_me.txt +++ b/deployment/read_me.txt @@ -21,32 +21,58 @@ | I have also updated the documentation for Ami-Express as many existing | | features were not properly documented. Some new features included in this | | release are: | -| * Full MUI Based Configuration / Setup Edit | +| * Full MUI Based Configuration / Setup Editor | | * Installer Script that allows upgrading and initial BBS setup | -| * FTP Direct Server - you can now log onto FTP directly and upload or | +| * Improved password encryption. | | | | All source code is publicly available at: | | https://github.com/dmcoles/AmiExpress along with the documentation. | | | -| Included in this archive are several sample bbs configurations using | -| tooltype (.info) and config file (.cfg) format. These are aimed at users | -| wanting to set up a bbs for the first time. There is also a file called | -| aeicon.json which can be imported using the json import tool or by | -| selecting the file the first time you start /X with no configuration in | -| place. This file will create a basic structure similar to the ones | -| included in the archive. | +| The sample bbs configurations included in previous versions of this tool | +| are no longer included. The new install process will create a default | +| minimal (but functional) BBS for you. You can then use the new setup tool | +| to fully configure the BBS and create a system tailored to your needs. | +| The default bbs also contains some useful doors that are typically used | +| on every Ami-Express bbs eg AquaScan and FileDescription. | | | | This verison of /X comes with both rexxdoor 1.3 and 2.2 - If you have 10 | -| nodes or more you *MUST* use 2.2 - the installer will prompt you to make | -| a decision on which version you prefer. | +| nodes or more you *MUST* use 2.2 - new installations will be configured | +| to use the newer version but upgrades will leave the the setup unaltered. | | | | If you are a pre-existing /X4 user, the ACP and Express files can just | | replace the old versions and should be as close to fully backwards | -| compatible as possible. Plesae do contact me or raise issues in github if | +| compatible as possible. Please do contact me or raise issues in github if | | you encounter any problems. | | | +| Copyright (c)2024 Darren Coles | +| Permission is hereby granted, free of charge, to any person obtaining a +| copy of this software and associated documentation files (the "Software"),| +| to deal in the Software without restriction, including without limitation | +| the rights to use, copy, modify, merge, publish, distribute, sublicense, | +| and/or sell copies of the Software, and to permit persons to whom the | +| Software is furnished to do so, subject to the following conditions: | +| | +| The above copyright notice and this permission notice shall be included | +| in all copies or substantial portions of the Software. | +| | +| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | +| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | +| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | +| NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | +| DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | +| OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | +| USE OR OTHER DEALINGS IN THE SOFTWARE. | +| | +| Installer and Installer project icon | +| (c) Copyright 1995-96 Escom AG. All Rights Reserved. | +| Reproduced and distributed under license from Escom AG. | +| | +| INSTALLER SOFTWARE IS PROVIDED "AS-IS" AND SUBJECT TO CHANGE; | +| NO WARRANTIES ARE MADE. ALL USE IS AT YOUR OWN RISK. NO LIABILITY | +| OR RESPONSIBILITY IS ASSUMED. | +| | |---------------------------------------------------------------------------| -| This release is dedicated to my partner Traci who was taken ill | +| This release is dedicated to my ex-partner Traci who was taken ill | | unexpectedly at the end of 2018 and passed away after suffering | | lung damage caused by Influenza. RIP Traci xx. | |---------------------------------------------------------------------------| diff --git a/makefile b/makefile index 3860ea8..746667a 100644 --- a/makefile +++ b/makefile @@ -19,7 +19,7 @@ release: options=$(releaseoptions) release: ACP express5 jsonImport icon2cfg qwk ftn axSetupTool: - make -B -C axSetupTool build=$(build) + $(MAKE) MAKEFLAGS=-B -C axSetupTool build=$(build) ACP: ACP.e acpversion.m axcommon.m jsonParser.m jsonCreate.m stringlist.m $(compiler) ACP $(options) @@ -125,6 +125,8 @@ dist: ACP express5 jsonImport icon2cfg qwk ftn axSetupTool makedir Rel/AmiExpress/AmiExpress makedir Rel/AmiExpress/AmiExpress/Utils lha x deployment/binaries.lha Rel/AmiExpress/ + Copy Rel/AmiExpress/Installer Rel/ + -delete Rel/AmiExpress/Installer Copy acp Rel/AmiExpress/AmiExpress/ Copy express5 Rel/AmiExpress/AmiExpress/express Copy jsonImport Rel/AmiExpress/AmiExpress/Utils/ @@ -140,5 +142,6 @@ dist: ACP express5 jsonImport icon2cfg qwk ftn axSetupTool Lha -r a t:Amix560.lha Rel/ Copy t:Amix560.lha Rel/ -delete t:Amix560.lha + join deployment/read_me.hdr deployment/read_me.txt TO Rel/Amix560.readme -.PHONY: expversion.e axSetupTool +.PHONY: expversion.e acpversion.e axSetupTool From 3c95eafd72230232965869e244de4e7cd7c87099 Mon Sep 17 00:00:00 2001 From: dmcoles Date: Tue, 2 Jan 2024 15:51:46 +0000 Subject: [PATCH 47/47] remove ftn.cfg from upgraded files in installer fix small typo in readme fix bug in Config Editor menu handling in acp --- ACP.e | 24 ++++++++++++------------ deployment/Install Ami-Express | 2 +- deployment/read_me.txt | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ACP.e b/ACP.e index a207dda..3821fca 100644 --- a/ACP.e +++ b/ACP.e @@ -4316,18 +4316,18 @@ PROC main() HANDLE ->quit menu item IF(menunum(im.code)=0) AND (itemnum(im.code)=6) THEN attemptShutdown() - IF(menunum(im.code)=1) AND (itemnum(im.code)=14) - IF FileLength(AX_SETUP_TOOL)>=0 THEN Execute(AX_SETUP_TOOL,0,0) - ENDIF - - IF(menunum(im.code)=1) - i:=button - button:=0 - menuSelect:=TRUE - handleEditGadget(NIL,GAD_SYSOPLOGIN+itemnum(im.code)) - handleEditGadget(NIL,GAD_NODES+subnum(im.code)) - button:=i - menuSelect:=FALSE + IF(menunum(im.code)=1) + IF (itemnum(im.code)=14) + IF FileLength(AX_SETUP_TOOL)>=0 THEN Execute(AX_SETUP_TOOL,0,0) + ELSE + i:=button + button:=0 + menuSelect:=TRUE + handleEditGadget(NIL,GAD_SYSOPLOGIN+itemnum(im.code)) + handleEditGadget(NIL,GAD_NODES+subnum(im.code)) + button:=i + menuSelect:=FALSE + ENDIF ENDIF IF(menunum(im.code)=2) num:=itemnum(im.code) diff --git a/deployment/Install Ami-Express b/deployment/Install Ami-Express index e94a154..db20546 100644 --- a/deployment/Install Ami-Express +++ b/deployment/Install Ami-Express @@ -357,7 +357,7 @@ (confirm "expert") (source "AmiExpress/AmiExpress/Utils") (dest "BBS:Utils") - (pattern "~(rexxdoor|qwk.cfg)") + (pattern "~(rexxdoor|qwk.cfg|ftn.cfg)") ) ( complete 80) diff --git a/deployment/read_me.txt b/deployment/read_me.txt index 1b17f82..5e0f246 100644 --- a/deployment/read_me.txt +++ b/deployment/read_me.txt @@ -35,7 +35,7 @@ | The default bbs also contains some useful doors that are typically used | | on every Ami-Express bbs eg AquaScan and FileDescription. | | | -| This verison of /X comes with both rexxdoor 1.3 and 2.2 - If you have 10 | +| This version of /X comes with both rexxdoor 1.3 and 2.2 - If you have 10 | | nodes or more you *MUST* use 2.2 - new installations will be configured | | to use the newer version but upgrades will leave the the setup unaltered. | | |