Statistics
| Branch: | Tag: | Revision:

root / Server / UAdminHandling.pas @ 13:c78b5eafa10e

History | View | Annotate | Download (12.4 kB)

1
(*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at
10
 * http://www.opensource.org/licenses/cddl1.php.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at
16
 * http://www.opensource.org/licenses/cddl1.php.  If applicable,
17
 * add the following below this CDDL HEADER, with the fields enclosed
18
 * by brackets "[]" replaced with your own identifying * information:
19
 *      Portions Copyright [yyyy] [name of copyright owner]
20
 *
21
 * CDDL HEADER END
22
 *
23
 *
24
 *      Portions Copyright 2008 Andreas Schneider
25
 *)
26
unit UAdminHandling;
27
28
{$mode objfpc}{$H+}
29
30
interface
31
32
uses
33
  Classes, SysUtils, math, UPacket, UPacketHandlers, UConfig, UAccount,
34
  UNetState, UEnhancedMemoryStream, UEnums, URegions;
35
36
type
37
38
  { TModifyUserResponsePacket }
39
40
  TModifyUserResponsePacket = class(TPacket)
41
    constructor Create(AStatus: TModifyUserStatus; AAccount: TAccount);
42
  end;
43
44
  { TDeleteUserResponsePacket }
45
46
  TDeleteUserResponsePacket = class(TPacket)
47
    constructor Create(AStatus: TDeleteUserStatus; AUsername: string);
48
  end;
49
50
  { TUserListPacket }
51
52
  TUserListPacket = class(TPacket)
53
    constructor Create;
54
  end;
55
56
  { TModifyRegionResponsePacket }
57
58
  TModifyRegionResponsePacket = class(TPacket)
59
    constructor Create(AStatus: TModifyRegionStatus; ARegion: TRegion);
60
  end;
61
62
  { TDeleteRegionResponsePacket }
63
64
  TDeleteRegionResponsePacket = class(TPacket)
65
    constructor Create(AStatus: TDeleteRegionStatus; ARegionName: string);
66
  end;
67
68
  { TUserRegionsPacket }
69
70
  TRegionListPacket = class(TPacket)
71
    constructor Create;
72
  end;
73
74
procedure OnAdminHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
75
procedure OnFlushPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
76
procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
77
procedure OnModifyUserPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
78
procedure OnDeleteUserPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
79
procedure OnListUsersPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
80
procedure OnModifyRegionPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
81
procedure OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
82
procedure OnListRegionsPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
83
84
85
var
86
  AdminPacketHandlers: array[0..$FF] of TPacketHandler;
87
88
implementation
89
90
uses
91
  md5, UCEDServer, UPackets, UClientHandling;
92
93
procedure AdminBroadcast(AAccessLevel: TAccessLevel; APacket: TPacket);
94
var
95
  netState: TNetState;
96
begin
97
  CEDServerInstance.TCPServer.IterReset;
98
  while CEDServerInstance.TCPServer.IterNext do
99
  begin
100
    netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData);
101
    if (netState <> nil) and (netState.Account.AccessLevel >= AAccessLevel) then
102
      CEDServerInstance.SendPacket(netState, APacket, False);
103
  end;
104
  APacket.Free;
105
end;
106
107
procedure OnAdminHandlerPacket(ABuffer: TEnhancedMemoryStream;
108
  ANetState: TNetState);
109
var
110
  packetHandler: TPacketHandler;
111
begin
112
  if not ValidateAccess(ANetState, alAdministrator) then Exit;
113
  packetHandler := AdminPacketHandlers[ABuffer.ReadByte];
114
  if packetHandler <> nil then
115
    packetHandler.Process(ABuffer, ANetState);
116
end;
117
118
procedure OnFlushPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
119
begin
120
  CEDServerInstance.Landscape.Flush;
121
  Config.Flush;
122
end;
123
124
procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
125
begin
126
  CEDServerInstance.Quit := True;
