/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/command.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/command.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
Branch point for: GNU
Content type: text/x-csrc
Initial revision

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

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1