1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
16 #define CLAN_INTERNAL_ACCESS
17 #include "common/setup_before.h"
18 #include <stdio.h>
19 #ifdef HAVE_STDDEF_H
20 # include <stddef.h>
21 #else
22 # ifndef NULL
23 #  define NULL ((void *)0)
24 # endif
25 #endif
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 #else
29 # ifdef HAVE_MALLOC_H
30 #  include <malloc.h>
31 # endif
32 #endif
33 #ifdef HAVE_STRING_H
34 # include <string.h>
35 #else
36 # ifdef HAVE_STRINGS_H
37 #  include <strings.h>
38 # endif
39 #endif
40 #include "compat/strrchr.h"
41 #include "compat/strdup.h"
42 #include "compat/strcasecmp.h"
43 #include "compat/strncasecmp.h"
44 #include "compat/pdir.h"
45 #include <errno.h>
46 #include "compat/strerror.h"
47 #ifdef TIME_WITH_SYS_TIME
48 # include <sys/time.h>
49 # include <time.h>
50 #else
51 # ifdef HAVE_SYS_TIME_H
52 #  include <sys/time.h>
53 # else
54 #  include <time.h>
55 # endif
56 #endif
57 #ifdef HAVE_SYS_TYPES_H
58 # include <sys/types.h>
59 #endif
60 #include "common/eventlog.h"
61 #include "common/packet.h"
62 #include "common/bnet_protocol.h"
63 #include "common/tag.h"
64 #include "common/util.h"
65 #include "common/bnettime.h"
66 #include "common/eventlog.h"
67 #include "common/list.h"
68 #include "common/proginfo.h"
69 #include "common/bn_type.h"
70 #include "common/xalloc.h"
71 #include "connection.h"
72 #include "anongame.h"
73 #include "prefs.h"
74 #include "friends.h"
75 #include "game.h"
76 #include "clan.h"
77 #include "account.h"
78 #include "channel.h"
79 #include "anongame.h"
80 #include "storage.h"
81 #include "server.h"
82 #include "compat/uint.h"
83 #include "common/setup_after.h"
84 
85 static t_list *clanlist_head = NULL;
86 int max_clanid = 0;
87 
88 /* callback function for storage use */
89 
_cb_load_clans(void * clan)90 static int _cb_load_clans(void *clan)
91 {
92     if (clanlist_add_clan(clan) < 0)
93     {
94 	eventlog(eventlog_level_error, __FUNCTION__, "failed to add clan to clanlist");
95 	return -1;
96     }
97 
98     if (((t_clan *) clan)->clanid > max_clanid)
99 	max_clanid = ((t_clan *) clan)->clanid;
100     return 0;
101 }
102 
103 /*
104 ** Packet Management
105 */
106 
clan_send_packet_to_online_members(t_clan * clan,t_packet * packet)107 extern int clan_send_packet_to_online_members(t_clan * clan, t_packet * packet)
108 {
109     t_elem *curr;
110 
111     if (!clan)
112     {
113 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
114 	return -1;
115     }
116 
117     if (!packet)
118     {
119 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet");
120 	return -1;
121     }
122 
123     LIST_TRAVERSE(clan->members, curr)
124     {
125 	t_clanmember *	member;
126 	t_clienttag	clienttag;
127 	t_connection *	conn;
128 
129 	if (!(member = elem_get_data(curr)))
130 	{
131 		eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list");
132 		continue;
133 	}
134 	if (!(conn = clanmember_get_conn(member)))
135 		continue;				// not online
136 
137 	if (!(clienttag = conn_get_clienttag(conn)))
138 	{
139 		eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag");
140 		continue;
141 	}
142 
143 	if ((clienttag !=  CLIENTTAG_WARCRAFT3_UINT ) && (clienttag != CLIENTTAG_WAR3XP_UINT))
144 		continue;				// online but wrong client
145 
146 	conn_push_outqueue(conn, packet);
147     }
148 
149     return 0;
150 }
151 
clan_send_status_window_on_create(t_clan * clan)152 extern int clan_send_status_window_on_create(t_clan * clan)
153 {
154     t_packet * rpacket;
155     t_elem *curr;
156 
157     if (!(clan))
158     {
159 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
160 	return -1;
161     }
162 
163     if ((rpacket = packet_create(packet_class_bnet)))
164     {
165 	char channelname[10];
166 	if (clan->clantag)
167 	    sprintf(channelname, "Clan %c%c%c%c", (clan->clantag >> 24), (clan->clantag >> 16) & 0xff, (clan->clantag >> 8) & 0xff, clan->clantag & 0xff);
168 	else
169 	{
170 	    sprintf(channelname, "Clans");
171 	    eventlog(eventlog_level_error,__FUNCTION__,"clan has NULL clantag");
172 	}
173 
174 	packet_set_size(rpacket, sizeof(t_server_w3xp_clan_clanack));
175 	packet_set_type(rpacket, SERVER_W3XP_CLAN_CLANACK);
176 	bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.unknow1, 0);
177 	bn_int_set(&rpacket->u.server_w3xp_clan_clanack.clantag, clan->clantag);
178 
179 	LIST_TRAVERSE(clan->members, curr)
180 	{
181 	    t_clanmember *	member;
182 	    t_clienttag 	clienttag;
183 	    t_connection *	conn;
184 
185 	    if (!(member = elem_get_data(curr)))
186 	    {
187 	    	eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list");
188 		continue;
189 	    }
190 	    if (!(conn = clanmember_get_conn(member)))
191 	    	continue;			// not online;
192 
193 	    if (!(clienttag = conn_get_clienttag(conn)))
194 	    {
195 		eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag");
196 		continue;
197 	    }
198 	    if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT))
199 	    	continue;			// online but wrong client
200 
201 	    if (conn_get_channel(conn))
202 	    {
203 	        conn_update_w3_playerinfo(conn);
204 	        channel_set_userflags(conn);
205 	        if (conn_set_channel(conn, channelname) < 0)
206 		    conn_set_channel(conn, CHANNEL_NAME_BANNED);	/* should not fail */
207 	    }
208 	    bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.status, member->status);
209 	    conn_push_outqueue(conn, rpacket);
210 	}
211 	packet_del_ref(rpacket);
212     }
213     return 0;
214 }
215 
clan_close_status_window_on_disband(t_clan * clan)216 extern int clan_close_status_window_on_disband(t_clan * clan)
217 {
218     t_packet * rpacket;
219     t_elem *curr;
220 
221     if (!(clan))
222     {
223 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
224 	return -1;
225     }
226 
227     if ((rpacket = packet_create(packet_class_bnet)))
228     {
229 	packet_set_size(rpacket, sizeof(t_server_w3xp_clanquitnotify));
230 	packet_set_type(rpacket, SERVER_W3XP_CLANQUITNOTIFY);
231 	bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.status, SERVER_W3XP_CLANQUITNOTIFY_STATUS_REMOVED_FROM_CLAN);
232 	LIST_TRAVERSE(clan->members, curr)
233 	{
234 	    t_clanmember *	member;
235 	    t_clienttag 	clienttag;
236 	    t_connection *	conn;
237 
238 	    if (!(member = elem_get_data(curr)))
239 	    {
240 	    	eventlog(eventlog_level_error,__FUNCTION__,"got NULL elem in list");
241 		continue;
242 	    }
243 	    if (!(conn = clanmember_get_conn(member)))
244 	    	continue;			// not online;
245 
246 	    if (!(clienttag = conn_get_clienttag(conn)))
247 	    {
248 		eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag");
249 		continue;
250 	    }
251 
252 	    if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT))
253 	    	continue;			// online but wrong client
254 
255 	    conn_push_outqueue(conn, rpacket);
256 	    conn_update_w3_playerinfo(conn);
257 	}
258 	packet_del_ref(rpacket);
259     }
260 
261 
262     return 0;
263 }
264 
clan_send_status_window(t_connection * c)265 extern int clan_send_status_window(t_connection * c)
266 {
267     t_packet * rpacket;
268     t_account *acc;
269     t_clanmember *member;
270     t_clienttag clienttag;
271     t_clan * clan;
272 
273     if (!(acc = conn_get_account(c)))
274 	return 0;
275 
276     if (!(member = account_get_clanmember(acc)))
277     	return 0;
278 
279     if (!(clan = member->clan))
280     {
281 	eventlog(eventlog_level_error,__FUNCTION__,"member has NULL clan");
282 	return -1;
283     }
284 
285     if (!(clan->clantag))
286     {
287 	eventlog(eventlog_level_error,__FUNCTION__,"clan has NULL clantag");
288 	return -1;
289     }
290 
291     if (!(clienttag = conn_get_clienttag(c)))
292     {
293 	eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag");
294 	return -1;
295     }
296 
297     if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT))
298     	return 0;
299 
300     if ((rpacket = packet_create(packet_class_bnet)))
301     {
302 	    packet_set_size(rpacket, sizeof(t_server_w3xp_clan_clanack));
303 	    packet_set_type(rpacket, SERVER_W3XP_CLAN_CLANACK);
304 	    bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.unknow1, 0);
305 	    bn_int_set(&rpacket->u.server_w3xp_clan_clanack.clantag, member->clan->clantag);
306 	    bn_byte_set(&rpacket->u.server_w3xp_clan_clanack.status, member->status);
307 	    conn_push_outqueue(c, rpacket);
308 	    packet_del_ref(rpacket);
309     }
310     return 0;
311 }
312 
clan_close_status_window(t_connection * c)313 extern int clan_close_status_window(t_connection * c)
314 {
315     t_packet * rpacket;
316     t_clienttag clienttag;
317 
318     if (!(clienttag = conn_get_clienttag(c)))
319     {
320     	eventlog(eventlog_level_error,__FUNCTION__,"conn has NULL clienttag");
321 	return -1;
322     }
323 
324     if ((clienttag != CLIENTTAG_WARCRAFT3_UINT) && (clienttag != CLIENTTAG_WAR3XP_UINT))
325     	return 0;
326 
327     if ((rpacket = packet_create(packet_class_bnet)))
328     {
329 	packet_set_size(rpacket, sizeof(t_server_w3xp_clanquitnotify));
330 	packet_set_type(rpacket, SERVER_W3XP_CLANQUITNOTIFY);
331 	bn_byte_set(&rpacket->u.server_w3xp_clanquitnotify.status, SERVER_W3XP_CLANQUITNOTIFY_STATUS_REMOVED_FROM_CLAN);
332 	conn_push_outqueue(c, rpacket);
333 	packet_del_ref(rpacket);
334     }
335     return 0;
336 }
337 
clan_send_memberlist(t_connection * c,t_packet const * const packet)338 extern int clan_send_memberlist(t_connection * c, t_packet const *const packet)
339 {
340     t_packet * rpacket;
341     t_elem *curr;
342     char const *username;
343     t_clanmember *member;
344     t_clan *clan;
345     t_account *account;
346     int count = 0;
347     char tmpstr[2];
348     const char *append_str;
349 
350     if (!(account = conn_get_account(c)))
351 	return -1;
352 
353     if (!(clan = account_get_clan(account)))
354 	return -1;
355 
356     if ((rpacket = packet_create(packet_class_bnet)))
357     {
358     	t_account * memberacc;
359 
360 	packet_set_size(rpacket, sizeof(t_server_w3xp_clanmemberlist_reply));
361 	packet_set_type(rpacket, SERVER_W3XP_CLANMEMBERLIST_REPLY);
362 	bn_int_set(&rpacket->u.server_w3xp_clanmemberlist_reply.count,
363 	           bn_int_get(packet->u.client_w3xp_clanmemberlist_req.count));
364 	LIST_TRAVERSE(clan->members, curr)
365 	{
366 	    if (!(member = elem_get_data(curr)))
367 	    {
368 		eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list");
369 		continue;
370 	    }
371 
372 	    if (!(memberacc = member->memberacc))
373 	    {
374 		eventlog(eventlog_level_error,__FUNCTION__,"member has NULL account");
375 		continue;
376 	    }
377 
378 	    username = account_get_name(memberacc);
379 	    packet_append_string(rpacket, username);
380 	    tmpstr[0] = member->status;
381 	    append_str = clanmember_get_online_status(member, &tmpstr[1]);
382 	    packet_append_data(rpacket, tmpstr, 2);
383 	    if (append_str)
384 		packet_append_string(rpacket, append_str);
385 	    else
386 		packet_append_string(rpacket, "");
387 	    count++;
388 	}
389 	bn_byte_set(&rpacket->u.server_w3xp_clanmemberlist_reply.member_count, count);
390 	conn_push_outqueue(c, rpacket);
391 	packet_del_ref(rpacket);
392 	return 0;
393     }
394 
395     return -1;
396 }
397 
clan_save_motd_chg(t_connection * c,t_packet const * const packet)398 extern int clan_save_motd_chg(t_connection * c, t_packet const *const packet)
399 {
400     t_account *account;
401     char const *motd;
402     int offset;
403     t_clan *clan;
404 
405     if ((account = conn_get_account(c)) == NULL)
406 	return -1;
407     if ((clan = account_get_clan(account)) == NULL)
408 	return -1;
409     offset = sizeof(packet->u.client_w3xp_clan_motdchg);
410     motd = packet_get_str_const(packet, offset, CLAN_MOTD_MAX);
411     eventlog(eventlog_level_trace, __FUNCTION__, "[%d] got W3XP_CLAN_MOTDCHG packet : %s", conn_get_socket(c), motd);
412     if (clan_set_motd(clan, motd) != 0)
413     {
414 	eventlog(eventlog_level_error, __FUNCTION__, "Failed to set clan motd.");
415 	return -1;
416     }
417     clan->modified = 1;
418     return 0;
419 }
420 
421 
clan_send_motd_reply(t_connection * c,t_packet const * const packet)422 extern int clan_send_motd_reply(t_connection * c, t_packet const *const packet)
423 {
424     t_packet * rpacket;
425     t_account *account;
426     t_clan *clan;
427 
428     if ((account = conn_get_account(c)) == NULL)
429 	return -1;
430     if ((clan = account_get_clan(account)) == NULL)
431 	return -1;
432     if (clan->clan_motd == NULL)
433     {
434 	eventlog(eventlog_level_error, __FUNCTION__, "Failed to get clan motd.");
435 	return -1;
436     }
437     if ((rpacket = packet_create(packet_class_bnet)))
438     {
439 	packet_set_size(rpacket, sizeof(t_server_w3xp_clan_motdreply));
440 	packet_set_type(rpacket, SERVER_W3XP_CLAN_MOTDREPLY);
441 	bn_int_set(&rpacket->u.server_w3xp_clan_motdreply.count, bn_int_get(packet->u.client_w3xp_clan_motdreq.count));
442 	bn_int_set(&rpacket->u.server_w3xp_clan_motdreply.unknow1, SERVER_W3XP_CLAN_MOTDREPLY_UNKNOW1);
443 	packet_append_string(rpacket, clan->clan_motd);
444 	conn_push_outqueue(c, rpacket);
445 	packet_del_ref(rpacket);
446     }
447 
448     return 0;
449 }
450 
451 /*
452 ** String / Function Management
453 */
454 
clan_get_possible_member(t_connection * c,t_packet const * const packet)455 extern int clan_get_possible_member(t_connection * c, t_packet const *const packet)
456 {
457     t_packet * rpacket;
458     t_channel *channel;
459     t_connection *conn;
460     char const *username;
461     t_account * account;
462 
463     int friend_count = 0;
464     int clantag;
465     clantag = bn_int_get(packet->u.client_w3xp_clan_createreq.clantag);
466     if ((rpacket = packet_create(packet_class_bnet)) == NULL)
467     {
468 	return -1;
469     }
470     packet_set_size(rpacket, sizeof(t_server_w3xp_clan_createreply));
471     packet_set_type(rpacket, SERVER_W3XP_CLAN_CREATEREPLY);
472     bn_int_set(&rpacket->u.server_w3xp_clan_createreply.count, bn_int_get(packet->u.client_w3xp_clan_createreq.count));
473     if (clanlist_find_clan_by_clantag(clantag) != NULL)
474     {
475 	bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.check_result, SERVER_W3XP_CLAN_CREATEREPLY_CHECK_ALLREADY_IN_USE);
476 	bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.friend_count, 0);
477 	conn_push_outqueue(c, rpacket);
478 	packet_del_ref(rpacket);
479 	return 0;
480     }
481     if ((account = conn_get_account(c)) && (account_get_clan(account) != NULL || account_get_creating_clan(account) != NULL))
482     {
483 	bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.check_result, SERVER_W3XP_CLAN_CREATEREPLY_CHECK_EXCEPTION);
484 	bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.friend_count, 0);
485 	conn_push_outqueue(c, rpacket);
486 	packet_del_ref(rpacket);
487 	return 0;
488     }
489     bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.check_result, SERVER_W3XP_CLAN_CREATEREPLY_CHECK_OK);
490     channel = conn_get_channel(c);
491     if (channel_get_permanent(channel))
492     {
493 	/* If not in a private channel, retreive number of mutual friend connected */
494 	t_list *flist = account_get_friends(conn_get_account(c));
495 	t_elem const *curr;
496 	t_friend *fr;
497 
498 	LIST_TRAVERSE_CONST(flist, curr)
499 	{
500 	    if ((fr = elem_get_data(curr)) != NULL)
501 	    {
502 		t_account *fr_acc = friend_get_account(fr);
503 		t_clienttag clienttag;
504 		if (fr->mutual
505 		    && ((conn = connlist_find_connection_by_account(fr_acc)) != NULL)
506 		    && (conn_get_channel(conn) == channel)
507 		    && (!account_get_clan(fr_acc))
508 		    && (!account_get_creating_clan(fr_acc))
509 		    && (clienttag = conn_get_clienttag(conn))
510 		    && ((clienttag == CLIENTTAG_WAR3XP_UINT) || (clienttag ==  CLIENTTAG_WARCRAFT3_UINT))
511 		    && (username = account_get_name(fr_acc)))
512 		{
513 		    friend_count++;
514 		    packet_append_string(rpacket, username);
515 		}
516 	    }
517 	}
518     } else
519     {
520 	/* If in a private channel, retreive all users in the channel */
521 	for (conn = channel_get_first(channel); conn; conn = channel_get_next())
522 	{
523 	    t_account * acc;
524 	    t_clienttag clienttag;
525 	    if ((conn != c)
526 		&& (acc = conn_get_account(conn))
527 		&& (!account_get_clan(acc))
528 		&& (!account_get_creating_clan(acc))
529 		&& (clienttag = conn_get_clienttag(conn))
530 		&& ((clienttag == CLIENTTAG_WAR3XP_UINT) || (clienttag ==  CLIENTTAG_WARCRAFT3_UINT))
531 	        && (username = conn_get_username(conn)))
532 	    {
533 		friend_count++;
534 		packet_append_string(rpacket, username);
535 	    }
536 	}
537     }
538     bn_byte_set(&rpacket->u.server_w3xp_clan_createreply.friend_count, friend_count);
539     conn_push_outqueue(c, rpacket);
540     packet_del_ref(rpacket);
541 
542     return 0;
543 }
544 
clanmember_on_change_status(t_clanmember * member)545 extern int clanmember_on_change_status(t_clanmember * member)
546 {
547     t_packet * rpacket;
548     if (member == NULL)
549     {
550 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
551 	return -1;
552     }
553     if (member->clan == NULL)
554     {
555 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
556 	return -1;
557     }
558     if ((rpacket = packet_create(packet_class_bnet)) != NULL)
559     {
560 	char tmpstr[2];
561 	const char *append_str;
562 	packet_set_size(rpacket, sizeof(t_server_w3xp_clanmemberupdate));
563 	packet_set_type(rpacket, SERVER_W3XP_CLANMEMBERUPDATE);
564 	packet_append_string(rpacket, account_get_name(member->memberacc));
565 	tmpstr[0] = member->status;
566 	append_str = clanmember_get_online_status(member, &tmpstr[1]);
567 	packet_append_data(rpacket, tmpstr, 2);
568 	if (append_str)
569 	    packet_append_string(rpacket, append_str);
570 	else
571 	    packet_append_string(rpacket, "");
572 	clan_send_packet_to_online_members(member->clan, rpacket);
573 	packet_del_ref(rpacket);
574     }
575     return 0;
576 }
577 
clanmember_on_change_status_by_connection(t_connection * conn)578 extern int clanmember_on_change_status_by_connection(t_connection * conn)
579 {
580     t_packet * rpacket;
581     t_account *acc;
582     t_clanmember *member;
583     if (!(conn))
584     {
585 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL conn");
586 	return -1;
587     }
588     if ((acc = conn_get_account(conn)) == NULL)
589 	return -1;
590     if ((member = account_get_clanmember(acc)) == NULL)
591 	return -1;
592     if (member->clan == NULL)
593 	return -1;
594     if ((rpacket = packet_create(packet_class_bnet)) != NULL)
595     {
596 	char tmpstr[2];
597 	const char *append_str;
598 	packet_set_size(rpacket, sizeof(t_server_w3xp_clanmemberupdate));
599 	packet_set_type(rpacket, SERVER_W3XP_CLANMEMBERUPDATE);
600 	packet_append_string(rpacket, account_get_name(acc));
601 	tmpstr[0] = member->status;
602 	append_str = clanmember_get_online_status_by_connection(conn, &tmpstr[1]);
603 	packet_append_data(rpacket, tmpstr, 2);
604 	if (append_str)
605 	    packet_append_string(rpacket, append_str);
606 	else
607 	    packet_append_string(rpacket, "");
608 	clan_send_packet_to_online_members(member->clan, rpacket);
609 	packet_del_ref(rpacket);
610     }
611     return 0;
612 }
613 
clan_unload_members(t_clan * clan)614 extern int clan_unload_members(t_clan * clan)
615 {
616     t_elem *curr;
617     t_clanmember *member;
618 
619     if (clan->members)
620     {
621 	LIST_TRAVERSE(clan->members, curr)
622 	{
623 	    if (!(member = elem_get_data(curr)))
624 	    {
625 		eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
626 		continue;
627 	    }
628 	    list_remove_elem(clan->members, &curr);
629 	    xfree((void *) member);
630 	}
631 
632 	if (list_destroy(clan->members) < 0)
633 	    return -1;
634 
635 	clan->members = NULL;
636     }
637 
638     return 0;
639 }
640 
clan_remove_all_members(t_clan * clan)641 extern int clan_remove_all_members(t_clan * clan)
642 {
643     t_elem *curr;
644     t_clanmember *member;
645 
646     if (clan->members)
647     {
648 	LIST_TRAVERSE(clan->members, curr)
649 	{
650 	    if (!(member = elem_get_data(curr)))
651 	    {
652 		eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
653 		continue;
654 	    }
655 	    if (member->memberacc != NULL)
656 		account_set_clanmember(member->memberacc, NULL);
657 	    list_remove_elem(clan->members, &curr);
658 	    xfree((void *) member);
659 	}
660 
661 	if (list_destroy(clan->members) < 0)
662 	    return -1;
663 
664 	clan->members = NULL;
665     }
666 
667     return 0;
668 }
669 
clanlist_remove_clan(t_clan * clan)670 extern int clanlist_remove_clan(t_clan * clan)
671 {
672     t_elem * elem;
673     if (clan == NULL)
674     {
675 	eventlog(eventlog_level_error, __FUNCTION__, "get NULL clan");
676 	return -1;
677     }
678     if (list_remove_data(clanlist_head, clan, &elem) < 0)
679     {
680 	eventlog(eventlog_level_error, __FUNCTION__, "could not delete clan entry");
681 	return -1;
682     }
683     return 0;
684 }
685 
clan_remove(int clantag)686 extern int clan_remove(int clantag)
687 {
688     return storage->remove_clan(clantag);
689 }
690 
clan_save(t_clan * clan)691 extern int clan_save(t_clan * clan)
692 {
693     if (clan->created <= 0)
694     {
695 	if (now - clan->creation_time > 120)
696 	{
697 	    clanlist_remove_clan(clan);
698 	    clan_destroy(clan);
699 	}
700 	return 0;
701     }
702 
703     storage->write_clan(clan);
704 
705     clan->modified = 0;
706 
707     return 0;
708 }
709 
clanlist(void)710 extern t_list *clanlist(void)
711 {
712     return clanlist_head;
713 }
714 
clanlist_add_clan(t_clan * clan)715 extern int clanlist_add_clan(t_clan * clan)
716 {
717     if (!(clan))
718     {
719 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
720 	return -1;
721     }
722 
723     if (!(clan->clanid))
724 	clan->clanid = ++max_clanid;
725 
726     list_append_data(clanlist_head, clan);
727 
728     return clan->clanid;
729 }
730 
clanlist_load(void)731 int clanlist_load(void)
732 {
733     // make sure to unload previous clanlist before loading again
734     if (clanlist_head)
735 	clanlist_unload();
736 
737     clanlist_head = list_create();
738 
739     storage->load_clans(_cb_load_clans);
740 
741     return 0;
742 }
743 
clanlist_save(void)744 extern int clanlist_save(void)
745 {
746     t_elem *curr;
747     t_clan *clan;
748 
749     if (clanlist_head)
750     {
751 	LIST_TRAVERSE(clanlist_head, curr)
752 	{
753 	    if (!(clan = elem_get_data(curr)))
754 	    {
755 		eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
756 		continue;
757 	    }
758 	    if (clan->modified)
759 		clan_save(clan);
760 	}
761 
762     }
763 
764     return 0;
765 }
766 
clanlist_unload(void)767 extern int clanlist_unload(void)
768 {
769     t_elem *curr;
770     t_clan *clan;
771 
772     if (clanlist_head)
773     {
774 	LIST_TRAVERSE(clanlist_head, curr)
775 	{
776 	    if (!(clan = elem_get_data(curr)))
777 	    {
778 		eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
779 		continue;
780 	    }
781 	    if (clan->clanname)
782 		xfree((void *) clan->clanname);
783 	    if (clan->clan_motd)
784 		xfree((void *) clan->clan_motd);
785 	    clan_unload_members(clan);
786 	    xfree((void *) clan);
787 	    list_remove_elem(clanlist_head, &curr);
788 	}
789 
790 	if (list_destroy(clanlist_head) < 0)
791 	    return -1;
792 
793 	clanlist_head = NULL;
794     }
795 
796     return 0;
797 }
798 
clanlist_find_clan_by_clanid(int cid)799 extern t_clan *clanlist_find_clan_by_clanid(int cid)
800 {
801     t_elem *curr;
802     t_clan *clan;
803 
804     if (clanlist_head)
805     {
806 	LIST_TRAVERSE(clanlist_head, curr)
807 	{
808 	    if (!(clan = elem_get_data(curr)))
809 	    {
810 		eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
811 		continue;
812 	    }
813 	    eventlog(eventlog_level_error, __FUNCTION__, "trace %d", clan->clanid);
814 	    if (clan->created && (clan->clanid == cid))
815 		return clan;
816 	}
817 
818     }
819 
820     return NULL;
821 }
822 
clanlist_find_clan_by_clantag(int clantag)823 extern t_clan *clanlist_find_clan_by_clantag(int clantag)
824 {
825     t_elem *curr;
826     t_clan *clan;
827 
828     if (clantag == 0)
829 	return NULL;
830     if (clanlist_head)
831     {
832 	LIST_TRAVERSE(clanlist_head, curr)
833 	{
834 	    if (!(clan = elem_get_data(curr)))
835 	    {
836 		eventlog(eventlog_level_error, __FUNCTION__, "found NULL entry in list");
837 		continue;
838 	    }
839 	    if (clan->created && (clan->clantag == clantag))
840 		return clan;
841 	}
842 
843     }
844 
845     return NULL;
846 }
847 
clan_find_member(t_clan * clan,t_account * memberacc)848 extern t_clanmember *clan_find_member(t_clan * clan, t_account * memberacc)
849 {
850     t_clanmember *member;
851     t_elem *curr;
852     if (!(clan))
853     {
854 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
855 	return NULL;
856     }
857     if (!(clan->members))
858     {
859 	eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members");
860 	return NULL;
861     }
862     LIST_TRAVERSE(clan->members, curr)
863     {
864 	if (!(member = elem_get_data(curr)))
865 	{
866 	    eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list");
867 	    return NULL;
868 	}
869 	if (member->memberacc == memberacc)
870 	    return member;
871     }
872 
873     return NULL;
874 }
875 
clan_find_member_by_name(t_clan * clan,char const * membername)876 extern t_clanmember *clan_find_member_by_name(t_clan * clan, char const *membername)
877 {
878     t_clanmember *member;
879     t_elem *curr;
880     if (!(clan))
881     {
882 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
883 	return NULL;
884     }
885     if (!(clan->members))
886     {
887 	eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members");
888 	return NULL;
889     }
890     LIST_TRAVERSE(clan->members, curr)
891     {
892 	if (!(member = elem_get_data(curr)))
893 	{
894 	    eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list");
895 	    return NULL;
896 	}
897 	if (strcasecmp(account_get_name(member->memberacc), membername) == 0)
898 	    return member;
899     }
900 
901     return NULL;
902 }
903 
clan_find_member_by_uid(t_clan * clan,unsigned int memberuid)904 extern t_clanmember *clan_find_member_by_uid(t_clan * clan, unsigned int memberuid)
905 {
906     t_clanmember *member;
907     t_elem *curr;
908     if (!(clan))
909     {
910 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
911 	return NULL;
912     }
913     if (!(clan->members))
914     {
915 	eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members");
916 	return NULL;
917     }
918     LIST_TRAVERSE(clan->members, curr)
919     {
920 	if (!(member = elem_get_data(curr)))
921 	{
922 	    eventlog(eventlog_level_error, __FUNCTION__, "got NULL element in list");
923 	    return NULL;
924 	}
925 	if (account_get_uid(member->memberacc) == memberuid)
926 	    return member;
927     }
928 
929     return NULL;
930 }
931 
clanmember_get_account(t_clanmember * member)932 extern t_account *clanmember_get_account(t_clanmember * member)
933 {
934     if (!(member))
935     {
936 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
937 	return NULL;
938     }
939 
940     return (t_account *) member->memberacc;
941 }
942 
clanmember_set_account(t_clanmember * member,t_account * memberacc)943 extern int clanmember_set_account(t_clanmember * member, t_account * memberacc)
944 {
945     if (!(member))
946     {
947 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
948 	return -1;
949     }
950 
951     member->memberacc = memberacc;
952     return 0;
953 }
954 
clanmember_get_conn(t_clanmember * member)955 extern t_connection *clanmember_get_conn(t_clanmember * member)
956 {
957     t_account * account;
958 
959     if (!(member))
960     {
961 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
962 	return NULL;
963     }
964 
965     if (!(account = member->memberacc))
966     {
967 	eventlog(eventlog_level_error,__FUNCTION__,"member as NULL account");
968 	return NULL;
969     }
970 
971     return account_get_conn(account);
972 }
973 
clanmember_get_status(t_clanmember * member)974 extern char clanmember_get_status(t_clanmember * member)
975 {
976     if (!(member))
977     {
978 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
979 	return 0;
980     }
981 
982     if ((member->status == CLAN_NEW) && (now - member->join_time > prefs_get_clan_newer_time() * 3600))
983     {
984 	member->status = CLAN_PEON;
985 	member->clan->modified = 1;
986 #ifdef WITH_SQL
987 	member->modified = 1;
988 #endif
989     }
990 
991     return member->status;
992 }
993 
clanmember_set_status(t_clanmember * member,char status)994 extern int clanmember_set_status(t_clanmember * member, char status)
995 {
996     if (!(member))
997     {
998 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
999 	return -1;
1000     }
1001 
1002     if (member->status != status)
1003     {
1004 	member->status = status;
1005 	member->clan->modified = 1;
1006 #ifdef WITH_SQL
1007 	member->modified = 1;
1008 #endif
1009     }
1010     return 0;
1011 }
1012 
clanmember_get_join_time(t_clanmember * member)1013 extern time_t clanmember_get_join_time(t_clanmember * member)
1014 {
1015     if (!(member))
1016     {
1017 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
1018 	return 0;
1019     }
1020 
1021     return member->join_time;
1022 }
1023 
clanmember_get_clan(t_clanmember * member)1024 extern t_clan *clanmember_get_clan(t_clanmember * member)
1025 {
1026     if (!(member))
1027     {
1028 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanmember");
1029 	return 0;
1030     }
1031 
1032     return member->clan;
1033 }
1034 
clanmember_get_online_status(t_clanmember * member,char * status)1035 extern const char *clanmember_get_online_status(t_clanmember * member, char *status)
1036 {
1037 	return clanmember_get_online_status_by_connection(clanmember_get_conn(member), status);
1038 }
1039 
clanmember_get_online_status_by_connection(t_connection * conn,char * status)1040 extern const char *clanmember_get_online_status_by_connection(t_connection * conn, char *status)
1041 {
1042     if (conn && (conn_get_state(conn)!=conn_state_empty))
1043     {
1044 	t_game *game;
1045 	t_channel *channel;
1046 	if ((game = conn_get_game(conn)) != NULL)
1047 	{
1048 	    if (game_get_flag(game) == game_flag_private)
1049 		(*status) = SERVER_W3XP_CLAN_MEMBER_PRIVATE_GAME;
1050 	    else
1051 		(*status) = SERVER_W3XP_CLAN_MEMBER_GAME;
1052 	    return game_get_name(game);
1053 	}
1054 	if ((channel = conn_get_channel(conn)) != NULL)
1055 	{
1056 	    (*status) = SERVER_W3XP_CLAN_MEMBER_CHANNEL;
1057 	    return channel_get_name(channel);
1058 	}
1059 
1060 	(*status) = SERVER_W3XP_CLAN_MEMBER_ONLINE;
1061     } else
1062 	(*status) = SERVER_W3XP_CLAN_MEMBER_OFFLINE;
1063     return NULL;
1064 }
1065 
clanmember_set_online(t_connection * c)1066 extern int clanmember_set_online(t_connection * c)
1067 {
1068     t_clanmember *member;
1069     t_account *acc;
1070 
1071     if (!c)
1072     {
1073 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
1074 	return -1;
1075     }
1076 
1077     if ((acc = conn_get_account(c)) && (member = account_get_clanmember(acc)))
1078     {
1079 	clanmember_on_change_status(member);
1080     }
1081 
1082     return 0;
1083 }
1084 
clanmember_set_offline(t_connection * c)1085 extern int clanmember_set_offline(t_connection * c)
1086 {
1087     t_clanmember *member;
1088     t_account *acc;
1089 
1090     if (!c)
1091     {
1092 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
1093 	return -1;
1094     }
1095 
1096     if ((acc = conn_get_account(c)) && (member = account_get_clanmember_forced(acc)))
1097     {
1098 	clanmember_on_change_status(member);
1099     }
1100 
1101     return 0;
1102 }
1103 
clan_get_created(t_clan * clan)1104 extern int clan_get_created(t_clan * clan)
1105 {
1106     if (!(clan))
1107     {
1108 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1109 	return -1;
1110     }
1111 
1112     return clan->created;
1113 }
1114 
clan_set_created(t_clan * clan,int created)1115 extern int clan_set_created(t_clan * clan, int created)
1116 {
1117     if (!(clan))
1118     {
1119 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1120 	return -1;
1121     }
1122 
1123     clan->created = created;
1124 
1125     return 0;
1126 }
1127 
clan_get_modified(t_clan * clan)1128 extern char clan_get_modified(t_clan * clan)
1129 {
1130     if (!(clan))
1131     {
1132 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1133 	return -1;
1134     }
1135 
1136     return clan->modified;
1137 }
1138 
clan_set_modified(t_clan * clan,char modified)1139 extern int clan_set_modified(t_clan * clan, char modified)
1140 {
1141     if (!(clan))
1142     {
1143 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1144 	return -1;
1145     }
1146 
1147     clan->modified = modified;
1148 
1149     return 0;
1150 }
1151 
clan_get_channel_type(t_clan * clan)1152 extern char clan_get_channel_type(t_clan * clan)
1153 {
1154     if (!(clan))
1155     {
1156 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1157 	return -1;
1158     }
1159 
1160     return clan->channel_type;
1161 }
1162 
clan_set_channel_type(t_clan * clan,char channel_type)1163 extern int clan_set_channel_type(t_clan * clan, char channel_type)
1164 {
1165     if (!(clan))
1166     {
1167 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1168 	return -1;
1169     }
1170 
1171     clan->channel_type = channel_type;
1172 
1173     return 0;
1174 }
1175 
clan_get_members(t_clan * clan)1176 extern t_list *clan_get_members(t_clan * clan)
1177 {
1178     if (!(clan))
1179     {
1180 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1181 	return NULL;
1182     }
1183 
1184     return clan->members;
1185 }
1186 
clan_get_name(t_clan * clan)1187 extern char const *clan_get_name(t_clan * clan)
1188 {
1189     if (!(clan))
1190     {
1191 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1192 	return NULL;
1193     }
1194 
1195     return clan->clanname;
1196 }
1197 
clan_get_clantag(t_clan * clan)1198 extern int clan_get_clantag(t_clan * clan)
1199 {
1200     if (!(clan))
1201     {
1202 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1203 	return 0;
1204     }
1205 
1206     return clan->clantag;
1207 }
1208 
clan_get_motd(t_clan * clan)1209 extern char const *clan_get_motd(t_clan * clan)
1210 {
1211     if (!(clan))
1212     {
1213 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1214 	return NULL;
1215     }
1216 
1217     return clan->clan_motd;
1218 }
1219 
clan_set_motd(t_clan * clan,const char * motd)1220 extern int clan_set_motd(t_clan * clan, const char *motd)
1221 {
1222     if (!(clan))
1223     {
1224 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1225 	return -1;
1226     }
1227     if (!(motd))
1228     {
1229 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL motd");
1230 	return -1;
1231     } else
1232     {
1233 	if (clan->clan_motd)
1234 	    xfree((void *) clan->clan_motd);
1235 	clan->clan_motd = xstrdup(motd);
1236     }
1237     return 0;
1238 }
1239 
clan_get_clanid(t_clan * clan)1240 extern unsigned int clan_get_clanid(t_clan * clan)
1241 {
1242     if (!(clan))
1243     {
1244 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1245 	return 0;
1246     }
1247 
1248     return clan->clanid;
1249 }
1250 
clan_set_creation_time(t_clan * clan,time_t c_time)1251 extern int clan_set_creation_time(t_clan * clan, time_t c_time)
1252 {
1253     if (!(clan))
1254     {
1255 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1256 	return -1;
1257     }
1258 
1259     clan->creation_time = c_time;
1260 
1261     return 0;
1262 }
1263 
clan_get_creation_time(t_clan * clan)1264 extern time_t clan_get_creation_time(t_clan * clan)
1265 {
1266     if (!(clan))
1267     {
1268 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1269 	return 0;
1270     }
1271 
1272     return clan->creation_time;
1273 }
1274 
clan_add_member(t_clan * clan,t_account * memberacc,char status)1275 extern t_clanmember *clan_add_member(t_clan * clan, t_account * memberacc, char status)
1276 {
1277     t_clanmember *member;
1278 
1279     if (!(clan))
1280     {
1281 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clan");
1282 	return NULL;
1283     }
1284 
1285     if (!(clan->members))
1286     {
1287 	eventlog(eventlog_level_error, __FUNCTION__, "found NULL clan->members");
1288 	return NULL;
1289     }
1290 
1291     member = xmalloc(sizeof(t_clanmember));
1292     member->memberacc = memberacc;
1293     member->status = status;
1294     member->join_time = now;
1295     member->clan = clan;
1296 #ifdef WITH_SQL
1297     member->modified = 1;
1298 #endif
1299 
1300     list_append_data(clan->members, member);
1301 
1302     account_set_clanmember(memberacc, member);
1303 
1304     clan->modified = 1;
1305 
1306     return member;
1307 }
1308 
clan_remove_member(t_clan * clan,t_clanmember * member)1309 extern int clan_remove_member(t_clan * clan, t_clanmember * member)
1310 {
1311     t_elem * elem;
1312 
1313     if (!member)
1314 	return -1;
1315     if (list_remove_data(clan->members, member, &elem) < 0)
1316     {
1317 	eventlog(eventlog_level_error, __FUNCTION__, "could not remove member");
1318 	return -1;
1319     }
1320     if (member->memberacc != NULL)
1321     {
1322 	account_set_clanmember(member->memberacc, NULL);
1323 	storage->remove_clanmember(account_get_uid(member->memberacc));
1324     }
1325     xfree((void *) member);
1326     clan->modified = 1;
1327     return 0;
1328 }
1329 
clan_create(t_account * chieftain_acc,int clantag,const char * clanname,const char * motd)1330 extern t_clan *clan_create(t_account * chieftain_acc, int clantag, const char *clanname, const char *motd)
1331 {
1332     t_clan *clan;
1333     t_clanmember *member;
1334 
1335     clan = xmalloc(sizeof(t_clan));
1336     member = xmalloc(sizeof(t_clanmember));
1337 
1338     if (!(clanname))
1339     {
1340 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL clanname");
1341 	xfree((void *) clan);
1342 	xfree((void *) member);
1343 	return NULL;
1344     }
1345 
1346     clan->clanname = xstrdup(clanname);
1347 
1348     if (!(motd))
1349 	clan->clan_motd = xstrdup("This is a newly created clan");
1350     else
1351 	clan->clan_motd = xstrdup(motd);
1352 
1353     clan->creation_time = now;
1354     clan->clantag = clantag;
1355     clan->clanid = ++max_clanid;
1356     clan->created = 0;
1357     clan->modified = 1;
1358     clan->channel_type = prefs_get_clan_channel_default_private();
1359 
1360     clan->members = list_create();
1361 
1362     member->memberacc = chieftain_acc;
1363     member->status = CLAN_CHIEFTAIN;
1364     member->join_time = clan->creation_time;
1365     member->clan = clan;
1366 #ifdef WITH_SQL
1367     member->modified = 1;
1368 #endif
1369 
1370     list_append_data(clan->members, member);
1371 
1372     account_set_clanmember(chieftain_acc, member);
1373 
1374     return clan;
1375 }
1376 
clan_destroy(t_clan * clan)1377 extern int clan_destroy(t_clan * clan)
1378 {
1379     if (!clan)
1380 	return 0;
1381     if (clan->clanname)
1382 	xfree((void *) clan->clanname);
1383     if (clan->clan_motd)
1384 	xfree((void *) clan->clan_motd);
1385     clan_remove_all_members(clan);
1386     xfree((void *) clan);
1387     return 0;
1388 }
1389 
clan_get_member_count(t_clan * clan)1390 extern int clan_get_member_count(t_clan * clan)
1391 {
1392     t_elem *curr;
1393     int count = 0;
1394     LIST_TRAVERSE(clan->members, curr)
1395     {
1396 	if ((elem_get_data(curr)) != NULL)
1397 	    count++;
1398     }
1399     return count;
1400 }
1401 
str_to_clantag(const char * str)1402 extern int str_to_clantag(const char *str)
1403 {
1404     int clantag = 0;
1405 
1406     if (!str)
1407 	return 0;
1408 
1409     if (str[0])
1410     {
1411 	clantag = str[0] << 24;
1412 	if (str[1])
1413 	{
1414 	    clantag += str[1] << 16;
1415 	    if (str[2])
1416 	    {
1417 		clantag += str[2] << 8;
1418 		if (str[3])
1419 		    clantag += str[3];
1420 	    }
1421 	}
1422     }
1423     return clantag;
1424 
1425 }
1426