]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/command/banning.qc
933eb3c83d8e85fc59ebb825136aa0e641d968cf
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / command / banning.qc
1 #include "banning.qh"
2
3 #include <common/command/_mod.qh>
4 #include <common/state.qh>
5 #include <common/stats.qh>
6 #include <common/util.qh>
7 #include <common/weapons/_all.qh>
8 #include <server/command/banning.qh>
9 #include <server/command/common.qh>
10 #include <server/ipban.qh>
11 #include <server/player.qh>
12
13 // =====================================================
14 //  Banning and kicking command code, written by Samual
15 //  Last updated: December 29th, 2011
16 // =====================================================
17
18 void BanCommand_ban(int request, int argc, string command)
19 {
20         switch (request)
21         {
22                 case CMD_REQUEST_COMMAND:
23                 {
24                         if (argc >= 2)
25                         {
26                                 string ip = argv(1);
27                                 float reason_arg, bantime;
28                                 string reason;
29
30                                 reason_arg = 2;
31
32                                 GET_BAN_ARG(bantime, autocvar_g_ban_default_bantime);
33                                 GET_BAN_REASON(reason, "No reason provided");
34
35                                 Ban_Insert(ip, bantime, reason, 1);
36                                 return;
37                         }
38                 }
39
40                 default:
41                         LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
42                 case CMD_REQUEST_USAGE:
43                 {
44                         LOG_HELP("Usage:^3 sv_cmd ban <address> [<bantime>] [<reason>]");
45                         LOG_HELP("  <address> is the IP address or range of the player to ban,");
46                         LOG_HELP("  <bantime> is the amount of time that the ban is active (default if not provided),");
47                         LOG_HELP("  and <reason> is the string to label the ban with as reason for banning.");
48                         LOG_HELP("See also: ^2banlist, kickban, unban^7");
49                         return;
50                 }
51         }
52 }
53
54 void BanCommand_banlist(int request)
55 {
56         switch (request)
57         {
58                 case CMD_REQUEST_COMMAND:
59                 {
60                         Ban_View();
61                         return;
62                 }
63
64                 default:
65                 case CMD_REQUEST_USAGE:
66                 {
67                         LOG_HELP("Usage:^3 sv_cmd banlist");
68                         LOG_HELP("  No arguments required.");
69                         LOG_HELP("See also: ^2ban, kickban, unban^7");
70                         return;
71                 }
72         }
73 }
74
75 void BanCommand_kickban(int request, int argc, string command)
76 {
77         switch (request)
78         {
79                 case CMD_REQUEST_COMMAND:
80                 {
81                         if (argc >= 2)
82                         {
83                                 entity client = GetIndexedEntity(argc, 1);
84                                 float accepted = VerifyKickableEntity(client);
85                                 float reason_arg, bantime, masksize;
86                                 string reason;
87
88                                 if (accepted > 0)
89                                 {
90                                         reason_arg = next_token;
91
92                                         GET_BAN_ARG(bantime, autocvar_g_ban_default_bantime);
93                                         GET_BAN_ARG(masksize, autocvar_g_ban_default_masksize);
94                                         GET_BAN_REASON(reason, "No reason provided");
95
96                                         Ban_KickBanClient(client, bantime, masksize, reason);
97
98                                         return;
99                                 }
100                                 else
101                                 {
102                                         LOG_INFO("kickban: ", GetClientErrorString(accepted, argv(1)), ".");
103                                 }
104                         }
105                 }
106
107                 default:
108                         LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
109                 case CMD_REQUEST_USAGE:
110                 {
111                         LOG_HELP("Usage:^3 sv_cmd kickban <client> [<bantime>] [<masksize>] [<reason>]");
112                         LOG_HELP("  <client> is the entity number or name of the player to ban,");
113                         LOG_HELP("  <bantime> is the amount of time that the ban is active (default if not provided),");
114                         LOG_HELP("  <masksize> is the range of the IP address (1-thru-4, default if not provided),");
115                         LOG_HELP("  and <reason> is the string to label the ban with as reason for banning.");
116                         LOG_HELP("See also: ^2ban, banlist, unban^7");
117                         return;
118                 }
119         }
120 }
121
122 void BanCommand_mute(int request, int argc, string command)
123 {
124         switch (request)
125         {
126                 case CMD_REQUEST_COMMAND:
127                 {
128                         if (argc >= 2)
129                         {
130                                 entity client = GetIndexedEntity(argc, 1);
131                                 float accepted = VerifyClientEntity(client, true, false);
132
133                                 if (accepted > 0)
134                                 {
135                                         string theid = "";
136                                         if(!PlayerInIPList(client, autocvar_g_muteban_list))
137                                                 theid = cons(theid, client.netaddress);
138                                         if(!PlayerInIDList(client, autocvar_g_muteban_list))
139                                                 theid = cons(theid, client.crypto_idfp);
140                                         CS(client).muted = true;
141                                         LOG_INFO(strcat("Mute-banning player ", GetCallerName(client), " (", argv(1), ")."));
142                                         cvar_set("g_muteban_list", cons(autocvar_g_muteban_list, theid));
143
144                                         return;
145                                 }
146                                 else
147                                 {
148                                         LOG_INFO("mute: ", GetClientErrorString(accepted, argv(1)), ".");
149                                 }
150                         }
151                 }
152
153                 default:
154                         LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
155                 case CMD_REQUEST_USAGE:
156                 {
157                         LOG_HELP("Usage:^3 sv_cmd mute <client>");
158                         LOG_HELP("  <client> is the entity number or name of the player to mute.");
159                         LOG_HELP("See also: ^2unmute, g_muteban_list^7");
160                         return;
161                 }
162         }
163 }
164
165 void BanCommand_playban(int request, int argc, string command)
166 {
167         switch (request)
168         {
169                 case CMD_REQUEST_COMMAND:
170                 {
171                         if (argc >= 2)
172                         {
173                                 entity client = GetIndexedEntity(argc, 1);
174                                 float accepted = VerifyClientEntity(client, true, false);
175
176                                 if (accepted > 0)
177                                 {
178                                         string theid = "";
179                                         if(!PlayerInIPList(client, autocvar_g_playban_list))
180                                                 theid = cons(theid, client.netaddress);
181                                         if(!PlayerInIDList(client, autocvar_g_playban_list))
182                                                 theid = cons(theid, client.crypto_idfp);
183
184                                         LOG_INFO(strcat("Play-banning player ", GetCallerName(client), " (", argv(1), ")."));
185                                         PutObserverInServer(client, true, true);
186                                         cvar_set("g_playban_list", cons(autocvar_g_playban_list, theid));
187
188                                         return;
189                                 }
190                                 else
191                                 {
192                                         LOG_INFO("playban: ", GetClientErrorString(accepted, argv(1)), ".");
193                                 }
194                         }
195                 }
196
197                 default:
198                         LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
199                 case CMD_REQUEST_USAGE:
200                 {
201                         LOG_HELP("Usage:^3 sv_cmd playban <client>");
202                         LOG_HELP("  <client> is the entity number or name of the player to ban being forced to spectate permanently,");
203                         LOG_HELP("See also: ^2g_playban_list, unplayban^7");
204                         return;
205                 }
206         }
207 }
208
209 void BanCommand_unban(int request, int argc)
210 {
211         switch (request)
212         {
213                 case CMD_REQUEST_COMMAND:
214                 {
215                         if (argv(1))
216                         {
217                                 float tmp_number = -1;
218                                 string tmp_string;
219
220                                 if (substring(argv(1), 0, 1) == "#")
221                                 {
222                                         tmp_string = substring(argv(1), 1, -1);
223
224                                         if (tmp_string != "") // is it all one token? like #1
225                                                 tmp_number = stof(tmp_string);
226                                         else if (argc > 2)    // no, it's two tokens? # 1
227                                                 tmp_number = stof(argv(2));
228                                         else tmp_number = -1;
229                                 }
230                                 else  // maybe it's ONLY a number?
231                                 {
232                                         tmp_number = stof(argv(1));
233
234                                         if ((tmp_number == 0) && (argv(1) != "0")) tmp_number = -1; }
235
236                                 if (tmp_number >= 0)
237                                 {
238                                         Ban_Delete(tmp_number);
239                                         return;
240                                 }
241                         }
242                 }
243
244                 default:
245                 case CMD_REQUEST_USAGE:
246                 {
247                         LOG_HELP("Usage:^3 sv_cmd unban <banid>");
248                         LOG_HELP("  Where <banid> is the ID of the ban of which to remove.");
249                         LOG_HELP("See also: ^2ban, banlist, kickban^7");
250                         return;
251                 }
252         }
253 }
254
255 void BanCommand_unmute(int request, int argc)
256 {
257         switch (request)
258         {
259                 case CMD_REQUEST_COMMAND:
260                 {
261                         if (argc >= 2)
262                         {
263                                 entity client = GetIndexedEntity(argc, 1);
264                                 float accepted = VerifyClientEntity(client, true, false);
265                                 string original_arg = argv(1);
266
267                                 if (accepted > 0)
268                                 {
269                                         string tmp_string = "";
270                                         FOREACH_WORD(autocvar_g_muteban_list, it != client.netaddress,
271                                         {
272                                                 if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
273                                                         continue;
274                                                 tmp_string = cons(tmp_string, it);
275                                         });
276
277                                         cvar_set("g_muteban_list", tmp_string);
278                                         LOG_INFO(strcat("Unmuting player ", GetCallerName(client), " (", original_arg, ")."));
279                                         CS(client).muted = false;
280
281                                         return;
282                                 }
283                                 else
284                                 {
285                                         LOG_INFO("unmute: ", GetClientErrorString(accepted, argv(1)), ".");
286                                 }
287                         }
288                 }
289
290                 default:
291                         LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
292                 case CMD_REQUEST_USAGE:
293                 {
294                         LOG_HELP("Usage:^3 sv_cmd unmute <client>");
295                         LOG_HELP("  <client> is the entity number or name of the player to unmute.");
296                         LOG_HELP("See also: ^2mute, g_muteban_list^7");
297                         return;
298                 }
299         }
300 }
301
302 void BanCommand_unplayban(int request, int argc)
303 {
304         switch (request)
305         {
306                 case CMD_REQUEST_COMMAND:
307                 {
308                         if (argv(1))
309                         {
310                                 entity client = GetIndexedEntity(argc, 1);
311                                 float accepted = VerifyClientEntity(client, true, false);
312                                 string original_arg = argv(1);
313
314                                 if (accepted > 0)
315                                 {
316                                         string tmp_string = "";
317                                         FOREACH_WORD(autocvar_g_playban_list, it != client.netaddress,
318                                         {
319                                                 if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
320                                                         continue;
321                                                 tmp_string = cons(tmp_string, it);
322                                         });
323
324                                         cvar_set("g_playban_list", tmp_string);
325                                         LOG_INFO(strcat("Releasing forced to spectate player ", GetCallerName(client), " (", original_arg, ")."));
326
327                                         return;
328                                 }
329                                 else
330                                 {
331                                         LOG_INFO("unplayban: ", GetClientErrorString(accepted, argv(1)), ".");
332                                 }
333                         }
334                 }
335
336                 default:
337                 case CMD_REQUEST_USAGE:
338                 {
339                         LOG_HELP("Usage:^3 sv_cmd unplayban <banid>");
340                         LOG_HELP("  Where <banid> is the ID of the forced to spectate ban of which to remove.");
341                         LOG_HELP("See also: ^2playban, g_playban_list^7");
342                         return;
343                 }
344         }
345 }
346
347 void BanCommand_unvoteban(int request, int argc)
348 {
349         switch (request)
350         {
351                 case CMD_REQUEST_COMMAND:
352                 {
353                         if (argv(1))
354                         {
355                                 entity client = GetIndexedEntity(argc, 1);
356                                 float accepted = VerifyClientEntity(client, true, false);
357                                 string original_arg = argv(1);
358
359                                 if (accepted > 0)
360                                 {
361                                         string tmp_string = "";
362                                         FOREACH_WORD(autocvar_g_voteban_list, it != client.netaddress,
363                                         {
364                                                 if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
365                                                         continue;
366                                                 tmp_string = cons(tmp_string, it);
367                                         });
368
369                                         cvar_set("g_voteban_list", tmp_string);
370                                         LOG_INFO(strcat("Unvote-banning player ", GetCallerName(client), " (", original_arg, ")."));
371
372                                         return;
373                                 }
374                                 else
375                                 {
376                                         LOG_INFO("unvoteban: ", GetClientErrorString(accepted, argv(1)), ".");
377                                 }
378                         }
379                 }
380
381                 default:
382                 case CMD_REQUEST_USAGE:
383                 {
384                         LOG_HELP("Usage:^3 sv_cmd unvoteban <banid>");
385                         LOG_HELP("  Where <banid> is the ID of the ban from voting of which to remove.");
386                         LOG_HELP("See also: ^2voteban, g_voteban_list^7");
387                         return;
388                 }
389         }
390 }
391
392 void BanCommand_voteban(int request, int argc, string command)
393 {
394         switch (request)
395         {
396                 case CMD_REQUEST_COMMAND:
397                 {
398                         if (argc >= 2)
399                         {
400                                 entity client = GetIndexedEntity(argc, 1);
401                                 float accepted = VerifyClientEntity(client, true, false);
402
403                                 if (accepted > 0)
404                                 {
405                                         string theid = "";
406                                         if(!PlayerInIPList(client, autocvar_g_voteban_list))
407                                                 theid = cons(theid, client.netaddress);
408                                         if(!PlayerInIDList(client, autocvar_g_voteban_list))
409                                                 theid = cons(theid, client.crypto_idfp);
410
411                                         LOG_INFO(strcat("Vote-banning player ", GetCallerName(client), " (", argv(1), ")."));
412                                         cvar_set("g_voteban_list", cons(autocvar_g_voteban_list, theid));
413
414                                         return;
415                                 }
416                                 else
417                                 {
418                                         LOG_INFO("voteban: ", GetClientErrorString(accepted, argv(1)), ".");
419                                 }
420                         }
421                 }
422
423                 default:
424                         LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
425                 case CMD_REQUEST_USAGE:
426                 {
427                         LOG_HELP("Usage:^3 sv_cmd voteban <client>");
428                         LOG_HELP("  <client> is the entity number or name of the player to ban from voting,");
429                         LOG_HELP("See also: ^2g_voteban_list, unvoteban^7");
430                         return;
431                 }
432         }
433 }
434
435 /* use this when creating a new command, making sure to place it in alphabetical order... also,
436 ** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
437 void BanCommand_(int request)
438 {
439     switch(request)
440     {
441         case CMD_REQUEST_COMMAND:
442         {
443
444             return;
445         }
446
447         default:
448         case CMD_REQUEST_USAGE:
449         {
450             LOG_HELP("Usage:^3 sv_cmd ");
451             LOG_HELP("  No arguments required.");
452             return;
453         }
454     }
455 }
456 */
457
458
459 // ==================================
460 //  Macro system for server commands
461 // ==================================
462
463 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
464 #define BAN_COMMANDS(request, arguments, command) \
465         BAN_COMMAND("ban",          BanCommand_ban(request, arguments, command),        "Ban an IP address or a range of addresses (like 1.2.3)") \
466         BAN_COMMAND("banlist",      BanCommand_banlist(request),                        "List all existing bans") \
467         BAN_COMMAND("kickban",      BanCommand_kickban(request, arguments, command),    "Disconnect a client and ban it at the same time") \
468         BAN_COMMAND("mute",         BanCommand_mute(request, arguments, command),       "Disallow a client from talking by muting them") \
469         BAN_COMMAND("playban",      BanCommand_playban(request, arguments, command),    "Force to spectate a client permanently") \
470         BAN_COMMAND("unban",        BanCommand_unban(request, arguments),               "Remove an existing ban") \
471         BAN_COMMAND("unmute",       BanCommand_unmute(request, arguments),              "Unmute a client") \
472         BAN_COMMAND("unvoteban",    BanCommand_unvoteban(request, arguments),           "Remove an existing voting ban") \
473         BAN_COMMAND("unplayban",    BanCommand_unplayban(request, arguments),           "Remove an existing forced to spectate ban") \
474         BAN_COMMAND("voteban",      BanCommand_voteban(request, arguments, command),    "Disallow a client from voting") \
475         /* nothing */
476
477 void BanCommand_macro_help()
478 {
479         #define BAN_COMMAND(name, function, description) \
480                 { if (strtolower(description) != "") { LOG_INFO("  ^2", name, "^7: ", description); } }
481
482         BAN_COMMANDS(0, 0, "");
483 #undef BAN_COMMAND
484 }
485
486 float BanCommand_macro_command(int argc, string command)
487 {
488         #define BAN_COMMAND(name, function, description) \
489                 { if (name == strtolower(argv(0))) { function; return true; } }
490
491         BAN_COMMANDS(CMD_REQUEST_COMMAND, argc, command);
492 #undef BAN_COMMAND
493
494         return false;
495 }
496
497 float BanCommand_macro_usage(int argc)
498 {
499         #define BAN_COMMAND(name, function, description) \
500                 { if (name == strtolower(argv(1))) { function; return true; } }
501
502         BAN_COMMANDS(CMD_REQUEST_USAGE, argc, "");
503 #undef BAN_COMMAND
504
505         return false;
506 }
507
508 void BanCommand_macro_write_aliases(float fh)
509 {
510         #define BAN_COMMAND(name, function, description) \
511                 { if (strtolower(description) != "") { CMD_Write_Alias("qc_cmd_sv", name, description); } }
512
513         BAN_COMMANDS(0, 0, "");
514 #undef BAN_COMMAND
515 }
516
517 float BanCommand(string command)
518 {
519         int argc = tokenize_console(command);
520
521         // Guide for working with argc arguments by example:
522         // argc:   1    - 2      - 3     - 4
523         // argv:   0    - 1      - 2     - 3
524         // cmd     vote - master - login - password
525
526         if (BanCommand_macro_command(argc, command)) // continue as usual and scan for normal commands
527                 return true;                             // handled by one of the above GenericCommand_* functions
528
529         return false;
530 }