1 /*
2  * Copyright (C) 1998  Mark Baysinger (mbaysing@ucsd.edu)
3  * Copyright (C) 1998,1999,2000,2001  Ross Combs (rocombs@cs.nmsu.edu)
4  * Copyright (C) 1999  Gediminas (gediminas_lt@mailexcite.com)
5  * Copyright (C) 1999  Rob Crittenden (rcrit@greyoak.com)
6  * Copyright (C) 2000,2001  Marco Ziech (mmz@gmx.net)
7  * Copyright (C) 2000  Dizzy
8  * Copyright (C) 2000  Onlyer (onlyer@263.net)
9  * Copyright (C) 2003,2004  Aaron
10  * Copyright (C) 2004  Donny Redmond (dredmond@linuxmail.org)
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26 #include "common/setup_before.h"
27 #include <stdio.h>
28 #ifdef HAVE_STDDEF_H
29 # include <stddef.h>
30 #else
31 # ifndef NULL
32 #  define NULL ((void *)0)
33 # endif
34 #endif
35 #ifdef STDC_HEADERS
36 # include <stdlib.h>
37 #else
38 # ifdef HAVE_MALLOC_H
39 #  include <malloc.h>
40 # endif
41 #endif
42 #include "compat/strtoul.h"
43 #ifdef HAVE_STRING_H
44 # include <string.h>
45 #else
46 # ifdef HAVE_STRINGS_H
47 #  include <strings.h>
48 # endif
49 #endif
50 #include "compat/strdup.h"
51 #include "compat/strcasecmp.h"
52 #include "compat/snprintf.h"
53 #include <ctype.h>
54 #include <errno.h>
55 #include "compat/strerror.h"
56 #ifdef TIME_WITH_SYS_TIME
57 # include <sys/time.h>
58 # include <time.h>
59 #else
60 # ifdef HAVE_SYS_TIME_H
61 #  include <sys/time.h>
62 # else
63 #  include <time.h>
64 # endif
65 #endif
66 #ifdef HAVE_SYS_TYPES
67 # include <sys/types.h>
68 #endif
69 #include "compat/strftime.h"
70 #include "message.h"
71 #include "common/tag.h"
72 #include "connection.h"
73 #include "channel.h"
74 #include "game.h"
75 #include "common/util.h"
76 #include "common/version.h"
77 #include "team.h"
78 #include "account.h"
79 #include "account_wrap.h"
80 #include "server.h"
81 #include "prefs.h"
82 #include "common/eventlog.h"
83 #include "ladder.h"
84 #include "timer.h"
85 #include "common/bnettime.h"
86 #include "common/addr.h"
87 #include "common/packet.h"
88 #include "helpfile.h"
89 #include "mail.h"
90 #include "common/bnethash.h"
91 #include "runprog.h"
92 #include "common/list.h"
93 #include "common/proginfo.h"
94 #include "alias_command.h"
95 #include "realm.h"
96 #include "ipban.h"
97 #include "command_groups.h"
98 #include "common/queue.h"
99 #include "common/bn_type.h"
100 #include "common/xalloc.h"
101 #include "command.h"
102 #include "news.h"
103 #include "common/trans.h"
104 #include "common/lstr.h"
105 // aaron
106 #include "topic.h"
107 #include "friends.h"
108 #include "clan.h"
109 #include "common/setup_after.h"
110 
111 
112 static char const * bnclass_get_str(unsigned int class);
113 static void do_whisper(t_connection * user_c, char const * dest, char const * text);
114 static void do_whois(t_connection * c, char const * dest);
115 static void user_timer_cb(t_connection * c, time_t now, t_timer_data str);
116 
117 char msgtemp[MAX_MESSAGE_LEN];
118 char msgtemp2[MAX_MESSAGE_LEN];
119 
bnclass_get_str(unsigned int class)120 static char const * bnclass_get_str(unsigned int class)
121 {
122     switch (class)
123     {
124     case PLAYERINFO_DRTL_CLASS_WARRIOR:
125 	return "warrior";
126     case PLAYERINFO_DRTL_CLASS_ROGUE:
127 	return "rogue";
128     case PLAYERINFO_DRTL_CLASS_SORCERER:
129 	return "sorcerer";
130     default:
131 	return "unknown";
132     }
133 }
134 
135 
do_whisper(t_connection * user_c,char const * dest,char const * text)136 static void do_whisper(t_connection * user_c, char const * dest, char const * text)
137 {
138     t_connection * dest_c;
139     char const *   tname;
140 
141     if (!(dest_c = connlist_find_connection_by_name(dest,conn_get_realm(user_c))))
142     {
143 	message_send_text(user_c,message_type_error,user_c,"That user is not logged on.");
144 	return;
145     }
146 
147     if (conn_get_dndstr(dest_c))
148     {
149         snprintf(msgtemp, sizeof(msgtemp), "%.64s is unavailable (%.128s)",conn_get_username(dest_c),conn_get_dndstr(dest_c));
150         message_send_text(user_c,message_type_info,user_c,msgtemp);
151         return;
152     }
153 
154     message_send_text(user_c,message_type_whisperack,dest_c,text);
155 
156     if (conn_get_awaystr(dest_c))
157     {
158         snprintf(msgtemp, sizeof(msgtemp), "%.64s is away (%.128s)",conn_get_username(dest_c),conn_get_awaystr(dest_c));
159         message_send_text(user_c,message_type_info,user_c,msgtemp);
160     }
161 
162     message_send_text(dest_c,message_type_whisper,user_c,text);
163 
164     if ((tname = conn_get_username(user_c)))
165     {
166         char username[1+USER_NAME_MAX]; /* '*' + username (including NUL) */
167 
168 	if (strlen(tname)<USER_NAME_MAX)
169 	{
170             sprintf(username,"*%s",tname);
171 	    conn_set_lastsender(dest_c,username);
172 	}
173     }
174 }
175 
176 
do_whois(t_connection * c,char const * dest)177 static void do_whois(t_connection * c, char const * dest)
178 {
179     t_connection *    dest_c;
180     char              namepart[136]; /* 64 + " (" + 64 + ")" + NUL */
181     char const *      verb;
182     t_game const *    game;
183     t_channel const * channel;
184 
185     if ((!(dest_c = connlist_find_connection_by_accountname(dest))) &&
186         (!(dest_c = connlist_find_connection_by_name(dest,conn_get_realm(c)))))
187     {
188 	t_account * dest_a;
189 	t_bnettime btlogin;
190 	time_t ulogin;
191 	struct tm * tmlogin;
192 
193 	if (!(dest_a = accountlist_find_account(dest))) {
194 	    message_send_text(c,message_type_error,c,"Unknown user.");
195 	    return;
196 	}
197 
198 	if (conn_get_class(c) == conn_class_bnet) {
199 	    btlogin = time_to_bnettime((time_t)account_get_ll_time(dest_a),0);
200 	    btlogin = bnettime_add_tzbias(btlogin, conn_get_tzbias(c));
201 	    ulogin = bnettime_to_time(btlogin);
202 	    if (!(tmlogin = gmtime(&ulogin)))
203 		strcpy(msgtemp, "User was last seen on ?");
204 	    else
205 		strftime(msgtemp, sizeof(msgtemp), "User was last seen on : %a %b %d %H:%M:%S",tmlogin);
206 	} else strcpy(msgtemp, "User is offline");
207 	message_send_text(c, message_type_info, c, msgtemp);
208 	return;
209     }
210 
211     if (c==dest_c)
212     {
213 	strcpy(namepart,"You");
214 	verb = "are";
215     }
216     else
217     {
218 	char const * tname;
219 
220 	sprintf(namepart,"%.64s",(tname = conn_get_chatcharname(dest_c,c)));
221 	conn_unget_chatcharname(dest_c,tname);
222 	verb = "is";
223     }
224 
225     if ((game = conn_get_game(dest_c)))
226     {
227 	snprintf(msgtemp, sizeof(msgtemp), "%s %s using %s and %s currently in %s game \"%.64s\".",
228 		namepart,
229 		verb,
230 		clienttag_get_title(conn_get_clienttag(dest_c)),
231 		verb,
232 		game_get_flag(game) == game_flag_private ? "private" : "",
233 		game_get_name(game));
234     }
235     else if ((channel = conn_get_channel(dest_c)))
236     {
237         snprintf(msgtemp, sizeof(msgtemp), "%s %s using %s and %s currently in channel \"%.64s\".",
238 		namepart,
239 		verb,
240 		clienttag_get_title(conn_get_clienttag(dest_c)),
241 		verb,
242 		channel_get_name(channel));
243     }
244     else
245 	snprintf(msgtemp, sizeof(msgtemp), "%s %s using %s.",
246 		namepart,
247 		verb,
248 		clienttag_get_title(conn_get_clienttag(dest_c)));
249     message_send_text(c,message_type_info,c,msgtemp);
250 
251     if (conn_get_dndstr(dest_c))
252     {
253         snprintf(msgtemp, sizeof(msgtemp), "%s %s refusing messages (%.128s)",
254 		namepart,
255 		verb,
256 		conn_get_dndstr(dest_c));
257 	message_send_text(c,message_type_info,c,msgtemp);
258     }
259     else
260         if (conn_get_awaystr(dest_c))
261         {
262             snprintf(msgtemp, sizeof(msgtemp), "%s away (%.128s)",
263 		    namepart,
264 		    conn_get_awaystr(dest_c));
265 	    message_send_text(c,message_type_info,c,msgtemp);
266         }
267 }
268 
269 
user_timer_cb(t_connection * c,time_t now,t_timer_data str)270 static void user_timer_cb(t_connection * c, time_t now, t_timer_data str)
271 {
272     if (!c)
273     {
274 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
275 	return;
276     }
277     if (!str.p)
278     {
279 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL str");
280 	return;
281     }
282 
283     if (now!=(time_t)0) /* zero means user logged out before expiration */
284 	message_send_text(c,message_type_info,c,str.p);
285     xfree(str.p);
286 }
287 
288 typedef int (* t_command)(t_connection * c, char const * text);
289 
290 typedef struct {
291 	const char * command_string;
292 	t_command    command_handler;
293 } t_command_table_row;
294 
295 static int command_set_flags(t_connection * c); // [Omega]
296 // command handler prototypes
297 static int _handle_clan_command(t_connection * c, char const * text);
298 static int _handle_admin_command(t_connection * c, char const * text);
299 static int _handle_aop_command(t_connection * c, char const * text);
300 static int _handle_op_command(t_connection * c, char const * text);
301 static int _handle_tmpop_command(t_connection * c, char const * text);
302 static int _handle_deop_command(t_connection * c, char const * text);
303 static int _handle_voice_command(t_connection * c, char const * text);
304 static int _handle_devoice_command(t_connection * c, char const * text);
305 static int _handle_vop_command(t_connection * c, char const * text);
306 static int _handle_friends_command(t_connection * c, char const * text);
307 static int _handle_me_command(t_connection * c, char const * text);
308 static int _handle_whisper_command(t_connection * c, char const * text);
309 static int _handle_status_command(t_connection * c, char const * text);
310 static int _handle_who_command(t_connection * c, char const * text);
311 static int _handle_whois_command(t_connection * c, char const * text);
312 static int _handle_whoami_command(t_connection * c, char const * text);
313 static int _handle_announce_command(t_connection * c, char const * text);
314 static int _handle_beep_command(t_connection * c, char const * text);
315 static int _handle_nobeep_command(t_connection * c, char const * text);
316 static int _handle_version_command(t_connection * c, char const * text);
317 static int _handle_copyright_command(t_connection * c, char const * text);
318 static int _handle_uptime_command(t_connection * c, char const * text);
319 static int _handle_stats_command(t_connection * c, char const * text);
320 static int _handle_time_command(t_connection * c, char const * text);
321 static int _handle_channel_command(t_connection * c, char const * text);
322 static int _handle_rejoin_command(t_connection * c, char const * text);
323 static int _handle_away_command(t_connection * c, char const * text);
324 static int _handle_dnd_command(t_connection * c, char const * text);
325 static int _handle_squelch_command(t_connection * c, char const * text);
326 static int _handle_unsquelch_command(t_connection * c, char const * text);
327 //static int _handle_designate_command(t_connection * c, char const * text); Obsolete function [Omega]
328 //static int _handle_resign_command(t_connection * c, char const * text); Obsolete function [Omega]
329 static int _handle_kick_command(t_connection * c, char const * text);
330 static int _handle_ban_command(t_connection * c, char const * text);
331 static int _handle_unban_command(t_connection * c, char const * text);
332 static int _handle_reply_command(t_connection * c, char const * text);
333 static int _handle_realmann_command(t_connection * c, char const * text);
334 static int _handle_watch_command(t_connection * c, char const * text);
335 static int _handle_unwatch_command(t_connection * c, char const * text);
336 static int _handle_watchall_command(t_connection * c, char const * text);
337 static int _handle_unwatchall_command(t_connection * c, char const * text);
338 static int _handle_lusers_command(t_connection * c, char const * text);
339 static int _handle_news_command(t_connection * c, char const * text);
340 static int _handle_games_command(t_connection * c, char const * text);
341 static int _handle_channels_command(t_connection * c, char const * text);
342 static int _handle_addacct_command(t_connection * c, char const * text);
343 static int _handle_chpass_command(t_connection * c, char const * text);
344 static int _handle_connections_command(t_connection * c, char const * text);
345 static int _handle_finger_command(t_connection * c, char const * text);
346 static int _handle_operator_command(t_connection * c, char const * text);
347 static int _handle_admins_command(t_connection * c, char const * text);
348 static int _handle_quit_command(t_connection * c, char const * text);
349 static int _handle_kill_command(t_connection * c, char const * text);
350 static int _handle_killsession_command(t_connection * c, char const * text);
351 static int _handle_gameinfo_command(t_connection * c, char const * text);
352 static int _handle_ladderactivate_command(t_connection * c, char const * text);
353 static int _handle_rehash_command(t_connection * c, char const * text);
354 //static int _handle_rank_all_accounts_command(t_connection * c, char const * text);
355 static int _handle_shutdown_command(t_connection * c, char const * text);
356 static int _handle_ladderinfo_command(t_connection * c, char const * text);
357 static int _handle_timer_command(t_connection * c, char const * text);
358 static int _handle_serverban_command(t_connection * c, char const * text);
359 static int _handle_netinfo_command(t_connection * c, char const * text);
360 static int _handle_quota_command(t_connection * c, char const * text);
361 static int _handle_lockacct_command(t_connection * c, char const * text);
362 static int _handle_unlockacct_command(t_connection * c, char const * text);
363 static int _handle_flag_command(t_connection * c, char const * text);
364 static int _handle_tag_command(t_connection * c, char const * text);
365 //static int _handle_ipban_command(t_connection * c, char const * text); Redirected to handle_ipban_command() in ipban.c [Omega]
366 static int _handle_set_command(t_connection * c, char const * text);
367 static int _handle_motd_command(t_connection * c, char const * text);
368 static int _handle_ping_command(t_connection * c, char const * text);
369 static int _handle_commandgroups_command(t_connection * c, char const * text);
370 static int _handle_topic_command(t_connection * c, char const * text);
371 static int _handle_moderate_command(t_connection * c, char const * text);
372 static int _handle_clearstats_command(t_connection * c, char const * text);
373 static int _handle_tos_command(t_connection * c, char const * text);
374 
375 static const t_command_table_row standard_command_table[] =
376 {
377 	{ "/clan"		, _handle_clan_command },
378 	{ "/c"			, _handle_clan_command },
379 	{ "/admin"		, _handle_admin_command },
380 	{ "/f"                  , _handle_friends_command },
381 	{ "/friends"            , _handle_friends_command },
382 	{ "/me"                 , _handle_me_command },
383 	{ "/msg"                , _handle_whisper_command },
384 	{ "/whisper"            , _handle_whisper_command },
385 	{ "/w"                  , _handle_whisper_command },
386 	{ "/m"                  , _handle_whisper_command },
387 	{ "/status"             , _handle_status_command },
388 	{ "/users"              , _handle_status_command },
389 	{ "/who"                , _handle_who_command },
390 	{ "/whois"              , _handle_whois_command },
391 	{ "/whereis"            , _handle_whois_command },
392 	{ "/where"              , _handle_whois_command },
393 	{ "/whoami"             , _handle_whoami_command },
394 	{ "/announce"           , _handle_announce_command },
395 	{ "/beep"               , _handle_beep_command },
396 	{ "/nobeep"             , _handle_nobeep_command },
397 	{ "/version"            , _handle_version_command },
398 	{ "/copyright"          , _handle_copyright_command },
399 	{ "/warrenty"           , _handle_copyright_command },
400 	{ "/license"            , _handle_copyright_command },
401 	{ "/uptime"             , _handle_uptime_command },
402 	{ "/stats"              , _handle_stats_command },
403 	{ "/astat"              , _handle_stats_command },
404 	{ "/time"               , _handle_time_command },
405         { "/channel"            , _handle_channel_command },
406 	{ "/join"               , _handle_channel_command },
407 	{ "/rejoin"             , _handle_rejoin_command },
408 	{ "/away"               , _handle_away_command },
409 	{ "/dnd"                , _handle_dnd_command },
410 	{ "/ignore"             , _handle_squelch_command },
411 	{ "/squelch"            , _handle_squelch_command },
412 	{ "/unignore"           , _handle_unsquelch_command },
413 	{ "/unsquelch"          , _handle_unsquelch_command },
414 //	{ "/designate"          , _handle_designate_command }, Obsotele command [Omega]
415 //	{ "/resign"             , _handle_resign_command }, Obsolete command [Omega]
416 	{ "/kick"               , _handle_kick_command },
417 	{ "/ban"                , _handle_ban_command },
418 	{ "/unban"              , _handle_unban_command },
419 	{ "/tos"              , _handle_tos_command },
420 
421 	{ NULL                  , NULL }
422 
423 };
424 
425 static const t_command_table_row extended_command_table[] =
426 {
427 	{ "/ann"                , _handle_announce_command },
428 	{ "/r"                  , _handle_reply_command },
429 	{ "/reply"              , _handle_reply_command },
430 	{ "/realmann"           , _handle_realmann_command },
431 	{ "/watch"              , _handle_watch_command },
432 	{ "/unwatch"            , _handle_unwatch_command },
433 	{ "/watchall"           , _handle_watchall_command },
434 	{ "/unwatchall"         , _handle_unwatchall_command },
435 	{ "/lusers"             , _handle_lusers_command },
436 	{ "/news"               , _handle_news_command },
437 	{ "/games"              , _handle_games_command },
438 	{ "/channels"           , _handle_channels_command },
439 	{ "/chs"                , _handle_channels_command },
440 	{ "/addacct"            , _handle_addacct_command },
441 	{ "/chpass"             , _handle_chpass_command },
442 	{ "/connections"        , _handle_connections_command },
443 	{ "/con"                , _handle_connections_command },
444 	{ "/finger"             , _handle_finger_command },
445 	{ "/operator"           , _handle_operator_command },
446 	{ "/aop"		, _handle_aop_command },
447 	{ "/op"           	, _handle_op_command },
448 	{ "/tmpop"           	, _handle_tmpop_command },
449 	{ "/deop"           	, _handle_deop_command },
450 	{ "/voice"		, _handle_voice_command },
451 	{ "/devoice"		, _handle_devoice_command },
452 	{ "/vop"		, _handle_vop_command },
453 	{ "/admins"             , _handle_admins_command },
454 	{ "/logout"             , _handle_quit_command },
455 	{ "/quit"               , _handle_quit_command },
456 	{ "/exit"               , _handle_quit_command },
457 	{ "/kill"               , _handle_kill_command },
458 	{ "/killsession"        , _handle_killsession_command },
459 	{ "/gameinfo"           , _handle_gameinfo_command },
460 	{ "/ladderactivate"     , _handle_ladderactivate_command },
461 	{ "/rehash"             , _handle_rehash_command },
462 //	{ "/rank_all_accounts"  , _handle_rank_all_accounts_command },
463 	{ "/shutdown"           , _handle_shutdown_command },
464 	{ "/ladderinfo"         , _handle_ladderinfo_command },
465 	{ "/timer"              , _handle_timer_command },
466 	{ "/serverban"          , _handle_serverban_command },
467 	{ "/netinfo"            , _handle_netinfo_command },
468 	{ "/quota"              , _handle_quota_command },
469 	{ "/lockacct"           , _handle_lockacct_command },
470 	{ "/unlockacct"         , _handle_unlockacct_command },
471 	{ "/flag"               , _handle_flag_command },
472 	{ "/tag"                , _handle_tag_command },
473 	{ "/help"               , handle_help_command },
474 	{ "/mail"               , handle_mail_command },
475 	{ "/ipban"              , handle_ipban_command }, // in ipban.c
476 	{ "/set"                , _handle_set_command },
477 	{ "/motd"               , _handle_motd_command },
478 	{ "/latency"            , _handle_ping_command },
479 	{ "/ping"               , _handle_ping_command },
480 	{ "/p"                  , _handle_ping_command },
481 	{ "/commandgroups"	, _handle_commandgroups_command },
482 	{ "/cg"			, _handle_commandgroups_command },
483 	{ "/topic"		, _handle_topic_command },
484 	{ "/moderate"		, _handle_moderate_command },
485 	{ "/clearstats"		, _handle_clearstats_command },
486 
487         { NULL                  , NULL }
488 
489 };
490 
skip_command(char const * org_text)491 char const * skip_command(char const * org_text)
492 {
493    unsigned int i;
494    char * text = (char *)org_text;
495    for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
496    if (text[i]!='\0') text[i++]='\0';             /* \0-terminate command */
497    for (; text[i]==' '; i++);
498    return &text[i];
499 }
500 
handle_command(t_connection * c,char const * text)501 extern int handle_command(t_connection * c,  char const * text)
502 {
503   t_command_table_row const *p;
504 
505   for (p = standard_command_table; p->command_string != NULL; p++)
506     {
507       if (strstart(text, p->command_string)==0)
508         {
509 	  if (!(command_get_group(p->command_string)))
510 	    {
511 	      message_send_text(c,message_type_error,c,"This command has been deactivated");
512 	      return 0;
513 	    }
514 	  if (!((command_get_group(p->command_string) & account_get_command_groups(conn_get_account(c)))))
515 	    {
516 	      message_send_text(c,message_type_error,c,"This command is reserved for admins.");
517 	      return 0;
518 	    }
519 	if (p->command_handler != NULL) return ((p->command_handler)(c,text));
520 	}
521     }
522 
523 
524     if (prefs_get_extra_commands()==0)
525     {
526 	message_send_text(c,message_type_error,c,"Unknown command.");
527 	eventlog(eventlog_level_debug,__FUNCTION__,"got unknown standard command \"%s\"",text);
528 	return 0;
529     }
530 
531     for (p = extended_command_table; p->command_string != NULL; p++)
532       {
533       if (strstart(text, p->command_string)==0)
534         {
535 	  if (!(command_get_group(p->command_string)))
536 	    {
537 	      message_send_text(c,message_type_error,c,"This command has been deactivated");
538 	      return 0;
539 	    }
540 	  if (!((command_get_group(p->command_string) & account_get_command_groups(conn_get_account(c)))))
541 	    {
542 	      message_send_text(c,message_type_error,c,"This command is reserved for admins.");
543 	      return 0;
544 	    }
545 	if (p->command_handler != NULL) return ((p->command_handler)(c,text));
546 	}
547     }
548 
549     if (strlen(text)>=2 && strncmp(text,"//",2)==0)
550     {
551 	handle_alias_command(c,text);
552 	return 0;
553     }
554 
555     message_send_text(c,message_type_error,c,"Unknown command.");
556     eventlog(eventlog_level_debug,__FUNCTION__,"got unknown command \"%s\"",text);
557     return 0;
558 }
559 
560 // +++++++++++++++++++++++++++++++++ command implementations +++++++++++++++++++++++++++++++++++++++
561 
_handle_clan_command(t_connection * c,char const * text)562 static int _handle_clan_command(t_connection * c, char const * text)
563 {
564   t_account * acc;
565   t_clanmember * member;
566   t_clan * clan;
567 
568   text = skip_command(text);
569 
570   if ( text[0] == '\0' )
571     {
572       message_send_text(c,message_type_info,c,"usage:");
573       message_send_text(c,message_type_info,c,"/clan public  /clan pub");
574       message_send_text(c,message_type_info,c,"Opens the clan channel up to the public so that anyone may enter.");
575       message_send_text(c,message_type_info,c,"/clan private  /clan priv");
576       message_send_text(c,message_type_info,c,"Closes the clan channel such that only members of the clan may enter.");
577       message_send_text(c,message_type_info,c,"/clan motd MESSAGE");
578       message_send_text(c,message_type_info,c,"Update the clan message of the day to MESSAGE.");
579       return 0;
580     }
581 
582   if((acc = conn_get_account(c)) && (member = account_get_clanmember(acc)) && (clan = clanmember_get_clan(member)))
583   {
584     if(clanmember_get_status(member)>=CLAN_SHAMAN)
585     {
586       if (strstart(text,"public")==0 || strstart(text,"pub")==0) {
587         if(clan_get_channel_type(clan)!=0)
588         {
589           clan_set_channel_type(clan,0);
590           message_send_text(c,message_type_info,c,"Clan channel is opened up!");
591         }
592         else
593           message_send_text(c,message_type_error,c,"Clan channel has already been opened up!");
594       }
595       else
596       if (strstart(text,"private")==0 || strstart(text,"priv")==0) {
597         if(clan_get_channel_type(clan)!=1)
598         {
599           clan_set_channel_type(clan,1);
600           message_send_text(c,message_type_info,c,"Clan channel is closed!");
601         }
602         else
603           message_send_text(c,message_type_error,c,"Clan channel has already been closed!");
604       }
605       else
606       if (strstart(text,"motd")==0) {
607         const char * msg=skip_command(text);
608         if(msg[0]=='\0')
609         {
610           message_send_text(c,message_type_info,c,"usage:");
611           message_send_text(c,message_type_info,c,"/clan motd MESSAGE");
612           message_send_text(c,message_type_info,c,"Update the clan message of the day to MESSAGE.");
613         }
614         else
615         {
616           clan_set_motd(clan, msg);
617           message_send_text(c,message_type_info,c,"Clan message of day is updated!");
618         }
619       }
620     }
621     else
622       message_send_text(c,message_type_error,c,"You are not the chieftain or shaman of clan!");
623   }
624   else
625     message_send_text(c,message_type_error,c,"You are not in a clan!");
626 
627   return 0;
628 }
629 
command_set_flags(t_connection * c)630 static int command_set_flags(t_connection * c)
631 {
632   return channel_set_userflags(c);
633 }
634 
_handle_admin_command(t_connection * c,char const * text)635 static int _handle_admin_command(t_connection * c, char const * text)
636 {
637     char const *	username;
638     char		command;
639     t_account *		acc;
640     t_connection *	dst_c;
641     int			changed=0;
642 
643     text = skip_command(text);
644 
645     if ((text[0]=='\0') || ((text[0] != '+') && (text[0] != '-'))) {
646 	message_send_text(c,message_type_info,c,"usage: /admin +username to promote user to Server Admin.");
647 	message_send_text(c,message_type_info,c,"       /admin -username to demote user from Server Admin.");
648 	return -1;
649     }
650 
651     command = text[0];
652     username = &text[1];
653 
654     if(!*username) {
655 	message_send_text(c,message_type_info,c,"You need to supply a username.");
656       return -1;
657     }
658 
659     if(!(acc = accountlist_find_account(username))) {
660 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
661 	message_send_text(c, message_type_info, c, msgtemp);
662 	return -1;
663     }
664     dst_c = account_get_conn(acc);
665 
666     if (command == '+') {
667 	if (account_get_auth_admin(acc,NULL) == 1) {
668 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s is already a Server Admin",username);
669 	} else {
670 	    account_set_auth_admin(acc,NULL,1);
671 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Server Admin",username);
672 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Server Admin",conn_get_loggeduser(c));
673 	    changed = 1;
674 	}
675     } else {
676 	if (account_get_auth_admin(acc,NULL) != 1)
677     	    snprintf(msgtemp, sizeof(msgtemp), "%.64s is no Server Admin, so you can't demote him",username);
678 	else {
679 	    account_set_auth_admin(acc,NULL,0);
680 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Server Admin",username);
681 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a Server Admin",conn_get_loggeduser(c));
682 	    changed = 1;
683 	}
684     }
685 
686     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
687     message_send_text(c, message_type_info, c, msgtemp);
688     command_set_flags(dst_c);
689     return 0;
690 }
691 
_handle_operator_command(t_connection * c,char const * text)692 static int _handle_operator_command(t_connection * c, char const * text)
693 {
694     char const *	username;
695     char		command;
696     t_account *		acc;
697     t_connection *	dst_c;
698     int			changed = 0;
699 
700     text = skip_command(text);
701 
702     if ((text[0]=='\0') || ((text[0] != '+') && (text[0] != '-'))) {
703 	message_send_text(c,message_type_info,c,"usage: /operator +username to promote user to Server Operator.");
704 	message_send_text(c,message_type_info,c,"       /operator -username to demote user from Server Operator.");
705 	return -1;
706     }
707 
708     command = text[0];
709     username = &text[1];
710 
711     if(!*username) {
712 	message_send_text(c,message_type_info,c,"You need to supply a username.");
713       return -1;
714     }
715 
716     if(!(acc = accountlist_find_account(username))) {
717 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
718 	message_send_text(c, message_type_info, c, msgtemp);
719 	return -1;
720     }
721     dst_c = account_get_conn(acc);
722 
723     if (command == '+') {
724 	if (account_get_auth_operator(acc,NULL) == 1)
725 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s is already a Server Operator",username);
726 	else {
727 	    account_set_auth_operator(acc,NULL,1);
728 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Server Operator",username);
729 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Server Operator",conn_get_loggeduser(c));
730 	    changed = 1;
731 	}
732     } else {
733 	if (account_get_auth_operator(acc,NULL) != 1)
734     	    snprintf(msgtemp, sizeof(msgtemp), "%.64s is no Server Operator, so you can't demote him",username);
735 	else {
736 	    account_set_auth_operator(acc,NULL,0);
737 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Server Operator",username);
738 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Server Operator",conn_get_loggeduser(c));
739 	    changed = 1;
740 	}
741     }
742 
743     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
744     message_send_text(c, message_type_info, c, msgtemp);
745     command_set_flags(dst_c);
746     return 0;
747 }
748 
_handle_aop_command(t_connection * c,char const * text)749 static int _handle_aop_command(t_connection * c, char const * text)
750 {
751     char const *	username;
752     char const *	channel;
753     t_account *		acc;
754     t_connection *	dst_c;
755     int			changed = 0;
756 
757     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
758 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
759 	return -1;
760     }
761 
762     if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && account_get_auth_admin(conn_get_account(c),channel)!=1) {
763 	message_send_text(c,message_type_error,c,"You must be at least a Channel Admin to use this command.");
764 	return -1;
765     }
766 
767     text = skip_command(text);
768 
769     if (!(username = &text[0])) {
770 	message_send_text(c, message_type_info, c, "You need to supply a username.");
771 	return -1;
772     }
773 
774     if(!(acc = accountlist_find_account(username))) {
775 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
776 	message_send_text(c, message_type_info, c, msgtemp);
777 	return -1;
778     }
779 
780     dst_c = account_get_conn(acc);
781 
782     if (account_get_auth_admin(acc,channel) == 1)
783 	snprintf(msgtemp, sizeof(msgtemp), "%.64s is already a Channel Admin",username);
784     else {
785 	account_set_auth_admin(acc,channel,1);
786 	snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Channel Admin",username);
787 	snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Channel Admin for channel \"%.128s\"",conn_get_loggeduser(c),channel);
788 	changed = 1;
789     }
790 
791     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
792     message_send_text(c, message_type_info, c, msgtemp);
793     command_set_flags(dst_c);
794     return 0;
795 }
796 
_handle_vop_command(t_connection * c,char const * text)797 static int _handle_vop_command(t_connection * c, char const * text)
798 {
799     char const *	username;
800     char const *	channel;
801     t_account *		acc;
802     t_connection *	dst_c;
803     int			changed = 0;
804 
805     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
806 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
807 	return -1;
808     }
809 
810     if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && account_get_auth_admin(conn_get_account(c),channel)!=1) {
811 	message_send_text(c,message_type_error,c,"You must be at least a Channel Admin to use this command.");
812 	return -1;
813     }
814 
815     text = skip_command(text);
816 
817     if (!(username = &text[0])) {
818 	message_send_text(c, message_type_info, c, "You need to supply a username.");
819 	return -1;
820     }
821 
822     if(!(acc = accountlist_find_account(username))) {
823 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
824 	message_send_text(c, message_type_info, c, msgtemp);
825 	return -1;
826     }
827 
828     dst_c = account_get_conn(acc);
829 
830     if (account_get_auth_voice(acc,channel) == 1)
831 	snprintf(msgtemp, sizeof(msgtemp), "%.64s is already on VOP list",username);
832     else {
833 	account_set_auth_voice(acc,channel,1);
834 	snprintf(msgtemp, sizeof(msgtemp), "%.64s has been added to the VOP list",username);
835 	snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has added you to the VOP list of channel \"%.128s\"",conn_get_loggeduser(c),channel);
836 	changed = 1;
837     }
838 
839     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
840     message_send_text(c, message_type_info, c, msgtemp);
841     command_set_flags(dst_c);
842     return 0;
843 }
844 
_handle_voice_command(t_connection * c,char const * text)845 static int _handle_voice_command(t_connection * c, char const * text)
846 {
847     char const *	username;
848     char const *	channel;
849     t_account *		acc;
850     t_connection *	dst_c;
851     int			changed = 0;
852 
853     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
854 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
855 	return -1;
856     }
857 
858     if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(conn_get_channel(c))))) {
859 	message_send_text(c,message_type_error,c,"You must be at least a Channel Operator to use this command.");
860 	return -1;
861     }
862 
863     text = skip_command(text);
864 
865     if (!(username = &text[0])) {
866 	message_send_text(c, message_type_info, c, "You need to supply a username.");
867 	return -1;
868     }
869 
870     if(!(acc = accountlist_find_account(username))) {
871 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
872 	message_send_text(c, message_type_info, c, msgtemp);
873 	return -1;
874     }
875     dst_c = account_get_conn(acc);
876     if (account_get_auth_voice(acc,channel)==1)
877 	snprintf(msgtemp, sizeof(msgtemp), "%s is already on VOP list, no need to Voice him", username);
878     else
879     {
880       if ((!dst_c) || conn_get_channel(c)!=conn_get_channel(dst_c))
881       {
882 	snprintf(msgtemp, sizeof(msgtemp), "%.64s must be on the same channel to voice him",username);
883       }
884       else
885       {
886         if (channel_conn_has_tmpVOICE(conn_get_channel(c),dst_c))
887 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has already Voice in this channel",username);
888         else {
889 	  if (account_is_operator_or_admin(acc,channel))
890 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s allready is operator or admin, no need to voice him",username);
891 	  else
892 	  {
893 	    conn_set_tmpVOICE_channel(dst_c,channel);
894 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been granted Voice in this channel",username);
895 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has granted you Voice in this channel",conn_get_loggeduser(c));
896 	    changed = 1;
897 	  }
898 	}
899       }
900     }
901 
902     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
903     message_send_text(c, message_type_info, c, msgtemp);
904     command_set_flags(dst_c);
905     return 0;
906 }
907 
_handle_devoice_command(t_connection * c,char const * text)908 static int _handle_devoice_command(t_connection * c, char const * text)
909 {
910     char const *	username;
911     char const *	channel;
912     t_account *		acc;
913     t_connection *	dst_c;
914     int			done = 0;
915     int			changed = 0;
916 
917     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
918 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
919 	return -1;
920     }
921 
922     if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(conn_get_channel(c))))) {
923 	message_send_text(c,message_type_error,c,"You must be at least a Channel Operator to use this command.");
924 	return -1;
925     }
926 
927     text = skip_command(text);
928 
929     if (!(username = &text[0])) {
930 	message_send_text(c, message_type_info, c, "You need to supply a username.");
931 	return -1;
932     }
933 
934     if(!(acc = accountlist_find_account(username))) {
935 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
936 	message_send_text(c, message_type_info, c, msgtemp);
937 	return -1;
938     }
939     dst_c = account_get_conn(acc);
940 
941     if (account_get_auth_voice(acc,channel)==1)
942     {
943 	if ((account_get_auth_admin(conn_get_account(c),channel)==1) || (account_get_auth_admin(conn_get_account(c),NULL)==1))
944 	{
945 	    account_set_auth_voice(acc,channel,0);
946 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been removed from VOP list.",username);
947 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has removed you from VOP list of channel \"%.128s\"",conn_get_loggeduser(c),channel);
948 	    changed = 1;
949 	}
950 	else
951 	{
952 	    snprintf(msgtemp, sizeof(msgtemp), "You must be at least Channel Admin to remove %.64s from the VOP list",username);
953 	}
954 	done = 1;
955     }
956 
957     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
958     message_send_text(c, message_type_info, c, msgtemp);
959     changed = 0;
960 
961     if ((dst_c) && channel_conn_has_tmpVOICE(conn_get_channel(c),dst_c)==1)
962     {
963       conn_set_tmpVOICE_channel(dst_c,NULL);
964       snprintf(msgtemp, sizeof(msgtemp), "Voice has been taken from %.64s in this channel",username);
965       snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has taken your Voice in channel \"%.128s\"",conn_get_loggeduser(c),channel);
966       changed = 1;
967       done = 1;
968     }
969 
970     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
971     message_send_text(c, message_type_info, c, msgtemp);
972 
973     if (!done)
974     {
975      snprintf(msgtemp, sizeof(msgtemp), "%.64s has no Voice in this channel, so it can't be taken away",username);
976      message_send_text(c, message_type_info, c, msgtemp);
977     }
978 
979     command_set_flags(dst_c);
980     return 0;
981 }
982 
_handle_op_command(t_connection * c,char const * text)983 static int _handle_op_command(t_connection * c, char const * text)
984 {
985     char const *	username;
986     char const *	channel;
987     t_account *		acc;
988     int			OP_lvl;
989     t_connection * 	dst_c;
990     int			changed = 0;
991 
992     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
993 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
994 	return -1;
995     }
996 
997     acc = conn_get_account(c);
998     OP_lvl = 0;
999 
1000     if (account_is_operator_or_admin(acc,channel))
1001       OP_lvl = 1;
1002     else if (channel_conn_is_tmpOP(conn_get_channel(c),c))
1003       OP_lvl = 2;
1004 
1005     if (OP_lvl==0)
1006     {
1007 	message_send_text(c,message_type_error,c,"You must be at least a Channel Operator or tempOP to use this command.");
1008 	return -1;
1009     }
1010 
1011     text = skip_command(text);
1012 
1013     if (!(username = &text[0])) {
1014 	message_send_text(c, message_type_info, c, "You need to supply a username.");
1015 	return -1;
1016     }
1017 
1018     if(!(acc = accountlist_find_account(username))) {
1019 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
1020 	message_send_text(c, message_type_info, c, msgtemp);
1021 	return -1;
1022     }
1023 
1024     dst_c = account_get_conn(acc);
1025 
1026     if (OP_lvl==1) // user is full op so he may fully op others
1027     {
1028       if (account_get_auth_operator(acc,channel) == 1)
1029 	  snprintf(msgtemp, sizeof(msgtemp), "%.64s is allready a Channel Operator",username);
1030       else {
1031 	  account_set_auth_operator(acc,channel,1);
1032 	  snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a Channel Operator",username);
1033 	  snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a Channel Operator in channel \"%.128s\"",conn_get_loggeduser(c),channel);
1034 	  changed = 1;
1035       }
1036     }
1037     else { // user is only tempOP so he may only tempOP others
1038          if ((!(dst_c)) || (conn_get_channel(c) != conn_get_channel(dst_c)))
1039           snprintf(msgtemp, sizeof(msgtemp), "%.64s must be on the same channel to tempOP him",username);
1040          else
1041          {
1042 	   if (account_is_operator_or_admin(acc,channel))
1043 	     snprintf(msgtemp, sizeof(msgtemp), "%.64s allready is operator or admin, no need to tempOP him",username);
1044 	   else
1045 	   {
1046              conn_set_tmpOP_channel(dst_c,channel);
1047 	     snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to a tempOP",username);
1048 	     snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a tempOP in this channel",conn_get_loggeduser(c));
1049 	     changed = 1;
1050 	   }
1051          }
1052     }
1053 
1054     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
1055     message_send_text(c, message_type_info, c, msgtemp);
1056     command_set_flags(dst_c);
1057     return 0;
1058 }
1059 
_handle_tmpop_command(t_connection * c,char const * text)1060 static int _handle_tmpop_command(t_connection * c, char const * text)
1061 {
1062     char const *	username;
1063     char const *	channel;
1064     t_account *		acc;
1065     t_connection *	dst_c;
1066     int			changed = 0;
1067 
1068     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
1069 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
1070 	return -1;
1071     }
1072 
1073     if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(conn_get_channel(c))) || channel_conn_is_tmpOP(conn_get_channel(c),c))) {
1074 	message_send_text(c,message_type_error,c,"You must be at least a Channel Operator or tmpOP to use this command.");
1075 	return -1;
1076     }
1077 
1078     text = skip_command(text);
1079 
1080     if (!(username = &text[0])) {
1081 	message_send_text(c, message_type_info, c, "You need to supply a username.");
1082 	return -1;
1083     }
1084 
1085     if(!(acc = accountlist_find_account(username))) {
1086 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
1087 	message_send_text(c, message_type_info, c, msgtemp);
1088 	return -1;
1089     }
1090 
1091     dst_c = account_get_conn(acc);
1092 
1093     if (channel_conn_is_tmpOP(conn_get_channel(c),dst_c))
1094        snprintf(msgtemp, sizeof(msgtemp), "%.64s has already tmpOP in this channel",username);
1095     else
1096     {
1097        if ((!(dst_c)) || (conn_get_channel(c) != conn_get_channel(dst_c)))
1098        snprintf(msgtemp, sizeof(msgtemp), "%.64s must be on the same channel to tempOP him",username);
1099        else
1100        {
1101 	 if (account_is_operator_or_admin(acc,channel))
1102 	   snprintf(msgtemp, sizeof(msgtemp), "%.64s allready is operator or admin, no need to tempOP him",username);
1103 	 else
1104 	 {
1105            conn_set_tmpOP_channel(dst_c,channel);
1106            snprintf(msgtemp, sizeof(msgtemp), "%.64s has been promoted to tmpOP in this channel",username);
1107 	   snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has promoted you to a tempOP in this channel",conn_get_loggeduser(c));
1108 	   changed = 1;
1109 	 }
1110        }
1111     }
1112 
1113     if (changed && dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
1114     message_send_text(c, message_type_info, c, msgtemp);
1115     command_set_flags(dst_c);
1116     return 0;
1117 }
1118 
_handle_deop_command(t_connection * c,char const * text)1119 static int _handle_deop_command(t_connection * c, char const * text)
1120 {
1121     char const *	username;
1122     char const *	channel;
1123     t_account *		acc;
1124     int			OP_lvl;
1125     t_connection *	dst_c;
1126     int			done = 0;
1127 
1128     if (!(conn_get_channel(c)) || !(channel = channel_get_name(conn_get_channel(c)))) {
1129 	message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
1130 	return -1;
1131     }
1132 
1133     acc = conn_get_account(c);
1134     OP_lvl = 0;
1135 
1136     if (account_is_operator_or_admin(acc,channel))
1137       OP_lvl = 1;
1138     else if (channel_conn_is_tmpOP(conn_get_channel(c),account_get_conn(acc)))
1139       OP_lvl = 2;
1140 
1141     if (OP_lvl==0)
1142     {
1143 	message_send_text(c,message_type_error,c,"You must be at least a Channel Operator or tempOP to use this command.");
1144 	return -1;
1145     }
1146 
1147     text = skip_command(text);
1148 
1149     if (!(username = &text[0])) {
1150 	message_send_text(c, message_type_info, c, "You need to supply a username.");
1151 	return -1;
1152     }
1153 
1154     if(!(acc = accountlist_find_account(username))) {
1155 	snprintf(msgtemp, sizeof(msgtemp), "There's no account with username %.64s.", username);
1156 	message_send_text(c, message_type_info, c, msgtemp);
1157 	return -1;
1158     }
1159 
1160     dst_c = account_get_conn(acc);
1161 
1162     if (OP_lvl==1) // user is real OP and allowed to deOP
1163       {
1164 	if (account_get_auth_admin(acc,channel) == 1 || account_get_auth_operator(acc,channel) == 1) {
1165 	  if (account_get_auth_admin(acc,channel) == 1) {
1166 	    if (account_get_auth_admin(conn_get_account(c),channel)!=1 && account_get_auth_admin(conn_get_account(c),NULL)!=1)
1167 	      message_send_text(c,message_type_info,c,"You must be at least a Channel Admin to demote another Channel Admin");
1168 	    else {
1169 	      account_set_auth_admin(acc,channel,0);
1170 	      snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Channel Admin.", username);
1171 	      message_send_text(c, message_type_info, c, msgtemp);
1172 	      if (dst_c)
1173 	      {
1174 	        snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a Channel Admin of channel \"%.128s\"",conn_get_loggeduser(c),channel);
1175                 message_send_text(dst_c, message_type_info, c, msgtemp2);
1176 	      }
1177 	    }
1178 	  }
1179 	  if (account_get_auth_operator(acc,channel) == 1) {
1180 	    account_set_auth_operator(acc,channel,0);
1181 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a Channel Operator",username);
1182 	    message_send_text(c, message_type_info, c, msgtemp);
1183 	    if (dst_c)
1184 	    {
1185 	      snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a Channel Operator of channel \"%.128s\"",conn_get_loggeduser(c),channel);
1186               message_send_text(dst_c, message_type_info, c, msgtemp2);
1187 	    }
1188 	  }
1189 	  done = 1;
1190 	}
1191 	if ((dst_c) && channel_conn_is_tmpOP(conn_get_channel(c),dst_c))
1192 	{
1193 	    conn_set_tmpOP_channel(dst_c,NULL);
1194 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a tempOP of this channel",username);
1195 	    message_send_text(c, message_type_info, c, msgtemp);
1196 	    if (dst_c)
1197 	    {
1198 	      snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a tmpOP of channel \"%.128s\"",conn_get_loggeduser(c),channel);
1199               message_send_text(dst_c, message_type_info, c, msgtemp2);
1200 	    }
1201 	    done = 1;
1202 	}
1203 	if (!done) {
1204 	  snprintf(msgtemp, sizeof(msgtemp), "%.64s is no Channel Admin or Channel Operator or tempOP, so you can't demote him.",username);
1205 	  message_send_text(c, message_type_info, c, msgtemp);
1206 	}
1207       }
1208     else //user is just a tempOP and may only deOP other tempOPs
1209       {
1210 	if (dst_c && channel_conn_is_tmpOP(conn_get_channel(c),dst_c))
1211 	  {
1212 	    conn_set_tmpOP_channel(account_get_conn(acc),NULL);
1213 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s has been demoted from a tempOP of this channel",username);
1214 	    message_send_text(c, message_type_info, c, msgtemp);
1215 	    snprintf(msgtemp2, sizeof(msgtemp2), "%.64s has demoted you from a tempOP of channel \"%.128s\"",conn_get_loggeduser(c),channel);
1216             if (dst_c) message_send_text(dst_c, message_type_info, c, msgtemp2);
1217 	  }
1218 	else
1219 	  {
1220 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s is no tempOP in this channel, so you can't demote him",username);
1221 	    message_send_text(c, message_type_info, c, msgtemp);
1222 	  }
1223       }
1224 
1225     command_set_flags(connlist_find_connection_by_accountname(username));
1226     return 0;
1227 }
1228 
_handle_friends_command(t_connection * c,char const * text)1229 static int _handle_friends_command(t_connection * c, char const * text)
1230 {
1231     int i;
1232     t_account *my_acc = conn_get_account(c);
1233 
1234     text = skip_command(text);;
1235 
1236     if(text[0]=='\0' || strstart(text,"help")==0 || strstart(text, "h")==0) {
1237 	message_send_text(c,message_type_info,c,"Friends List (Used in Arranged Teams and finding online friends.)");
1238 	message_send_text(c,message_type_info,c,"Type: /f add <username> (adds a friend to your list)");
1239 	message_send_text(c,message_type_info,c,"Type: /f del <username> (removes a friend from your list)");
1240 	message_send_text(c,message_type_info,c,"Type: /f promote <username> (promote a friend in your list)");
1241 	message_send_text(c,message_type_info,c,"Type: /f demote <username> (demote a friend in your list)");
1242 	message_send_text(c,message_type_info,c,"Type: /f list (shows your full friends list)");
1243 	message_send_text(c,message_type_info,c,"Type: /f msg (whispers a message to all your friends at once)");
1244 	return 0;
1245     }
1246 
1247     if (strstart(text,"add")==0 || strstart(text,"a")==0) {
1248 	char msgtemp[MAX_MESSAGE_LEN];
1249 	t_packet 	* rpacket;
1250 	t_connection 	* dest_c;
1251 	t_account    	* friend_acc;
1252 	t_server_friendslistreply_status status;
1253 	t_game * game;
1254 	t_channel * channel;
1255         char stat;
1256 	t_list * flist;
1257 	t_friend * fr;
1258 
1259 	text = skip_command(text);
1260 
1261 	if (text[0] == '\0') {
1262 	    message_send_text(c,message_type_info,c,"usage: /f add <username>");
1263 	    return 0;
1264 	}
1265 
1266 	if (!(friend_acc = accountlist_find_account(text))) {
1267 	    message_send_text(c,message_type_info,c,"That user does not exist.");
1268 	    return 0;
1269 	}
1270 
1271 	switch(account_add_friend(my_acc, friend_acc)) {
1272 	    case -1:
1273     		message_send_text(c,message_type_error,c,"Server error.");
1274     		return 0;
1275 	    case -2:
1276     		message_send_text(c,message_type_info,c,"You can't add yourself to your friends list.");
1277     		return 0;
1278 	    case -3:
1279     		snprintf(msgtemp, sizeof(msgtemp), "You can only have a maximum of %d friends.", prefs_get_max_friends());
1280     		message_send_text(c,message_type_info,c,msgtemp);
1281     		return 0;
1282 	    case -4:
1283 		snprintf(msgtemp, sizeof(msgtemp), "%.64s is already on your friends list!", text);
1284 		message_send_text(c,message_type_info,c,msgtemp);
1285 		return 0;
1286 	}
1287 
1288 	snprintf(msgtemp, sizeof(msgtemp), "Added %.64s to your friends list.", text);
1289 	message_send_text(c,message_type_info,c,msgtemp);
1290 	dest_c = connlist_find_connection_by_account(friend_acc);
1291 	if(dest_c!=NULL) {
1292     	    snprintf(msgtemp, sizeof(msgtemp), "%.64s added you to his/her friends list.",conn_get_username(c));
1293     	    message_send_text(dest_c,message_type_info,dest_c,msgtemp);
1294 	}
1295 
1296 	if ((conn_get_class(c)!=conn_class_bnet) || (!(rpacket = packet_create(packet_class_bnet))))
1297     	    return 0;
1298 
1299 	packet_set_size(rpacket,sizeof(t_server_friendadd_ack));
1300 	packet_set_type(rpacket,SERVER_FRIENDADD_ACK);
1301 
1302 	packet_append_string(rpacket, account_get_name(friend_acc));
1303 
1304 	game = NULL;
1305         channel = NULL;
1306 
1307 	if(!(dest_c))
1308           {
1309 	    bn_byte_set(&status.location,FRIENDSTATUS_OFFLINE);
1310 	    bn_byte_set(&status.status,0);
1311             bn_int_set(&status.clienttag,0);
1312           }
1313 	  else
1314           {
1315 	    bn_int_set(&status.clienttag, conn_get_clienttag(dest_c));
1316             stat = 0;
1317 	    flist = account_get_friends(my_acc);
1318 	    fr = friendlist_find_account(flist,friend_acc);
1319             if ((friend_get_mutual(fr)))    stat |= FRIEND_TYPE_MUTUAL;
1320             if ((conn_get_dndstr(dest_c)))  stat |= FRIEND_TYPE_DND;
1321 	    if ((conn_get_awaystr(dest_c))) stat |= FRIEND_TYPE_AWAY;
1322 	    bn_byte_set(&status.status,stat);
1323             if((game = conn_get_game(dest_c)))
1324 	      {
1325 	        if (game_get_flag(game) != game_flag_private)
1326 		  bn_byte_set(&status.location,FRIENDSTATUS_PUBLIC_GAME);
1327 		else
1328                   bn_byte_set(&status.location,FRIENDSTATUS_PRIVATE_GAME);
1329 	      }
1330 	    else if((channel = conn_get_channel(dest_c)))
1331 	      {
1332 	        bn_byte_set(&status.location,FRIENDSTATUS_CHAT);
1333 	      }
1334 	    else
1335 	      {
1336 		bn_byte_set(&status.location,FRIENDSTATUS_ONLINE);
1337 	      }
1338           }
1339 
1340 	packet_append_data(rpacket, &status, sizeof(status));
1341 
1342         if (game) packet_append_string(rpacket,game_get_name(game));
1343 	else if (channel) packet_append_string(rpacket,channel_get_name(channel));
1344 	else packet_append_string(rpacket,"");
1345 
1346 	conn_push_outqueue(c,rpacket);
1347 	packet_del_ref(rpacket);
1348 
1349 	return 0;
1350     }
1351 
1352     if (strstart(text,"msg")==0 || strstart(text,"w")==0 || strstart(text,"whisper")==0 || strstart(text,"m")==0)
1353     {
1354 	char const *msg;
1355 	int cnt = 0;
1356 	t_connection * dest_c;
1357 	t_elem  * curr;
1358 	t_friend * fr;
1359 	t_list  * flist;
1360 
1361 	msg = skip_command(text);
1362 	/* if the message test is empty then ignore command */
1363 	if (msg[0]=='\0') {
1364 	    message_send_text(c,message_type_info,c,"Did not message any friends. Type some text next time.");
1365 	    return 0;
1366 	}
1367 
1368 	flist=account_get_friends(my_acc);
1369 	if(flist==NULL)
1370     	    return -1;
1371 
1372 	LIST_TRAVERSE(flist,curr)
1373 	{
1374     	    if (!(fr = elem_get_data(curr))) {
1375         	eventlog(eventlog_level_error,__FUNCTION__,"found NULL entry in list");
1376         	continue;
1377     	    }
1378     	    if(friend_get_mutual(fr)) {
1379         	dest_c = connlist_find_connection_by_account(friend_get_account(fr));
1380 		if (!dest_c) continue;
1381         	message_send_text(dest_c,message_type_whisper,c,msg);
1382         	cnt++;
1383     	    }
1384 	}
1385 	if(cnt)
1386 	    message_send_text(c,message_type_friendwhisperack,c,msg);
1387         else
1388 	    message_send_text(c,message_type_info,c,"All your friends are offline.");
1389 
1390 	return 0;
1391     }
1392 
1393     if (strstart(text,"r")==0 || strstart(text,"remove")==0
1394 	|| strstart(text,"del")==0 || strstart(text,"delete")==0) {
1395 
1396 	int num;
1397 	char msgtemp[MAX_MESSAGE_LEN];
1398 	t_packet * rpacket;
1399 
1400 	text = skip_command(text);
1401 
1402 	if (text[0]=='\0') {
1403 	    message_send_text(c,message_type_info,c,"usage: /f remove <username>");
1404 	    return 0;
1405 	}
1406 
1407 	switch((num = account_remove_friend2(my_acc, text))) {
1408 	    case -1: return -1;
1409 	    case -2:
1410 		snprintf(msgtemp, sizeof(msgtemp), "%.64s was not found on your friends list.", text);
1411 		message_send_text(c,message_type_info,c,msgtemp);
1412 		return 0;
1413 	    default:
1414 		snprintf(msgtemp, sizeof(msgtemp), "Removed %.64s from your friends list.", text);
1415 		message_send_text(c,message_type_info,c,msgtemp);
1416 
1417 		if ((conn_get_class(c)!=conn_class_bnet) || (!(rpacket = packet_create(packet_class_bnet))))
1418 	    	    return 0;
1419 
1420 		packet_set_size(rpacket,sizeof(t_server_frienddel_ack));
1421 		packet_set_type(rpacket,SERVER_FRIENDDEL_ACK);
1422 
1423 		bn_byte_set(&rpacket->u.server_frienddel_ack.friendnum, num);
1424 
1425 		conn_push_outqueue(c,rpacket);
1426 		packet_del_ref(rpacket);
1427 
1428     		return 0;
1429 	}
1430     }
1431 
1432     if (strstart(text,"p")==0 || strstart(text,"promote")==0) {
1433 	int num;
1434 	int n;
1435 	char msgtemp[MAX_MESSAGE_LEN];
1436 	char const * dest_name;
1437 	t_packet * rpacket;
1438 	t_list * flist;
1439 	t_friend * fr;
1440 	t_account * dest_acc;
1441 	unsigned int dest_uid;
1442 
1443 	text = skip_command(text);
1444 
1445 	if (text[0]=='\0') {
1446 	    message_send_text(c,message_type_info,c,"usage: /f promote <username>");
1447 	    return 0;
1448 	}
1449 
1450 	num = account_get_friendcount(my_acc);
1451 	flist = account_get_friends(my_acc);
1452 	for(n = 1; n<num; n++)
1453 	    if( (dest_uid = account_get_friend(my_acc, n)) &&
1454 		(fr = friendlist_find_uid(flist, dest_uid)) &&
1455 		(dest_acc = friend_get_account(fr)) &&
1456 		(dest_name = account_get_name(dest_acc)) &&
1457 		(strcasecmp(dest_name, text) == 0) )
1458 	    {
1459 		account_set_friend(my_acc, n, account_get_friend(my_acc, n-1));
1460 		account_set_friend(my_acc, n-1, dest_uid);
1461 		snprintf(msgtemp, sizeof(msgtemp), "Premoted %.64s in your friends list.", dest_name);
1462 		message_send_text(c,message_type_info,c,msgtemp);
1463 
1464 		if ((conn_get_class(c)!=conn_class_bnet) || (!(rpacket = packet_create(packet_class_bnet))))
1465 	    	    return 0;
1466 
1467 		packet_set_size(rpacket,sizeof(t_server_friendmove_ack));
1468 		packet_set_type(rpacket,SERVER_FRIENDMOVE_ACK);
1469     		bn_byte_set(&rpacket->u.server_friendmove_ack.pos1, n-1);
1470     		bn_byte_set(&rpacket->u.server_friendmove_ack.pos2, n);
1471 
1472 		conn_push_outqueue(c,rpacket);
1473 		packet_del_ref(rpacket);
1474 		return 0;
1475 	    }
1476 	return 0;
1477     }
1478 
1479     if (strstart(text,"d")==0 || strstart(text,"demote")==0) {
1480 	int num;
1481 	int n;
1482 	char msgtemp[MAX_MESSAGE_LEN];
1483 	char const * dest_name;
1484 	t_packet * rpacket;
1485 	t_list * flist;
1486 	t_friend * fr;
1487 	t_account * dest_acc;
1488 	unsigned int dest_uid;
1489 
1490 	text = skip_command(text);
1491 
1492 	if (text[0]=='\0') {
1493 	    message_send_text(c,message_type_info,c,"usage: /f demote <username>");
1494 	    return 0;
1495 	}
1496 
1497 	num = account_get_friendcount(my_acc);
1498 	flist = account_get_friends(my_acc);
1499 	for(n = 0; n<num-1; n++)
1500 	    if( (dest_uid = account_get_friend(my_acc, n)) &&
1501 		(fr = friendlist_find_uid(flist, dest_uid)) &&
1502 		(dest_acc = friend_get_account(fr)) &&
1503 		(dest_name = account_get_name(dest_acc)) &&
1504 		(strcasecmp(dest_name, text) == 0) )
1505 	    {
1506 		account_set_friend(my_acc, n, account_get_friend(my_acc, n+1));
1507 		account_set_friend(my_acc, n+1, dest_uid);
1508 		snprintf(msgtemp, sizeof(msgtemp), "Premoted %.64s in your friends list.", dest_name);
1509 		message_send_text(c,message_type_info,c,msgtemp);
1510 
1511 		if ((conn_get_class(c)!=conn_class_bnet) || (!(rpacket = packet_create(packet_class_bnet))))
1512 	    	    return 0;
1513 
1514 		packet_set_size(rpacket,sizeof(t_server_friendmove_ack));
1515 		packet_set_type(rpacket,SERVER_FRIENDMOVE_ACK);
1516     		bn_byte_set(&rpacket->u.server_friendmove_ack.pos1, n);
1517     		bn_byte_set(&rpacket->u.server_friendmove_ack.pos2, n+1);
1518 
1519 		conn_push_outqueue(c,rpacket);
1520 		packet_del_ref(rpacket);
1521 		return 0;
1522 	    }
1523 	return 0;
1524     }
1525 
1526     if (strstart(text,"list")==0 || strstart(text,"l")==0) {
1527 	char const * friend;
1528 	char status[128];
1529 	char software[64];
1530 	char msgtemp[MAX_MESSAGE_LEN];
1531 	t_connection * dest_c;
1532 	t_account * friend_acc;
1533 	t_game const * game;
1534 	t_channel const * channel;
1535 	t_friend * fr;
1536 	t_list  * flist;
1537 	int num;
1538 	unsigned int uid;
1539 
1540 	message_send_text(c,message_type_info,c,"Your PvPGN - Friends List");
1541 	message_send_text(c,message_type_info,c,"=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
1542 	num = account_get_friendcount(my_acc);
1543 
1544 	flist=account_get_friends(my_acc);
1545 	if(flist!=NULL) {
1546 	    for (i=0;i<num;i++)
1547 	    {
1548     		if ((!(uid = account_get_friend(my_acc,i))) || (!(fr = friendlist_find_uid(flist,uid))))
1549     		{
1550         	    eventlog(eventlog_level_error,__FUNCTION__,"friend uid in list");
1551         	    continue;
1552     		}
1553     		software[0]='\0';
1554     		friend_acc=friend_get_account(fr);
1555 		if (!(dest_c = connlist_find_connection_by_account(friend_acc)))
1556 	    	    sprintf(status, ", offline");
1557 		else {
1558 	    	    sprintf(software," using %s", clienttag_get_title(conn_get_clienttag(dest_c)));
1559 
1560 	    	    if(friend_get_mutual(fr)) {
1561 		        if ((game = conn_get_game(dest_c)))
1562 		            sprintf(status, ", in game \"%.64s\"", game_get_name(game));
1563 		        else if ((channel = conn_get_channel(dest_c))) {
1564 		            if(strcasecmp(channel_get_name(channel),"Arranged Teams")==0)
1565 		                sprintf(status, ", in game AT Preparation");
1566 		            else
1567 		                sprintf(status, ", in channel \"%.64s\",", channel_get_name(channel));
1568 		    	    }
1569 		        else
1570 		            sprintf(status, ", is in AT Preparation");
1571 	    	    } else {
1572 		        if ((game = conn_get_game(dest_c)))
1573 		            sprintf(status, ", is in a game");
1574 		        else if ((channel = conn_get_channel(dest_c)))
1575 		            sprintf(status, ", is in a chat channel");
1576 		        else
1577 		            sprintf(status, ", is in AT Preparation");
1578 	    	    }
1579 		}
1580 
1581 		friend=account_get_name(friend_acc);
1582     		if (software[0]) snprintf(msgtemp, sizeof(msgtemp), "%d: %c%.16s%.128s, %.64s", i+1, friend_get_mutual(fr)?'*':' ', friend, status,software);
1583 		else snprintf(msgtemp, sizeof(msgtemp), "%d: %.16s%.128s", i+1, friend, status);
1584 		message_send_text(c,message_type_info,c,msgtemp);
1585 	    }
1586 	}
1587 	message_send_text(c,message_type_info,c,"=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
1588 	message_send_text(c,message_type_info,c,"End of Friends List");
1589 
1590 	return 0;
1591     }
1592 
1593     return 0;
1594 }
1595 
_handle_me_command(t_connection * c,char const * text)1596 static int _handle_me_command(t_connection * c, char const * text)
1597 {
1598   t_channel const * channel;
1599 
1600   if (!(channel = conn_get_channel(c)))
1601     {
1602       message_send_text(c,message_type_error,c,"You are not in a channel.");
1603       return 0;
1604     }
1605 
1606   text = skip_command(text);
1607 
1608   if ((text[0]!='\0') && (!conn_quota_exceeded(c,text)))
1609     channel_message_send(channel,message_type_emote,c,text);
1610   return 0;
1611 }
1612 
_handle_whisper_command(t_connection * c,char const * text)1613 static int _handle_whisper_command(t_connection * c, char const *text)
1614 {
1615   char         dest[USER_NAME_MAX+REALM_NAME_LEN]; /* both include NUL, so no need to add one for middle @ or * */
1616   unsigned int i,j;
1617 
1618   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
1619   for (; text[i]==' '; i++);
1620   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
1621     if (j<sizeof(dest)-1) dest[j++] = text[i];
1622   dest[j] = '\0';
1623   for (; text[i]==' '; i++);
1624 
1625   if ((dest[0]=='\0') || (text[i]=='\0'))
1626     {
1627       message_send_text(c,message_type_info,c,"usage: /whisper <username> <text to whisper>");
1628       return 0;
1629     }
1630 
1631   do_whisper(c,dest,&text[i]);
1632 
1633   return 0;
1634 }
1635 
_handle_status_command(t_connection * c,char const * text)1636 static int _handle_status_command(t_connection * c, char const *text)
1637 {
1638     char ctag[5];
1639     unsigned int i,j;
1640     t_clienttag clienttag;
1641 
1642     for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
1643     for (; text[i]==' '; i++);
1644     for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get clienttag */
1645 	if (j<sizeof(ctag)-1) ctag[j++] = text[i];
1646     ctag[j] = '\0';
1647 
1648     if (ctag[0]=='\0') {
1649 	snprintf(msgtemp, sizeof(msgtemp), "There are currently %d users online, in %d games and %d channels.",
1650 	    connlist_login_get_length(),
1651 	    gamelist_get_length(),
1652 	    channellist_get_length());
1653 	message_send_text(c,message_type_info,c,msgtemp);
1654 	tag_uint_to_str(ctag,conn_get_clienttag(c));
1655     }
1656 
1657     for (i=0; i<strlen(ctag); i++)
1658 	if (isascii((int)ctag[i]) && islower((int)ctag[i]))
1659 	    ctag[i] = toupper((int)ctag[i]);
1660 
1661     if (strcmp(ctag,"ALL") == 0)
1662 	clienttag = 0;
1663     else
1664 	clienttag = tag_case_str_to_uint(ctag);
1665 
1666     switch (clienttag)
1667     {
1668 	case 0:
1669 	case CLIENTTAG_WAR3XP_UINT:
1670 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1671 		conn_get_user_count_by_clienttag(CLIENTTAG_WAR3XP_UINT),
1672 		game_get_count_by_clienttag(CLIENTTAG_WAR3XP_UINT),
1673 		clienttag_get_title(CLIENTTAG_WAR3XP_UINT));
1674 	    message_send_text(c,message_type_info,c,msgtemp);
1675 	    if (clienttag) break;
1676 	case CLIENTTAG_WARCRAFT3_UINT:
1677 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1678 		conn_get_user_count_by_clienttag(CLIENTTAG_WARCRAFT3_UINT),
1679 		game_get_count_by_clienttag(CLIENTTAG_WARCRAFT3_UINT),
1680 		clienttag_get_title(CLIENTTAG_WARCRAFT3_UINT));
1681 	    message_send_text(c,message_type_info,c,msgtemp);
1682 	    if (clienttag) break;
1683 	case CLIENTTAG_DIABLO2XP_UINT:
1684 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1685 		conn_get_user_count_by_clienttag(CLIENTTAG_DIABLO2XP_UINT),
1686 		game_get_count_by_clienttag(CLIENTTAG_DIABLO2XP_UINT),
1687 		clienttag_get_title(CLIENTTAG_DIABLO2XP_UINT));
1688 	    message_send_text(c,message_type_info,c,msgtemp);
1689 	    if (clienttag) break;
1690 	case CLIENTTAG_DIABLO2DV_UINT:
1691 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1692 		conn_get_user_count_by_clienttag(CLIENTTAG_DIABLO2DV_UINT),
1693 		game_get_count_by_clienttag(CLIENTTAG_DIABLO2DV_UINT),
1694 		clienttag_get_title(CLIENTTAG_DIABLO2DV_UINT));
1695 	    message_send_text(c,message_type_info,c,msgtemp);
1696 	    if (clienttag) break;
1697 	case CLIENTTAG_BROODWARS_UINT:
1698 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1699 		conn_get_user_count_by_clienttag(CLIENTTAG_BROODWARS_UINT),
1700 		game_get_count_by_clienttag(CLIENTTAG_BROODWARS_UINT),
1701 		clienttag_get_title(CLIENTTAG_BROODWARS_UINT));
1702 	    message_send_text(c,message_type_info,c,msgtemp);
1703 	    if (clienttag) break;
1704 	case CLIENTTAG_STARCRAFT_UINT:
1705 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1706 		conn_get_user_count_by_clienttag(CLIENTTAG_STARCRAFT_UINT),
1707 		game_get_count_by_clienttag(CLIENTTAG_STARCRAFT_UINT),
1708 		clienttag_get_title(CLIENTTAG_STARCRAFT_UINT));
1709 	    message_send_text(c,message_type_info,c,msgtemp);
1710 	    if (clienttag) break;
1711 	case CLIENTTAG_WARCIIBNE_UINT:
1712 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1713 		conn_get_user_count_by_clienttag(CLIENTTAG_WARCIIBNE_UINT),
1714 		game_get_count_by_clienttag(CLIENTTAG_WARCIIBNE_UINT),
1715 		clienttag_get_title(CLIENTTAG_WARCIIBNE_UINT));
1716 	    message_send_text(c,message_type_info,c,msgtemp);
1717 	    if (clienttag) break;
1718 	case CLIENTTAG_DIABLORTL_UINT:
1719 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1720 		conn_get_user_count_by_clienttag(CLIENTTAG_DIABLORTL_UINT),
1721 		game_get_count_by_clienttag(CLIENTTAG_DIABLORTL_UINT),
1722 		clienttag_get_title(CLIENTTAG_DIABLORTL_UINT));
1723 	    message_send_text(c,message_type_info,c,msgtemp);
1724 	    if (clienttag) break;
1725 	default:
1726 	    snprintf(msgtemp, sizeof(msgtemp), "There are currently %u user(s) in %u games of %.128s",
1727 		conn_get_user_count_by_clienttag(conn_get_clienttag(c)),
1728 		game_get_count_by_clienttag(conn_get_clienttag(c)),
1729 		clienttag_get_title(conn_get_clienttag(c)));
1730 	    message_send_text(c,message_type_info,c,msgtemp);
1731     }
1732 
1733     return 0;
1734 }
1735 
_handle_who_command(t_connection * c,char const * text)1736 static int _handle_who_command(t_connection * c, char const *text)
1737 {
1738   t_connection const * conn;
1739   t_channel const *    channel;
1740   unsigned int         i;
1741   char const *         tname;
1742 
1743   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
1744   for (; text[i]==' '; i++);
1745 
1746   if (text[i]=='\0')
1747   {
1748 	message_send_text(c,message_type_info,c,"usage: /who <channel>");
1749 	return 0;
1750   }
1751 
1752   if (!(channel = channellist_find_channel_by_name(&text[i],conn_get_country(c),realm_get_name(conn_get_realm(c)))))
1753     {
1754       message_send_text(c,message_type_error,c,"That channel does not exist.");
1755       message_send_text(c,message_type_error,c,"(If you are trying to search for a user, use the /whois command.)");
1756       return 0;
1757     }
1758   if (channel_check_banning(channel,c)==1)
1759     {
1760       message_send_text(c,message_type_error,c,"You are banned from that channel.");
1761       return 0;
1762     }
1763 
1764   snprintf(msgtemp, sizeof(msgtemp), "Users in channel %.64s:",&text[i]);
1765   i = strlen(msgtemp);
1766   for (conn=channel_get_first(channel); conn; conn=channel_get_next())
1767     {
1768       if (i+strlen((tname = conn_get_username(conn)))+2>sizeof(msgtemp)) /* " ", name, '\0' */
1769 	{
1770 	  message_send_text(c,message_type_info,c,msgtemp);
1771 	  i = 0;
1772 	}
1773       sprintf(&msgtemp[i]," %s",tname);
1774       i += strlen(&msgtemp[i]);
1775     }
1776   if (i>0)
1777     message_send_text(c,message_type_info,c,msgtemp);
1778 
1779   return 0;
1780 }
1781 
_handle_whois_command(t_connection * c,char const * text)1782 static int _handle_whois_command(t_connection * c, char const * text)
1783 {
1784   unsigned int i;
1785 
1786   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
1787   for (; text[i]==' '; i++);
1788 
1789   if (text[i]=='\0')
1790   {
1791     message_send_text(c,message_type_info,c,"usage: /whois <username>");
1792     return 0;
1793   }
1794 
1795   do_whois(c,&text[i]);
1796 
1797   return 0;
1798 }
1799 
_handle_whoami_command(t_connection * c,char const * text)1800 static int _handle_whoami_command(t_connection * c, char const *text)
1801 {
1802   char const * tname;
1803 
1804   if (!(tname = conn_get_username(c)))
1805     {
1806       message_send_text(c,message_type_error,c,"Unable to obtain your account name.");
1807       return 0;
1808     }
1809 
1810   do_whois(c,tname);
1811 
1812   return 0;
1813 }
1814 
_handle_announce_command(t_connection * c,char const * text)1815 static int _handle_announce_command(t_connection * c, char const *text)
1816 {
1817   unsigned int i;
1818   t_message *  message;
1819 
1820   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
1821   for (; text[i]==' '; i++);
1822 
1823   if (text[i]=='\0')
1824   {
1825 	message_send_text(c,message_type_info,c,"usage: /announce <announcement>");
1826 	return 0;
1827   }
1828 
1829   snprintf(msgtemp, sizeof(msgtemp), "Announcement from %.64s: %.128s",conn_get_username(c),&text[i]);
1830   if (!(message = message_create(message_type_broadcast,c,NULL,msgtemp)))
1831     message_send_text(c,message_type_info,c,"Could not broadcast message.");
1832   else
1833     {
1834       if (message_send_all(message)<0)
1835 	message_send_text(c,message_type_info,c,"Could not broadcast message.");
1836       message_destroy(message);
1837     }
1838 
1839   return 0;
1840 }
1841 
_handle_beep_command(t_connection * c,char const * text)1842 static int _handle_beep_command(t_connection * c, char const *text)
1843 {
1844   message_send_text(c,message_type_info,c,"Audible notification on."); /* FIXME: actually do something */
1845   return 0; /* FIXME: these only affect CHAT clients... I think they prevent ^G from being sent */
1846 }
1847 
_handle_nobeep_command(t_connection * c,char const * text)1848 static int _handle_nobeep_command(t_connection * c, char const *text)
1849 {
1850   message_send_text(c,message_type_info,c,"Audible notification off."); /* FIXME: actually do something */
1851   return 0;
1852 }
1853 
_handle_version_command(t_connection * c,char const * text)1854 static int _handle_version_command(t_connection * c, char const *text)
1855 {
1856   message_send_text(c,message_type_info,c,PVPGN_SOFTWARE" "PVPGN_VERSION);
1857   return 0;
1858 }
1859 
_handle_copyright_command(t_connection * c,char const * text)1860 static int _handle_copyright_command(t_connection * c, char const *text)
1861 {
1862   static char const * const info[] =
1863     {
1864       " Copyright (C) 2002  See source for details",
1865       " ",
1866       " PvPGN is free software; you can redistribute it and/or",
1867       " modify it under the terms of the GNU General Public License",
1868       " as published by the Free Software Foundation; either version 2",
1869       " of the License, or (at your option) any later version.",
1870       " ",
1871       " This program is distributed in the hope that it will be useful,",
1872       " but WITHOUT ANY WARRANTY; without even the implied warranty of",
1873       " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
1874       " GNU General Public License for more details.",
1875       " ",
1876       " You should have received a copy of the GNU General Public License",
1877       " along with this program; if not, write to the Free Software",
1878       " Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.",
1879       NULL
1880     };
1881   unsigned int i;
1882 
1883   for (i=0; info[i]; i++)
1884     message_send_text(c,message_type_info,c,info[i]);
1885 
1886   return 0;
1887 }
1888 
_handle_uptime_command(t_connection * c,char const * text)1889 static int _handle_uptime_command(t_connection * c, char const *text)
1890 {
1891 
1892   snprintf(msgtemp, sizeof(msgtemp), "Uptime: %.128s",seconds_to_timestr(server_get_uptime()));
1893   message_send_text(c,message_type_info,c,msgtemp);
1894 
1895   return 0;
1896 }
1897 
_handle_stats_command(t_connection * c,char const * text)1898 static int _handle_stats_command(t_connection * c, char const *text)
1899 {
1900     char         dest[USER_NAME_MAX];
1901     unsigned int i,j;
1902     t_account *  account;
1903     char const * clienttag=NULL;
1904     t_clienttag  clienttag_uint;
1905     char         clienttag_str[5];
1906 
1907     for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
1908     for (; text[i]==' '; i++);
1909     for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
1910 	if (j<sizeof(dest)-1) dest[j++] = text[i];
1911     dest[j] = '\0';
1912     for (; text[i]==' '; i++);
1913 
1914     if (!dest[0]) {
1915 	account = conn_get_account(c);
1916     } else if (!(account = accountlist_find_account(dest))) {
1917 	message_send_text(c,message_type_error,c,"Invalid user.");
1918 	return 0;
1919     }
1920 
1921     if (text[i]!='\0')
1922 	clienttag = &text[i];
1923     else if (!(clienttag = tag_uint_to_str(clienttag_str,conn_get_clienttag(c)))) {
1924 	message_send_text(c,message_type_error,c,"Unable to determine client game.");
1925 	return 0;
1926     }
1927 
1928     if (strlen(clienttag)!=4) {
1929 	snprintf(msgtemp, sizeof(msgtemp), "You must supply a user name and a valid program ID. (Program ID \"%.32s\" is invalid.)",clienttag);
1930 	message_send_text(c,message_type_error,c,msgtemp);
1931 	message_send_text(c,message_type_error,c,"Example: /stats joe STAR");
1932 	return 0;
1933     }
1934 
1935     clienttag_uint = tag_case_str_to_uint(clienttag);
1936 
1937     switch (clienttag_uint)
1938     {
1939 	case CLIENTTAG_BNCHATBOT_UINT:
1940 	    message_send_text(c,message_type_error,c,"This game does not support win/loss records.");
1941 	    message_send_text(c,message_type_error,c,"You must supply a user name and a valid program ID.");
1942 	    message_send_text(c,message_type_error,c,"Example: /stats joe STAR");
1943 	    return 0;
1944 	case CLIENTTAG_DIABLORTL_UINT:
1945 	case CLIENTTAG_DIABLOSHR_UINT:
1946 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s's record:",account_get_name(account));
1947 	    message_send_text(c,message_type_info,c,msgtemp);
1948 	    snprintf(msgtemp, sizeof(msgtemp), "level: %u",account_get_normal_level(account,clienttag_uint));
1949 	    message_send_text(c,message_type_info,c,msgtemp);
1950 	    snprintf(msgtemp, sizeof(msgtemp), "class: %.16s",bnclass_get_str(account_get_normal_class(account,clienttag_uint)));
1951 	    message_send_text(c,message_type_info,c,msgtemp);
1952 	    snprintf(msgtemp, sizeof(msgtemp), "stats: %u str  %u mag  %u dex  %u vit  %u gld",
1953 		account_get_normal_strength(account,clienttag_uint),
1954 		account_get_normal_magic(account,clienttag_uint),
1955 		account_get_normal_dexterity(account,clienttag_uint),
1956 		account_get_normal_vitality(account,clienttag_uint),
1957 		account_get_normal_gold(account,clienttag_uint));
1958 	    message_send_text(c,message_type_info,c,msgtemp);
1959 	    snprintf(msgtemp, sizeof(msgtemp), "Diablo kills: %u",account_get_normal_diablo_kills(account,clienttag_uint));
1960 	    message_send_text(c,message_type_info,c,msgtemp);
1961 	    return 0;
1962 	case CLIENTTAG_WARCIIBNE_UINT:
1963 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s's record:",account_get_name(account));
1964 	    message_send_text(c,message_type_info,c,msgtemp);
1965 	    snprintf(msgtemp, sizeof(msgtemp), "Normal games: %u-%u-%u",
1966 		account_get_normal_wins(account,clienttag_uint),
1967 		account_get_normal_losses(account,clienttag_uint),
1968 		account_get_normal_disconnects(account,clienttag_uint));
1969 	    message_send_text(c,message_type_info,c,msgtemp);
1970 	    if (account_get_ladder_rating(account,clienttag_uint,ladder_id_normal)>0)
1971 		snprintf(msgtemp, sizeof(msgtemp), "Ladder games: %u-%u-%u (rating %d)",
1972 		    account_get_ladder_wins(account,clienttag_uint,ladder_id_normal),
1973 		    account_get_ladder_losses(account,clienttag_uint,ladder_id_normal),
1974 		    account_get_ladder_disconnects(account,clienttag_uint,ladder_id_normal),
1975 		    account_get_ladder_rating(account,clienttag_uint,ladder_id_normal));
1976 	    else
1977 		strcpy(msgtemp,"Ladder games: 0-0-0");
1978 	    message_send_text(c,message_type_info,c,msgtemp);
1979 	    if (account_get_ladder_rating(account,clienttag_uint,ladder_id_ironman)>0)
1980 		snprintf(msgtemp, sizeof(msgtemp), "IronMan games: %u-%u-%u (rating %d)",
1981 		    account_get_ladder_wins(account,clienttag_uint,ladder_id_ironman),
1982 		    account_get_ladder_losses(account,clienttag_uint,ladder_id_ironman),
1983 		    account_get_ladder_disconnects(account,clienttag_uint,ladder_id_ironman),
1984 		    account_get_ladder_rating(account,clienttag_uint,ladder_id_ironman));
1985 	    else
1986 		strcpy(msgtemp,"IronMan games: 0-0-0");
1987 	    message_send_text(c,message_type_info,c,msgtemp);
1988 	    return 0;
1989 	case CLIENTTAG_WARCRAFT3_UINT:
1990 	case CLIENTTAG_WAR3XP_UINT:
1991 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s's Ladder Record's:",account_get_name(account));
1992 	    message_send_text(c,message_type_info,c,msgtemp);
1993 	    snprintf(msgtemp, sizeof(msgtemp), "Users Solo Level: %u, Experience: %u",
1994 		account_get_ladder_level(account,clienttag_uint,ladder_id_solo),
1995 		account_get_ladder_xp(account,clienttag_uint,ladder_id_solo));
1996 	    message_send_text(c,message_type_info,c,msgtemp);
1997 	    snprintf(msgtemp, sizeof(msgtemp), "SOLO Ladder Record: %u-%u-0",
1998 		account_get_ladder_wins(account,clienttag_uint,ladder_id_solo),
1999 		account_get_ladder_losses(account,clienttag_uint,ladder_id_solo));
2000 	    message_send_text(c,message_type_info,c,msgtemp);
2001 	    snprintf(msgtemp, sizeof(msgtemp), "SOLO Rank: %u",
2002 		account_get_ladder_rank(account,clienttag_uint,ladder_id_solo));
2003 	    message_send_text(c,message_type_info,c,msgtemp);
2004 	    snprintf(msgtemp, sizeof(msgtemp), "Users Team Level: %u, Experience: %u",
2005 		account_get_ladder_level(account,clienttag_uint,ladder_id_team),
2006 		account_get_ladder_xp(account,clienttag_uint,ladder_id_team));
2007 	    message_send_text(c,message_type_info,c,msgtemp);
2008 	    snprintf(msgtemp, sizeof(msgtemp), "TEAM Ladder Record: %u-%u-0",
2009 		account_get_ladder_wins(account,clienttag_uint,ladder_id_team),
2010 		account_get_ladder_losses(account,clienttag_uint,ladder_id_team));
2011 	    message_send_text(c,message_type_info,c,msgtemp);
2012 	    snprintf(msgtemp, sizeof(msgtemp), "TEAM Rank: %u",
2013 		account_get_ladder_rank(account,clienttag_uint,ladder_id_team));
2014 	    message_send_text(c,message_type_info,c,msgtemp);
2015 	    snprintf(msgtemp, sizeof(msgtemp), "Users FFA Level: %u, Experience: %u",
2016 		account_get_ladder_level(account,clienttag_uint,ladder_id_ffa),
2017 		account_get_ladder_xp(account,clienttag_uint,ladder_id_ffa));
2018 	    message_send_text(c,message_type_info,c,msgtemp);
2019 	    snprintf(msgtemp, sizeof(msgtemp), "FFA Ladder Record: %u-%u-0",
2020 		account_get_ladder_wins(account,clienttag_uint,ladder_id_ffa),
2021 		account_get_ladder_losses(account,clienttag_uint,ladder_id_ffa));
2022 	    message_send_text(c,message_type_info,c,msgtemp);
2023 	    snprintf(msgtemp, sizeof(msgtemp), "FFA Rank: %u",
2024 		account_get_ladder_rank(account,clienttag_uint,ladder_id_ffa));
2025 	    message_send_text(c,message_type_info,c,msgtemp);
2026 	    if (account_get_teams(account)) {
2027 		t_elem * curr;
2028 		t_list * list;
2029 		t_team * team;
2030 		int teamcount = 0;
2031 
2032 		list = account_get_teams(account);
2033 
2034 		LIST_TRAVERSE(list,curr)
2035 		{
2036 	    	  if (!(team = elem_get_data(curr)))
2037 	    	  {
2038 	      	    eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
2039 	      	    continue;
2040 	    	    }
2041 
2042 	          if (team_get_clienttag(team) != clienttag_uint)
2043 	            continue;
2044 
2045 		    teamcount++;
2046 		    snprintf(msgtemp, sizeof(msgtemp), "Users AT Team No. %u",teamcount);
2047 		    message_send_text(c,message_type_info,c,msgtemp);
2048 		    snprintf(msgtemp, sizeof(msgtemp), "Users AT TEAM Level: %u, Experience: %u",
2049 			team_get_level(team),team_get_xp(team));
2050 		    message_send_text(c,message_type_info,c,msgtemp);
2051 		    snprintf(msgtemp, sizeof(msgtemp), "AT TEAM Ladder Record: %u-%u-0",
2052 			team_get_wins(team),team_get_losses(team));
2053 		    message_send_text(c,message_type_info,c,msgtemp);
2054 		    snprintf(msgtemp, sizeof(msgtemp), "AT TEAM Rank: %u",
2055 			team_get_rank(team));
2056 		    message_send_text(c,message_type_info,c,msgtemp);
2057 		}
2058 	    }
2059 	    return 0;
2060 	default:
2061 	    snprintf(msgtemp, sizeof(msgtemp), "%.64s's record:",account_get_name(account));
2062 	    message_send_text(c,message_type_info,c,msgtemp);
2063 	    snprintf(msgtemp, sizeof(msgtemp), "Normal games: %u-%u-%u",
2064 		account_get_normal_wins(account,clienttag_uint),
2065 		account_get_normal_losses(account,clienttag_uint),
2066 		account_get_normal_disconnects(account,clienttag_uint));
2067 	    message_send_text(c,message_type_info,c,msgtemp);
2068 	    if (account_get_ladder_rating(account,clienttag_uint,ladder_id_normal)>0)
2069 		snprintf(msgtemp, sizeof(msgtemp), "Ladder games: %u-%u-%u (rating %d)",
2070 		    account_get_ladder_wins(account,clienttag_uint,ladder_id_normal),
2071 		    account_get_ladder_losses(account,clienttag_uint,ladder_id_normal),
2072 		    account_get_ladder_disconnects(account,clienttag_uint,ladder_id_normal),
2073 		    account_get_ladder_rating(account,clienttag_uint,ladder_id_normal));
2074 	    else
2075 		strcpy(msgtemp,"Ladder games: 0-0-0");
2076 	    message_send_text(c,message_type_info,c,msgtemp);
2077 	    return 0;
2078     }
2079 }
2080 
_handle_time_command(t_connection * c,char const * text)2081 static int _handle_time_command(t_connection * c, char const *text)
2082 {
2083   t_bnettime  btsystem;
2084   t_bnettime  btlocal;
2085   time_t      now;
2086   struct tm * tmnow;
2087 
2088   btsystem = bnettime();
2089 
2090   /* Battle.net time: Wed Jun 23 15:15:29 */
2091   btlocal = bnettime_add_tzbias(btsystem,local_tzbias());
2092   now = bnettime_to_time(btlocal);
2093   if (!(tmnow = gmtime(&now)))
2094     strcpy(msgtemp,"PvPGN Server Time: ?");
2095   else
2096     strftime(msgtemp,sizeof(msgtemp),"PvPGN Server Time: %a %b %d %H:%M:%S",tmnow);
2097   message_send_text(c,message_type_info,c,msgtemp);
2098   if (conn_get_class(c)==conn_class_bnet)
2099     {
2100       btlocal = bnettime_add_tzbias(btsystem,conn_get_tzbias(c));
2101       now = bnettime_to_time(btlocal);
2102       if (!(tmnow = gmtime(&now)))
2103 	strcpy(msgtemp,"Your local time: ?");
2104       else
2105 	strftime(msgtemp,sizeof(msgtemp),"Your local time: %a %b %d %H:%M:%S",tmnow);
2106       message_send_text(c,message_type_info,c,msgtemp);
2107     }
2108 
2109   return 0;
2110 }
2111 
_handle_channel_command(t_connection * c,char const * text)2112 static int _handle_channel_command(t_connection * c, char const *text)
2113  {
2114    t_channel * channel;
2115 
2116    text = skip_command(text);
2117 
2118    if (conn_get_wol(c)) {
2119       message_send_text(c,message_type_error,c,"Sorry, this command is currently disabled for WOL clients.");
2120       return 0;
2121 
2122    }
2123 
2124    if (text[0]=='\0')
2125      {
2126        message_send_text(c,message_type_info,c,"usage /channel <channel>");
2127        return 0;
2128      }
2129 
2130    if(strcasecmp(text,"Arranged Teams")==0)
2131      {
2132 //       if(account_get_auth_admin(conn_get_account(c))>0)
2133 //	 {
2134 //	   message_send_text(c,message_type_error,c,"Please do not talk in channel Arranged Teams");
2135 //	   message_send_text(c,message_type_error,c,"This channel is dedicated for the preparation of");
2136 //	   message_send_text(c,message_type_error,c,"Arranged Team Games.");
2137 //	 }
2138 //       else
2139 //	 {
2140 	   message_send_text(c,message_type_error,c,"Channel Arranged Teams is a RESTRICTED Channel!");
2141 	   return 0;
2142 //	 }
2143      }
2144 
2145    if (!(strlen(text) < CHANNEL_NAME_LEN))
2146    {
2147      snprintf(msgtemp, sizeof(msgtemp), "max channel name length exceeded (max %d symbols)", CHANNEL_NAME_LEN - 1);
2148      message_send_text(c,message_type_error,c,msgtemp);
2149      return 0;
2150    }
2151 
2152    if ((channel = conn_get_channel(c)) && (strcasecmp(channel_get_name(channel),text)==0))
2153      return 0; // we don't have to do anything, we are allready in this channel
2154 
2155    if (conn_set_channel(c,text)<0)
2156      conn_set_channel(c,CHANNEL_NAME_BANNED); /* should not fail */
2157    if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) == CLIENTTAG_WAR3XP_UINT))
2158      conn_update_w3_playerinfo(c);
2159    command_set_flags(c);
2160 
2161    return 0;
2162  }
2163 
_handle_rejoin_command(t_connection * c,char const * text)2164 static int _handle_rejoin_command(t_connection * c, char const *text)
2165 {
2166 
2167   if (channel_rejoin(c)!=0)
2168       message_send_text(c,message_type_error,c,"You are not in a channel.");
2169   if ((conn_get_clienttag(c) == CLIENTTAG_WARCRAFT3_UINT) || (conn_get_clienttag(c) ==  CLIENTTAG_WAR3XP_UINT))
2170     conn_update_w3_playerinfo(c);
2171   command_set_flags(c);
2172 
2173   return 0;
2174 }
2175 
_handle_away_command(t_connection * c,char const * text)2176 static int _handle_away_command(t_connection * c, char const *text)
2177 {
2178 
2179   text = skip_command(text);
2180 
2181   if (text[0]=='\0') /* toggle away mode */
2182     {
2183       if (!conn_get_awaystr(c))
2184       {
2185 	message_send_text(c,message_type_info,c,"You are now marked as being away.");
2186 	conn_set_awaystr(c,"Currently not available");
2187       }
2188       else
2189       {
2190         message_send_text(c,message_type_info,c,"You are no longer marked as away.");
2191         conn_set_awaystr(c,NULL);
2192       }
2193     }
2194   else
2195     {
2196       message_send_text(c,message_type_info,c,"You are now marked as being away.");
2197       conn_set_awaystr(c,text);
2198     }
2199 
2200   return 0;
2201 }
2202 
_handle_dnd_command(t_connection * c,char const * text)2203 static int _handle_dnd_command(t_connection * c, char const *text)
2204 {
2205 
2206   text = skip_command(text);
2207 
2208   if (text[0]=='\0') /* toggle dnd mode */
2209     {
2210       if (!conn_get_dndstr(c))
2211       {
2212 	message_send_text(c,message_type_info,c,"Do Not Disturb mode engaged.");
2213 	conn_set_dndstr(c,"Not available");
2214       }
2215       else
2216       {
2217         message_send_text(c,message_type_info,c,"Do Not Disturb mode cancelled.");
2218         conn_set_dndstr(c,NULL);
2219       }
2220     }
2221   else
2222     {
2223       message_send_text(c,message_type_info,c,"Do Not Disturb mode engaged.");
2224       conn_set_dndstr(c,text);
2225     }
2226 
2227   return 0;
2228 }
2229 
_handle_squelch_command(t_connection * c,char const * text)2230 static int _handle_squelch_command(t_connection * c, char const *text)
2231 {
2232   t_account *  account;
2233 
2234   text = skip_command(text);
2235 
2236   /* D2 puts * before username */
2237   if (text[0]=='*')
2238     text++;
2239 
2240   if (text[0]=='\0')
2241     {
2242       message_send_text(c,message_type_info,c,"usage: /squelch <username>");
2243       return 0;
2244     }
2245 
2246   if (!(account = accountlist_find_account(text)))
2247     {
2248       message_send_text(c,message_type_error,c,"No such user.");
2249       return 0;
2250     }
2251 
2252   if (conn_get_account(c)==account)
2253     {
2254       message_send_text(c,message_type_error,c,"You can't squelch yourself.");
2255       return 0;
2256     }
2257 
2258   if (conn_add_ignore(c,account)<0)
2259     message_send_text(c,message_type_error,c,"Could not squelch user.");
2260   else
2261     {
2262       snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been squelched.",account_get_name(account));
2263       message_send_text(c,message_type_info,c,msgtemp);
2264     }
2265 
2266   return 0;
2267 }
2268 
_handle_unsquelch_command(t_connection * c,char const * text)2269 static int _handle_unsquelch_command(t_connection * c, char const *text)
2270 {
2271   t_account * account;
2272   t_connection * dest_c;
2273 
2274   text = skip_command(text);
2275 
2276   /* D2 puts * before username */
2277   if (text[0]=='*')
2278     text++;
2279 
2280   if (text[0]=='\0')
2281     {
2282       message_send_text(c,message_type_info,c,"usage: /unsquelch <username>");
2283       return 0;
2284     }
2285 
2286   if (!(account = accountlist_find_account(text)))
2287     {
2288       message_send_text(c,message_type_info,c,"No such user.");
2289       return 0;
2290     }
2291 
2292   if (conn_del_ignore(c,account)<0)
2293     message_send_text(c,message_type_info,c,"User was not being ignored.");
2294   else
2295     {
2296       t_message * message;
2297 
2298       message_send_text(c,message_type_info,c,"No longer ignoring.");
2299 
2300       if ((dest_c = account_get_conn(account)))
2301       {
2302         if (!(message = message_create(message_type_userflags,dest_c,NULL,NULL))) /* handles NULL text */
2303 	    return 0;
2304         message_send(message,c);
2305         message_destroy(message);
2306       }
2307     }
2308 
2309   return 0;
2310 }
2311 
_handle_kick_command(t_connection * c,char const * text)2312 static int _handle_kick_command(t_connection * c, char const *text)
2313 {
2314   char              dest[USER_NAME_MAX];
2315   unsigned int      i,j;
2316   t_channel const * channel;
2317   t_connection *    kuc;
2318   t_account *	    acc;
2319 
2320   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2321   for (; text[i]==' '; i++);
2322   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
2323     if (j<sizeof(dest)-1) dest[j++] = text[i];
2324   dest[j] = '\0';
2325   for (; text[i]==' '; i++);
2326 
2327   if (dest[0]=='\0')
2328     {
2329       message_send_text(c,message_type_info,c,"usage: /kick <username>");
2330       return 0;
2331     }
2332 
2333   if (!(channel = conn_get_channel(c)))
2334     {
2335       message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
2336       return 0;
2337     }
2338 
2339   acc = conn_get_account(c);
2340   if (account_get_auth_admin(acc,NULL)!=1 && /* default to false */
2341       account_get_auth_admin(acc,channel_get_name(channel))!=1 && /* default to false */
2342       account_get_auth_operator(acc,NULL)!=1 && /* default to false */
2343       account_get_auth_operator(acc,channel_get_name(channel))!=1 && /* default to false */
2344       !channel_conn_is_tmpOP(channel,account_get_conn(acc)))
2345     {
2346       message_send_text(c,message_type_error,c,"You have to be at least a Channel Operator or tempOP to use this command.");
2347       return 0;
2348     }
2349   if (!(kuc = connlist_find_connection_by_accountname(dest)))
2350     {
2351       message_send_text(c,message_type_error,c,"That user is not logged in.");
2352       return 0;
2353     }
2354   if (conn_get_channel(kuc)!=channel)
2355     {
2356       message_send_text(c,message_type_error,c,"That user is not in this channel.");
2357       return 0;
2358     }
2359   if (account_get_auth_admin(conn_get_account(kuc),NULL)==1 ||
2360     account_get_auth_admin(conn_get_account(kuc),channel_get_name(channel))==1)
2361     {
2362       message_send_text(c,message_type_error,c,"You cannot kick administrators.");
2363       return 0;
2364     }
2365   else if (account_get_auth_operator(conn_get_account(kuc),NULL)==1 ||
2366     account_get_auth_operator(conn_get_account(kuc),channel_get_name(channel))==1)
2367     {
2368       message_send_text(c,message_type_error,c,"You cannot kick operators.");
2369       return 0;
2370     }
2371 
2372   {
2373     char const * tname1;
2374     char const * tname2;
2375 
2376     tname1 = conn_get_loggeduser(kuc);
2377     tname2 = conn_get_loggeduser(c);
2378     if (!tname1 || !tname2) {
2379 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL username");
2380 	return -1;
2381     }
2382 
2383     if (text[i]!='\0')
2384       snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been kicked by %-.20s (%.128s).",tname1,tname2,&text[i]);
2385     else
2386       snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been kicked by %-.20s.",tname1,tname2);
2387     channel_message_send(channel,message_type_info,c,msgtemp);
2388   }
2389   conn_set_channel(kuc,CHANNEL_NAME_KICKED); /* should not fail */
2390 
2391   return 0;
2392 }
2393 
_handle_ban_command(t_connection * c,char const * text)2394 static int _handle_ban_command(t_connection * c, char const *text)
2395 {
2396   char           dest[USER_NAME_MAX];
2397   unsigned int   i,j;
2398   t_channel *    channel;
2399   t_connection * buc;
2400 
2401   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2402   for (; text[i]==' '; i++);
2403   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
2404     if (j<sizeof(dest)-1) dest[j++] = text[i];
2405   dest[j] = '\0';
2406   for (; text[i]==' '; i++);
2407 
2408   if (dest[0]=='\0')
2409     {
2410       message_send_text(c,message_type_info,c,"usage. /ban <username>");
2411       return 0;
2412     }
2413 
2414   if (!(channel = conn_get_channel(c)))
2415     {
2416       message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
2417       return 0;
2418     }
2419   if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && /* default to false */
2420       account_get_auth_admin(conn_get_account(c),channel_get_name(channel))!=1 && /* default to false */
2421       account_get_auth_operator(conn_get_account(c),NULL)!=1 && /* default to false */
2422       account_get_auth_operator(conn_get_account(c),channel_get_name(channel))!=1) /* default to false */
2423     {
2424       message_send_text(c,message_type_error,c,"You have to be at least a Channel Operator to use this command.");
2425       return 0;
2426     }
2427   {
2428     t_account * account;
2429 
2430     if (!(account = accountlist_find_account(dest)))
2431       message_send_text(c,message_type_info,c,"That account doesn't currently exist, banning anyway.");
2432     else if (account_get_auth_admin(account,NULL)==1 || account_get_auth_admin(account,channel_get_name(channel))==1)
2433       {
2434         message_send_text(c,message_type_error,c,"You cannot ban administrators.");
2435         return 0;
2436       }
2437     else if (account_get_auth_operator(account,NULL)==1 ||
2438 	account_get_auth_operator(account,channel_get_name(channel))==1)
2439       {
2440         message_send_text(c,message_type_error,c,"You cannot ban operators.");
2441         return 0;
2442       }
2443   }
2444 
2445   if (channel_ban_user(channel,dest)<0)
2446     {
2447       snprintf(msgtemp, sizeof(msgtemp), "Unable to ban %-.20s.",dest);
2448       message_send_text(c,message_type_error,c,msgtemp);
2449     }
2450   else
2451     {
2452       char const * tname;
2453 
2454       tname = conn_get_loggeduser(c);
2455       if (text[i]!='\0')
2456 	snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been banned by %-.20s (%.128s).",dest,tname?tname:"unknown",&text[i]);
2457       else
2458 	snprintf(msgtemp, sizeof(msgtemp), "%-.20s has been banned by %-.20s.",dest,tname?tname:"unknown");
2459       channel_message_send(channel,message_type_info,c,msgtemp);
2460     }
2461   if ((buc = connlist_find_connection_by_accountname(dest)) &&
2462       conn_get_channel(buc)==channel)
2463     conn_set_channel(buc,CHANNEL_NAME_BANNED);
2464 
2465   return 0;
2466 }
2467 
_handle_unban_command(t_connection * c,char const * text)2468 static int _handle_unban_command(t_connection * c, char const *text)
2469 {
2470   t_channel *  channel;
2471   unsigned int i;
2472 
2473   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2474   for (; text[i]==' '; i++);
2475 
2476   if (text[i]=='\0')
2477     {
2478       message_send_text(c,message_type_info,c,"usage: /unban <username>");
2479       return 0;
2480     }
2481 
2482   if (!(channel = conn_get_channel(c)))
2483     {
2484       message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
2485       return 0;
2486     }
2487   if (account_get_auth_admin(conn_get_account(c),NULL)!=1 && /* default to false */
2488       account_get_auth_admin(conn_get_account(c),channel_get_name(channel))!=1 && /* default to false */
2489       account_get_auth_operator(conn_get_account(c),NULL)!=1 && /* default to false */
2490       account_get_auth_operator(conn_get_account(c),channel_get_name(channel))!=1) /* default to false */
2491     {
2492       message_send_text(c,message_type_error,c,"You are not a channel operator.");
2493       return 0;
2494     }
2495 
2496   if (channel_unban_user(channel,&text[i])<0)
2497     message_send_text(c,message_type_error,c,"That user is not banned.");
2498   else
2499     {
2500       snprintf(msgtemp, sizeof(msgtemp), "%.64s is no longer banned from this channel.",&text[i]);
2501       message_send_text(c,message_type_info,c,msgtemp);
2502     }
2503 
2504   return 0;
2505 }
2506 
_handle_reply_command(t_connection * c,char const * text)2507 static int _handle_reply_command(t_connection * c, char const *text)
2508 {
2509   unsigned int i;
2510   char const * dest;
2511 
2512   if (!(dest = conn_get_lastsender(c)))
2513     {
2514       message_send_text(c,message_type_error,c,"No one messaged you, use /m instead");
2515       return 0;
2516     }
2517 
2518   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2519   for (; text[i]==' '; i++);
2520 
2521   if (text[i]=='\0')
2522     {
2523       message_send_text(c,message_type_info,c,"usage: /reply <replytext>");
2524       return 0;
2525     }
2526   do_whisper(c,dest,&text[i]);
2527   return 0;
2528 }
2529 
_handle_realmann_command(t_connection * c,char const * text)2530 static int _handle_realmann_command(t_connection * c, char const *text)
2531 {
2532   unsigned int i;
2533   t_realm * realm;
2534   t_realm * trealm;
2535   t_connection * tc;
2536   t_elem const * curr;
2537   t_message    * message;
2538 
2539   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2540   for (; text[i]==' '; i++);
2541 
2542   if (!(realm=conn_get_realm(c))) {
2543     message_send_text(c,message_type_info,c,"You must join a realm first");
2544     return 0;
2545   }
2546 
2547   if (text[i]=='\0')
2548   {
2549     message_send_text(c,message_type_info,c,"usage: /realmann <announcement text>");
2550     return 0;
2551   }
2552 
2553   snprintf(msgtemp, sizeof(msgtemp), "Announcement from %.32s@%.32s: %.128s",conn_get_username(c),realm_get_name(realm),&text[i]);
2554   if (!(message = message_create(message_type_broadcast,c,NULL,msgtemp)))
2555     {
2556       message_send_text(c,message_type_info,c,"Could not broadcast message.");
2557     }
2558   else
2559     {
2560       LIST_TRAVERSE_CONST(connlist(),curr)
2561 	{
2562 	  tc = elem_get_data(curr);
2563 	  if (!tc)
2564 	    continue;
2565 	  if ((trealm = conn_get_realm(tc)) && (trealm==realm))
2566 	    {
2567 	      message_send(message,tc);
2568 	    }
2569 	}
2570     }
2571   return 0;
2572 }
2573 
_handle_watch_command(t_connection * c,char const * text)2574 static int _handle_watch_command(t_connection * c, char const *text)
2575 {
2576   unsigned int i;
2577   t_account *  account;
2578 
2579   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2580   for (; text[i]==' '; i++);
2581 
2582   if (text[i]=='\0')
2583     {
2584       message_send_text(c,message_type_info,c,"usage: /watch <username>");
2585       return 0;
2586     }
2587   if (!(account = accountlist_find_account(&text[i])))
2588     {
2589       message_send_text(c,message_type_info,c,"That user does not exist.");
2590       return 0;
2591     }
2592 
2593   if (conn_add_watch(c,account,0)<0) /* FIXME: adds all events for now */
2594     message_send_text(c,message_type_error,c,"Add to watch list failed.");
2595   else
2596     {
2597       snprintf(msgtemp, sizeof(msgtemp), "User %.64s added to your watch list.",&text[i]);
2598       message_send_text(c,message_type_info,c,msgtemp);
2599     }
2600 
2601   return 0;
2602 }
2603 
_handle_unwatch_command(t_connection * c,char const * text)2604 static int _handle_unwatch_command(t_connection * c, char const *text)
2605  {
2606    unsigned int i;
2607    t_account *  account;
2608 
2609    for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2610    for (; text[i]==' '; i++);
2611 
2612    if (text[i]=='\0')
2613      {
2614        message_send_text(c,message_type_info,c,"usage: /unwatch <username>");
2615        return 0;
2616      }
2617    if (!(account = accountlist_find_account(&text[i])))
2618      {
2619        message_send_text(c,message_type_info,c,"That user does not exist.");
2620        return 0;
2621      }
2622 
2623    if (conn_del_watch(c,account,0)<0) /* FIXME: deletes all events for now */
2624      message_send_text(c,message_type_error,c,"Removal from watch list failed.");
2625    else
2626      {
2627        snprintf(msgtemp, sizeof(msgtemp), "User %.64s removed from your watch list.",&text[i]);
2628        message_send_text(c,message_type_info,c,msgtemp);
2629      }
2630 
2631    return 0;
2632  }
2633 
_handle_watchall_command(t_connection * c,char const * text)2634 static int _handle_watchall_command(t_connection * c, char const *text)
2635 {
2636     t_clienttag clienttag=0;
2637     char clienttag_str[5];
2638 
2639     text = skip_command(text);
2640 
2641     if(text[0] != '\0') {
2642 	if (strlen(text) != 4) {
2643     	    message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID.");
2644     	    message_send_text(c,message_type_error,c,"Example: /watchall STAR");
2645     	    return 0;
2646 	}
2647 	clienttag = tag_case_str_to_uint(text);
2648     }
2649 
2650     if (conn_add_watch(c,NULL,clienttag)<0) /* FIXME: adds all events for now */
2651 	message_send_text(c,message_type_error,c,"Add to watch list failed.");
2652     else
2653 	if(clienttag) {
2654 	    char msgtemp[MAX_MESSAGE_LEN];
2655 	    snprintf(msgtemp, sizeof(msgtemp), "All %.128s users added to your watch list.", tag_uint_to_str(clienttag_str,clienttag));
2656 	    message_send_text(c,message_type_info,c,msgtemp);
2657 	}
2658 	else
2659 	    message_send_text(c,message_type_info,c,"All users added to your watch list.");
2660 
2661     return 0;
2662 }
2663 
_handle_unwatchall_command(t_connection * c,char const * text)2664 static int _handle_unwatchall_command(t_connection * c, char const *text)
2665 {
2666     t_clienttag clienttag=0;
2667     char clienttag_str[5];
2668 
2669     text = skip_command(text);
2670 
2671     if(text[0] != '\0') {
2672 	if (strlen(text) != 4) {
2673     	    message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID.");
2674     	    message_send_text(c,message_type_error,c,"Example: /unwatchall STAR");
2675 	}
2676 	clienttag = tag_case_str_to_uint(text);
2677     }
2678 
2679     if (conn_del_watch(c,NULL,clienttag)<0) /* FIXME: deletes all events for now */
2680 	message_send_text(c,message_type_error,c,"Removal from watch list failed.");
2681     else
2682 	if(clienttag) {
2683 	    char msgtemp[MAX_MESSAGE_LEN];
2684 	    snprintf(msgtemp, sizeof(msgtemp), "All %.128s users removed from your watch list.", tag_uint_to_str(clienttag_str,clienttag));
2685 	    message_send_text(c,message_type_info,c,msgtemp);
2686 	}
2687 	else
2688 	    message_send_text(c,message_type_info,c,"All users removed from your watch list.");
2689 
2690     return 0;
2691 }
2692 
_handle_lusers_command(t_connection * c,char const * text)2693 static int _handle_lusers_command(t_connection * c, char const *text)
2694 {
2695   t_channel *    channel;
2696   t_elem const * curr;
2697   char const *   banned;
2698   unsigned int   i;
2699 
2700   if (!(channel = conn_get_channel(c)))
2701     {
2702       message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
2703       return 0;
2704     }
2705 
2706   strcpy(msgtemp,"Banned users:");
2707   i = strlen(msgtemp);
2708   LIST_TRAVERSE_CONST(channel_get_banlist(channel),curr)
2709     {
2710       banned = elem_get_data(curr);
2711       if (i+strlen(banned)+2>sizeof(msgtemp)) /* " ", name, '\0' */
2712 	{
2713 	  message_send_text(c,message_type_info,c,msgtemp);
2714 	  i = 0;
2715 	}
2716       sprintf(&msgtemp[i]," %s",banned);
2717       i += strlen(&msgtemp[i]);
2718     }
2719   if (i>0)
2720     message_send_text(c,message_type_info,c,msgtemp);
2721 
2722   return 0;
2723 }
2724 
_news_cb(time_t date,t_lstr * lstr,void * data)2725 static int _news_cb(time_t date, t_lstr *lstr, void *data)
2726 {
2727     char	strdate[64];
2728     struct tm 	*tm;
2729     char	save, *p, *q;
2730     t_connection *c = (t_connection*)data;
2731 
2732     tm = localtime(&date);
2733     if (tm) strftime(strdate, 64,"%B %d, %Y", tm);
2734     else strcpy(strdate, "(invalid date)");
2735     message_send_text(c,message_type_info,c,strdate);
2736 
2737     for (p = lstr_get_str(lstr); *p;) {
2738 	for(q = p; *q && *q != '\r' && *q != '\n';q++);
2739 	save = *q;
2740 	*q = '\0';
2741 	message_send_text(c,message_type_info,c,p);
2742 	*q = save;
2743 	p = q;
2744 	for(;*p == '\n' || *p == '\r';p++);
2745     }
2746 
2747     return 0;
2748 }
2749 
_handle_news_command(t_connection * c,char const * text)2750 static int _handle_news_command(t_connection * c, char const *text)
2751 {
2752     news_traverse(_news_cb,c);
2753     return 0;
2754 }
2755 
2756 struct glist_cb_struct {
2757     t_game_difficulty diff;
2758     t_clienttag tag;
2759     t_connection *c;
2760 };
2761 
_glist_cb(t_game * game,void * data)2762 static int _glist_cb(t_game *game, void *data)
2763 {
2764     struct glist_cb_struct *cbdata = (struct glist_cb_struct*)data;
2765 
2766     if ((!cbdata->tag || !prefs_get_hide_pass_games() || game_get_flag(game) != game_flag_private) &&
2767 	(!cbdata->tag || game_get_clienttag(game)==cbdata->tag) &&
2768         (cbdata->diff==game_difficulty_none || game_get_difficulty(game)==cbdata->diff))
2769     {
2770 	snprintf(msgtemp, sizeof(msgtemp), " %-16.16s %1.1s %-8.8s %-21.21s %5u ",
2771 	    game_get_name(game),
2772 	    game_get_flag(game) != game_flag_private ? "n":"y",
2773 	    game_status_get_str(game_get_status(game)),
2774 	    game_type_get_str(game_get_type(game)),
2775 	    game_get_ref(game));
2776 
2777 	if (!cbdata->tag)
2778 	{
2779 
2780 	  strcat(msgtemp,clienttag_uint_to_str(game_get_clienttag(game)));
2781 	  strcat(msgtemp," ");
2782 	}
2783 
2784 	if ((!prefs_get_hide_addr()) || (account_get_command_groups(conn_get_account(cbdata->c)) & command_get_group("/admin-addr"))) /* default to false */
2785 	  strcat(msgtemp, addr_num_to_addr_str(game_get_addr(game),game_get_port(game)));
2786 
2787 	message_send_text(cbdata->c,message_type_info,cbdata->c,msgtemp);
2788     }
2789 
2790     return 0;
2791 }
2792 
_handle_games_command(t_connection * c,char const * text)2793 static int _handle_games_command(t_connection * c, char const *text)
2794 {
2795   unsigned int   i;
2796   unsigned int   j;
2797   char           clienttag_str[5];
2798   char           dest[5];
2799   struct glist_cb_struct cbdata;
2800 
2801   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2802   for (; text[i]==' '; i++);
2803   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
2804     if (j<sizeof(dest)-1) dest[j++] = text[i];
2805   dest[j] = '\0';
2806   for (; text[i]==' '; i++);
2807 
2808   cbdata.c = c;
2809 
2810   if(strcmp(&text[i],"norm")==0)
2811     cbdata.diff = game_difficulty_normal;
2812   else if(strcmp(&text[i],"night")==0)
2813     cbdata.diff = game_difficulty_nightmare;
2814   else if(strcmp(&text[i],"hell")==0)
2815     cbdata.diff = game_difficulty_hell;
2816   else
2817     cbdata.diff = game_difficulty_none;
2818 
2819   if (dest[0]=='\0')
2820     {
2821       cbdata.tag = conn_get_clienttag(c);
2822       message_send_text(c,message_type_info,c,"Currently accessable games:");
2823     }
2824   else if (strcasecmp(&dest[0],"all")==0)
2825     {
2826       cbdata.tag = 0;
2827       message_send_text(c,message_type_info,c,"All current games:");
2828     }
2829   else
2830     {
2831       cbdata.tag = tag_case_str_to_uint(&dest[0]);
2832 
2833       if (!tag_check_client(cbdata.tag))
2834       {
2835 	message_send_text(c,message_type_error,c,"No valid clienttag specified.");
2836 	return -1;
2837       }
2838 
2839       if(cbdata.diff==game_difficulty_none)
2840         snprintf(msgtemp, sizeof(msgtemp), "Current games of type %.64s",tag_uint_to_str(clienttag_str,cbdata.tag));
2841       else
2842         snprintf(msgtemp, sizeof(msgtemp), "Current games of type %.64s %.128s",tag_uint_to_str(clienttag_str,cbdata.tag),&text[i]);
2843       message_send_text(c,message_type_info,c,msgtemp);
2844     }
2845 
2846   snprintf(msgtemp, sizeof(msgtemp), " ------name------ p -status- --------type--------- count ");
2847   if (!cbdata.tag)
2848     strcat(msgtemp,"ctag ");
2849   if ((!prefs_get_hide_addr()) || (account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) /* default to false */
2850     strcat(msgtemp,"--------addr--------");
2851   message_send_text(c,message_type_info,c,msgtemp);
2852   gamelist_traverse(_glist_cb,&cbdata);
2853 
2854   return 0;
2855 }
2856 
_handle_channels_command(t_connection * c,char const * text)2857 static int _handle_channels_command(t_connection * c, char const *text)
2858 {
2859   unsigned int      i;
2860   t_elem const *    curr;
2861   t_channel const * channel;
2862   char const *      tag;
2863   t_connection const * conn;
2864   t_account * acc;
2865   char const * name;
2866   int first;
2867 
2868 
2869   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
2870   for (; text[i]==' '; i++);
2871 
2872   if (text[i]=='\0')
2873     {
2874       tag = clienttag_uint_to_str(conn_get_clienttag(c));
2875       message_send_text(c,message_type_info,c,"Currently accessable channels:");
2876     }
2877   else if (strcmp(&text[i],"all")==0)
2878     {
2879       tag = NULL;
2880       message_send_text(c,message_type_info,c,"All current channels:");
2881     }
2882   else
2883     {
2884       tag = &text[i];
2885       snprintf(msgtemp, sizeof(msgtemp), "Current channels of type %.64s",tag);
2886       message_send_text(c,message_type_info,c,msgtemp);
2887     }
2888 
2889   snprintf(msgtemp, sizeof(msgtemp), " -----------name----------- users ----admin/operator----");
2890   message_send_text(c,message_type_info,c,msgtemp);
2891   LIST_TRAVERSE_CONST(channellist(),curr)
2892     {
2893       channel = elem_get_data(curr);
2894       if ((!(channel_get_flags(channel) & channel_flags_clan)) && (!tag || !prefs_get_hide_temp_channels() || channel_get_permanent(channel)) &&
2895 	  (!tag || !channel_get_clienttag(channel) ||
2896 	   strcasecmp(channel_get_clienttag(channel),tag)==0) &&
2897 	   ((channel_get_max(channel)!=0) || //only show restricted channels to OPs and Admins
2898 	    ((channel_get_max(channel)==0 && account_is_operator_or_admin(conn_get_account(c),NULL)))) &&
2899 	    (!(channel_get_flags(channel) & channel_flags_thevoid)) // don't list TheVoid
2900 	)
2901 	{
2902 
2903 	  snprintf(msgtemp, sizeof(msgtemp), " %-26.26s %5u - ",
2904 		  channel_get_name(channel),
2905 		  channel_get_length(channel));
2906 
2907 	  first = 1;
2908 
2909 	  for (conn = channel_get_first(channel);conn;conn=channel_get_next())
2910 	  {
2911 		acc = conn_get_account(conn);
2912 		if (account_is_operator_or_admin(acc,channel_get_name(channel)) ||
2913 		    channel_conn_is_tmpOP(channel,account_get_conn(acc)))
2914 		{
2915 		  name = conn_get_loggeduser(conn);
2916 		  if (strlen(msgtemp) + strlen(name) +6 >= MAX_MESSAGE_LEN) break;
2917 		  if (!first) strcat(msgtemp," ,");
2918 		  strcat(msgtemp,name);
2919 		  if (account_get_auth_admin(acc,NULL)==1) strcat(msgtemp,"(A)");
2920 		  else if (account_get_auth_operator(acc,NULL)==1) strcat(msgtemp,"(O)");
2921 		  else if (account_get_auth_admin(acc,channel_get_name(channel))==1) strcat(msgtemp,"(a)");
2922 		  else if (account_get_auth_operator(acc,channel_get_name(channel))==1) strcat(msgtemp,"(o)");
2923 		  first = 0;
2924 		}
2925 	  }
2926 
2927 	  message_send_text(c,message_type_info,c,msgtemp);
2928 	}
2929     }
2930 
2931   return 0;
2932 }
2933 
_handle_addacct_command(t_connection * c,char const * text)2934 static int _handle_addacct_command(t_connection * c, char const *text)
2935 {
2936     unsigned int i,j;
2937     t_account  * temp;
2938     t_hash       passhash;
2939     char         username[USER_NAME_MAX];
2940     char         pass[256];
2941 
2942     for (i=0; text[i]!=' ' && text[i]!='\0'; i++);
2943     for (; text[i]==' '; i++);
2944 
2945     for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get username */
2946 	if (j<sizeof(username)-1) username[j++] = text[i];
2947     username[j] = '\0';
2948 
2949     for (; text[i]==' '; i++); /* skip spaces */
2950     for (j=0; text[i]!='\0'; i++) /* get pass (spaces are allowed) */
2951 	if (j<sizeof(pass)-1) pass[j++] = text[i];
2952     pass[j] = '\0';
2953 
2954     if (username[0]=='\0' || pass[0]=='\0') {
2955 	message_send_text(c,message_type_info,c,"usage: /addacct <username> <password>");
2956         return 0;
2957     }
2958 
2959     if (account_check_name(username)<0) {
2960         message_send_text(c,message_type_error,c,"Account name contains some invalid symbol!");
2961         return 0;
2962     }
2963 
2964     /* FIXME: truncate or err on too long password */
2965     for (i=0; i<strlen(pass); i++)
2966 	if (isupper((int)pass[i])) pass[i] = tolower((int)pass[i]);
2967 
2968     bnet_hash(&passhash,strlen(pass),pass);
2969 
2970     snprintf(msgtemp, sizeof(msgtemp), "Trying to add account \"%.64s\" with password \"%.64s\"",username,pass);
2971     message_send_text(c,message_type_info,c,msgtemp);
2972 
2973     snprintf(msgtemp, sizeof(msgtemp), "Hash is: %.128s",hash_get_str(passhash));
2974     message_send_text(c,message_type_info,c,msgtemp);
2975 
2976     temp = accountlist_create_account(username,hash_get_str(passhash));
2977     if (!temp) {
2978 	message_send_text(c,message_type_error,c,"Failed to create account!");
2979         eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" not created (failed)",conn_get_socket(c),username);
2980 	return 0;
2981     }
2982 
2983     snprintf(msgtemp, sizeof(msgtemp), "Account "UID_FORMAT" created.",account_get_uid(temp));
2984     message_send_text(c,message_type_info,c,msgtemp);
2985     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" created",conn_get_socket(c),username);
2986 
2987     return 0;
2988 }
2989 
_handle_chpass_command(t_connection * c,char const * text)2990 static int _handle_chpass_command(t_connection * c, char const *text)
2991 {
2992   unsigned int i,j;
2993   t_account  * account;
2994   t_account  * temp;
2995   t_hash       passhash;
2996   char         arg1[256];
2997   char         arg2[256];
2998   char const * username;
2999   char *       pass;
3000 
3001   for (i=0; text[i]!=' ' && text[i]!='\0'; i++);
3002   for (; text[i]==' '; i++);
3003 
3004   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get username/pass */
3005     if (j<sizeof(arg1)-1) arg1[j++] = text[i];
3006   arg1[j] = '\0';
3007 
3008   for (; text[i]==' '; i++); /* skip spaces */
3009   for (j=0; text[i]!='\0'; i++) /* get pass (spaces are allowed) */
3010     if (j<sizeof(arg2)-1) arg2[j++] = text[i];
3011   arg2[j] = '\0';
3012 
3013   if (arg2[0]=='\0')
3014     {
3015       username = conn_get_username(c);
3016       pass     = arg1;
3017     }
3018   else
3019     {
3020       username = arg1;
3021       pass     = arg2;
3022     }
3023 
3024   if (pass[0]=='\0')
3025     {
3026       message_send_text(c,message_type_info,c,"usage: /chpass [username] <password>");
3027       return 0;
3028     }
3029 
3030   temp = accountlist_find_account(username);
3031 
3032   account = conn_get_account(c);
3033 
3034   if ((temp==account && account_get_auth_changepass(account)==0) || /* default to true */
3035       (temp!=account && !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-chpass")))) /* default to false */
3036     {
3037       eventlog(eventlog_level_info,__FUNCTION__,"[%d] password change for \"%s\" refused (no change access)",conn_get_socket(c),username);
3038       message_send_text(c,message_type_error,c,"Only admins may change passwords for other accounts.");
3039       return 0;
3040     }
3041 
3042   if (!temp)
3043     {
3044       message_send_text(c,message_type_error,c,"Account does not exist.");
3045       return 0;
3046     }
3047 
3048   if (strlen(pass) > USER_PASS_MAX)
3049   {
3050     snprintf(msgtemp, sizeof(msgtemp), "Maximum password length allowed is %d",USER_PASS_MAX);
3051     message_send_text(c,message_type_error,c,msgtemp);
3052     return 0;
3053   }
3054 
3055   for (i=0; i<strlen(pass); i++)
3056     if (isupper((int)pass[i])) pass[i] = tolower((int)pass[i]);
3057 
3058   bnet_hash(&passhash,strlen(pass),pass);
3059 
3060   snprintf(msgtemp, sizeof(msgtemp), "Trying to change password for account \"%.64s\" to \"%.64s\"",username,pass);
3061   message_send_text(c,message_type_info,c,msgtemp);
3062 
3063   if (account_set_pass(temp,hash_get_str(passhash))<0)
3064     {
3065       message_send_text(c,message_type_error,c,"Unable to set password.");
3066       return 0;
3067     }
3068 
3069   if (account_get_auth_admin(account,NULL) == 1 ||
3070       account_get_auth_operator(account,NULL) == 1) {
3071     snprintf(msgtemp, sizeof(msgtemp),
3072       "Password for account "UID_FORMAT" updated.",account_get_uid(temp));
3073     message_send_text(c,message_type_info,c,msgtemp);
3074 
3075     snprintf(msgtemp, sizeof(msgtemp), "Hash is: %.128s",hash_get_str(passhash));
3076     message_send_text(c,message_type_info,c,msgtemp);
3077   } else {
3078     snprintf(msgtemp, sizeof(msgtemp),
3079       "Password for account %.64s updated.",username);
3080     message_send_text(c,message_type_info,c,msgtemp);
3081   }
3082 
3083   return 0;
3084 }
3085 
_handle_connections_command(t_connection * c,char const * text)3086 static int _handle_connections_command(t_connection *c, char const *text)
3087 {
3088   t_elem const * curr;
3089   t_connection * conn;
3090   char           name[19];
3091   unsigned int   i; /* for loop */
3092   char const *   channel_name;
3093   char const *   game_name;
3094   char           clienttag_str[5];
3095 
3096   if (!prefs_get_enable_conn_all() && !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-con"))) /* default to false */
3097     {
3098       message_send_text(c,message_type_error,c,"This command is only enabled for admins.");
3099       return 0;
3100     }
3101 
3102   message_send_text(c,message_type_info,c,"Current connections:");
3103   /* addon */
3104   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3105   for (; text[i]==' '; i++);
3106 
3107   if (text[i]=='\0')
3108     {
3109       snprintf(msgtemp, sizeof(msgtemp), " -class -tag -----name------ -lat(ms)- ----channel---- --game--");
3110       message_send_text(c,message_type_info,c,msgtemp);
3111     }
3112   else
3113     if (strcmp(&text[i],"all")==0) /* print extended info */
3114       {
3115 	if (prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr")))
3116 	  snprintf(msgtemp, sizeof(msgtemp), " -#- -class ----state--- -tag -----name------ -session-- -flag- -lat(ms)- ----channel---- --game--");
3117 	else
3118 	  snprintf(msgtemp, sizeof(msgtemp), " -#- -class ----state--- -tag -----name------ -session-- -flag- -lat(ms)- ----channel---- --game-- ---------addr--------");
3119 	message_send_text(c,message_type_info,c,msgtemp);
3120       }
3121     else
3122       {
3123 	message_send_text(c,message_type_error,c,"Unknown option.");
3124 	return 0;
3125 	  }
3126 
3127   LIST_TRAVERSE_CONST(connlist(),curr)
3128   {
3129       conn = elem_get_data(curr);
3130       if (conn_get_account(conn))
3131 	  sprintf(name,"\"%.16s\"",conn_get_username(conn));
3132       else
3133 	strcpy(name,"(none)");
3134 
3135       if (conn_get_channel(conn)!=NULL)
3136 	channel_name = channel_get_name(conn_get_channel(conn));
3137       else channel_name = "none";
3138       if (conn_get_game(conn)!=NULL)
3139 	game_name = game_get_name(conn_get_game(conn));
3140       else game_name = "none";
3141 
3142       if (text[i]=='\0')
3143 	snprintf(msgtemp, sizeof(msgtemp), " %-6.6s %4.4s %-15.15s %9u %-16.16s %-8.8s",
3144 		conn_class_get_str(conn_get_class(conn)),
3145 		tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(conn)),
3146 		name,
3147 		conn_get_latency(conn),
3148 		channel_name,
3149 		game_name);
3150       else
3151 	if (prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) /* default to false */
3152 	  snprintf(msgtemp, sizeof(msgtemp), " %3d %-6.6s %-12.12s %4.4s %-15.15s 0x%08x 0x%04x %9u %-16.16s %-8.8s",
3153 		  conn_get_socket(conn),
3154 		  conn_class_get_str(conn_get_class(conn)),
3155 		  conn_state_get_str(conn_get_state(conn)),
3156 		  tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(conn)),
3157 		  name,
3158 		  conn_get_sessionkey(conn),
3159 		  conn_get_flags(conn),
3160 		  conn_get_latency(conn),
3161 		  channel_name,
3162 		  game_name);
3163 	else
3164 	  snprintf(msgtemp, sizeof(msgtemp), " %3u %-6.6s %-12.12s %4.4s %-15.15s 0x%08x 0x%04x %9u %-16.16s %-8.8s %s",
3165 		  conn_get_socket(conn),
3166 		  conn_class_get_str(conn_get_class(conn)),
3167 		  conn_state_get_str(conn_get_state(conn)),
3168 		  tag_uint_to_str(clienttag_str,conn_get_fake_clienttag(conn)),
3169 		  name,
3170 		  conn_get_sessionkey(conn),
3171 		  conn_get_flags(conn),
3172 		  conn_get_latency(conn),
3173 		  channel_name,
3174 		  game_name,
3175 		  addr_num_to_addr_str(conn_get_addr(conn),conn_get_port(conn)));
3176 
3177       message_send_text(c,message_type_info,c,msgtemp);
3178     }
3179 
3180   return 0;
3181 }
3182 
_handle_finger_command(t_connection * c,char const * text)3183 static int _handle_finger_command(t_connection * c, char const *text)
3184 {
3185   char           dest[USER_NAME_MAX];
3186   unsigned int   i,j;
3187   t_account *    account;
3188   t_connection * conn;
3189   char const *   ip;
3190   char *         tok;
3191   t_clanmember * clanmemb;
3192 
3193   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3194   for (; text[i]==' '; i++);
3195   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
3196     if (j<sizeof(dest)-1) dest[j++] = text[i];
3197   dest[j] = '\0';
3198   for (; text[i]==' '; i++);
3199 
3200   if (dest[0]=='\0')
3201   {
3202     message_send_text(c,message_type_info,c,"usage: /finger <account>");
3203     return 0;
3204   }
3205 
3206   if (!(account = accountlist_find_account(dest)))
3207     {
3208       message_send_text(c,message_type_error,c,"Invalid user.");
3209       return 0;
3210     }
3211   snprintf(msgtemp, sizeof(msgtemp), "Login: %-16.16s "UID_FORMAT" Sex: %.14s",
3212 	  account_get_name(account),
3213 	  account_get_uid(account),
3214 	  account_get_sex(account));
3215   message_send_text(c,message_type_info,c,msgtemp);
3216 
3217   if ((clanmemb = account_get_clanmember(account)))
3218   {
3219     t_clan *	 clan;
3220     char	 status;
3221 
3222     if ((clan = clanmember_get_clan(clanmemb)))
3223     {
3224 	snprintf(msgtemp, sizeof(msgtemp), "Clan : %-64.64s",clan_get_name(clan));
3225 	if ((status = clanmember_get_status(clanmemb)))
3226 	{
3227 	    switch (status)
3228 	    {
3229 		case CLAN_CHIEFTAIN:
3230 		   strcat(msgtemp,"  Rank: Chieftain");
3231 		   break;
3232 		case CLAN_SHAMAN:
3233 		   strcat(msgtemp,"  Rank: Shaman");
3234 		   break;
3235 		case CLAN_GRUNT:
3236 		   strcat(msgtemp,"  Rank: Grunt");
3237 		   break;
3238 		case CLAN_PEON:
3239 		   strcat(msgtemp,"  Rank: Peon");
3240 		   break;
3241 		default:;
3242 	    }
3243 	}
3244 	message_send_text(c,message_type_info,c,msgtemp);
3245 
3246     }
3247   }
3248 
3249   snprintf(msgtemp, sizeof(msgtemp), "Location: %-23.23s Age: %.14s",
3250 	  account_get_loc(account),
3251 	  account_get_age(account));
3252   message_send_text(c,message_type_info,c,msgtemp);
3253 
3254   if((conn = connlist_find_connection_by_accountname(dest)))
3255   {
3256 	  snprintf(msgtemp, sizeof(msgtemp), "Client: %s    Ver: %s   Country: %s",
3257 		  clienttag_get_title(conn_get_clienttag(conn)),
3258 		  conn_get_clientver(conn),
3259 		  conn_get_country(conn));
3260 	  message_send_text(c,message_type_info,c,msgtemp);
3261   }
3262 
3263   if (!(ip=account_get_ll_ip(account)) ||
3264       !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) /* default to false */
3265     ip = "unknown";
3266 
3267   {
3268     time_t      then;
3269     struct tm * tmthen;
3270 
3271     then = account_get_ll_time(account);
3272     tmthen = localtime(&then); /* FIXME: determine user's timezone */
3273     if (!(conn))
3274       if (tmthen)
3275 	strftime(msgtemp,sizeof(msgtemp),"Last login %a %b %d %H:%M %Y from ",tmthen);
3276       else
3277 	strcpy(msgtemp,"Last login ? from ");
3278     else
3279       if (tmthen)
3280 	strftime(msgtemp,sizeof(msgtemp),"On since %a %b %d %H:%M %Y from ",tmthen);
3281       else
3282 	strcpy(msgtemp,"On since ? from ");
3283   }
3284   strncat(msgtemp,ip,32);
3285   message_send_text(c,message_type_info,c,msgtemp);
3286 
3287   /* check /admin-addr for admin privileges */
3288   if ( (account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr")))
3289   {
3290       /* the player who requested /finger has admin privileges
3291          give him more info about the one he querys;
3292          is_admin, is_operator, is_locked, email */
3293          snprintf(msgtemp, sizeof(msgtemp), "email:%.128s , is_operator: %d , is_admin: %d , is_acc_locked: %d",
3294          account_get_email(account),
3295          account_get_auth_operator(account,NULL),
3296          account_get_auth_admin(account,NULL),
3297          account_get_auth_lock(account));
3298          message_send_text(c,message_type_info,c,msgtemp);
3299   }
3300 
3301 
3302   if (conn)
3303     {
3304       snprintf(msgtemp, sizeof(msgtemp), "Idle %.128s",seconds_to_timestr(conn_get_idletime(conn)));
3305       message_send_text(c,message_type_info,c,msgtemp);
3306     }
3307 
3308   strncpy(msgtemp,account_get_desc(account),sizeof(msgtemp));
3309   msgtemp[sizeof(msgtemp)-1] = '\0';
3310   for (tok=strtok(msgtemp,"\r\n"); tok; tok=strtok(NULL,"\r\n"))
3311     message_send_text(c,message_type_info,c,tok);
3312   message_send_text(c,message_type_info,c,"");
3313 
3314   return 0;
3315 }
3316 
3317 /*
3318  * rewrote command /operator to add and remove operator status [Omega]
3319  *
3320  * Fixme: rewrite /operators to show Currently logged on Server and/or Channel operators ...??
3321  */
3322 /*
3323 static int _handle_operator_command(t_connection * c, char const *text)
3324 {
3325   t_connection const * opr;
3326   t_channel const *    channel;
3327 
3328   if (!(channel = conn_get_channel(c)))
3329     {
3330       message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
3331       return 0;
3332     }
3333 
3334   if (!(opr = channel_get_operator(channel)))
3335     strcpy(msgtemp,"There is no operator.");
3336   else
3337       snprintf(msgtemp, sizeof(msgtemp), "%.64s is the operator.",conn_get_username(opr));
3338   message_send_text(c,message_type_info,c,msgtemp);
3339   return 0;
3340 }
3341 */
3342 
3343 /* FIXME: do we want to show just Server Admin or Channel Admin Also? [Omega] */
_handle_admins_command(t_connection * c,char const * text)3344 static int _handle_admins_command(t_connection * c, char const *text)
3345 {
3346   unsigned int    i;
3347   t_elem const *  curr;
3348   t_connection *  tc;
3349   char const *    nick;
3350 
3351   strcpy(msgtemp,"Currently logged on Administrators:");
3352   i = strlen(msgtemp);
3353   LIST_TRAVERSE_CONST(connlist(),curr)
3354     {
3355       tc = elem_get_data(curr);
3356       if (!tc)
3357 	continue;
3358       if (!conn_get_account(tc))
3359         continue;
3360       if (account_get_auth_admin(conn_get_account(tc),NULL)==1)
3361 	{
3362 	  if ((nick = conn_get_username(tc)))
3363 	    {
3364 	      if (i+strlen(nick)+2>sizeof(msgtemp)) /* " ", name, '\0' */
3365 		{
3366 		  message_send_text(c,message_type_info,c,msgtemp);
3367 		  i = 0;
3368 		}
3369 	      sprintf(&msgtemp[i]," %s", nick);
3370 	      i += strlen(&msgtemp[i]);
3371 	    }
3372 	}
3373     }
3374   if (i>0)
3375     message_send_text(c,message_type_info,c,msgtemp);
3376 
3377   return 0;
3378 }
3379 
_handle_quit_command(t_connection * c,char const * text)3380 static int _handle_quit_command(t_connection * c, char const *text)
3381 {
3382     if (conn_get_game(c))
3383 	eventlog(eventlog_level_warn, __FUNCTION__,"[%d] user '%s' tried to disconnect while in game, cheat attempt ?", conn_get_socket(c), conn_get_loggeduser(c));
3384     else {
3385 	message_send_text(c,message_type_info,c,"Connection closed.");
3386 	conn_set_state(c,conn_state_destroy);
3387     }
3388 
3389     return 0;
3390 }
3391 
_handle_kill_command(t_connection * c,char const * text)3392 static int _handle_kill_command(t_connection * c, char const *text)
3393 {
3394   unsigned int	i,j;
3395   t_connection *	user;
3396   char		usrnick[USER_NAME_MAX]; /* max length of nick + \0 */  /* FIXME: Is it somewhere defined? */
3397 
3398   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3399   for (; text[i]==' '; i++);
3400   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get nick */
3401     if (j<sizeof(usrnick)-1) usrnick[j++] = text[i];
3402   usrnick[j]='\0';
3403   for (; text[i]==' '; i++);
3404 
3405   if (usrnick[0]=='\0' || (usrnick[0]=='#' && (usrnick[1] < '0' || usrnick[1] > '9')))
3406     {
3407       message_send_text(c,message_type_info,c,"usage: /kill {<username>|#<socket>} [<min>]");
3408       return 0;
3409     }
3410 
3411   if (usrnick[0] == '#') {
3412      if (!(user = connlist_find_connection_by_socket(atoi(usrnick + 1)))) {
3413         message_send_text(c,message_type_error,c,"That connection doesnt exist.");
3414         return 0;
3415      }
3416   } else {
3417      if (!(user = connlist_find_connection_by_accountname(usrnick))) {
3418         message_send_text(c,message_type_error,c,"That user is not logged in?");
3419         return 0;
3420      }
3421   }
3422 
3423   if (text[i]!='\0' && ipbanlist_add(c,addr_num_to_ip_str(conn_get_addr(user)),ipbanlist_str_to_time_t(c,&text[i]))==0)
3424     {
3425       ipbanlist_save(prefs_get_ipbanfile());
3426       message_send_text(user,message_type_info,user,"Connection closed by admin and banned your ip.");
3427     }
3428   else
3429     message_send_text(user,message_type_info,user,"Connection closed by admin.");
3430   conn_set_state(user,conn_state_destroy);
3431 
3432   message_send_text(c,message_type_info,c,"Operation successful.");
3433 
3434   return 0;
3435 }
3436 
_handle_killsession_command(t_connection * c,char const * text)3437 static int _handle_killsession_command(t_connection * c, char const *text)
3438 {
3439   unsigned int	i,j;
3440   t_connection *	user;
3441   char		session[16];
3442 
3443   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3444   for (; text[i]==' '; i++);
3445   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get nick */
3446     if (j<sizeof(session)-1) session[j++] = text[i];
3447   session[j]='\0';
3448   for (; text[i]==' '; i++);
3449 
3450   if (session[0]=='\0')
3451     {
3452       message_send_text(c,message_type_info,c,"usage: /killsession <session> [min]");
3453       return 0;
3454     }
3455   if (!isxdigit((int)session[0]))
3456     {
3457       message_send_text(c,message_type_error,c,"That is not a valid session.");
3458       return 0;
3459     }
3460   if (!(user = connlist_find_connection_by_sessionkey((unsigned int)strtoul(session,NULL,16))))
3461     {
3462       message_send_text(c,message_type_error,c,"That session does not exist.");
3463       return 0;
3464     }
3465   if (text[i]!='\0' && ipbanlist_add(c,addr_num_to_ip_str(conn_get_addr(user)),ipbanlist_str_to_time_t(c,&text[i]))==0)
3466     {
3467       ipbanlist_save(prefs_get_ipbanfile());
3468       message_send_text(user,message_type_info,user,"Connection closed by admin and banned your ip's.");
3469     }
3470   else
3471     message_send_text(user,message_type_info,user,"Connection closed by admin.");
3472   conn_set_state(user,conn_state_destroy);
3473   return 0;
3474 }
3475 
_handle_gameinfo_command(t_connection * c,char const * text)3476 static int _handle_gameinfo_command(t_connection * c, char const *text)
3477 {
3478   unsigned int   i;
3479   t_game const * game;
3480   char clienttag_str[5];
3481 
3482   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3483   for (; text[i]==' '; i++);
3484 
3485   if (text[i]=='\0')
3486     {
3487       if (!(game = conn_get_game(c)))
3488 	{
3489 	  message_send_text(c,message_type_error,c,"You are not in a game.");
3490 	  return 0;
3491 	}
3492     }
3493   else
3494     if (!(game = gamelist_find_game(&text[i],conn_get_clienttag(c),game_type_all)))
3495       {
3496 	message_send_text(c,message_type_error,c,"That game does not exist.");
3497 	return 0;
3498       }
3499 
3500   snprintf(msgtemp, sizeof(msgtemp), "Name: %-20.20s    ID: "GAMEID_FORMAT" (%s)",game_get_name(game),game_get_id(game),game_get_flag(game) != game_flag_private ? "public":"private");
3501   message_send_text(c,message_type_info,c,msgtemp);
3502 
3503   {
3504     t_account *  owner;
3505     char const * tname;
3506     char const * namestr;
3507 
3508     if (!(owner = conn_get_account(game_get_owner(game))))
3509       {
3510 	tname = NULL;
3511 	namestr = "none";
3512       }
3513     else
3514       if (!(tname = conn_get_loggeduser(game_get_owner(game))))
3515 	namestr = "unknown";
3516       else
3517 	namestr = tname;
3518 
3519     snprintf(msgtemp, sizeof(msgtemp), "Owner: %-20.20s",namestr);
3520 
3521   }
3522   message_send_text(c,message_type_info,c,msgtemp);
3523 
3524   if (!prefs_get_hide_addr() || (account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) /* default to false */
3525     {
3526       unsigned int   addr;
3527       unsigned short port;
3528       unsigned int   taddr;
3529       unsigned short tport;
3530 
3531       taddr=addr = game_get_addr(game);
3532       tport=port = game_get_port(game);
3533       trans_net(conn_get_addr(c),&taddr,&tport);
3534 
3535       if (taddr==addr && tport==port)
3536 	snprintf(msgtemp, sizeof(msgtemp), "Address: %.64s",
3537 		addr_num_to_addr_str(addr,port));
3538       else
3539 	snprintf(msgtemp, sizeof(msgtemp), "Address: %.64s (trans %.64s)",
3540 		addr_num_to_addr_str(addr,port),
3541 		addr_num_to_addr_str(taddr,tport));
3542       message_send_text(c,message_type_info,c,msgtemp);
3543     }
3544 
3545   snprintf(msgtemp, sizeof(msgtemp), "Client: %4s (version %.64s, startver %u)",tag_uint_to_str(clienttag_str,game_get_clienttag(game)),vernum_to_verstr(game_get_version(game)),game_get_startver(game));
3546   message_send_text(c,message_type_info,c,msgtemp);
3547 
3548   {
3549     time_t      gametime;
3550     struct tm * gmgametime;
3551 
3552     gametime = game_get_create_time(game);
3553     if (!(gmgametime = localtime(&gametime)))
3554       strcpy(msgtemp,"Created: ?");
3555     else
3556       strftime(msgtemp,sizeof(msgtemp),"Created: "GAME_TIME_FORMAT,gmgametime);
3557     message_send_text(c,message_type_info,c,msgtemp);
3558 
3559     gametime = game_get_start_time(game);
3560     if (gametime!=(time_t)0)
3561       {
3562 	if (!(gmgametime = localtime(&gametime)))
3563 	  strcpy(msgtemp,"Started: ?");
3564 	else
3565 	  strftime(msgtemp,sizeof(msgtemp),"Started: "GAME_TIME_FORMAT,gmgametime);
3566       }
3567     else
3568       strcpy(msgtemp,"Started: ");
3569     message_send_text(c,message_type_info,c,msgtemp);
3570   }
3571 
3572   snprintf(msgtemp, sizeof(msgtemp), "Status: %.64s",game_status_get_str(game_get_status(game)));
3573   message_send_text(c,message_type_info,c,msgtemp);
3574 
3575   snprintf(msgtemp, sizeof(msgtemp), "Type: %-20.20s",game_type_get_str(game_get_type(game)));
3576   message_send_text(c,message_type_info,c,msgtemp);
3577 
3578   snprintf(msgtemp, sizeof(msgtemp), "Speed: %.64s",game_speed_get_str(game_get_speed(game)));
3579   message_send_text(c,message_type_info,c,msgtemp);
3580 
3581   snprintf(msgtemp, sizeof(msgtemp), "Difficulty: %.64s",game_difficulty_get_str(game_get_difficulty(game)));
3582   message_send_text(c,message_type_info,c,msgtemp);
3583 
3584   snprintf(msgtemp, sizeof(msgtemp), "Option: %.64s",game_option_get_str(game_get_option(game)));
3585   message_send_text(c,message_type_info,c,msgtemp);
3586 
3587   {
3588     char const * mapname;
3589 
3590     if (!(mapname = game_get_mapname(game)))
3591       mapname = "unknown";
3592     snprintf(msgtemp, sizeof(msgtemp), "Map: %-20.20s",mapname);
3593     message_send_text(c,message_type_info,c,msgtemp);
3594   }
3595 
3596   snprintf(msgtemp, sizeof(msgtemp), "Map Size: %ux%u",game_get_mapsize_x(game),game_get_mapsize_y(game));
3597   message_send_text(c,message_type_info,c,msgtemp);
3598   snprintf(msgtemp, sizeof(msgtemp), "Map Tileset: %.64s",game_tileset_get_str(game_get_tileset(game)));
3599   message_send_text(c,message_type_info,c,msgtemp);
3600   snprintf(msgtemp, sizeof(msgtemp), "Map Type: %.64s",game_maptype_get_str(game_get_maptype(game)));
3601   message_send_text(c,message_type_info,c,msgtemp);
3602 
3603   snprintf(msgtemp, sizeof(msgtemp), "Players: %u current, %u total, %u max",game_get_ref(game),game_get_count(game),game_get_maxplayers(game));
3604   message_send_text(c,message_type_info,c,msgtemp);
3605 
3606   {
3607     char const * description;
3608 
3609     if (!(description = game_get_description(game)))
3610       description = "";
3611     snprintf(msgtemp, sizeof(msgtemp), "Description: %-20.20s",description);
3612   }
3613 
3614   return 0;
3615 }
3616 
_handle_ladderactivate_command(t_connection * c,char const * text)3617 static int _handle_ladderactivate_command(t_connection * c, char const *text)
3618 {
3619   ladderlist_make_all_active();
3620   message_send_text(c,message_type_info,c,"Copied current scores to active scores on all ladders.");
3621   return 0;
3622 }
3623 
_handle_rehash_command(t_connection * c,char const * text)3624 static int _handle_rehash_command(t_connection * c, char const *text)
3625 {
3626   server_restart_wraper();
3627   return 0;
3628 }
3629 
3630 /*
3631 static int _handle_rank_all_accounts_command(t_connection * c, char const *text)
3632 {
3633   // rank all accounts here
3634   accounts_rank_all();
3635   return 0;
3636 }
3637 */
3638 
_handle_shutdown_command(t_connection * c,char const * text)3639 static int _handle_shutdown_command(t_connection * c, char const *text)
3640 {
3641   char         dest[32];
3642   unsigned int i,j;
3643   unsigned int delay;
3644 
3645   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3646   for (; text[i]==' '; i++);
3647   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
3648     if (j<sizeof(dest)-1) dest[j++] = text[i];
3649   dest[j] = '\0';
3650   for (; text[i]==' '; i++);
3651 
3652   if (dest[0]=='\0')
3653     delay = prefs_get_shutdown_delay();
3654   else
3655     if (clockstr_to_seconds(dest,&delay)<0)
3656       {
3657 	message_send_text(c,message_type_error,c,"Invalid delay.");
3658 	return 0;
3659       }
3660 
3661   server_quit_delay(delay);
3662 
3663   if (delay)
3664     message_send_text(c,message_type_info,c,"You initialized the shutdown sequence.");
3665   else
3666     message_send_text(c,message_type_info,c,"You canceled the shutdown sequence.");
3667 
3668   return 0;
3669 }
3670 
_handle_ladderinfo_command(t_connection * c,char const * text)3671 static int _handle_ladderinfo_command(t_connection * c, char const *text)
3672 {
3673   char         dest[32];
3674   unsigned int rank;
3675   unsigned int i,j;
3676   t_account *  account;
3677   t_clienttag clienttag;
3678 
3679   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3680   for (; text[i]==' '; i++);
3681   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
3682     if (j<sizeof(dest)-1) dest[j++] = text[i];
3683   dest[j] = '\0';
3684   for (; text[i]==' '; i++);
3685 
3686   if (dest[0]=='\0')
3687     {
3688       message_send_text(c,message_type_info,c,"usage: /ladderinfo <rank> [clienttag]");
3689       return 0;
3690     }
3691   if (str_to_uint(dest,&rank)<0 || rank<1)
3692     {
3693       message_send_text(c,message_type_error,c,"Invalid rank.");
3694       return 0;
3695     }
3696 
3697   if (text[i]!='\0') {
3698     if (strlen(&text[i])!=4) {
3699       message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID.");
3700       message_send_text(c,message_type_error,c,"Example: /ladderinfo 1 STAR");
3701       return 0;
3702     }
3703     clienttag = tag_case_str_to_uint(&text[i]);
3704   } else if (!(clienttag = conn_get_clienttag(c)))
3705     {
3706       message_send_text(c,message_type_error,c,"Unable to determine client game.");
3707       return 0;
3708     }
3709   if (clienttag==CLIENTTAG_STARCRAFT_UINT)
3710     {
3711       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)))
3712 	{
3713 	  snprintf(msgtemp, sizeof(msgtemp), "Starcraft active  %5u: %-20.20s %u/%u/%u rating %u",
3714 		  rank,
3715 		  account_get_name(account),
3716 		  account_get_ladder_active_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),
3717 		  account_get_ladder_active_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),
3718 		  account_get_ladder_active_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),
3719 		  account_get_ladder_active_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal));
3720 	}
3721       else
3722 	snprintf(msgtemp, sizeof(msgtemp), "Starcraft active  %5u: <none>",rank);
3723       message_send_text(c,message_type_info,c,msgtemp);
3724 
3725       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal)))
3726 	{
3727 	  snprintf(msgtemp, sizeof(msgtemp), "Starcraft current %5u: %-20.20s %u/%u/%u rating %u",
3728 		  rank,
3729 		  account_get_name(account),
3730 		  account_get_ladder_wins(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),
3731 		  account_get_ladder_losses(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),
3732 		  account_get_ladder_disconnects(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal),
3733 		  account_get_ladder_rating(account,CLIENTTAG_STARCRAFT_UINT,ladder_id_normal));
3734 	}
3735       else
3736 	snprintf(msgtemp, sizeof(msgtemp), "Starcraft current %5u: <none>",rank);
3737       message_send_text(c,message_type_info,c,msgtemp);
3738     }
3739   else if (clienttag==CLIENTTAG_BROODWARS_UINT)
3740     {
3741       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)))
3742 	{
3743 	  snprintf(msgtemp, sizeof(msgtemp), "Brood War active  %5u: %-20.20s %u/%u/%u rating %u",
3744 		  rank,
3745 		  account_get_name(account),
3746 		  account_get_ladder_active_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal),
3747 		  account_get_ladder_active_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal),
3748 		  account_get_ladder_active_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal),
3749 		  account_get_ladder_active_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal));
3750 	}
3751       else
3752 	snprintf(msgtemp, sizeof(msgtemp), "Brood War active  %5u: <none>",rank);
3753       message_send_text(c,message_type_info,c,msgtemp);
3754 
3755       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_BROODWARS_UINT,ladder_id_normal)))
3756 	{
3757 	  snprintf(msgtemp, sizeof(msgtemp), "Brood War current %5u: %-20.20s %u/%u/%u rating %u",
3758 		  rank,
3759 		  account_get_name(account),
3760 		  account_get_ladder_wins(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal),
3761 		  account_get_ladder_losses(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal),
3762 		  account_get_ladder_disconnects(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal),
3763 		  account_get_ladder_rating(account,CLIENTTAG_BROODWARS_UINT,ladder_id_normal));
3764 	}
3765       else
3766 	snprintf(msgtemp, sizeof(msgtemp), "Brood War current %5u: <none>",rank);
3767       message_send_text(c,message_type_info,c,msgtemp);
3768     }
3769   else if (clienttag==CLIENTTAG_WARCIIBNE_UINT)
3770     {
3771       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)))
3772 	{
3773 	  snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard active  %5u: %-20.20s %u/%u/%u rating %u",
3774 		  rank,
3775 		  account_get_name(account),
3776 		  account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),
3777 		  account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),
3778 		  account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),
3779 		  account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal));
3780 	}
3781       else
3782 	snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard active  %5u: <none>",rank);
3783       message_send_text(c,message_type_info,c,msgtemp);
3784 
3785       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_active,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)))
3786 	{
3787 	  snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan active   %5u: %-20.20s %u/%u/%u rating %u",
3788 		  rank,
3789 		  account_get_name(account),
3790 		  account_get_ladder_active_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),
3791 		  account_get_ladder_active_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),
3792 		  account_get_ladder_active_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),
3793 		  account_get_ladder_active_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman));
3794 	}
3795       else
3796 	snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan active   %5u: <none>",rank);
3797       message_send_text(c,message_type_info,c,msgtemp);
3798 
3799       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal)))
3800 	{
3801 	  snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard current %5u: %-20.20s %u/%u/%u rating %u",
3802 		  rank,
3803 		  account_get_name(account),
3804 		  account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),
3805 		  account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),
3806 		  account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal),
3807 		  account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_normal));
3808 	}
3809       else
3810 	snprintf(msgtemp, sizeof(msgtemp), "Warcraft II standard current %5u: <none>",rank);
3811       message_send_text(c,message_type_info,c,msgtemp);
3812 
3813       if ((account = ladder_get_account_by_rank(rank,ladder_sort_highestrated,ladder_time_current,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman)))
3814 	{
3815 	  snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan current  %5u: %-20.20s %u/%u/%u rating %u",
3816 		  rank,
3817 		  account_get_name(account),
3818 		  account_get_ladder_wins(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),
3819 		  account_get_ladder_losses(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),
3820 		  account_get_ladder_disconnects(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman),
3821 		  account_get_ladder_rating(account,CLIENTTAG_WARCIIBNE_UINT,ladder_id_ironman));
3822 	}
3823       else
3824 	snprintf(msgtemp, sizeof(msgtemp), "Warcraft II IronMan current  %5u: <none>",rank);
3825       message_send_text(c,message_type_info,c,msgtemp);
3826     }
3827   // --> aaron
3828   else if (clienttag==CLIENTTAG_WARCRAFT3_UINT || clienttag==CLIENTTAG_WAR3XP_UINT)
3829     {
3830       unsigned int teamcount = 0;
3831       if ((account = ladder_get_account(solo_ladder(clienttag),rank,&teamcount,clienttag)))
3832 	{
3833 	  snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Solo   %5u: %-20.20s %u/%u/0",
3834 		  rank,
3835 		  account_get_name(account),
3836 		  account_get_ladder_wins(account,clienttag,ladder_id_solo),
3837 		  account_get_ladder_losses(account,clienttag,ladder_id_solo));
3838 	}
3839       else
3840 	snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Solo   %5u: <none>",rank);
3841       message_send_text(c,message_type_info,c,msgtemp);
3842 
3843       if ((account = ladder_get_account(team_ladder(clienttag),rank,&teamcount,clienttag)))
3844 	{
3845 	  snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Team   %5u: %-20.20s %u/%u/0",
3846 		  rank,
3847 		  account_get_name(account),
3848 		  account_get_ladder_wins(account,clienttag,ladder_id_team),
3849 		  account_get_ladder_losses(account,clienttag,ladder_id_team));
3850 	}
3851       else
3852 	snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 Team   %5u: <none>",rank);
3853       message_send_text(c,message_type_info,c,msgtemp);
3854 
3855       if ((account = ladder_get_account(ffa_ladder(clienttag),rank,&teamcount,clienttag)))
3856 	{
3857 	  snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 FFA   %5u: %-20.20s %u/%u/0",
3858 		  rank,
3859 		  account_get_name(account),
3860 		  account_get_ladder_wins(account,clienttag,ladder_id_ffa),
3861 		  account_get_ladder_losses(account,clienttag,ladder_id_ffa));
3862 	}
3863       else
3864 	snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 FFA   %5u: <none>",rank);
3865       message_send_text(c,message_type_info,c,msgtemp);
3866 
3867       if ((account = ladder_get_account(at_ladder(clienttag),rank,&teamcount,clienttag)))
3868 	{
3869 	/*
3870 	  if (account_get_atteammembers(account,teamcount,clienttag))
3871 	    snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 AT Team   %5u: %-80.80s %u/%u/0",
3872 		    rank,
3873 		    account_get_atteammembers(account,teamcount,clienttag),
3874 		    account_get_atteamwin(account,teamcount,clienttag),
3875 		    account_get_atteamloss(account,teamcount,clienttag));
3876 
3877 	  else */
3878 	    snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 AT Team   %5u: <invalid team info>",rank);
3879 	}
3880       else
3881 	snprintf(msgtemp, sizeof(msgtemp), "WarCraft3 AT Team  %5u: <none>",rank);
3882       message_send_text(c,message_type_info,c,msgtemp);
3883     }
3884   //<---
3885   else
3886     {
3887       message_send_text(c,message_type_error,c,"This game does not support win/loss records.");
3888       message_send_text(c,message_type_error,c,"You must supply a rank and a valid program ID.");
3889       message_send_text(c,message_type_error,c,"Example: /ladderinfo 1 STAR");
3890     }
3891 
3892   return 0;
3893 }
3894 
_handle_timer_command(t_connection * c,char const * text)3895 static int _handle_timer_command(t_connection * c, char const *text)
3896 {
3897   unsigned int i,j;
3898   unsigned int delta;
3899   char         deltastr[64];
3900   t_timer_data data;
3901 
3902   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
3903   for (; text[i]==' '; i++);
3904   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get comm */
3905     if (j<sizeof(deltastr)-1) deltastr[j++] = text[i];
3906   deltastr[j] = '\0';
3907   for (; text[i]==' '; i++);
3908 
3909   if (deltastr[0]=='\0')
3910     {
3911       message_send_text(c,message_type_info,c,"usage: /timer <duration>");
3912       return 0;
3913     }
3914 
3915   if (clockstr_to_seconds(deltastr,&delta)<0)
3916     {
3917       message_send_text(c,message_type_error,c,"Invalid duration.");
3918       return 0;
3919     }
3920 
3921   if (text[i]=='\0')
3922     data.p = xstrdup("Your timer has expired.");
3923   else
3924     data.p = xstrdup(&text[i]);
3925 
3926   if (timerlist_add_timer(c,time(NULL)+(time_t)delta,user_timer_cb,data)<0)
3927     {
3928       eventlog(eventlog_level_error,__FUNCTION__,"could not add timer");
3929       xfree(data.p);
3930       message_send_text(c,message_type_error,c,"Could not set timer.");
3931     }
3932   else
3933     {
3934       snprintf(msgtemp, sizeof(msgtemp), "Timer set for %.128s",seconds_to_timestr(delta));
3935       message_send_text(c,message_type_info,c,msgtemp);
3936     }
3937 
3938   return 0;
3939 }
3940 
_handle_serverban_command(t_connection * c,char const * text)3941 static int _handle_serverban_command(t_connection *c, char const *text)
3942 {
3943   char dest[USER_NAME_MAX];
3944   t_connection * dest_c;
3945   unsigned int i,j;
3946 
3947   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); // skip command
3948   for (; text[i]==' '; i++);
3949   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) // get dest
3950     if (j<sizeof(dest)-1) dest[j++] = text[i];
3951   dest[j] = '\0';
3952   for (; text[i]==' '; i++);
3953 
3954       if (dest[0]=='\0')
3955       {
3956 	message_send_text(c,message_type_info,c,"usage: /serverban <account>");
3957 	return 0;
3958       }
3959 
3960       if (!(dest_c = connlist_find_connection_by_accountname(dest)))
3961 	{
3962 	  message_send_text(c,message_type_error,c,"That user is not logged on.");
3963 	  return 0;
3964 	}
3965       snprintf(msgtemp, sizeof(msgtemp), "Banning User %.64s who is using IP %.64s",conn_get_username(dest_c),addr_num_to_ip_str(conn_get_game_addr(dest_c)));
3966       message_send_text(c,message_type_info,c,msgtemp);
3967       message_send_text(c,message_type_info,c,"Users Account is also LOCKED! Only a Admin can Unlock it!");
3968       snprintf(msgtemp, sizeof(msgtemp), "/ipban a %.64s",addr_num_to_ip_str(conn_get_game_addr(dest_c)));
3969       handle_ipban_command(c,msgtemp);
3970       account_set_auth_lock(conn_get_account(dest_c),1);
3971       //now kill the connection
3972       snprintf(msgtemp, sizeof(msgtemp), "You have been banned by Admin: %.64s",conn_get_username(c));
3973       message_send_text(dest_c,message_type_error,dest_c,msgtemp);
3974       message_send_text(dest_c,message_type_error,dest_c,"Your account is also LOCKED! Only a admin can UNLOCK it!");
3975       conn_set_state(dest_c, conn_state_destroy);
3976       return 0;
3977 }
3978 
_handle_netinfo_command(t_connection * c,char const * text)3979 static int _handle_netinfo_command(t_connection * c, char const *text)
3980 {
3981   char           dest[USER_NAME_MAX];
3982   unsigned int   i,j;
3983   t_connection * conn;
3984   t_game const * game;
3985   unsigned int   addr;
3986   unsigned short port;
3987   unsigned int   taddr;
3988   unsigned short tport;
3989 
3990   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); // skip command
3991   for (; text[i]==' '; i++);
3992   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) // get dest
3993     if (j<sizeof(dest)-1) dest[j++] = text[i];
3994   dest[j] = '\0';
3995   for (; text[i]==' '; i++);
3996 
3997   if (dest[0]=='\0')
3998       strcpy(dest,conn_get_username(c));
3999 
4000   if (!(conn = connlist_find_connection_by_accountname(dest)))
4001     {
4002       message_send_text(c,message_type_error,c,"That user is not logged on.");
4003       return 0;
4004     }
4005 
4006   if (conn_get_account(conn)!=conn_get_account(c) &&
4007       prefs_get_hide_addr() && !(account_get_command_groups(conn_get_account(c)) & command_get_group("/admin-addr"))) // default to false
4008     {
4009       message_send_text(c,message_type_error,c,"Address information for other users is only available to admins.");
4010       return 0;
4011     }
4012 
4013   snprintf(msgtemp, sizeof(msgtemp), "Server TCP: %.64s (bind %.64s)",addr_num_to_addr_str(conn_get_real_local_addr(conn),conn_get_real_local_port(conn)),addr_num_to_addr_str(conn_get_local_addr(conn),conn_get_local_port(conn)));
4014   message_send_text(c,message_type_info,c,msgtemp);
4015 
4016   snprintf(msgtemp, sizeof(msgtemp), "Client TCP: %.64s",addr_num_to_addr_str(conn_get_addr(conn),conn_get_port(conn)));
4017   message_send_text(c,message_type_info,c,msgtemp);
4018 
4019   taddr=addr = conn_get_game_addr(conn);
4020   tport=port = conn_get_game_port(conn);
4021   trans_net(conn_get_addr(c),&taddr,&tport);
4022 
4023   if (taddr==addr && tport==port)
4024     snprintf(msgtemp, sizeof(msgtemp), "Client UDP: %.64s",
4025 	    addr_num_to_addr_str(addr,port));
4026   else
4027     snprintf(msgtemp, sizeof(msgtemp), "Client UDP: %.64s (trans %.64s)",
4028 	    addr_num_to_addr_str(addr,port),
4029 	    addr_num_to_addr_str(taddr,tport));
4030   message_send_text(c,message_type_info,c,msgtemp);
4031 
4032   if ((game = conn_get_game(conn)))
4033     {
4034       taddr=addr = game_get_addr(game);
4035       tport=port = game_get_port(game);
4036       trans_net(conn_get_addr(c),&taddr,&tport);
4037 
4038       if (taddr==addr && tport==port)
4039 	snprintf(msgtemp, sizeof(msgtemp), "Game UDP:  %.64s",
4040 		addr_num_to_addr_str(addr,port));
4041       else
4042 	snprintf(msgtemp, sizeof(msgtemp), "Game UDP:  %.64s (trans %.64s)",
4043 		addr_num_to_addr_str(addr,port),
4044 		addr_num_to_addr_str(taddr,tport));
4045     }
4046   else
4047     strcpy(msgtemp,"Game UDP:  none");
4048   message_send_text(c,message_type_info,c,msgtemp);
4049 
4050   return 0;
4051 }
4052 
_handle_quota_command(t_connection * c,char const * text)4053 static int _handle_quota_command(t_connection * c, char const * text)
4054 {
4055   snprintf(msgtemp, sizeof(msgtemp), "Your quota allows you to write %u lines per %u seconds.",prefs_get_quota_lines(),prefs_get_quota_time());
4056   message_send_text(c,message_type_info,c,msgtemp);
4057   snprintf(msgtemp, sizeof(msgtemp), "Long lines will be considered to wrap every %u characters.",prefs_get_quota_wrapline());
4058   message_send_text(c,message_type_info,c,msgtemp);
4059   snprintf(msgtemp, sizeof(msgtemp), "You are not allowed to send lines with more than %u characters.",prefs_get_quota_maxline());
4060   message_send_text(c,message_type_info,c,msgtemp);
4061 
4062   return 0;
4063 }
4064 
_handle_lockacct_command(t_connection * c,char const * text)4065 static int _handle_lockacct_command(t_connection * c, char const *text)
4066 {
4067   t_connection * user;
4068   t_account *    account;
4069 
4070   text = skip_command(text);
4071 
4072   if (text[0]=='\0')
4073     {
4074       message_send_text(c,message_type_info,c,"usage: /lockacct <username>");
4075       return 0;
4076     }
4077 
4078   if (!(account = accountlist_find_account(text)))
4079     {
4080       message_send_text(c,message_type_error,c,"Invalid user.");
4081       return 0;
4082     }
4083   if ((user = connlist_find_connection_by_accountname(text)))
4084     message_send_text(user,message_type_info,user,"Your account has just been locked by admin.");
4085 
4086   account_set_auth_lock(account,1);
4087   message_send_text(c,message_type_error,c,"That user account is now locked.");
4088   return 0;
4089 }
4090 
_handle_unlockacct_command(t_connection * c,char const * text)4091 static int _handle_unlockacct_command(t_connection * c, char const *text)
4092 {
4093   t_connection * user;
4094   t_account *    account;
4095 
4096   text = skip_command(text);
4097 
4098   if (text[0]=='\0')
4099     {
4100       message_send_text(c,message_type_info,c,"usage: /unlockacct <username>");
4101       return 0;
4102     }
4103   if (!(account = accountlist_find_account(text)))
4104     {
4105       message_send_text(c,message_type_error,c,"Invalid user.");
4106       return 0;
4107     }
4108 
4109   if ((user = connlist_find_connection_by_accountname(text)))
4110     message_send_text(user,message_type_info,user,"Your account has just been unlocked by admin.");
4111 
4112   account_set_auth_lock(account,0);
4113   message_send_text(c,message_type_error,c,"That user account is now unlocked.");
4114   return 0;
4115 }
4116 
_handle_flag_command(t_connection * c,char const * text)4117 static int _handle_flag_command(t_connection * c, char const *text)
4118 {
4119   char         dest[32];
4120   unsigned int i,j;
4121   unsigned int newflag;
4122 
4123   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
4124   for (; text[i]==' '; i++);
4125   for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
4126     if (j<sizeof(dest)-1) dest[j++] = text[i];
4127   dest[j] = '\0';
4128   for (; text[i]==' '; i++);
4129 
4130   if (dest[0]=='\0')
4131     {
4132       message_send_text(c,message_type_info,c,"usage: /flag <flag>");
4133       return 0;
4134     }
4135 
4136   newflag = strtoul(dest,NULL,0);
4137   conn_set_flags(c,newflag);
4138 
4139   snprintf(msgtemp, sizeof(msgtemp), "Flags set to 0x%08x.",newflag);
4140   message_send_text(c,message_type_info,c,msgtemp);
4141   return 0;
4142 }
4143 
_handle_tag_command(t_connection * c,char const * text)4144 static int _handle_tag_command(t_connection * c, char const *text)
4145 {
4146     char         dest[8];
4147     unsigned int i,j;
4148     unsigned int newtag;
4149 
4150     for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
4151     for (; text[i]==' '; i++);
4152     for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
4153     if (j<sizeof(dest)-1) dest[j++] = text[i];
4154     dest[j] = '\0';
4155     for (; text[i]==' '; i++);
4156 
4157     if (dest[0]=='\0')
4158     {
4159 	message_send_text(c,message_type_info,c,"usage: /tag <clienttag>");
4160 	return 0;
4161     }
4162     if (strlen(dest)!=4)
4163     {
4164 	message_send_text(c,message_type_error,c,"Client tag should be four characters long.");
4165 	return 0;
4166     }
4167     newtag = tag_case_str_to_uint(dest);
4168     if (tag_check_client(newtag))
4169     {
4170         unsigned int oldflags = conn_get_flags(c);
4171         conn_set_clienttag(c,newtag);
4172 	if ((newtag==CLIENTTAG_WARCRAFT3_UINT) || (newtag==CLIENTTAG_WAR3XP_UINT))
4173 	  conn_update_w3_playerinfo(c);
4174 	channel_rejoin(c);
4175 	conn_set_flags(c,oldflags);
4176 	channel_update_userflags(c);
4177         snprintf(msgtemp, sizeof(msgtemp), "Client tag set to %.64s.",dest);
4178     }
4179     else
4180     snprintf(msgtemp, sizeof(msgtemp), "Invalid clienttag %.64s specified",dest);
4181     message_send_text(c,message_type_info,c,msgtemp);
4182     return 0;
4183 }
4184 
_handle_set_command(t_connection * c,char const * text)4185 static int _handle_set_command(t_connection * c, char const *text)
4186 {
4187   t_account * account;
4188   char *accname;
4189   char *key;
4190   char *value;
4191   char t[MAX_MESSAGE_LEN];
4192   unsigned int i,j;
4193   char         arg1[256];
4194   char         arg2[256];
4195   char         arg3[256];
4196 
4197   strncpy(t, text, MAX_MESSAGE_LEN - 1);
4198   for (i=0; t[i]!=' ' && t[i]!='\0'; i++); /* skip command /set */
4199 
4200   for (; t[i]==' '; i++); /* skip spaces */
4201   for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get username */
4202     if (j<sizeof(arg1)-1) arg1[j++] = t[i];
4203   arg1[j] = '\0';
4204 
4205   for (; t[i]==' '; i++); /* skip spaces */
4206   for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get key */
4207     if (j<sizeof(arg2)-1) arg2[j++] = t[i];
4208   arg2[j] = '\0';
4209 
4210   for (; t[i]==' '; i++); /* skip spaces */
4211   for (j=0; t[i]!='\0'; i++) /* get value */
4212     if (j<sizeof(arg3)-1) arg3[j++] = t[i];
4213   arg3[j] = '\0';
4214 
4215   accname = arg1;
4216   key     = arg2;
4217   value   = arg3;
4218 
4219   if ((arg1[0] =='\0') || (arg2[0]=='\0'))
4220   {
4221 	message_send_text(c,message_type_info,c,"usage: /set <username> <key> [value]");
4222   }
4223 
4224   if (!(account = accountlist_find_account(accname)))
4225     {
4226       message_send_text(c,message_type_error,c,"Invalid user.");
4227       return 0;
4228     }
4229 
4230   if (*value == '\0')
4231     {
4232       if (account_get_strattr(account,key))
4233 	{
4234 	  snprintf(msgtemp, sizeof(msgtemp), "current value of %.64s is \"%.128s\"",key,account_get_strattr(account,key));
4235 	  message_send_text(c,message_type_error,c,msgtemp);
4236 	}
4237       else
4238 	message_send_text(c,message_type_error,c,"value currently not set");
4239       return 0;
4240     }
4241 
4242   if (account_set_strattr(account,key,value)<0)
4243     message_send_text(c,message_type_error,c,"Unable to set key");
4244   else
4245     message_send_text(c,message_type_error,c,"Key set succesfully");
4246 
4247   return 0;
4248 }
4249 
_handle_motd_command(t_connection * c,char const * text)4250 static int _handle_motd_command(t_connection * c, char const *text)
4251 {
4252   char const * filename;
4253   FILE *       fp;
4254 
4255   if ((filename = prefs_get_motdfile())) {
4256     if ((fp = fopen(filename,"r")))
4257       {
4258 	message_send_file(c,fp);
4259 	if (fclose(fp)<0)
4260 	  eventlog(eventlog_level_error,__FUNCTION__,"could not close motd file \"%s\" after reading (fopen: %s)",filename,pstrerror(errno));
4261       }
4262     else
4263       {
4264 	eventlog(eventlog_level_error,__FUNCTION__,"could not open motd file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
4265 	message_send_text(c,message_type_error,c,"Unable to open motd.");
4266       }
4267     return 0;
4268   } else {
4269     message_send_text(c,message_type_error,c,"No motd.");
4270     return 0;
4271   }
4272 }
4273 
_handle_tos_command(t_connection * c,char const * text)4274 static int _handle_tos_command(t_connection * c, char const * text)
4275 {
4276 /* handle /tos - shows terms of service by user request -raistlinthewiz */
4277 
4278   char * filename=NULL;
4279   FILE * fp;
4280 
4281   filename = buildpath(prefs_get_filedir(),prefs_get_tosfile());
4282 
4283   /* FIXME: if user enters relative path to tos file in config,
4284      above routine will fail */
4285 
4286     if ((fp = fopen(filename,"r")))
4287     {
4288 
4289          char * buff;
4290          int len;
4291 
4292          while ((buff = file_get_line(fp)))
4293          {
4294 
4295                if ((len=strlen(buff)) < MAX_MESSAGE_LEN)
4296                   message_send_text(c,message_type_info,c,buff);
4297                else {
4298                /*  lines in TOS file can be > MAX_MESSAGE_LEN, so split them
4299                truncating is not an option for TOS -raistlinthewiz
4300                */
4301 
4302                   while ( len  > MAX_MESSAGE_LEN - 1)
4303                   {
4304                         strncpy(msgtemp,buff,MAX_MESSAGE_LEN-1);
4305                         msgtemp[MAX_MESSAGE_LEN]='\0';
4306                         buff += MAX_MESSAGE_LEN - 1;
4307                         len -= MAX_MESSAGE_LEN - 1;
4308                         message_send_text(c,message_type_info,c,msgtemp);
4309                   }
4310 
4311                   if ( len > 0 ) /* does it exist a small last part ? */
4312                      message_send_text(c,message_type_info,c,buff);
4313 
4314                }
4315          }
4316 
4317 
4318        	if (fclose(fp)<0)
4319 	       eventlog(eventlog_level_error,__FUNCTION__,"could not close tos file \"%s\" after reading (fopen: %s)",filename,pstrerror(errno));
4320     }
4321     else
4322     {
4323 	    eventlog(eventlog_level_error,__FUNCTION__,"could not open tos file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
4324         message_send_text(c,message_type_error,c,"Unable to send TOS (terms of service).");
4325     }
4326     xfree((void *)filename);
4327     return 0;
4328 
4329 }
4330 
4331 
_handle_ping_command(t_connection * c,char const * text)4332 static int _handle_ping_command(t_connection * c, char const *text)
4333 {
4334   unsigned int i;
4335   t_connection *	user;
4336   t_game 	*	game;
4337 
4338   for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
4339   for (; text[i]==' '; i++);
4340 
4341   if (text[i]=='\0')
4342     {
4343       if ((game=conn_get_game(c)))
4344 	{
4345 	  for (i=0; i<game_get_count(game); i++)
4346 	    {
4347 	      if ((user = game_get_player_conn(game, i)))
4348 		{
4349 		  snprintf(msgtemp, sizeof(msgtemp), "%.64s latency: %9u",conn_get_username(user),conn_get_latency(user));
4350 		  message_send_text(c,message_type_info,c,msgtemp);
4351 		}
4352 	    }
4353 	  return 0;
4354 	}
4355       snprintf(msgtemp, sizeof(msgtemp), "Your latency %9u",conn_get_latency(c));
4356     }
4357   else if ((user = connlist_find_connection_by_accountname(&text[i])))
4358     snprintf(msgtemp, sizeof(msgtemp), "%.64s latency %9u",&text[i],conn_get_latency(user));
4359   else
4360     snprintf(msgtemp, sizeof(msgtemp), "Invalid user");
4361 
4362   message_send_text(c,message_type_info,c,msgtemp);
4363   return 0;
4364 }
4365 
4366 /* Redirected to handle_ipban_command in ipban.c [Omega]
4367 static int _handle_ipban_command(t_connection * c, char const *text)
4368 {
4369   handle_ipban_command(c,text);
4370   return 0;
4371 }
4372 */
4373 
_handle_commandgroups_command(t_connection * c,char const * text)4374 static int _handle_commandgroups_command(t_connection * c, char const * text)
4375 {
4376     t_account *	account;
4377     char *	command;
4378     char *	username;
4379     unsigned int usergroups;	// from user account
4380     unsigned int groups = 0;	// converted from arg3
4381     char	tempgroups[9];	// converted from usergroups
4382     char 	t[MAX_MESSAGE_LEN];
4383     unsigned int i,j;
4384     char	arg1[256];
4385     char	arg2[256];
4386     char	arg3[256];
4387 
4388     strncpy(t, text, MAX_MESSAGE_LEN - 1);
4389     for (i=0; t[i]!=' ' && t[i]!='\0'; i++); /* skip command /groups */
4390 
4391     for (; t[i]==' '; i++); /* skip spaces */
4392     for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get command */
4393 	if (j<sizeof(arg1)-1) arg1[j++] = t[i];
4394     arg1[j] = '\0';
4395 
4396     for (; t[i]==' '; i++); /* skip spaces */
4397     for (j=0; t[i]!=' ' && t[i]!='\0'; i++) /* get username */
4398 	if (j<sizeof(arg2)-1) arg2[j++] = t[i];
4399     arg2[j] = '\0';
4400 
4401     for (; t[i]==' '; i++); /* skip spaces */
4402     for (j=0; t[i]!='\0'; i++) /* get groups */
4403 	if (j<sizeof(arg3)-1) arg3[j++] = t[i];
4404     arg3[j] = '\0';
4405 
4406     command = arg1;
4407     username = arg2;
4408 
4409     if (arg1[0] =='\0') {
4410 	message_send_text(c,message_type_info,c,"usage: /cg <command> <username> [<group(s)>]");
4411 	return 0;
4412     }
4413 
4414     if (!strcmp(command,"help") || !strcmp(command,"h")) {
4415 	message_send_text(c,message_type_info,c,"Command Groups (Defines the Groups of Commands a User Can Use.)");
4416 	message_send_text(c,message_type_info,c,"Type: /cg add <username> <group(s)> - adds group(s) to user profile");
4417 	message_send_text(c,message_type_info,c,"Type: /cg del <username> <group(s)> - deletes group(s) from user profile");
4418 	message_send_text(c,message_type_info,c,"Type: /cg list <username> - shows current groups user can use");
4419 	return 0;
4420     }
4421 
4422     if (arg2[0] =='\0') {
4423 	message_send_text(c,message_type_info,c,"usage: /cg <command> <username> [<group(s)>]");
4424 	return 0;
4425     }
4426 
4427     if (!(account = accountlist_find_account(username))) {
4428 	message_send_text(c,message_type_error,c,"Invalid user.");
4429 	return 0;
4430     }
4431 
4432     usergroups = account_get_command_groups(account);
4433 
4434     if (!strcmp(command,"list") || !strcmp(command,"l")) {
4435 	if (usergroups & 1) tempgroups[0] = '1'; else tempgroups[0] = ' ';
4436 	if (usergroups & 2) tempgroups[1] = '2'; else tempgroups[1] = ' ';
4437 	if (usergroups & 4) tempgroups[2] = '3'; else tempgroups[2] = ' ';
4438 	if (usergroups & 8) tempgroups[3] = '4'; else tempgroups[3] = ' ';
4439 	if (usergroups & 16) tempgroups[4] = '5'; else tempgroups[4] = ' ';
4440 	if (usergroups & 32) tempgroups[5] = '6'; else tempgroups[5] = ' ';
4441 	if (usergroups & 64) tempgroups[6] = '7'; else tempgroups[6] = ' ';
4442 	if (usergroups & 128) tempgroups[7] = '8'; else tempgroups[7] = ' ';
4443 	tempgroups[8] = '\0';
4444 	snprintf(msgtemp, sizeof(msgtemp), "%.64s's command group(s): %.128s", username, tempgroups);
4445 	message_send_text(c,message_type_info,c,msgtemp);
4446 	return 0;
4447     }
4448 
4449     if (arg3[0] =='\0') {
4450 	message_send_text(c,message_type_info,c,"usage: /cg <command> <username> [<group(s)>]");
4451 	return 0;
4452     }
4453 
4454     for (i=0; arg3[i] != '\0'; i++) {
4455 	if (arg3[i] == '1') groups |= 1;
4456 	else if (arg3[i] == '2') groups |= 2;
4457 	else if (arg3[i] == '3') groups |= 4;
4458 	else if (arg3[i] == '4') groups |= 8;
4459 	else if (arg3[i] == '5') groups |= 16;
4460 	else if (arg3[i] == '6') groups |= 32;
4461 	else if (arg3[i] == '7') groups |= 64;
4462 	else if (arg3[i] == '8') groups |= 128;
4463 	else {
4464 	    snprintf(msgtemp, sizeof(msgtemp), "got bad group: %c", arg3[i]);
4465 	    message_send_text(c,message_type_info,c,msgtemp);
4466 	    return 0;
4467 	}
4468     }
4469 
4470     if (!strcmp(command,"add") || !strcmp(command,"a")) {
4471 	account_set_command_groups(account, usergroups | groups);
4472 	snprintf(msgtemp, sizeof(msgtemp), "groups %.128s has been added to user: %.64s", arg3, username);
4473 	message_send_text(c,message_type_info,c,msgtemp);
4474 	return 0;
4475     }
4476 
4477     if (!strcmp(command,"del") || !strcmp(command,"d")) {
4478 	account_set_command_groups(account, usergroups & (255 - groups));
4479 	snprintf(msgtemp, sizeof(msgtemp), "groups %.128s has been deleted from user: %.64s", arg3, username);
4480 	message_send_text(c,message_type_info,c,msgtemp);
4481 	return 0;
4482     }
4483 
4484     snprintf(msgtemp, sizeof(msgtemp), "got unknown command: %.64s", command);
4485     message_send_text(c,message_type_info,c,msgtemp);
4486     return 0;
4487 }
4488 
_handle_topic_command(t_connection * c,char const * text)4489 static int _handle_topic_command(t_connection * c, char const * text)
4490 {
4491   char const * channel_name;
4492   char const * topic;
4493   char * tmp;
4494   t_channel * channel;
4495   int  do_save = NO_SAVE_TOPIC;
4496 
4497   channel_name = skip_command(text);
4498 
4499   if ((topic = strchr(channel_name,'"')))
4500   {
4501     tmp = (char *)topic;
4502     for (tmp--;tmp[0]==' ';tmp--);
4503     tmp[1]='\0';
4504     topic++;
4505     tmp  = strchr(topic,'"');
4506     if (tmp) tmp[0]='\0';
4507   }
4508 
4509   if (!(conn_get_channel(c))) {
4510     message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
4511     return -1;
4512   }
4513 
4514   if (channel_name[0]=='\0')
4515   {
4516     if (channel_get_topic(channel_get_name(conn_get_channel(c))))
4517     {
4518       snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: %.128s",channel_get_name(conn_get_channel(c)),channel_get_topic(channel_get_name(conn_get_channel(c))));
4519     }
4520     else
4521     {
4522       snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: no topic",channel_get_name(conn_get_channel(c)));
4523     }
4524     message_send_text(c,message_type_info,c,msgtemp);
4525 
4526     return 0;
4527   }
4528 
4529   if (!(topic))
4530   {
4531     if (channel_get_topic(channel_name))
4532     {
4533       snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: %.128s",channel_name, channel_get_topic(channel_name));
4534     }
4535     else
4536     {
4537       snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: no topic",channel_name);
4538     }
4539     message_send_text(c,message_type_info,c,msgtemp);
4540     return 0;
4541   }
4542 
4543   if (!(channel = channellist_find_channel_by_name(channel_name,conn_get_country(c),realm_get_name(conn_get_realm(c)))))
4544   {
4545     message_send_text(c,message_type_error,c,"no such channel, can't set topic");
4546     return -1;
4547   }
4548 
4549   if (strlen(topic) >= MAX_TOPIC_LEN)
4550   {
4551     snprintf(msgtemp, sizeof(msgtemp), "max topic length exceeded (max %d symbols)", MAX_TOPIC_LEN);
4552     message_send_text(c,message_type_error,c,msgtemp);
4553     return -1;
4554   }
4555 
4556   channel_name = channel_get_name(channel);
4557 
4558   if (!(account_is_operator_or_admin(conn_get_account(c),channel_name))) {
4559 	snprintf(msgtemp, sizeof(msgtemp), "You must be at least a Channel Operator of %.64s to set the topic",channel_name);
4560 	message_send_text(c,message_type_error,c,msgtemp);
4561 	return -1;
4562   }
4563 
4564   if (channel_get_permanent(channel))
4565     do_save = DO_SAVE_TOPIC;
4566 
4567   channel_set_topic(channel_name, topic, do_save);
4568 
4569   snprintf(msgtemp, sizeof(msgtemp), "%.64s topic: %.128s",channel_name, topic);
4570   message_send_text(c,message_type_info,c,msgtemp);
4571 
4572   return 0;
4573 }
4574 
_handle_moderate_command(t_connection * c,char const * text)4575 static int _handle_moderate_command(t_connection * c, char const * text)
4576 {
4577   t_channel_flags oldflags;
4578   t_channel * channel;
4579 
4580   if (!(channel = conn_get_channel(c))) {
4581     message_send_text(c,message_type_error,c,"This command can only be used inside a channel.");
4582     return -1;
4583   }
4584 
4585   if (!(account_is_operator_or_admin(conn_get_account(c),channel_get_name(channel)))) {
4586 	message_send_text(c,message_type_error,c,"You must be at least a Channel Operator to use this command.");
4587 	return -1;
4588   }
4589 
4590   oldflags = channel_get_flags(channel);
4591 
4592   if (channel_set_flags(channel, oldflags ^ channel_flags_moderated)) {
4593 	eventlog(eventlog_level_error,__FUNCTION__,"could not set channel %s flags",channel_get_name(channel));
4594 	message_send_text(c,message_type_error,c,"Unable to change channel flags.");
4595 	return -1;
4596   }
4597   else {
4598   	if (oldflags & channel_flags_moderated)
4599 		channel_message_send(channel,message_type_info,c,"Channel is now unmoderated");
4600 	else
4601 		channel_message_send(channel,message_type_info,c,"Channel is now moderated");
4602   }
4603 
4604   return 0;
4605 }
4606 
_reset_d1_stats(t_account * account,t_clienttag ctag,t_connection * c)4607 static void _reset_d1_stats(t_account *account, t_clienttag ctag, t_connection *c)
4608 {
4609     account_set_normal_level(account,ctag,0);
4610     account_set_normal_strength(account,ctag,0),
4611     account_set_normal_magic(account,ctag,0),
4612     account_set_normal_dexterity(account,ctag,0),
4613     account_set_normal_vitality(account,ctag,0),
4614     account_set_normal_gold(account,ctag,0);
4615 
4616     snprintf(msgtemp, sizeof(msgtemp), "Resetted %.64s's %.64s Stats",account_get_name(account),clienttag_get_title(ctag));
4617     message_send_text(c,message_type_info,c,msgtemp);
4618 }
4619 
_reset_scw2_stats(t_account * account,t_clienttag ctag,t_connection * c)4620 static void _reset_scw2_stats(t_account *account, t_clienttag ctag, t_connection *c)
4621 {
4622     account_set_normal_wins(account,ctag,0);
4623     account_set_normal_losses(account,ctag,0);
4624     account_set_normal_disconnects(account,ctag,0);
4625 
4626     if (account_get_ladder_rating(account,ctag,ladder_id_normal)>0) {
4627 	account_set_ladder_wins(account,ctag,ladder_id_normal,0);
4628 	account_set_ladder_losses(account,ctag,ladder_id_normal,0);
4629 	account_set_ladder_disconnects(account,ctag,ladder_id_normal,0);
4630 	account_set_ladder_rating(account,ctag,ladder_id_normal,0);
4631     }
4632 
4633     if (account_get_ladder_rating(account,ctag,ladder_id_ironman)>0) {
4634 	account_set_ladder_wins(account,ctag,ladder_id_ironman,0);
4635 	account_set_ladder_losses(account,ctag,ladder_id_ironman,0);
4636 	account_set_ladder_disconnects(account,ctag,ladder_id_ironman,0);
4637 	account_set_ladder_rating(account,ctag,ladder_id_ironman,0);
4638     }
4639 
4640     snprintf(msgtemp, sizeof(msgtemp), "Resetted %.64s's %.64s Stats",account_get_name(account),clienttag_get_title(ctag));
4641     message_send_text(c,message_type_info,c,msgtemp);
4642 }
4643 
_reset_w3_stats(t_account * account,t_clienttag ctag,t_connection * c)4644 static void _reset_w3_stats(t_account *account, t_clienttag ctag, t_connection *c)
4645 {
4646     account_set_ladder_level(account,ctag,ladder_id_solo,0);
4647     account_set_ladder_xp(account,ctag,ladder_id_solo,0);
4648     account_set_ladder_wins(account,ctag,ladder_id_solo,0);
4649     account_set_ladder_losses(account,ctag,ladder_id_solo,0);
4650     account_set_ladder_rank(account,ctag,ladder_id_solo,0);
4651 
4652     account_set_ladder_level(account,ctag,ladder_id_team,0);
4653     account_set_ladder_xp(account,ctag,ladder_id_team,0);
4654     account_set_ladder_wins(account,ctag,ladder_id_team,0);
4655     account_set_ladder_losses(account,ctag,ladder_id_team,0);
4656     account_set_ladder_rank(account,ctag,ladder_id_team,0);
4657 
4658     account_set_ladder_level(account,ctag,ladder_id_ffa,0);
4659     account_set_ladder_xp(account,ctag,ladder_id_ffa,0);
4660     account_set_ladder_wins(account,ctag,ladder_id_ffa,0);
4661     account_set_ladder_losses(account,ctag,ladder_id_ffa,0);
4662     account_set_ladder_rank(account,ctag,ladder_id_ffa,0);
4663     // this would now need a way to delete the team for all members now
4664     //account_set_atteamcount(account,ctag,0);
4665 
4666     snprintf(msgtemp, sizeof(msgtemp), "Resetted %.64s's %.64s Stats",account_get_name(account),clienttag_get_title(ctag));
4667     message_send_text(c,message_type_info,c,msgtemp);
4668 }
4669 
_handle_clearstats_command(t_connection * c,char const * text)4670 static int _handle_clearstats_command(t_connection *c, char const *text)
4671 {
4672     char         dest[USER_NAME_MAX];
4673     unsigned int i,j,all;
4674     t_account *  account;
4675     t_clienttag  ctag = 0;
4676 
4677     for (i=0; text[i]!=' ' && text[i]!='\0'; i++); /* skip command */
4678     for (; text[i]==' '; i++);
4679 
4680     if (!text[i]) {
4681 	message_send_text(c,message_type_error,c,"Missing user, syntax error.");
4682 	message_send_text(c,message_type_error,c,"Usage example: /clearstats <username> <clienttag>");
4683 	message_send_text(c,message_type_error,c,"  where <clienttag> can be any valid client or ALL for all clients");
4684 	return 0;
4685     }
4686 
4687     for (j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get dest */
4688 	if (j<sizeof(dest)-1) dest[j++] = text[i];
4689     dest[j] = '\0';
4690 
4691     account = accountlist_find_account(dest);
4692     if (!account) {
4693 	message_send_text(c,message_type_error,c,"Invalid user.");
4694 	return 0;
4695     }
4696 
4697     for (; text[i]==' '; i++);
4698     if (!text[i]) {
4699 	message_send_text(c,message_type_error,c,"Missing clienttag, syntax error.");
4700 	message_send_text(c,message_type_error,c,"Usage example: /clearstats <username> <clienttag>");
4701 	message_send_text(c,message_type_error,c,"  where <clienttag> can be any valid client or ALL for all clients");
4702 	return 0;
4703     }
4704 
4705     if (strcasecmp(text + i,"all")) {
4706 	if (strlen(text + i) != 4) {
4707 	    message_send_text(c,message_type_error,c,"Invalid clienttag, syntax error.");
4708 	    return 0;
4709 	}
4710 	ctag = tag_case_str_to_uint(text + i);
4711 	all = 0;
4712     } else all = 1;
4713 
4714     if (all || ctag == CLIENTTAG_DIABLORTL_UINT)
4715 	_reset_d1_stats(account,CLIENTTAG_DIABLORTL_UINT,c);
4716 
4717     if (all || ctag == CLIENTTAG_DIABLOSHR_UINT)
4718 	_reset_d1_stats(account,CLIENTTAG_DIABLOSHR_UINT,c);
4719 
4720     if (all || ctag == CLIENTTAG_WARCIIBNE_UINT)
4721 	_reset_scw2_stats(account,CLIENTTAG_WARCIIBNE_UINT,c);
4722 
4723     if (all || ctag == CLIENTTAG_STARCRAFT_UINT)
4724 	_reset_scw2_stats(account,CLIENTTAG_STARCRAFT_UINT,c);
4725 
4726     if (all || ctag == CLIENTTAG_BROODWARS_UINT)
4727 	_reset_scw2_stats(account,CLIENTTAG_BROODWARS_UINT,c);
4728 
4729     if (all || ctag == CLIENTTAG_SHAREWARE_UINT)
4730 	_reset_scw2_stats(account,CLIENTTAG_SHAREWARE_UINT,c);
4731 
4732     if (all || ctag == CLIENTTAG_WARCRAFT3_UINT)
4733 	_reset_w3_stats(account,CLIENTTAG_WARCRAFT3_UINT,c);
4734 
4735     if (all || ctag == CLIENTTAG_WAR3XP_UINT)
4736 	_reset_w3_stats(account,CLIENTTAG_WAR3XP_UINT,c);
4737 
4738     return 0;
4739 }
4740