127
end;
128
129
procedure OnModifyUserPacket(ABuffer: TEnhancedMemoryStream;
130
  ANetState: TNetState);
131
var
132
  account: TAccount;
133
  username, password: string;
134
  accessLevel: TAccessLevel;
135
  netState: TNetState;
136
  regions: TStringList;
137
  i, regionCount: Integer;
138
begin
139
  username := ABuffer.ReadStringNull;
140
  password := ABuffer.ReadStringNull;
141
  accessLevel := TAccessLevel(ABuffer.ReadByte);
142
143
  regionCount := ABuffer.ReadByte;
144
145
  account := Config.Accounts.Find(username);
146
  if account <> nil then
147
  begin
148
    if password <> '' then
149
      account.PasswordHash := MD5Print(MD5String(password));
150
151
    account.Regions.Clear;
152
    for i := 0 to regionCount - 1 do
153
      account.Regions.Add(ABuffer.ReadStringNull);
154
    account.Invalidate;
155
156
    if account.AccessLevel <> accessLevel then
157
    begin
158
      account.AccessLevel := accessLevel;
159
      CEDServerInstance.TCPServer.IterReset;
160
      while CEDServerInstance.TCPServer.IterNext do
161
      begin
162
        netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData);
163
        if (netState <> nil) and (netState.Account = account) then
164
        begin
165
          CEDServerInstance.SendPacket(netState,
166
            TAccessLevelChangedPacket.Create(accessLevel));
167
        end;
168
      end;
169
    end;
170
    CEDServerInstance.SendPacket(ANetState,
171
      TModifyUserResponsePacket.Create(muModified, account));
172
  end else
173
  begin
174
    if username = '' then
175
    begin
176
      CEDServerInstance.SendPacket(ANetState,
177
        TModifyUserResponsePacket.Create(muInvalidUsername, account));
178
      Exit;
179
    end else
180
    begin
181
      regions := TStringList.Create;
182
      for i := 0 to regionCount - 1 do
183
        regions.Add(ABuffer.ReadStringNull);
184
185
      account := TAccount.Create(Config.Accounts, username,
186
        MD5Print(MD5String(password)), accessLevel, regions);
187
188
      Config.Accounts.Add(account);
189
      Config.Accounts.Invalidate;
190
      CEDServerInstance.SendPacket(ANetState,
191
        TModifyUserResponsePacket.Create(muAdded, account));
192
    end;
193
  end;
194
end;
195
196
procedure OnDeleteUserPacket(ABuffer: TEnhancedMemoryStream;
197
  ANetState: TNetState);
198
var
199
  account: TAccount;
200
  username: string;
201
  netState: TNetState;
202
begin
203
  username := ABuffer.ReadStringNull;
204
  account := Config.Accounts.Find(username);
205
  if (account <> nil) and (account <> ANetState.Account) then
206
  begin
207
    CEDServerInstance.TCPServer.IterReset;
208
    while CEDServerInstance.TCPServer.IterNext do
209
    begin
210
      netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData);
211
      if (netState <> nil) and (netState.Account = account) then
212
      begin
213
        CEDServerInstance.Disconnect(CEDServerInstance.TCPServer.Iterator);
214
        netState.Account := nil;
215
      end;
216
    end;
217
    Config.Accounts.Remove(account);
218
    Config.Invalidate;
219
    CEDServerInstance.SendPacket(ANetState,
220
      TDeleteUserResponsePacket.Create(duDeleted, username));
221
  end else
222
    CEDServerInstance.SendPacket(ANetState,
223
      TDeleteUserResponsePacket.Create(duNotFound, username));
224
end;
225
226
procedure OnListUsersPacket(ABuffer: TEnhancedMemoryStream;
227
  ANetState: TNetState);
228
begin
229
  CEDServerInstance.SendPacket(ANetState,
230
    TCompressedPacket.Create(TUserListPacket.Create));
231
end;
232
233
procedure OnModifyRegionPacket(ABuffer: TEnhancedMemoryStream;
234
  ANetState: TNetState);
