1 /*
2  * Copyright (C) 2002 TheUndying
3  * Copyright (C) 2002 zap-zero
4  * Copyright (C) 2002,2003,2005 Dizzy
5  * Copyright (C) 2002 Zzzoom
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21 
22 #include "common/setup_before.h"
23 #ifdef WITH_SQL
24 #include <stdio.h>
25 
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 #else
29 # ifdef HAVE_MALLOC_H
30 #  include <malloc.h>
31 # endif
32 #endif
33 
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #else
37 # ifdef HAVE_STRINGS_H
38 #  include <strings.h>
39 # endif
40 #endif
41 
42 #include "compat/strdup.h"
43 #include "compat/strcasecmp.h"
44 #include "compat/strncasecmp.h"
45 #include "compat/strtoul.h"
46 #include "compat/snprintf.h"
47 
48 #ifdef TIME_WITH_SYS_TIME
49 # include <sys/time.h>
50 # include <time.h>
51 #else
52 # ifdef HAVE_SYS_TIME_H
53 #  include <sys/time.h>
54 # else
55 #  include <time.h>
56 # endif
57 #endif
58 
59 #include "common/eventlog.h"
60 #include "prefs.h"
61 #include "common/util.h"
62 
63 #define CLAN_INTERNAL_ACCESS
64 #define TEAM_INTERNAL_ACCESS
65 #include "team.h"
66 #include "account.h"
67 #include "connection.h"
68 #include "clan.h"
69 #undef TEAM_INTERNAL_ACCESS
70 #undef CLAN_INTERNAL_ACCESS
71 #include "common/tag.h"
72 #include "common/xalloc.h"
73 #include "common/flags.h"
74 #include "sql_dbcreator.h"
75 #define SQL_INTERNAL
76 # include "sql_common.h"
77 #undef SQL_INTERNAL
78 #ifdef WITH_SQL_MYSQL
79 #include "sql_mysql.h"
80 #endif
81 #ifdef WITH_SQL_PGSQL
82 #include "sql_pgsql.h"
83 #endif
84 #ifdef WITH_SQL_SQLITE3
85 #include "sql_sqlite3.h"
86 #endif
87 #ifdef WITH_SQL_ODBC
88 #include "sql_odbc.h"
89 #endif
90 #include "common/elist.h"
91 #include "common/setup_after.h"
92 
93 unsigned int sql_defacct;
94 t_sql_engine *sql = NULL;
95 
96 #ifndef SQL_ON_DEMAND
97 char *sql_tables[] = { "BNET", "Record", "profile", "friend", "Team", NULL };
98 #endif	/* SQL_ON_DEMAND */
99 
100 const char* tab_prefix = SQL_DEFAULT_PREFIX;
101 
102 static char query[1024];
103 
sql_init(const char * dbpath)104 extern int sql_init(const char *dbpath)
105 {
106     char *tok, *path, *tmp, *p;
107     const char *dbhost = NULL;
108     const char *dbname = NULL;
109     const char *dbuser = NULL;
110     const char *dbpass = NULL;
111     const char *driver = NULL;
112     const char *dbport = NULL;
113     const char *dbsocket = NULL;
114     const char *def = NULL;
115     const char *pref = NULL;
116 
117     path = xstrdup(dbpath);
118     tmp = path;
119     while ((tok = strtok(tmp, ";")) != NULL)
120     {
121 	tmp = NULL;
122 	if ((p = strchr(tok, '=')) == NULL)
123 	{
124 	    eventlog(eventlog_level_error, __FUNCTION__, "invalid storage_path, no '=' present in token");
125 	    xfree((void *) path);
126 	    return -1;
127 	}
128 	*p = '\0';
129 	if (strcasecmp(tok, "host") == 0)
130 	    dbhost = p + 1;
131 	else if (strcasecmp(tok, "mode") == 0)
132 	    driver = p + 1;
133 	else if (strcasecmp(tok, "name") == 0)
134 	    dbname = p + 1;
135 	else if (strcasecmp(tok, "port") == 0)
136 	    dbport = p + 1;
137 	else if (strcasecmp(tok, "socket") == 0)
138 	    dbsocket = p + 1;
139 	else if (strcasecmp(tok, "user") == 0)
140 	    dbuser = p + 1;
141 	else if (strcasecmp(tok, "pass") == 0)
142 	    dbpass = p + 1;
143 	else if (strcasecmp(tok, "default") == 0)
144 	    def = p + 1;
145 	else if (strcasecmp(tok, "prefix") == 0)
146 	    pref = p + 1;
147 	else
148 	    eventlog(eventlog_level_warn, __FUNCTION__, "unknown token in storage_path : '%s'", tok);
149     }
150 
151     if (driver == NULL)
152     {
153 	eventlog(eventlog_level_error, __FUNCTION__, "no mode specified");
154 	xfree((void *) path);
155 	return -1;
156     }
157 
158     if (def == NULL)
159 	sql_defacct = STORAGE_SQL_DEFAULT_UID;
160     else
161 	sql_defacct = atoi(def);
162 
163     if (pref == NULL)
164     	tab_prefix = SQL_DEFAULT_PREFIX;
165     else
166     	tab_prefix = xstrdup(pref);
167 
168     do
169     {
170 #ifdef WITH_SQL_MYSQL
171 	if (strcasecmp(driver, "mysql") == 0)
172 	{
173 	    sql = &sql_mysql;
174 	    if (sql->init(dbhost, dbport, dbsocket, dbname, dbuser, dbpass))
175 	    {
176 		eventlog(eventlog_level_error, __FUNCTION__, "got error init db");
177 		sql = NULL;
178 		xfree((void *) path);
179 		return -1;
180 	    }
181 	    break;
182 	}
183 #endif				/* WITH_SQL_MYSQL */
184 #ifdef WITH_SQL_PGSQL
185 	if (strcasecmp(driver, "pgsql") == 0)
186 	{
187 	    sql = &sql_pgsql;
188 	    if (sql->init(dbhost, dbport, dbsocket, dbname, dbuser, dbpass))
189 	    {
190 		eventlog(eventlog_level_error, __FUNCTION__, "got error init db");
191 		sql = NULL;
192 		xfree((void *) path);
193 		return -1;
194 	    }
195 	    break;
196 	}
197 #endif				/* WITH_SQL_PGSQL */
198 #ifdef WITH_SQL_SQLITE3
199 	if (strcasecmp(driver, "sqlite3") == 0)
200 	{
201 	    sql = &sql_sqlite3;
202 	    if (sql->init(NULL, 0, NULL, dbname, NULL, NULL))
203 	    {
204 		eventlog(eventlog_level_error, __FUNCTION__, "got error init db");
205 		sql = NULL;
206 		xfree((void *) path);
207 		return -1;
208 	    }
209 	    break;
210 	}
211 #endif				/* WITH_SQL_SQLITE3 */
212 #ifdef WITH_SQL_ODBC
213 	if (strcasecmp(driver, "odbc") == 0)
214 	{
215 	    sql = &sql_odbc;
216 	    if (sql->init(dbhost, dbport, dbsocket, dbname, dbuser, dbpass))
217 	    {
218 		eventlog(eventlog_level_error, __FUNCTION__, "got error init db");
219 		sql = NULL;
220 		free((void *) path);
221 		return -1;
222 	    }
223 	    break;
224 	}
225 #endif				/* WITH_SQL_ODBC */
226 	eventlog(eventlog_level_error, __FUNCTION__, "no driver found for '%s'", driver);
227 	xfree((void *) path);
228 	return -1;
229     }
230     while (0);
231 
232     xfree((void *) path);
233 
234     sql_dbcreator(sql);
235 
236     return 0;
237 }
238 
sql_close(void)239 extern int sql_close(void)
240 {
241     if (sql == NULL)
242     {
243 	eventlog(eventlog_level_error, __FUNCTION__, "sql not initilized");
244 	return -1;
245     }
246 
247     sql->close();
248     sql = NULL;
249     if (tab_prefix != SQL_DEFAULT_PREFIX) {
250     	xfree((void*)tab_prefix);
251     	tab_prefix = NULL;
252     }
253 
254     return 0;
255 }
256 
sql_read_maxuserid(void)257 extern unsigned sql_read_maxuserid(void)
258 {
259     t_sql_res *result;
260     t_sql_row *row;
261     long maxuid;
262 
263     if (sql == NULL)
264     {
265 	eventlog(eventlog_level_error, __FUNCTION__, "sql not initilized");
266 	return 0;
267     }
268 
269     snprintf(query, sizeof(query), "SELECT max("SQL_UID_FIELD") FROM %sBNET", tab_prefix);
270     if ((result = sql->query_res(query)) == NULL) {
271 	eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"SELECT max("SQL_UID_FIELD") FROM %sBNET\"", tab_prefix);
272 	return 0;
273     }
274 
275     row = sql->fetch_row(result);
276     if (row == NULL || row[0] == NULL)
277     {
278 	sql->free_result(result);
279 	eventlog(eventlog_level_error, __FUNCTION__, "got NULL max");
280 	return 0;
281     }
282 
283     maxuid = atol(row[0]);
284     sql->free_result(result);
285     if (maxuid < 0)
286     {
287 	eventlog(eventlog_level_error, __FUNCTION__, "got invalid maxuserid");
288 	return 0;
289     }
290 
291     return maxuid;
292 }
293 
sql_read_accounts(int flag,t_read_accounts_func cb,void * data)294 extern int sql_read_accounts(int flag,t_read_accounts_func cb, void *data)
295 {
296     t_sql_res *result = NULL;
297     t_sql_row *row;
298     t_storage_info *info;
299 
300     if (!sql)
301     {
302 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
303 	return -1;
304     }
305 
306     if (cb == NULL)
307     {
308 	eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
309 	return -1;
310     }
311 
312     /* don't actually load anything here if ST_FORCE is not set as SQL is indexed */
313     if (!FLAG_ISSET(flag,ST_FORCE)) return 1;
314 
315     snprintf(query, sizeof(query), "SELECT DISTINCT("SQL_UID_FIELD") FROM %sBNET", tab_prefix);
316     if ((result = sql->query_res(query)) != NULL)
317     {
318 	if (sql->num_rows(result) <= 1)
319 	{
320 	    sql->free_result(result);
321 	    return 0;		/* empty user list */
322 	}
323 
324 	while ((row = sql->fetch_row(result)) != NULL)
325 	{
326 	    if (row[0] == NULL)
327 	    {
328 		eventlog(eventlog_level_error, __FUNCTION__, "got NULL uid from db");
329 		continue;
330 	    }
331 
332 	    if ((unsigned int) atoi(row[0]) == sql_defacct)
333 		continue;	/* skip default account */
334 
335 	    info = xmalloc(sizeof(t_sql_info));
336 	    *((unsigned int *) info) = atoi(row[0]);
337 	    cb(info, data);
338 	}
339 	sql->free_result(result);
340     } else
341     {
342 	eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query);
343 	return -1;
344     }
345 
346     return 0;
347 }
348 
sql_cmp_info(t_storage_info * info1,t_storage_info * info2)349 extern int sql_cmp_info(t_storage_info * info1, t_storage_info * info2)
350 {
351     return *((unsigned int *) info1) != *((unsigned int *) info2);
352 }
353 
sql_free_info(t_storage_info * info)354 extern int sql_free_info(t_storage_info * info)
355 {
356     if (info)
357 	xfree((void *) info);
358 
359     return 0;
360 }
361 
sql_get_defacct(void)362 extern t_storage_info *sql_get_defacct(void)
363 {
364     t_storage_info *info;
365 
366     info = xmalloc(sizeof(t_sql_info));
367     *((unsigned int *) info) = sql_defacct;
368 
369     return info;
370 }
371 
sql_load_clans(t_load_clans_func cb)372 extern int sql_load_clans(t_load_clans_func cb)
373 {
374     t_sql_res *result;
375     t_sql_res *result2;
376     t_sql_row *row;
377     t_sql_row *row2;
378     t_clan *clan;
379     int member_uid;
380     t_clanmember *member;
381 
382     if (!sql)
383     {
384 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
385 	return -1;
386     }
387 
388     if (cb == NULL)
389     {
390 	eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
391 	return -1;
392     }
393 
394     snprintf(query, sizeof(query), "SELECT cid, short, name, motd, creation_time FROM %sclan WHERE cid > 0", tab_prefix);
395     if ((result = sql->query_res(query)) != NULL)
396     {
397 	if (sql->num_rows(result) < 1)
398 	{
399 	    sql->free_result(result);
400 	    return 0;		/* empty clan list */
401 	}
402 
403 	while ((row = sql->fetch_row(result)) != NULL)
404 	{
405 	    if (row[0] == NULL)
406 	    {
407 		eventlog(eventlog_level_error, __FUNCTION__, "got NULL cid from db");
408 		continue;
409 	    }
410 
411 	    clan = xmalloc(sizeof(t_clan));
412 
413 	    if (!(clan->clanid = atoi(row[0])))
414 	    {
415 		eventlog(eventlog_level_error, __FUNCTION__, "got bad cid");
416 		sql->free_result(result);
417 		return -1;
418 	    }
419 
420 	    clan->clantag = atoi(row[1]);
421 
422 	    clan->clanname = xstrdup(row[2]);
423 	    clan->clan_motd = xstrdup(row[3]);
424 	    clan->creation_time = atoi(row[4]);
425 	    clan->created = 1;
426 	    clan->modified = 0;
427 	    clan->channel_type = prefs_get_clan_channel_default_private();
428 	    clan->members = list_create();
429 
430 	    snprintf(query, sizeof(query), "SELECT "SQL_UID_FIELD", status, join_time FROM %sclanmember WHERE cid='%u'", tab_prefix, clan->clanid);
431 
432 	    if ((result2 = sql->query_res(query)) != NULL)
433 	    {
434 		if (sql->num_rows(result2) >= 1)
435 		    while ((row2 = sql->fetch_row(result2)) != NULL)
436 		    {
437 			member = xmalloc(sizeof(t_clanmember));
438 			if (row2[0] == NULL)
439 			{
440 			    eventlog(eventlog_level_error, __FUNCTION__, "got NULL uid from db");
441 			    continue;
442 			}
443 			if (!(member_uid = atoi(row2[0])))
444 			    continue;
445 			if (!(member->memberacc = accountlist_find_account_by_uid(member_uid)))
446 			{
447 			    eventlog(eventlog_level_error, __FUNCTION__, "cannot find uid %u", member_uid);
448 			    xfree((void *) member);
449 			    continue;
450 			}
451 			member->status = atoi(row2[1]);
452 			member->join_time = atoi(row2[2]);
453 			member->clan	  = clan;
454 
455 			if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600))
456 			{
457 			    member->status = CLAN_PEON;
458 			    clan->modified = 1;
459 			    member->modified = 1;
460 			}
461 
462 			list_append_data(clan->members, member);
463 
464 			account_set_clanmember(member->memberacc, member);
465 			eventlog(eventlog_level_trace, __FUNCTION__, "added member: uid: %i status: %c join_time: %u", member_uid, member->status + '0', (unsigned) member->join_time);
466 		    }
467 		sql->free_result(result2);
468 		cb(clan);
469 	    } else
470 		eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query);
471 	}
472 
473 	sql->free_result(result);
474     } else
475     {
476 	eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query);
477 	return -1;
478     }
479     return 0;
480 }
481 
sql_write_clan(void * data)482 extern int sql_write_clan(void *data)
483 {
484     char esc_motd[CLAN_MOTD_MAX * 2 + 1];
485     t_sql_res *result;
486     t_sql_row *row;
487     t_elem *curr;
488     t_clanmember *member;
489     t_clan *clan = (t_clan *) data;
490     int num;
491 
492     if (!sql)
493     {
494 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
495 	return -1;
496     }
497 
498     snprintf(query, sizeof(query), "SELECT count(*) FROM %sclan WHERE cid='%u'", tab_prefix, clan->clanid);
499     if ((result = sql->query_res(query)) != NULL)
500     {
501 	row = sql->fetch_row(result);
502 	if (row == NULL || row[0] == NULL)
503 	{
504 	    sql->free_result(result);
505 	    eventlog(eventlog_level_error, __FUNCTION__, "got NULL count");
506 	    return -1;
507 	}
508 	num = atol(row[0]);
509 	sql->free_result(result);
510 	sql->escape_string(esc_motd, clan->clan_motd, strlen(clan->clan_motd));
511 	if (num < 1)
512 	    snprintf(query, sizeof(query), "INSERT INTO %sclan (cid, short, name, motd, creation_time) VALUES('%u', '%d', '%s', '%s', '%u')", tab_prefix, clan->clanid, clan->clantag, clan->clanname, esc_motd, (unsigned) clan->creation_time);
513 	else
514 	    snprintf(query, sizeof(query), "UPDATE %sclan SET short='%d', name='%s', motd='%s', creation_time='%u' WHERE cid='%u'", tab_prefix, clan->clantag, clan->clanname, esc_motd, (unsigned) clan->creation_time, clan->clanid);
515 	if (sql->query(query) < 0)
516 	{
517 	    eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
518 	    return -1;
519 	}
520 	LIST_TRAVERSE(clan->members, curr)
521 	{
522 	    unsigned int uid;
523 
524 	    if (!(member = elem_get_data(curr)))
525 	    {
526 		eventlog(eventlog_level_error, __FUNCTION__, "got NULL elem in list");
527 		continue;
528 	    }
529 	    if ((member->status == CLAN_NEW) && (time(NULL) - member->join_time > prefs_get_clan_newer_time() * 3600))
530 	    {
531 		member->status = CLAN_PEON;
532 		member->modified = 1;
533 	    }
534 	    if (member->modified)
535 	    {
536 		uid = account_get_uid(member->memberacc);
537 		snprintf(query, sizeof(query), "SELECT count(*) FROM %sclanmember WHERE "SQL_UID_FIELD"='%u'",  tab_prefix, uid);
538 		if ((result = sql->query_res(query)) != NULL)
539 		{
540 		    row = sql->fetch_row(result);
541 		    if (row == NULL || row[0] == NULL)
542 		    {
543 			sql->free_result(result);
544 			eventlog(eventlog_level_error, __FUNCTION__, "got NULL count");
545 			return -1;
546 		    }
547 		    num = atol(row[0]);
548 		    sql->free_result(result);
549 		    if (num < 1)
550 			snprintf(query, sizeof(query), "INSERT INTO %sclanmember (cid, "SQL_UID_FIELD", status, join_time) VALUES('%u', '%u', '%d', '%u')", tab_prefix, clan->clanid, uid, member->status, (unsigned) member->join_time);
551 		    else
552 			snprintf(query, sizeof(query), "UPDATE %sclanmember SET cid='%u', status='%d', join_time='%u' WHERE "SQL_UID_FIELD"='%u'", tab_prefix, clan->clanid, member->status, (unsigned) member->join_time, uid);
553 		    if (sql->query(query) < 0)
554 		    {
555 			eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
556 			return -1;
557 		    }
558 		} else
559 		{
560 		    eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
561 		    return -1;
562 		}
563 		member->modified = 0;
564 	    }
565 	}
566     } else
567     {
568 	eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
569 	return -1;
570     }
571 
572     return 0;
573 }
574 
sql_remove_clan(int clantag)575 extern int sql_remove_clan(int clantag)
576 {
577     t_sql_res *result;
578     t_sql_row *row;
579 
580     if (!sql)
581     {
582 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
583 	return -1;
584     }
585 
586     snprintf(query, sizeof(query), "SELECT cid FROM %sclan WHERE short = '%d'", tab_prefix, clantag);
587     if (!(result = sql->query_res(query)))
588     {
589 	eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query);
590 	return -1;
591     }
592 
593     if (sql->num_rows(result) != 1)
594     {
595 	sql->free_result(result);
596 	return -1;		/*clan not found or found more than 1 */
597     }
598 
599     if ((row = sql->fetch_row(result)))
600     {
601 	unsigned int cid = atoi(row[0]);
602 	snprintf(query, sizeof(query), "DELETE FROM %sclanmember WHERE cid='%u'", tab_prefix, cid);
603 	if (sql->query(query) != 0)
604 	    return -1;
605 	snprintf(query, sizeof(query), "DELETE FROM %sclan WHERE cid='%u'", tab_prefix, cid);
606 	if (sql->query(query) != 0)
607 	    return -1;
608     }
609 
610     sql->free_result(result);
611 
612     return 0;
613 }
614 
sql_remove_clanmember(int uid)615 extern int sql_remove_clanmember(int uid)
616 {
617     if (!sql)
618     {
619 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
620 	return -1;
621     }
622 
623     snprintf(query, sizeof(query), "DELETE FROM %sclanmember WHERE "SQL_UID_FIELD"='%u'", tab_prefix, uid);
624     if (sql->query(query) != 0)
625     {
626 	eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
627 	return -1;
628     }
629 
630     return 0;
631 }
632 
sql_load_teams(t_load_teams_func cb)633 extern int sql_load_teams(t_load_teams_func cb)
634 {
635     t_sql_res *result;
636     t_sql_row *row;
637     t_team *team;
638     int i;
639 
640     if (!sql)
641     {
642 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
643 	return -1;
644     }
645 
646     if (cb == NULL)
647     {
648 	eventlog(eventlog_level_error, __FUNCTION__, "get NULL callback");
649 	return -1;
650     }
651 
652     snprintf(query, sizeof(query), "SELECT teamid, size, clienttag, lastgame, member1, member2, member3, member4, wins,losses, xp, level, rank FROM %sarrangedteam WHERE teamid > 0", tab_prefix);
653     if ((result = sql->query_res(query)) != NULL)
654     {
655 	if (sql->num_rows(result) < 1)
656 	{
657 	    sql->free_result(result);
658 	    return 0;		/* empty team list */
659 	}
660 
661 	while ((row = sql->fetch_row(result)) != NULL)
662 	{
663 	    if (row[0] == NULL)
664 	    {
665 		eventlog(eventlog_level_error, __FUNCTION__, "got NULL teamid from db");
666 		continue;
667 	    }
668 
669 	    team = xmalloc(sizeof(t_team));
670 
671 	    if (!(team->teamid = atoi(row[0])))
672 	    {
673 		eventlog(eventlog_level_error, __FUNCTION__, "got bad teamid");
674 		sql->free_result(result);
675 		return -1;
676 	    }
677 
678 	    team->size = atoi(row[1]);
679 	    team->clienttag=tag_str_to_uint(row[2]);
680 	    team->lastgame = strtoul(row[3],NULL,10);
681 	    team->teammembers[0] = strtoul(row[4],NULL,10);
682 	    team->teammembers[1] = strtoul(row[5],NULL,10);
683 	    team->teammembers[2] = strtoul(row[6],NULL,10);
684 	    team->teammembers[3] = strtoul(row[7],NULL,10);
685 
686 	    for (i=0; i<MAX_TEAMSIZE;i++)
687 	    {
688 	       if (i<team->size)
689 	       {
690 		    if ((team->teammembers[i]==0))
691 		    {
692 	    		eventlog(eventlog_level_error,__FUNCTION__,"invalid team data: too few members");
693 	    		free((void *)team);
694 	    		goto load_team_failure;
695 		    }
696 	       }
697 	       else
698 	       {
699 	   	    if ((team->teammembers[i]!=0))
700 		    {
701 	    		eventlog(eventlog_level_error,__FUNCTION__,"invalid team data: too many members");
702 	    		free((void *)team);
703 	    		goto load_team_failure;
704 		    }
705 
706 	       }
707 	       team->members[i] = NULL;
708 	    }
709 
710 	    team->wins = atoi(row[8]);
711 	    team->losses = atoi(row[9]);
712 	    team->xp = atoi(row[10]);
713 	    team->level = atoi(row[11]);
714 	    team->rank = atoi(row[12]);
715 
716 	    eventlog(eventlog_level_trace,__FUNCTION__,"succesfully loaded team %u",team->teamid);
717 	    cb(team);
718 	    load_team_failure:
719 	    ;
720 	}
721 
722 	sql->free_result(result);
723     } else
724     {
725 	eventlog(eventlog_level_error, __FUNCTION__, "error query db (query:\"%s\")", query);
726 	return -1;
727     }
728     return 0;
729 }
730 
sql_write_team(void * data)731 extern int sql_write_team(void *data)
732 {
733     t_sql_res *result;
734     t_sql_row *row;
735     t_team *team = (t_team *) data;
736     int num;
737 
738     if (!sql)
739     {
740 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
741 	return -1;
742     }
743 
744     snprintf(query, sizeof(query), "SELECT count(*) FROM %sarrangedteam WHERE teamid='%u'", tab_prefix, team->teamid);
745     if ((result = sql->query_res(query)) != NULL)
746     {
747 	row = sql->fetch_row(result);
748 	if (row == NULL || row[0] == NULL)
749 	{
750 	    sql->free_result(result);
751 	    eventlog(eventlog_level_error, __FUNCTION__, "got NULL count");
752 	    return -1;
753 	}
754 	num = atol(row[0]);
755 	sql->free_result(result);
756 	if (num < 1)
757 	    snprintf(query, sizeof(query), "INSERT INTO %sarrangedteam (teamid, size, clienttag, lastgame, member1, member2, member3, member4, wins,losses, xp, level, rank) VALUES('%u', '%c', '%s', '%u', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d')", tab_prefix,  team->teamid, team->size + '0', clienttag_uint_to_str(team->clienttag),(unsigned int)team->lastgame, team->teammembers[0], team->teammembers[1], team->teammembers[2], team->teammembers[3], team->wins, team->losses, team->xp, team->level, team->rank);
758 	else
759 	    snprintf(query, sizeof(query), "UPDATE %sarrangedteam SET size='%c', clienttag='%s', lastgame='%u', member1='%u', member2='%u', member3='%u', member4='%u', wins='%d', losses='%d', xp='%d', level='%d', rank='%d' WHERE teamid='%u'", tab_prefix, team->size + '0', clienttag_uint_to_str(team->clienttag),(unsigned int)team->lastgame, team->teammembers[0], team->teammembers[1], team->teammembers[2], team->teammembers[3], team->wins, team->losses, team->xp, team->level, team->rank, team->teamid);
760 	if (sql->query(query) < 0)
761 	{
762 	    eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
763 	    return -1;
764 	}
765     } else
766     {
767 	eventlog(eventlog_level_error, __FUNCTION__, "error trying query: \"%s\"", query);
768 	return -1;
769     }
770 
771     return 0;
772 }
773 
sql_remove_team(unsigned int teamid)774 extern int sql_remove_team(unsigned int teamid)
775 {
776     if (!sql)
777     {
778 	eventlog(eventlog_level_error, __FUNCTION__, "sql layer not initilized");
779 	return -1;
780     }
781 
782     snprintf(query, sizeof(query), "DELETE FROM %sarrangedteam WHERE teamid='%u'", tab_prefix, teamid);
783     if (sql->query(query) != 0)
784         return -1;
785 
786     return 0;
787 }
788 
789 #endif				/* WITH_SQL */
790