MODULE UserInfos; IMPORT a:= Arguments, ac:= ANSIConsole, st:= Strings, cv:= Conversions, io, s:= SYSTEM, e:= Exec, d:= Dos, ol:= OberonLib, bo:= BBSColours, bs:= BBSStructures, bc:= BBSConstants, hn:= HBBSNode, hc:= HBBSCommon, req:= Requests; CONST EOF = -1; LF = 0AH; LineLength = 80; LTRUE = 1; LFALSE = 0; NumericChars = "0123456789"; TYPE LineNodePtr = UNTRACED POINTER TO LineNode; LineNode = STRUCT prev, next: LineNodePtr; text: ARRAY LineLength OF CHAR; END; VAR BBSGlobal: bs.BBSGlobalDataPtr; NnD: bs.NodeDataPtr; NodeNum: LONGINT; argList: LineNodePtr; CountArgs: INTEGER; textPool: e.MemPoolPtr; menuName: LineNodePtr; PROCEDURE cleanup(num: LONGINT); BEGIN IF hn.HBBSNodeBase # NIL THEN hn.HBBSCleanUpDoor; e.CloseLibrary(hn.HBBSNodeBase); hn.HBBSNodeBase:= NIL; END; IF hc.HBBSCommonBase # NIL THEN hc.HBBSCleanUpCommon; e.CloseLibrary(hc.HBBSCommonBase); hc.HBBSCommonBase:= NIL; END; IF num # 0 THEN io.WriteString("Door Error = "); io.WriteInt(num, 0); io.WriteLn; (* io.Format("Door Error = %d\n", s.ADR(num)) *) END; END cleanup; PROCEDURE init(name: e.STRPTR); BEGIN IF hc.HBBSCommonBase = NIL THEN cleanup(1); RETURN END; IF NOT hc.HBBSInitCommon() THEN cleanup(2); RETURN END; IF hn.HBBSNodeBase = NIL THEN cleanup(3); RETURN END; IF NOT hn.HBBSInitDoor(SHORT(NodeNum), name) THEN cleanup(4); RETURN END; END init; PROCEDURE AddNode(VAR list: LineNodePtr; at: INTEGER): LineNodePtr; VAR last, new: LineNodePtr; dummy: LineNode; BEGIN new:= e.AllocPooled(textPool, s.SIZE(dummy)); IF list = NIL THEN IF new # NIL THEN new^.prev:= NIL; new^.next:= NIL; END; list:= new; ELSE IF at <= 1 THEN IF new # NIL THEN new^.prev:= NIL; new^.next:= list; list^.prev:= new; list:= new; END; ELSE last:= list; WHILE (last^.next # NIL) & (at > 2) DO last:= last^.next; at:= at - 1 END; IF new # NIL THEN new^.next:= last^.next; new^.prev:= last; IF last^.next # NIL THEN last^.next^.prev:= new END; last^.next:= new; END; END; END; RETURN new; END AddNode; PROCEDURE DeleteNode(VAR list: LineNodePtr; at: INTEGER); VAR this: LineNodePtr; dummy: LineNode; BEGIN IF list # NIL THEN this:= list; IF at <= 1 THEN list:= this^.next; IF list # NIL THEN list^.prev:= NIL END; ELSE WHILE (this^.next # NIL) & (at > 1) DO this:= this^.next; at:= at - 1 END; IF this^.prev # NIL THEN this^.prev^.next:= this^.next END; IF this^.next # NIL THEN this^.next^.prev:= this^.prev; END; END; e.FreePooled(textPool, this, s.SIZE(dummy)); END; END DeleteNode; PROCEDURE GetNode(list: LineNodePtr; at: INTEGER): LineNodePtr; BEGIN IF list = NIL THEN RETURN NIL END; WHILE (list # NIL) & (at > 1) DO list:= list^.next; at:= at - 1; END; RETURN list; END GetNode; PROCEDURE ReqNumber(l: LONGINT); VAR str: ARRAY 80 OF CHAR; ok: BOOLEAN; count: INTEGER; factor: LONGINT; BEGIN factor:= 1000000000; count:= 10; WHILE (ABS(l) < factor) & (count > 1) DO count:= count - 1; factor:= factor DIV 10 END; ok:= cv.IntToString(l, str, count); IF ok THEN req.BreakPoint(str) END; END ReqNumber; VAR str: ARRAY 80 OF CHAR; PROCEDURE PutNumber(l: LONGINT); VAR ok: BOOLEAN; count: INTEGER; factor: LONGINT; BEGIN factor:= 1000000000; count:= 10; WHILE (ABS(l) < factor) & (count > 1) DO count:= count - 1; factor:= factor DIV 10 END; ok:= cv.IntToString(l, str, count); IF ok THEN hn.DOORWriteText(s.ADR(str)); END; END PutNumber; VAR str1: ARRAY 2 OF CHAR; PROCEDURE PutChar(ch: CHAR); BEGIN str1[0]:= ch; str1[1]:= CHR(0); hn.DOORWriteText(s.ADR(str1)); END PutChar; PROCEDURE ReplyArgs; VAR i: INTEGER; thisArg: LineNodePtr; BEGIN i:= 1; LOOP thisArg:= GetNode(argList, i); IF thisArg # NIL THEN hn.DOORWriteText(s.ADR(thisArg^.text)) END; hn.DOORWriteText(s.ADR(" ")); IF thisArg = NIL THEN EXIT END; i:= i + 1 END; END ReplyArgs; VAR sysopOptions, readOnly: BOOLEAN; sysopFlag: LONGINT; userData: bs.UserDataPtr; dummyUser: bs.UserData; PROCEDURE GetStringAt(row, column: INTEGER; len, minlen: LONGINT; VAR str: ARRAY OF CHAR): BOOLEAN; VAR res: LONGINT; BEGIN LOOP ac.CURSORGoTo(PutChar, row, column); ac.SetStyle(PutChar, ac.stBold); ac.SetColor(PutChar, ac.cForeWhite); res:= hn.DOORGetLine(bc.GlDisplay + bc.GlNoOLM + bc.GlEdit + bc.GlNoDisturb + sysopFlag, CHR(0), len, 0, s.ADR(str)); IF (res = bc.InGotLine) THEN IF st.Length(NnD^.CurrentLine^) >= minlen THEN hc.strNcpy(s.ADR(str), NnD^.CurrentLine, SHORT(len)); RETURN TRUE; END; ELSE RETURN FALSE END; END; END GetStringAt; PROCEDURE GetNumberAt(row, column: INTEGER; len: INTEGER; VAR n: LONGINT): BOOLEAN; VAR str: ARRAY 80 OF CHAR; ok: BOOLEAN; BEGIN NnD^.CharsAllowed:= s.ADR(NumericChars); cv.IntToStringLeft(n, str); ok:= GetStringAt(row, column, len, 0, str); NnD^.CharsAllowed:= NIL; IF ok THEN IF cv.StringToInt(str, n) THEN END; END; RETURN ok; END GetNumberAt; PROCEDURE GetBoolAt(row, column: INTEGER; VAR b: LONGINT) : BOOLEAN; VAR res: LONGINT; BEGIN LOOP ac.CURSORGoTo(PutChar, row, column); ac.SetStyle(PutChar, ac.stBold); ac.SetColor(PutChar, ac.cForeWhite); res:= hn.DOORGetLine(bc.GlNoOLM + bc.GlImmediate + bc.GlNoDisturb + sysopFlag, CHR(0), 1, 0, NIL); IF (res = bc.InGotLine) OR (res = bc.InImmediate) THEN hc.CVTUCase(NnD^.CurrentLine); CASE NnD^.CurrentLine^[0] OF "Y": hn.DOORWriteText(s.ADR("Y")); ac.SetStyle(PutChar, ac.stPlain); hn.DOORWriteText(s.ADR("es")); b:= bc.LTRUE; RETURN TRUE |"N": hn.DOORWriteText(s.ADR("N")); ac.SetStyle(PutChar, ac.stPlain); hn.DOORWriteText(s.ADR("o ")); b:= bc.LFALSE; RETURN TRUE |CHR(0): RETURN TRUE ELSE END; ELSE RETURN FALSE END; END; END GetBoolAt; PROCEDURE GetPasswordAt(row, column: INTEGER; len, minlen: LONGINT; VAR str: ARRAY OF CHAR): BOOLEAN; VAR res: LONGINT; BEGIN LOOP ac.CURSORGoTo(PutChar, row, column); ac.SetStyle(PutChar, ac.stBold); ac.SetColor(PutChar, ac.cForeWhite); res:= hn.DOORGetLine(bc.GlDisplay + bc.GlNoOLM + bc.GlEdit + bc.GlNoDisturb + sysopFlag, "*", len, 0, s.ADR(str)); IF (res = bc.InGotLine) THEN IF st.Length(NnD^.CurrentLine^) >= minlen THEN hc.strNcpy(s.ADR(str), NnD^.CurrentLine, SHORT(len)); RETURN TRUE; END; ELSE RETURN FALSE END; END; END GetPasswordAt; PROCEDURE GetUserStateAt(row, column: INTEGER; VAR state: CHAR): BOOLEAN; PROCEDURE WriteState(s1, sz: ARRAY OF CHAR); BEGIN hn.DOORWriteText(s.ADR(s1)); ac.SetStyle(PutChar, ac.stPlain); hn.DOORWriteText(s.ADR(sz)); END WriteState; VAR res: LONGINT; BEGIN ac.CURSORGoTo(PutChar, row, column); ac.SetStyle(PutChar, ac.stBold); ac.SetColor(PutChar, ac.cForeWhite); LOOP res:= hn.DOORGetLine(bc.GlNoOLM + bc.GlImmediate + bc.GlNoDisturb + sysopFlag, CHR(0), 1, 0, NIL); IF (res = bc.InGotLine) OR (res = bc.InImmediate) THEN hc.CVTUCase(NnD^.CurrentLine); CASE NnD^.CurrentLine^[0] OF bc.UserNew : WriteState("N", "ew "); EXIT; | bc.UserValidated : WriteState("V", "alidated "); EXIT; | bc.UserDeleted : WriteState("D", "eleted "); EXIT; | bc.UserInactive : WriteState("I", "nactive "); EXIT; | bc.UserLoginsDenied: WriteState("L", "ocked "); EXIT; | bc.UserOverwritable: WriteState("O", "verwritable"); EXIT; | CHR(0) : RETURN TRUE (* canceled *) ELSE END; ELSE RETURN FALSE END; END; state:= NnD^.CurrentLine^[0]; RETURN TRUE; END GetUserStateAt; PROCEDURE Pad(count: LONGINT; char: ARRAY OF CHAR); BEGIN WHILE count > 0 DO hn.DOORWriteText(s.ADR(char)); DEC(count); END; END Pad; PROCEDURE GetListItemAt(row, column: INTEGER; list: e.ListPtr; listcount, offset: LONGINT; VAR index: LONGINT): BOOLEAN; VAR res: LONGINT; maxchars: LONGINT; str, spaces: ARRAY 20 OF CHAR; node: e.NodePtr; BEGIN cv.IntToStringLeft(index - offset, str); ac.SetColor(PutChar, ac.cForeWhite); maxchars:= 1; IF listcount >= 10 THEN maxchars:= 2 END; IF listcount >= 100 THEN maxchars:= 3 END; IF listcount >= 1000 THEN maxchars:= 4 END; NnD^.CharsAllowed:= s.ADR(NumericChars); LOOP ac.CURSORGoTo(PutChar, row, column); ac.SetStyle(PutChar, ac.stBold); res:= hn.DOORGetLine(bc.GlDisplay + bc.GlNoOLM + bc.GlImmediate + bc.GlNoDisturb + sysopFlag + bc.GlNoReturn, CHR(0), maxchars, 0, NIL); IF (res = bc.InGotLine) OR (res = bc.InImmediate) THEN hc.strNcpy(s.ADR(str), NnD^.CurrentLine, SHORT(maxchars)); (* IF st.Length(str) = 0 THEN cv.IntToStringLeft(index, str); hn.DOORWriteText(s.ADR(str)); END; *) IF cv.StringToInt(str, index) THEN ac.CURSORGoTo(PutChar, row, column); cv.IntToStringLeft(index, str); hn.DOORWriteText(s.ADR(str)); node:= hc.GetNode(list, SHORT(index)); IF (node # NIL) AND (index < listcount) THEN Pad(maxchars - st.Length(str) + 1 , " "); (*hn.DOORWriteText(s.ADR(" ")); *) ac.SetStyle(PutChar, ac.stPlain); spaces:= " "; (* fill chain with spaces *) st.OverWrite(spaces, node^.name^, 0); hn.DOORWriteText(s.ADR(spaces)); IF res = bc.InGotLine THEN index:= index + offset; RETURN TRUE END; END; ELSE hc.UpperCase(s.ADR(str)); IF st.Occurs(str, "N")>= 0 THEN ac.CURSORGoTo(PutChar, row, column); ac.SetStyle(PutChar, ac.stBold); hn.DOORWriteText(s.ADR("?")); ac.SetStyle(PutChar, ac.stPlain); Pad(maxchars, " "); hn.DOORWriteText(s.ADR("< none > ")); index:= 0; IF res = bc.InGotLine THEN RETURN TRUE END; END; END; ELSE RETURN FALSE END; END; END GetListItemAt; PROCEDURE Enlight (check: BOOLEAN); BEGIN IF check THEN ac.SetStyle(PutChar, ac.stBold); ac.SetColor(PutChar, ac.cForeWhite) ELSE ac.SetStyle(PutChar, ac.stPlain); ac.SetColor(PutChar, ac.cForeWhite) END; END Enlight; PROCEDURE WriteMask(str: e.STRPTR); VAR s2: ARRAY 80 OF CHAR; idx: INTEGER; BEGIN idx:= 0; WHILE str^[idx] # CHR(0) DO s2[idx]:= "*"; INC(idx) END; s2[idx]:= CHR(0); hn.DOORWriteText(s.ADR(s2)); END WriteMask; PROCEDURE WriteNumber(n: LONGINT); VAR s2: ARRAY 30 OF CHAR; BEGIN cv.IntToStringLeft(n, s2); hn.DOORWriteText(s.ADR(s2)); END WriteNumber; PROCEDURE WriteState(ch: CHAR; canModify: BOOLEAN); BEGIN Enlight(canModify); CASE ch OF bc.UserNew: hn.DOORWriteText(s.ADR("N")); Enlight(FALSE); hn.DOORWriteText(s.ADR("ew")); | bc.UserValidated: hn.DOORWriteText(s.ADR("V")); Enlight(FALSE); hn.DOORWriteText(s.ADR("alidated")); | bc.UserInactive: hn.DOORWriteText(s.ADR("I")); Enlight(FALSE); hn.DOORWriteText(s.ADR("nactive")); | bc.UserLoginsDenied: hn.DOORWriteText(s.ADR("L")); Enlight(FALSE); hn.DOORWriteText(s.ADR("ocked")); | bc.UserOverwritable: hn.DOORWriteText(s.ADR("O")); Enlight(FALSE); hn.DOORWriteText(s.ADR("verwritable")); ELSE hn.DOORWriteText(s.ADR("?")); END; END WriteState; PROCEDURE WriteListItem(list: e.ListPtr; index, offset, count: LONGINT; canModify: BOOLEAN); VAR s2: ARRAY 30 OF CHAR; node: e.NodePtr; spaces: LONGINT; BEGIN Enlight(canModify); IF count < 10 THEN spaces:= 1 ELSIF count < 100 THEN spaces:= 2 ELSIF count < 1000 THEN spaces:= 3 ELSE spaces:= 4 END; IF index < offset THEN hn.DOORWriteText(s.ADR("?")); Pad(spaces, " "); Enlight(FALSE); hn.DOORWriteText(s.ADR("< none >")); ELSE cv.IntToStringLeft(index - offset, s2); hn.DOORWriteText(s.ADR(s2)); node:= hc.GetNode(list, SHORT(index - offset)); IF node # NIL THEN Enlight(FALSE); hn.DOORWriteText(s.ADR(" ")); hn.DOORWriteText(node^.name); END; END; END WriteListItem; PROCEDURE WriteBool(b, canModify: BOOLEAN); BEGIN Enlight(canModify); IF b THEN hn.DOORWriteText(s.ADR("Y")) ELSE hn.DOORWriteText(s.ADR("N")) END; Enlight(FALSE); IF b THEN hn.DOORWriteText(s.ADR("es")) ELSE hn.DOORWriteText(s.ADR("o")) END; END WriteBool; PROCEDURE DisplayInfos(readOnly, sysopOptions: BOOLEAN); BEGIN ac.CURSORGoTo(PutChar, 3, 18); Enlight((hn.HBBSCheckAccess(bc.AcsEditRealName) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.RealName)); ac.CURSORGoTo(PutChar, 4, 18); Enlight((hn.HBBSCheckAccess(bc.AcsEditHandle) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.Handle)); ac.CURSORGoTo(PutChar, 4, 58); Enlight((hn.HBBSCheckAccess(bc.AcsEditPassword) = bc.LTRUE) AND NOT readOnly); IF sysopOptions THEN hn.DOORWriteText(s.ADR(userData^.Password[1])); ELSE WriteMask(s.ADR(userData^.Password[1])); END; ac.CURSORGoTo(PutChar, 6, 18); Enlight((hn.HBBSCheckAccess(bc.AcsEditGroup) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.Group[1])); ac.CURSORGoTo(PutChar, 7, 18); Enlight((hn.HBBSCheckAccess(bc.AcsEditCountry) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.Country[1])); ac.CURSORGoTo(PutChar, 8, 18); Enlight((hn.HBBSCheckAccess(bc.AcsEditComputer) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.ComputerType)); ac.CURSORGoTo(PutChar, 6, 58); Enlight((hn.HBBSCheckAccess(bc.AcsEditLocation) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.GeoLocation)); ac.CURSORGoTo(PutChar, 7, 58); Enlight((hn.HBBSCheckAccess(bc.AcsEditPhoneNumber) = bc.LTRUE) AND NOT readOnly); hn.DOORWriteText(s.ADR(userData^.PhoneNumber)); ac.CURSORGoTo(PutChar, 8, 58); Enlight(sysopOptions); WriteNumber(userData^.Access); ac.CURSORGoTo(PutChar, 10, 18); WriteState(userData^.Status, sysopOptions); ac.CURSORGoTo(PutChar, 11, 18); Enlight((hn.HBBSCheckAccess(bc.AcsEditLines) = bc.LTRUE) AND NOT readOnly); WriteNumber(userData^.LinesPerScreen); ac.CURSORGoTo(PutChar, 12, 18); WriteListItem(BBSGlobal^.LanguageName, userData^.Language, 1, BBSGlobal^.Languages, (hn.HBBSCheckAccess(bc.AcsEditScreenType) = bc.LTRUE) AND NOT readOnly); ac.CURSORGoTo(PutChar, 13, 18); Enlight(sysopOptions); WriteNumber(userData^.TimeAllowed); ac.CURSORGoTo(PutChar, 10, 58); WriteListItem(BBSGlobal^.ConfList, userData^.PreferedConf, 1, BBSGlobal^.Conferences, NOT readOnly); ac.CURSORGoTo(PutChar, 11, 58); WriteListItem(BBSGlobal^.ProtocolList, userData^.Protocol, 1, BBSGlobal^.Protocols, (hn.HBBSCheckAccess(bc.AcsEditProtocol) = bc.LTRUE) AND NOT readOnly); ac.CURSORGoTo(PutChar, 12, 58); WriteBool(userData^.Editor = bc.LTRUE, (hn.HBBSCheckAccess(bc.AcsEditEditor) = bc.LTRUE) AND NOT readOnly); ac.CURSORGoTo(PutChar, 13, 58); WriteBool(userData^.UserType = bc.UserTypeExpert, NOT readOnly); ac.CURSORGoTo(PutChar, 15, 18); Enlight(sysopOptions); WriteNumber(userData^.FilesRatio); IF userData^.FilesRatio = 0 THEN Enlight(FALSE); hn.DOORWriteText(s.ADR(" disabled")); END; ac.CURSORGoTo(PutChar, 16, 18); Enlight(sysopOptions); WriteNumber(userData^.UploadFiles); ac.CURSORGoTo(PutChar, 17, 18); Enlight(sysopOptions); WriteNumber(userData^.DownloadFiles); ac.CURSORGoTo(PutChar, 15, 58); Enlight(sysopOptions); WriteNumber(userData^.BytesRatio); IF userData^.BytesRatio = 0 THEN Enlight(FALSE); hn.DOORWriteText(s.ADR(" disabled")); END; ac.CURSORGoTo(PutChar, 16, 58); Enlight(sysopOptions); WriteNumber(userData^.UploadFiles); ac.CURSORGoTo(PutChar, 17, 58); Enlight(sysopOptions); WriteNumber(userData^.UploadBytes); ac.CURSORGoTo(PutChar, 19, 18); Enlight(sysopOptions); WriteNumber(userData^.TimeUsed); ac.CURSORGoTo(PutChar, 20, 18); Enlight(sysopOptions); WriteNumber(userData^.MessagesWritten); ac.CURSORGoTo(PutChar, 21, 18); Enlight(sysopOptions); WriteNumber(userData^.BestCPSDown); ac.CURSORGoTo(PutChar, 19, 58); Enlight(sysopOptions); WriteNumber(userData^.CallsMade); ac.CURSORGoTo(PutChar, 20, 58); Enlight(sysopOptions); WriteNumber(userData^.PagesMade); ac.CURSORGoTo(PutChar, 21, 58); Enlight(sysopOptions); WriteNumber(userData^.BestCPSUp); END DisplayInfos; PROCEDURE GetValue(option: CHAR; sysopOptions: BOOLEAN): BOOLEAN; VAR ok: BOOLEAN; expertMode: LONGINT; tmpstr: ARRAY 80 OF CHAR; BEGIN ok:= TRUE; CASE option OF "A": IF hn.HBBSCheckAccess(bc.AcsEditRealName) = bc.LTRUE THEN ok:= GetStringAt(3, 18, 21, 1, userData^.RealName); END; | "B": IF hn.HBBSCheckAccess(bc.AcsEditHandle) = bc.LTRUE THEN ok:= GetStringAt(4, 18, 21, 1, userData^.Handle); END; | "C": hc.StrFCpy(s.ADR(tmpstr), s.ADR(userData^.Password), 1); IF sysopOptions THEN (* non masked password *) ok:= GetStringAt(4, 58, bc.LenPassword, BBSGlobal^.MinPasswordLength, tmpstr); ELSIF hn.HBBSCheckAccess(bc.AcsEditPassword) = bc.LTRUE THEN (* masked password *) ok:= GetPasswordAt(4, 58, bc.LenPassword, BBSGlobal^.MinPasswordLength, tmpstr); END; hc.StrFCpy(s.ADR(userData^.Password[1]), s.ADR(tmpstr), 0); | "D": IF hn.HBBSCheckAccess(bc.AcsEditGroup) = bc.LTRUE THEN hc.StrFCpy(s.ADR(tmpstr), s.ADR(userData^.Group), 1); ok:= GetStringAt(6, 18, 21, 0, tmpstr); hc.StrFCpy(s.ADR(userData^.Group[1]), s.ADR(tmpstr), 0); END; | "E": IF hn.HBBSCheckAccess(bc.AcsEditCountry) = bc.LTRUE THEN hc.StrFCpy(s.ADR(tmpstr), s.ADR(userData^.Country), 1); ok:= GetStringAt(7, 18, bc.LenCountry, 0, tmpstr); hc.StrFCpy(s.ADR(userData^.Country[1]), s.ADR(tmpstr), 0); END; | "F": IF hn.HBBSCheckAccess(bc.AcsEditComputer) = bc.LTRUE THEN ok:= GetStringAt(8, 18, 21, 0, userData^.ComputerType); END; | "G": IF hn.HBBSCheckAccess(bc.AcsEditLocation) = bc.LTRUE THEN ok:= GetStringAt(6, 58, bc.LenGeoLocation, 0, userData^.GeoLocation); END; | "H": IF hn.HBBSCheckAccess(bc.AcsEditPhoneNumber) = bc.LTRUE THEN ok:= GetStringAt(7, 58, bc.LenPhoneNumber, 0, userData^.PhoneNumber); END; | "I": IF sysopOptions THEN ok:= GetNumberAt(8, 58, 4, userData^.Access) END; | "J": IF sysopOptions THEN ok:= GetUserStateAt(10, 18, userData^.Status) END; | "K": IF hn.HBBSCheckAccess(bc.AcsEditLines) = bc.LTRUE THEN ok:= GetNumberAt(11, 18, 4, userData^.LinesPerScreen); IF userData = s.ADR(NnD^.User.NormalData) THEN (* this is to fix a crash in FileLister *) NnD^.User.CallData.LinesPerScreen:= userData^.LinesPerScreen END; END; | "L": IF hn.HBBSCheckAccess(bc.AcsEditScreenType) = bc.LTRUE THEN ok:= GetListItemAt(12, 18, BBSGlobal^.LanguageName, BBSGlobal^.Languages, 1, userData^.Language); END; | "M": IF sysopOptions THEN ok:= GetNumberAt(13, 18, 6, userData^.TimeAllowed) END; | "N": (* always dispo *) ok:= GetListItemAt(10, 58, BBSGlobal^.ConfList, BBSGlobal^.Conferences, 1, userData^.PreferedConf); | "O": IF hn.HBBSCheckAccess(bc.AcsEditProtocol) = bc.LTRUE THEN ok:= GetListItemAt(11, 58, BBSGlobal^.ProtocolList, BBSGlobal^.Protocols, 1, userData^.Protocol); END; | "P": IF hn.HBBSCheckAccess(bc.AcsEditEditor) = bc.LTRUE THEN ok:= GetBoolAt(12, 58, userData^.Editor); END; | "Q": (* always dispo *) IF userData^.UserType = bc.UserTypeExpert THEN expertMode:= bc.LTRUE ELSE expertMode:= bc.LFALSE END; ok:= GetBoolAt(13, 58, expertMode); IF expertMode = bc.LTRUE THEN userData^.UserType:= bc.UserTypeExpert ELSE userData^.UserType:= bc.UserTypeNormal END; | "R": IF sysopOptions THEN ok:= GetNumberAt(15, 18, 1, userData^.FilesRatio); IF userData^.FilesRatio = 0 THEN ac.CURSORGoTo(PutChar, 15, 20); ac.SetStyle(PutChar, ac.stPlain); ac.SetColor(PutChar, ac.cForeWhite); hn.DOORWriteText(s.ADR("disabled")); END; END; | "S": IF sysopOptions THEN ok:= GetNumberAt(16, 18, 20, userData^.UploadFiles); END; | "T": IF sysopOptions THEN ok:= GetNumberAt(17, 18, 20, userData^.DownloadFiles); END; | "U": IF sysopOptions THEN ok:= GetNumberAt(15, 58, 1, userData^.BytesRatio); IF userData^.BytesRatio = 0 THEN ac.CURSORGoTo(PutChar, 15, 60); ac.SetStyle(PutChar, ac.stPlain); ac.SetColor(PutChar, ac.cForeWhite); hn.DOORWriteText(s.ADR("disabled")); END; END; | "V": IF sysopOptions THEN ok:= GetNumberAt(16, 58, 20, userData^.UploadBytes); END; | "W": IF sysopOptions THEN ok:= GetNumberAt(17, 58, 20, userData^.DownloadBytes); END; | "0": IF sysopOptions THEN ok:= GetNumberAt(19, 18, 4, userData^.TimeUsed); END; | "1": IF sysopOptions THEN ok:= GetNumberAt(20, 18, 20, userData^.MessagesWritten); END; | "2": IF sysopOptions THEN ok:= GetNumberAt(21, 18, 20, userData^.BestCPSDown); END; | "3": IF sysopOptions THEN ok:= GetNumberAt(19, 58, 20, userData^.CallsMade); END; | "4": IF sysopOptions THEN ok:= GetNumberAt(20, 58, 20, userData^.PagesMade); END; | "5": IF sysopOptions THEN ok:= GetNumberAt(21, 58, 20, userData^.BestCPSUp); END; | "?": IF hn.DOORDisplaySpecialScreen(s.ADR("USERINFOHELP")) = e.LTRUE THEN END; IF hn.DOORDisplaySpecialScreen(s.ADR("USERINFOS")) = e.LTRUE THEN END; DisplayInfos(readOnly, sysopOptions); ELSE END; RETURN ok; END GetValue; PROCEDURE DoorMain; VAR iStart, iEnd: LONGINT; arg: LineNodePtr; myself, userID: LONGINT; sUserID: ARRAY 10 OF CHAR; option: CHAR; res: LONGINT; so: BOOLEAN; BEGIN IF NnD^.NodeDevice.SysopNode = bc.LTRUE THEN sysopFlag:= bc.GlSysop ELSE sysopFlag:= 0 END; so:= st.Occurs(NnD^.ActiveDoor^.SystemOptions^, "SYSOP") >= 0; myself:= NnD^.User.CallData.UserID; userID:= myself; IF CountArgs > 1 THEN arg:= GetNode(argList, 2); IF arg # NIL THEN iStart:= st.Occurs(arg^.text,"USERID="); hc.StrFCpy(s.ADR(sUserID), s.ADR(arg^.text), SHORT(iStart + 7)); IF NOT cv.StringToInt(sUserID, userID) THEN END; END; END; readOnly:= (userID # myself) AND NOT so; (* allow user to view friend's account, but not to modify *) (* so:= sysopOptions; *) IF userID # myself THEN (* user is not online *) IF NOT hc.HBBSLoadUser(userID, NIL, NIL, s.VAL(bs.UserDataPtr, s.ADR(dummyUser))) THEN RETURN END; userData:= s.VAL(bs.UserDataPtr, s.ADR(dummyUser)); ELSE (* user is online, change take effect immediatly *) userData:= s.VAL(bs.UserDataPtr, s.ADR(NnD^.User.NormalData)); END; IF NOT(hn.DOORDisplaySpecialScreen(s.ADR("USERINFOS")) = bc.LTRUE) THEN RETURN END; DisplayInfos(readOnly, so); (* sysopOptions:= so; *) LOOP ac.CURSORGoTo(PutChar, 22, 2); res:= hn.DOORGetLine(bc.GlImmediate + bc.GlNoOLM + bc.GlNoDisturb + sysopFlag, CHR(0), 1, 0, NIL); IF (res = bc.InGotLine) THEN option:= NnD^.CurrentLine^[0]; IF option = CHR(0) THEN EXIT END; IF NOT readOnly THEN IF (option >="a") AND (option <="z") THEN option:= CHR(ORD(option) - 32); END; IF NOT GetValue(option, so) THEN RETURN END; END; ELSE EXIT END; END; IF NOT readOnly THEN ac.CURSORGoTo(PutChar, 22, 2); IF userID # myself THEN hn.DOORWriteText(s.ADR("Updating user...")); ELSE hn.DOORWriteText(s.ADR("Updating your data...")); END; hc.HBBSSaveUserData(userData); hn.HBBSSetAccess; hn.DOORWriteText(s.ADR("Ok")); END; END DoorMain; PROCEDURE ParseArgs; VAR i: INTEGER; newArg: LineNodePtr; s: ARRAY 80 OF CHAR; ok: BOOLEAN; BEGIN CountArgs:= a.NumArgs(); i:= 1; WHILE i <= CountArgs DO newArg:= AddNode(argList, MAX(INTEGER)); IF newArg # NIL THEN a.GetArg(i, newArg^.text); ELSE CountArgs:= i; END; i:= i + 1 END; END ParseArgs; VAR newArg: LineNodePtr; dummy: LineNode; BEGIN textPool:= e.CreatePool(LONGSET{}, s.SIZE(dummy), s.SIZE(dummy)); ParseArgs; IF CountArgs > 0 THEN newArg:= GetNode(argList, 1); IF cv.StringToInt(newArg^.text, NodeNum) THEN init(s.ADR("UserInfos Menu")); IF hc.HBBSCommonBase # NIL THEN BBSGlobal:= hc.HBBSGimmeBBS(); IF BBSGlobal # NIL THEN NnD:= hc.HBBSNodeDataPtr(SHORT(NodeNum)); IF NnD # NIL THEN DoorMain; END; END; END; cleanup(0); ELSE io.WriteString("Invalid Param for door!\n") END; ELSE io.WriteString("No Param for door!\n"); END; CLOSE cleanup(0); e.DeletePool(textPool); END UserInfos.