235
var
236
  regionName: string;
237
  region: TRegion;
238
  status: TModifyRegionStatus;
239
  i, areaCount: Integer;
240
  x1, y1, x2, y2: Word;
241
begin
242
  regionName := ABuffer.ReadStringNull;
243
244
  region := Config.Regions.Find(regionName);
245
  if region = nil then
246
  begin
247
    region := TRegion.Create(Config.Regions, regionName);
248
    Config.Regions.Add(region);
249
    status := mrAdded;
250
  end else
251
  begin
252
    region.Areas.Clear;
253
    status := mrModified;
254
  end;
255
256
  areaCount := ABuffer.ReadByte;
257
  for i := 0 to areaCount - 1 do
258
  begin
259
    x1 := ABuffer.ReadWord;
260
    y1 := ABuffer.ReadWord;
261
    x2 := ABuffer.ReadWord;
262
    y2 := ABuffer.ReadWord;
263
    region.Areas.Add(Min(x1, x2), Min(y1, y2),
264
                     Max(x1, x2), Max(y1, y2));
265
  end;
266
267
  Config.Regions.Invalidate;
268
269
  AdminBroadcast(alAdministrator,
270
    TModifyRegionResponsePacket.Create(status, region));
271
end;
272
273
procedure OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream;
274
  ANetState: TNetState);
275
var
276
  regionName: string;
277
  regions: TRegionList;
278
  i: Integer;
279
  status: TDeleteRegionStatus;
280
begin
281
  regionName := ABuffer.ReadStringNull;
282
  i := 0;
283
  status := drNotFound;
284
  regions := Config.Regions;
285
  while (i < regions.Count) and (status = drNotFound) do
286
  begin
287
    if TRegion(regions[i]).Name = regionName then
288
    begin
289
      regions.Delete(i);
290
      regions.Invalidate;
291
      status := drDeleted;
292
    end else
293
      inc(i);
294
  end;
295
296
  AdminBroadcast(alAdministrator,
297
    TDeleteRegionResponsePacket.Create(status, regionName));
298
end;
299
300
procedure OnListRegionsPacket(ABuffer: TEnhancedMemoryStream;
301
  ANetState: TNetState);
302
begin
303
  CEDServerInstance.SendPacket(ANetState,
304
    TCompressedPacket.Create(TRegionListPacket.Create));
305
end;
306
307
{ TModifyUserResponsePacket }
308
309
constructor TModifyUserResponsePacket.Create(AStatus: TModifyUserStatus;
310
  AAccount: TAccount);
311
var
312
  i: Integer;
313
begin
314
  inherited Create($03, 0);
315
  FStream.WriteByte($05);
316
  FStream.WriteByte(Byte(AStatus));
317
  FStream.WriteStringNull(AAccount.Name);
318
  if (AStatus = muAdded) or (AStatus = muModified) then
319
  begin
320
    FStream.WriteByte(Byte(AAccount.AccessLevel));
321
    FStream.WriteByte(AAccount.Regions.Count);
322
    for i := 0 to AAccount.Regions.Count - 1 do
323
      FStream.WriteStringNull(AAccount.Regions[i]);
324
  end;
325
  {TODO : check for client side modifications!}
326
end;
327
328
{ TDeleteUserResponsePacket }
329
330
constructor TDeleteUserResponsePacket.Create(AStatus: TDeleteUserStatus; AUsername: string);
331
begin
332
  inherited Create($03, 0);
333
  FStream.WriteByte($06);
334
  FStream.WriteByte(Byte(AStatus));
335
  FStream.WriteStringNull(AUsername);
336
end;
337
338
{ TUserListPacket }
339
340
constructor TUserListPacket.Create;
341
var
342
  i, j: Integer;
343
  account: TAccount;
344
begin
345
  inherited Create($03, 0);
346
  FStream.WriteByte($07);
347
  FStream.WriteWord(Config.Accounts.Count);
348
  for i := 0 to Config.Accounts.Count - 1 do
349
  begin
