www.pudn.com > pino3srv-src.zip > actuser.pas
unit actuser;
interface
uses Classes, abstuser, misc;
type TActUser = class(TUser)
private
{ Private-Deklarationen }
tokens:TStringList;
Away:Boolean;
AwayReason,Invited:string;
RegUser:PRegUser;
protected
procedure CheckAway(cmd:Char;user:TActUser;room:string);
procedure Execute; override;
procedure IncommingData(st:string); override;
function LoggedIn(msg:Char):Boolean;
public
Color:string[6];
Hidden:Boolean;
Lastact:TDateTime;
Nick:string[20];
Rooms:TStringList;
procedure SendLine(cmd,stat,err:Char;msg:string);
procedure UpdateUserInfo;
procedure UserAction(action,status:Char;user:TActUser;msg:string);
function UserStatus(room:Pointer;showaway:Boolean):Char;
end;
implementation
{ Wichtig: Methoden und Eigenschaften eines Objekts in der VCL
können nur in einem Methodenaufruf mit SYNCHRONIZE
genutzt werden, z.B.
Synchronize(UpdateCaption);
und UpdateCaption könnte sein,
procedure TActUser.UpdateCaption;
begin
Form1.Caption := 'Updated in einem Thread';
end; }
{ TActUser }
uses room, SysUtils, tools, Windows, WinSock;
{$I ..\..\defines.inc}
function StrToBool(st:string;default:Boolean):Boolean;
begin
Result:=default;
if (Length(st)>0)and(st[1] in ['0'..'1']) then Result:=Boolean(Byte(st[1])-48);
end;
function ValidNickname(st:string):Boolean;
var i,l:Integer;
begin
Result:=false;
l:=Length(st);
if l in [1..20]=false then Exit;
Result:=true;
for i:=1 to l do Result:=(Result)and(st[i] in [#33..#255])and(st[i]<>#160);
end;
procedure WriteUserData(ru:PRegUser);
var i:Integer;
begin
SetFilePointer(userdb,RegUsers.IndexOfObject(TObject(ru))*soru,nil,FILE_BEGIN);
WriteFile(userdb,ru^,soru,i,nil);
FlushFileBuffers(userdb);
end;
procedure TActUser.CheckAway(cmd:Char;user:TActUser;room:string);
begin
if Away then user.SendLine(cmd,SC_USERISAWAY,EC_NOERROR,Nick+#1+AwayReason+#1+room);
end;
procedure TActUser.Execute;
var i:Integer;acc_conn:Boolean;
begin
// ActUsers.AddObject(' '+IntToStr(Socket),self);
// Writeln('User connected: Connected users ',ActUsers.Count);
tokens:=TStringList.Create;
Rooms:=TStringList.Create;
Away:=false;
AwayReason:='';
Color:='000000';
Hidden:=true;
Invited:='';
Lastact:=Now;
Nick:=' '+IntToStr(Socket);
RegUser:=nil;
EnterCriticalSection(synchronizer);
ActUsers.AddObject(Nick,self);
Log('Incoming user connection from '+inet_ntoa(IP)+' - User connections: '+IntToStr(ActUsers.Count));
acc_conn:=true;
if (maxusers>0)and(ActUsers.Count>maxusers) then
begin
SendLine(PM_DISCONN,SC_NORMAL,EC_TOOMANYUSERS,'');
acc_conn:=false;
end;
if AllowedIP(inet_ntoa(IP),UserIPs,true)=false then
begin
SendLine(PM_DISCONN,SC_NORMAL,EC_BANNED,'');
acc_conn:=false;
end;
i:=OPKicked.IndexOfObject(Pointer(IP.S_addr));
if i>-1 then
begin
if StrToFloat(OPKicked[i])>Now then
begin
SendLine(PM_DISCONN,SC_NORMAL,EC_TEMPBANNED,'');
acc_conn:=false;
end else OPKicked.Delete(i);
end;
if acc_conn then
begin
SendLine(PM_HELLO,SC_NORMAL,EC_NOERROR,'3.'+IntToStr(Build));
LeaveCriticalSection(synchronizer);
inherited Execute;
EnterCriticalSection(synchronizer);
end else Close;
ActUsers.Delete(ActUsers.IndexOf(Nick));
for i:=Rooms.Count-1 downto 0 do TRoom(Rooms.Objects[i]).RemoveUser(self);
if Hidden=false then for i:=0 to ActUsers.Count-1 do TActUser(Actusers.Objects[i]).SendLine(PM_USERLIST,SC_REMOVE,EC_NOERROR,Nick);
LeaveCriticalSection(synchronizer);
Rooms.Free;
tokens.Free;
Log('Closed user connection for '+inet_ntoa(IP)+' ('+Nick+') - User connections: '+IntToStr(ActUsers.Count));
end;
procedure TActUser.IncommingData(st:string);
var cmd,stat:Char;i{,i2}:Integer;room:TRoom;au:TActUser;ru:PRegUser;
begin
if Length(st)<2 then Exit;
cmd:=st[1];
stat:=st[2];
Delete(st,1,2);
Lastact:=Now;
case cmd of
PM_HELLO :begin
SendLine(PM_INIT,SC_INFO,EC_NOERROR,chatname+#1+welcome.Text);
if bannerupdate>0 then SendLine(PM_INIT,SC_BANNER,EC_NOERROR,IntToStr(bannerupdate)+':'+banners.Text);
st:='';
for i:=0 to RoomList.Count-1 do
begin
room:=TRoom(RoomList.Objects[i]);
if room.Hidden=false then st:=st+room.RoomInfo+#2;
end;
SendLine(PM_INIT,SC_ROOMLIST,EC_NOERROR,st);
st:='';
for i:=0 to ActUsers.Count-1 do
begin
au:=TActUser(ActUsers.Objects[i]);
if au.Hidden=false then st:=st+au.Nick+#1+au.Color+#1+au.UserStatus(nil,true)+#2;
end;
SendLine(PM_INIT,SC_USERLIST,EC_NOERROR,st);
end;
PM_NICK :begin
DivUp(st,#1,tokens,2,2);
Log(inet_ntoa(IP)+' wants to log in as '+tokens[0]);
if ValidNickname(tokens[0])=false then
begin
Log('Nickname is invalid ('+tokens[0]+')');
SendLine(PM_NICK,SC_NORMAL,EC_INVALIDNICK,'');
Exit;
end;
if ActUsers.IndexOf(tokens[0])>-1 then
begin
Log('Nickname is already in use ('+tokens[0]+')');
SendLine(PM_NICK,SC_NORMAL,EC_NICKINUSE,'');
Exit;
end;
i:=RegUsers.IndexOf(tokens[0]);
if (i=-1)and(noanos) then
begin
SendLine(PM_NICK,SC_NORMAL,EC_NOANONYMOUS,'');
Exit;
end;
if i>-1 then
begin
if tokens[1]<>IntToStr(PRegUser(RegUsers.Objects[i])^.pwd) then
begin
SendLine(PM_NICK,SC_NORMAL,EC_WRONGPWD,'');
Exit;
end;
if PRegUser(RegUsers.Objects[i])^.active=false then
begin
SendLine(PM_NICK,SC_NORMAL,EC_ACCTDISABLED,'');
Exit;
end;
RegUser:=Pointer(RegUsers.Objects[i]);
RegUser^.lastlogin:=Now;
WriteUserData(RegUser);
end else RegUser:=nil;
st:=Nick;
ActUsers[ActUsers.IndexOf(Nick)]:=tokens[0];
Nick:=tokens[0];
if RegUser<>nil then Color:=Format('%.6x',[RegUser^.color]);
for i:=0 to Rooms.Count-1 do
begin
with TRoom(Rooms.Objects[i]) do
begin
Users[Users.IndexOf(st)]:=Nick;
RoomAction(RA_NICK,SC_NORMAL,self,st+#1+UserStatus(Rooms.Objects[i],true));
end;
end;
cmd:=UserStatus(nil,true);
for i:=0 to ActUsers.Count-1 do
begin
au:=TActUser(ActUsers.Objects[i]);
if (st[1]<>' ')and(Hidden=false) then au.SendLine(PM_USERLIST,SC_REMOVE,EC_NOERROR,st);
if ((st[1]<>' ')xor(Hidden))and not((RegUser<>nil)and(RegUser^.cloak)) then au.SendLine(PM_USERLIST,SC_ADD,EC_NOERROR,Nick+#1+Color+#1+cmd);
end;
Hidden:=not (((st[1]<>' ')xor(Hidden))and not((RegUser<>nil)and(RegUser^.cloak)));
Log(inet_ntoa(IP)+' successfully logged in as '+tokens[0]);
if RegUser=nil then SendLine(PM_NICK,SC_NORMAL,EC_NOERROR,'') else SendLine(PM_NICK,SC_NORMAL,EC_NOERROR,Color);
end;
PM_CLOAK :begin
if LoggedIn(PM_CLOAK)=false then Exit;
case stat of
SC_NORMAL:Hidden:=not Hidden;
SC_SET :if Hidden=false then Hidden:=true else Exit;
SC_UNSET :if Hidden=true then Hidden:=false else Exit;
end;
if Hidden=false then
begin
st:=Nick+#1+Color+#1+UserStatus(nil,true);
for i:=0 to ActUsers.Count-1 do TActUser(ActUsers.Objects[i]).SendLine(PM_USERLIST,SC_ADD,EC_NOERROR,st);
end else for i:=0 to ActUsers.Count-1 do TActUser(ActUsers.Objects[i]).SendLine(PM_USERLIST,SC_REMOVE,EC_NOERROR,Nick);
SendLine(PM_CLOAK,BS[Hidden],EC_NOERROR,'');
end;
PM_JOIN :begin
if st='' then st:=Invited;
if (LoggedIn(PM_JOIN)=false)or(st='') then Exit;
i:=RoomList.IndexOf(st);
if i=-1 then
begin
if (maxrooms>-1)and(RoomList.Count-SystemRoomCount>=maxrooms) then
begin
SendLine(PM_JOIN,SC_NORMAL,EC_TOOMANYROOMS,'');
Exit;
end;
room:=TRoom.Create(st);
end else room:=TRoom(RoomList.Objects[i]);
room.AddUser(self,st=Invited);
if Invited=st then Invited:='';
end;
PM_LEAVE :begin
i:=Rooms.IndexOf(st);
if (LoggedIn(PM_LEAVE)=false)or(i=-1) then Exit;
TRoom(Rooms.Objects[i]).RemoveUser(self);
end;
PM_PRIVMSG :begin
if LoggedIn(PM_PRIVMSG)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=ActUsers.IndexOf(tokens[0]);
if i>-1 then
begin
au:=TActUser(ActUsers.Objects[i]);
au.CheckAway(PM_PRIVMSG,self,'');
SendLine(PM_PRIVMSG,SC_NORMAL,EC_NOERROR,tokens[0]+#1+Color+#1+tokens[1]);
au.UserAction(UA_PRIVMSG,SC_NORMAL,self,tokens[1]);
end else SendLine(PM_PRIVMSG,SC_NORMAL,EC_USERNOTFOUND,tokens[0]);
end;
PM_ROOMMSG :begin
if LoggedIn(PM_ROOMMSG)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=Rooms.IndexOf(tokens[0]);
if i=-1 then Exit;
room:=TRoom(Rooms.Objects[i]);
if room.Gagged.IndexOf(self)>-1 then
begin
SendLine(PM_ROOMMSG,SC_NORMAL,EC_GAGGED,tokens[0]);
Exit;
end;
if (stat=SC_ALERT)and(UserStatus(room,false)=US_NOOP) then
begin
SendLine(PM_ROOMMSG,SC_ALERT,EC_FORBIDDENCMD,tokens[0]);
Exit;
end;
room.RoomAction(RA_MESSAGE,stat,self,tokens[1]);
end;
PM_COLOR :begin
if (LoggedIn(PM_COLOR)=false)or(StrToIntDef('$'+st,-1)=-1)or(Length(st)<>6) then Exit;
Color:=st;
if RegUser<>nil then
begin
RegUser^.color:=StrToInt('$'+Color);
WriteUserData(RegUser);
end;
for i:=0 to Rooms.Count-1 do TRoom(Rooms.Objects[i]).RoomAction(RA_COLOR,SC_NORMAL,self,'');
UpdateUserInfo;
end;
PM_INVITE :begin
if LoggedIn(PM_INVITE)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=ActUsers.IndexOf(tokens[1]); // Ist eingeladener Benutzer vorhanden?
if i>-1 then
begin // falls ja...
au:=TActUser(ActUsers.Objects[i]); // speicher Benutzerobjekt in "au"
i:=Rooms.IndexOf(tokens[0]); // Ist Einlader im Zielraum?
if (i=-1)or(au.Rooms.IndexOf(tokens[0])>-1) then Exit; // falls nein oder Benutzer schon im Raum, abbrechen
if UserStatus(Rooms.Objects[i],false)=US_NOOP then // falls Einladender kein RoomOP, ChatOP oder RoomOwner ist
begin
SendLine(PM_INVITE,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]); // schicke Fehlermeldung
Exit; // und breche ab
end;
au.Invited:=tokens[0]; // speichere Zielraum in "Invited" des Eingeladenen ab
au.CheckAway(PM_INVITE,self,tokens[0]);
SendLine(PM_INVITE,SC_NORMAL,EC_NOERROR,tokens[0]+#1+tokens[1]); // informiere Einladenden
au.UserAction(UA_INVITE,SC_NORMAL,self,tokens[0]);
end else SendLine(PM_INVITE,SC_NORMAL,EC_USERNOTFOUND,tokens[0]+#1+tokens[1]); // falls nein schicke Fehlermeldung an Einladenden
end;
PM_KICK :begin
if LoggedIn(PM_KICK)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=Rooms.IndexOf(tokens[0]);
if i=-1 then Exit;
room:=TRoom(Rooms.Objects[i]);
i:=room.Users.IndexOf(tokens[1]);
if i=-1 then
begin
SendLine(PM_KICK,SC_NORMAL,EC_USERNOTFOUND,tokens[0]+#1+tokens[1]);
Exit;
end;
au:=TActUser(room.Users.Objects[i]);
if (UserStatus(room,false)>US_NOOP)and(room.Owner<>au) then
begin
room.RoomAction(RA_KICK,SC_NORMAL,self,tokens[1]);
room.RemoveUser(au);
au.UserAction(UA_KICK,SC_NORMAL,self,tokens[0]);
end else SendLine(PM_KICK,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
end;
PM_AWAY :begin
if (LoggedIn(PM_AWAY)=false)or(stat=SC_UNSET)and(Away=false) then Exit;
Away:=stat<>SC_UNSET;
if Away then AwayReason:=st;
for i:=0 to Rooms.Count-1 do
begin
room:=TRoom(Rooms.Objects[i]);
room.RoomAction(RA_AWAY,BS[Away],self,AwayReason+#1+UserStatus(room,true));
end;
UpdateUserInfo;
if Away=false then AwayReason:='';
end;
PM_SETRIGHTS :begin
if LoggedIn(PM_SETRIGHTS)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=Rooms.IndexOf(tokens[0]);
if i=-1 then Exit;
room:=TRoom(Rooms.Objects[i]);
i:=room.Users.IndexOf(tokens[1]);
if i=-1 then
begin
SendLine(PM_SETRIGHTS,SC_NORMAL,EC_USERNOTFOUND,tokens[0]+#1+tokens[1]);
Exit;
end;
au:=TActUser(room.Users.Objects[i]);
case stat of
US_NOOP :begin
if (UserStatus(room,false)US_ROOMOP) then
begin
SendLine(PM_SETRIGHTS,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
Exit;
end;
if room.ROPS.Remove(au)=-1 then Exit;
stat:=SC_LOST_ROP;
end;
US_ROOMOP :begin
if UserStatus(room,false)=US_NOOP then
begin
SendLine(PM_SETRIGHTS,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
Exit;
end;
if room.ROPS.IndexOf(au)=-1 then room.ROPS.Add(au);
stat:=SC_GOT_ROP;
end;
US_ROOMOWNER:begin
if room.Owner<>self then
begin
SendLine(PM_SETRIGHTS,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
Exit;
end;
room.Owner:=au;
if room.ROPS.IndexOf(au)=-1 then room.ROPS.Add(au);
room.RoomAction(RA_RIGHTS,SC_LOST_ROW,nil,Nick+#1+UserStatus(room,true));
stat:=SC_GOT_ROW;
end;
end;
room.RoomAction(RA_RIGHTS,stat,self,au.Nick+#1+au.UserStatus(room,true));
end;
PM_BOOT :begin
if LoggedIn(PM_BOOT)=false then Exit;
if (RegUser=nil)or(RegUser^.chatop=false) then
begin
SendLine(PM_BOOT,SC_NORMAL,EC_FORBIDDENCMD,'');
Exit;
end;
DivUp(st,#1,tokens,1,2);
i:=ActUsers.IndexOf(tokens[0]);
if i=-1 then
begin
SendLine(PM_BOOT,SC_NORMAL,EC_USERNOTFOUND,tokens[0]);
Exit;
end;
au:=TActUser(ActUsers.Objects[i]);
if tokens.Count=2 then OPKicked.AddObject(FloatToStr(Now+StrToIntDef(tokens[1],0)*0.0006944444),Pointer(au.IP.S_addr));
for i:=0 to au.Rooms.Count-1 do
begin
room:=TRoom(au.Rooms.Objects[i]);
room.RoomAction(RA_BOOT,SC_NORMAL,self,au.Nick);
end;
au.SendLine(PM_DISCONN,SC_NORMAL,EC_BOOTED,Nick);
SendLine(PM_BOOT,SC_NORMAL,EC_NOERROR,au.Nick);
au.Close;
end;
PM_BAN :begin
if LoggedIn(PM_BAN)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=ActUsers.IndexOf(tokens[1]);
if i>-1 then
begin
au:=TActUser(ActUsers.Objects[i]);
i:=Rooms.IndexOf(tokens[0]);
if i=-1 then Exit;
room:=TRoom(Rooms.Objects[i]);
if UserStatus(room,false)=US_NOOP then
begin
SendLine(PM_BAN,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
Exit;
end;
case stat of
SC_NORMAL:if room.BannedIPs.Remove(Pointer(au.IP.S_addr))=-1 then room.BannedIPs.Add(Pointer(au.IP.S_addr));
SC_SET :if room.BannedIPs.IndexOf(Pointer(au.IP.S_addr))=-1 then room.BannedIPs.Add(Pointer(au.IP.S_addr)) else Exit;
SC_UNSET :if room.BannedIPs.Remove(Pointer(au.IP.S_addr))=-1 then Exit;
end;
room.RoomAction(RA_BAN,BS[room.BannedIPs.IndexOf(Pointer(au.IP.S_addr))>-1],self,au.Nick);
end else SendLine(PM_BAN,SC_NORMAL,EC_USERNOTFOUND,tokens[0]+#1+tokens[1]);
end;
PM_GAG :begin
if LoggedIn(PM_GAG)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=Rooms.IndexOf(tokens[0]);
if i=-1 then Exit;
room:=TRoom(Rooms.Objects[i]);
i:=room.Users.IndexOf(tokens[1]);
if i=-1 then
begin
SendLine(PM_GAG,SC_NORMAL,EC_USERNOTFOUND,tokens[0]+#1+tokens[1]);
Exit;
end;
au:=TActUser(room.Users.Objects[i]);
if (UserStatus(room,false)>US_NOOP)and(room.Owner<>au)and(au<>self)or(room.Owner=self) then
begin
case stat of
SC_NORMAL:if room.Gagged.Remove(au)=-1 then room.Gagged.Add(au);
SC_SET :if room.Gagged.IndexOf(au)=-1 then room.Gagged.Add(au) else Exit;
SC_UNSET :if room.Gagged.Remove(au)=-1 then Exit;
end;
room.RoomAction(RA_GAG,BS[room.Gagged.IndexOf(au)>-1],self,au.Nick);
end else SendLine(PM_GAG,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
end;
PM_PROFILE :begin
DivUp(st,#1,tokens,6,6);
case stat of
SC_REGISTER:begin
if ValidNickname(tokens[0])=false then
begin
SendLine(PM_PROFILE,SC_REGISTER,EC_INVALIDNICK,'');
Exit;
end;
i:=RegUsers.IndexOf(tokens[0]);
if i>-1 then
begin
SendLine(PM_PROFILE,SC_REGISTER,EC_NICKREGED,'');
Exit;
end;
i:=ActUsers.IndexOf(tokens[0]);
if (i>-1)and(ActUsers.Objects[i]<>self) then
begin
SendLine(PM_PROFILE,SC_REGISTER,EC_NICKINUSE,'');
Exit;
end;
if (regpass<>0)and(tokens[1]<>IntToStr(regpass)) then
begin
SendLine(PM_PROFILE,SC_REGISTER,EC_WRONGPWD,'');
Exit;
end;
New(ru);
ru^.nick:=tokens[0];
ru^.pwd:=StrToIntDef(tokens[1],0);
ru^.email:=tokens[2];
ru^.hp:=tokens[3];
ru^.note:=tokens[4];
if Nick=ru^.nick then ru^.color:=StrToInt('$'+Color) else ru^.Color:=$000000;
ru^.cloak:=StrToBool(tokens[5],false);
ru^.reged:=Now;
if Nick=ru^.nick then ru^.lastlogin:=Now else ru^.lastlogin:=0;
ru^.active:=true;
ru^.chatop:=false;
i:=RegUsers.IndexOf('');
if i>-1 then
begin
RegUsers[i]:=ru^.nick;
RegUsers.Objects[i]:=Pointer(ru);
end else RegUsers.AddObject(ru^.nick,Pointer(ru));
WriteUserData(ru);
if Nick=ru^.nick then RegUser:=ru;
SendLine(PM_PROFILE,SC_REGISTER,EC_NOERROR,'');
end;
SC_GET :begin
if (LoggedIn(PM_PROFILE)=false)or(RegUser=nil) then Exit;
if tokens[0]<>IntToStr(RegUser^.pwd) then
begin
SendLine(PM_PROFILE,SC_GET,EC_WRONGPWD,'');
Exit;
end;
SendLine(PM_PROFILE,SC_GET,EC_NOERROR,RegUser^.email+#1+RegUser^.hp+#1+RegUser^.note+#1+BS[RegUser^.cloak]);
end;
SC_EDIT :begin
if (LoggedIn(PM_PROFILE)=false)or(RegUser=nil) then Exit;
if tokens[0]<>IntToStr(RegUser^.pwd) then
begin
SendLine(PM_PROFILE,SC_EDIT,EC_WRONGPWD,'');
Exit;
end;
RegUser^.pwd:=StrToIntDef(tokens[1],0);
RegUser^.email:=tokens[2];
RegUser^.hp:=tokens[3];
RegUser^.note:=tokens[4];
RegUser^.cloak:=StrToBool(tokens[5],false);
WriteUserData(RegUser);
SendLine(PM_PROFILE,SC_EDIT,EC_NOERROR,'');
end;
SC_DELETE :begin
if (LoggedIn(PM_PROFILE)=false)or(RegUser=nil) then Exit;
if tokens[0]<>IntToStr(RegUser^.pwd) then
begin
SendLine(PM_PROFILE,SC_DELETE,EC_WRONGPWD,'');
Exit;
end;
stat:=Char(RegUser^.chatop);
RegUser^.nick:='';
WriteUserData(RegUser);
Dispose(RegUser);
RegUser:=nil;
i:=RegUsers.IndexOf(Nick);
RegUsers[i]:='';
if Boolean(stat) then
begin
for i:=0 to Rooms.Count-1 do
begin
room:=TRoom(Rooms.Objects[i]);
room.RoomAction(RA_RIGHTS,SC_LOST_COP,nil,Nick+#1+UserStatus(room,true));
end;
UpdateUserInfo;
end;
SendLine(PM_PROFILE,SC_DELETE,EC_NOERROR,'');
end;
end;
end;
PM_GETUSERINFO:begin
if LoggedIn(PM_GETUSERINFO)=false then Exit;
i:=ActUsers.IndexOf(st);
if i>-1 then au:=TActUser(ActUsers.Objects[i]) else au:=nil;
i:=RegUsers.IndexOf(st);
if i>-1 then ru:=PRegUser(RegUsers.Objects[i]) else ru:=nil;
if (au=nil)and(ru=nil) then
begin
SendLine(PM_GETUSERINFO,SC_NORMAL,EC_USERNOTFOUND,st);
Exit;
end;
tokens.Clear;
for i:=1 to 10 do tokens.Add('');
if au<>nil then
begin
tokens[0]:=au.Nick;
tokens[1]:=au.Color;
tokens[2]:=BS[au.Away];
tokens[3]:=au.AwayReason;
try
tokens[4]:=IntToStr(Round((Now-au.Lastact)/1.15740740740741E-5));
except
Writeln('Fatal error 915: Please contact alcomp''s support at support@alcomp.net');
Writeln('Additionally information: '+FloatToStr(au.Lastact)+':'+FloatToStr(Now));
tokens[4]:='0';
end;
if (RegUser<>nil)and(RegUser^.chatop) then tokens[5]:=inet_ntoa(au.IP);
end;
if ru<>nil then
begin
tokens[0]:=ru^.nick;
tokens[1]:=Format('%.6x',[ru^.color]);
tokens[6]:=ru^.email;
tokens[7]:=ru^.hp;
tokens[8]:=ru^.note;
tokens[9]:=BS[ru^.chatop];
end;
SendLine(PM_GETUSERINFO,SC_NORMAL,EC_NOERROR,tokens[0]+#1+tokens[1]+#1+tokens[2]+#1+tokens[3]+#1+tokens[4]+#1+tokens[5]+#1+tokens[6]+#1+tokens[7]+#1+tokens[8]+#1+tokens[9]);
end;
PM_GETROOMINFO:begin
i:=Rooms.IndexOf(st);
if (LoggedIn(PM_GETROOMINFO)=false)or(i=-1) then Exit;
room:=TRoom(Rooms.Objects[i]);
SendLine(PM_GETROOMINFO,BS[not(room.System or (UserStatus(room,false)=US_NOOP))],EC_NOERROR,room.RoomInfo);
end;
PM_SETROOMINFO:begin
if LoggedIn(PM_SETROOMINFO)=false then Exit;
DivUp(st,#1,tokens,6,6);
i:=Rooms.IndexOf(tokens[0]);
if i=-1 then Exit;
room:=TRoom(Rooms.Objects[i]);
if (room.System)or(UserStatus(room,false)=US_NOOP) then
begin
SendLine(PM_SETROOMINFO,SC_NORMAL,EC_FORBIDDENCMD,tokens[0]);
Exit;
end;
if Byte(stat) and RI_TOPIC<>0 then room.Topic:=tokens[1];
if (Byte(stat) and RI_COLOR<>0)and(StrToIntDef('$'+tokens[2],-1)>-1)and(Length(tokens[2])=6) then room.BgCol:=tokens[2];
if Byte(stat) and RI_USERS<>0 then room.MaxUsers:=StrToIntDef(tokens[3],0);
if Byte(stat) and RI_LOCKED<>0 then room.Closed:=StrToBool(tokens[4],not room.Closed);
if Byte(stat) and RI_HIDDEN<>0 then
begin
room.Hidden:=StrToBool(tokens[5],not room.Hidden);
if room.Hidden then for i:=0 to ActUsers.Count-1 do TActUser(ActUsers.Objects[i]).SendLine(PM_ROOMLIST,SC_REMOVE,EC_NOERROR,room.Name);
end;
room.RoomAction(RA_ROOMINFO,stat,self,room.RoomInfo);
room.UpdateRoomInfo;
end;
PM_DIRCON :begin
if LoggedIn(PM_DIRCON)=false then Exit;
DivUp(st,#1,tokens,2,2);
i:=ActUsers.IndexOf(tokens[0]);
if i>-1 then
begin
au:=TActUser(ActUsers.Objects[i]);
au.CheckAway(PM_DIRCON,self,'');
au.UserAction(UA_DIRCON,SC_NORMAL,self,inet_ntoa(IP)+#1+tokens[1]);
end else SendLine(PM_DIRCON,SC_NORMAL,EC_USERNOTFOUND,tokens[0]);
end;
end;
end;
function TActUser.LoggedIn(msg:Char):Boolean;
begin
Result:=Nick[1]<>' ';
if Result=false then SendLine(msg,SC_NORMAL,EC_NOTLOGGEDIN,'');
end;
procedure TActUser.SendLine(cmd,stat,err:Char;msg:string);
begin
Send(cmd+stat+err+msg);
end;
procedure TActUser.UpdateUserInfo;
var i:Integer;st:string;
begin
if Hidden then Exit;
st:=Nick+#1+Color+#1+UserStatus(nil,true);
for i:=0 to ActUsers.Count-1 do TActUser(ActUsers.Objects[i]).SendLine(PM_USERLIST,SC_ADD,EC_NOERROR,st);
end;
procedure TActUser.UserAction(action,status:Char;user:TActUser;msg:string);
begin
SendLine(PM_USERACTION,action,EC_NOERROR,status+user.Nick+#1+user.Color+#1+msg);
end;
function TActUser.UserStatus(room:Pointer;showaway:Boolean):Char;
begin
Result:=US_NOOP;
if room<>nil then
begin
if TRoom(room).ROPS.IndexOf(self)>-1 then Result:=US_ROOMOP;
if TRoom(room).Owner=self then Result:=US_ROOMOWNER;
end;
if (RegUser<>nil)and(RegUser^.chatop) then Result:=US_CHATOP;
if (Away)and(showaway) then Result:=US_AWAY;
end;
end.