350
    account := TAccount(Config.Accounts.Items[i]);
351
    FStream.WriteStringNull(account.Name);
352
    FStream.WriteByte(Byte(account.AccessLevel));
353
    FStream.WriteByte(account.Regions.Count);
354
    for j := 0 to account.Regions.Count - 1 do
355
      FStream.WriteStringNull(account.Regions[j]);
356
  end;
357
end;
358
359
{ TModifyRegionResponsePacket }
360
361
constructor TModifyRegionResponsePacket.Create(AStatus: TModifyRegionStatus;
362
  ARegion: TRegion);
363
var
364
  i, areaCount: Integer;
365
begin
366
  inherited Create($03, 0);
367
  FStream.WriteByte($08);
368
  FStream.WriteByte(Byte(AStatus));
369
  FStream.WriteStringNull(ARegion.Name);
370
  if (AStatus = mrAdded) or (AStatus = mrModified) then
371
  begin
372
    areaCount := ARegion.Areas.Count;
373
    FStream.WriteByte(areaCount);
374
    for i := 0 to areaCount - 1 do
375
      with ARegion.Areas.Rects[i] do
376
      begin
377
        FStream.WriteWord(Left);
378
        FStream.WriteWord(Top);
379
        FStream.WriteWord(Right);
380
        FStream.WriteWord(Bottom);
381
      end;
382
  end;
383
end;
384
385
{ TDeleteRegionResponsePacket }
386
387
constructor TDeleteRegionResponsePacket.Create(AStatus: TDeleteRegionStatus;
388
  ARegionName: string);
389
begin
390
  inherited Create($03, 0);
391
  FStream.WriteByte($09);
392
  FStream.WriteByte(Byte(AStatus));
393
  FStream.WriteStringNull(ARegionName);
394
end;
395
396
{ TRegionListPacket }
397
398
constructor TRegionListPacket.Create;
399
var
400
  i, j: Integer;
401
  region: TRegion;
402
begin
403
  inherited Create($03, 0);
404
  FStream.WriteByte($0A);
405
  FStream.WriteByte(Config.Regions.Count);
406
  for i := 0 to Config.Regions.Count - 1 do
407
  begin
408
    region := TRegion(Config.Regions.Items[i]);
409
    FStream.WriteStringNull(region.Name);
410
    FStream.WriteByte(region.Areas.Count);
411
    for j := 0 to region.Areas.Count - 1 do
412
      with region.Areas.Rects[j] do
413
      begin
414
        FStream.WriteWord(Left);
415
        FStream.WriteWord(Top);
416
        FStream.WriteWord(Right);
417
        FStream.WriteWord(Bottom);
418
      end;
419
  end;
420
end;
421
422
{$WARNINGS OFF}
423
var
424
  i: Integer;
425
426
initialization
427
  for i := 0 to $FF do
428
    AdminPacketHandlers[i] := nil;
429
  AdminPacketHandlers[$01] := TPacketHandler.Create(0, @OnFlushPacket);
430
  AdminPacketHandlers[$02] := TPacketHandler.Create(0, @OnQuitPacket);
431
  AdminPacketHandlers[$05] := TPacketHandler.Create(0, @OnModifyUserPacket);
432
  AdminPacketHandlers[$06] := TPacketHandler.Create(0, @OnDeleteUserPacket);
433
  AdminPacketHandlers[$07] := TPacketHandler.Create(0, @OnListUsersPacket);
434
  AdminPacketHandlers[$08] := TPacketHandler.Create(0, @OnModifyRegionPacket);
435
  AdminPacketHandlers[$09] := TPacketHandler.Create(0, @OnDeleteRegionPacket);
436
  AdminPacketHandlers[$0A] := TPacketHandler.Create(0, @OnListRegionsPacket);
437
finalization
438
  for i := 0 to $FF do
439
    if AdminPacketHandlers[i] <> nil then
440
      AdminPacketHandlers[i].Free;
441
{$WARNINGS ON}
442
443
end.
444