1 /*
2  *     gtkatlantic - the gtk+ monopd client, enjoy network monopoly games
3  *
4  *
5  *  Copyright © 2002-2015 Sylvain Rochet
6  *
7  *  gtkatlantic is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (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; see the file COPYING. If not, see
19  *  <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdbool.h>
29 
30 #include <gtk/gtk.h>
31 #include <libxml/parser.h>
32 
33 #include "engine.h"
34 
35 #include "xmlparse.h"
36 #include "game.h"
37 #include "client.h"
38 #include "interface.h"
39 #include "global.h"
40 #include "load.h"
41 #include "callback.h"
42 #include "display.h"
43 #include "trade.h"
44 
45 /*
46 ok	server
47 ok	client
48 ok	msg
49 ok	display
50 dep	updateplayerlist
51 dep	updategamelist
52 ok	playerupdate
53 ok	deleteplayer
54 ok	estateupdate
55 ok	cardupdate
56 ok	estategroupupdate
57 ok	tradeupdate
58 ok	auctionupdate
59 ok	gameupdate
60 ok	deletegame
61 dep	commandlist
62 ok	configupdate
63 */
64 
65 /*
66 ok	.R
67 
68 ok	.gn
69 no-need	.gl
70 ok	.gj
71 ok	.gx
72 todo	.gk
73 todo	.gu
74 ok	.gc
75 todo	.gS
76 
77 ok	.Tn
78 ok	.Tc
79 ok	.Te
80 ok	.Tm
81 ok	.Ta
82 ok	.Tr
83 
84 ok	.r
85 ok	.E
86 ok	.t
87 
88 ok	.D
89 no-need	.p
90 
91 ok	.eb
92 ok	.es
93 ok	.ea
94 ok	.hb
95 ok	.hs
96 ok	.em
97 
98 ok	.ab
99 
100 ok	.jc
101 ok	.jp
102 ok	.jr
103 
104 ok	.T$
105 ok	.T%
106 
107 no-need	.pi
108 
109 todo	.gd
110 ok	.gs
111 
112 no-need	.d
113 ok	.n
114 no-need	.f
115 */
116 
117 
xmlparse_getgamelist_plugger(connection * c,gchar * buffer)118 void xmlparse_getgamelist_plugger(connection *c, gchar *buffer)  {
119 
120 	xmlDocPtr doc;
121 	xmlNodePtr cur;
122 
123 	doc = xmlParseMemory(buffer, strlen(buffer));
124 	if (doc == NULL) {
125 		return;
126 	}
127 
128 	cur = xmlDocGetRootElement(doc);
129 	if (cur == NULL) {
130 		xmlFreeDoc(doc);
131 		return;
132 	}
133 
134 	if( xmlStrcmp(cur->name, SERVER_XMLROOTELEMENT) )  {
135 		xmlFreeDoc(doc);
136 		return;
137 	}
138 
139 	for( cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next)  {
140 
141 		if(! xmlStrcmp(cur->name, (xmlChar*)"server") )  xmlparse_server(c, doc, cur);
142 		if(! xmlStrcmp(cur->name, (xmlChar*)"gameupdate") )  xmlparse_gamelist_gameupdate(c, doc, cur);
143 		if(! xmlStrcmp(cur->name, (xmlChar*)"deletegame") )  xmlparse_gamelist_deletegame(c, doc, cur);
144 	}
145 
146 	xmlFreeDoc(doc);
147 }
148 
149 
150 
151 
xmlparse_game_plugger(connection * c,gchar * buffer)152 void xmlparse_game_plugger(connection *c, gchar *buffer)  {
153 
154 	xmlDocPtr doc;
155 	xmlNodePtr cur;
156 
157 	doc = xmlParseMemory(buffer, strlen(buffer));
158 	if (doc == NULL) {
159 		return;
160 	}
161 
162 	cur = xmlDocGetRootElement(doc);
163 	if (cur == NULL) {
164 		xmlFreeDoc(doc);
165 		return;
166 	}
167 
168 	if( xmlStrcmp(cur->name, SERVER_XMLROOTELEMENT) )  {
169 		xmlFreeDoc(doc);
170 		return;
171 	}
172 
173 	for(cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next)  {
174 
175 		if(! xmlStrcmp(cur->name, (xmlChar*)"gameupdate") )  xmlparse_gameupdate(c, doc, cur);
176 		if(! xmlStrcmp(cur->name, (xmlChar*)"deletegame") )  xmlparse_deletegame(c, doc, cur);
177 		if(! xmlStrcmp(cur->name, (xmlChar*)"server") )  xmlparse_server(c, doc, cur);
178 		if(! xmlStrcmp(cur->name, (xmlChar*)"client") )  xmlparse_client(c, doc, cur);
179 		if(! xmlStrcmp(cur->name, (xmlChar*)"msg") )  xmlparse_message(c, doc, cur);
180 		if(! xmlStrcmp(cur->name, (xmlChar*)"estateupdate") )  xmlparse_estateupdate(c, doc, cur);
181 		if(! xmlStrcmp(cur->name, (xmlChar*)"playerupdate") )  xmlparse_playerupdate(c, doc, cur);
182 		if(! xmlStrcmp(cur->name, (xmlChar*)"auctionupdate") )  xmlparse_auctionupdate(c, doc, cur);
183 		if(! xmlStrcmp(cur->name, (xmlChar*)"display") )  xmlparse_display(c, doc, cur);
184 		if(! xmlStrcmp(cur->name, (xmlChar*)"configupdate") )  xmlparse_configupdate(c, doc, cur);
185 		if(! xmlStrcmp(cur->name, (xmlChar*)"tradeupdate") )  xmlparse_tradeupdate(c, doc, cur);
186 		if(! xmlStrcmp(cur->name, (xmlChar*)"cardupdate") )  xmlparse_cardupdate(c, doc, cur);
187 		if(! xmlStrcmp(cur->name, (xmlChar*)"estategroupupdate") )  xmlparse_estategroupupdate(c, doc, cur);
188 		if(! xmlStrcmp(cur->name, (xmlChar*)"deleteplayer") )  xmlparse_deleteplayer(c, doc, cur);
189 	}
190 
191 	xmlFreeDoc(doc);
192 }
193 
194 
195 
196 
xmlparse_server(connection * c,xmlDocPtr doc,xmlNodePtr cur)197 void xmlparse_server(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
198 	(void)doc;
199 
200 	c->server_version = (gchar*)xmlGetProp(cur, (xmlChar*)"version");
201 }
202 
203 
204 
205 
xmlparse_client(connection * c,xmlDocPtr doc,xmlNodePtr cur)206 void xmlparse_client(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
207 
208 	xmlChar *tmp;
209 	(void)c;
210 	(void)doc;
211 
212 	tmp = xmlGetProp(cur, (xmlChar*)"playerid");
213 	if( tmp )  {
214 		global->my_playerid = atoi( (gchar*)tmp );
215 		g_free(tmp);
216 	}
217 
218 	tmp = xmlGetProp(cur, (xmlChar*)"cookie");
219 	if( tmp )  {
220 		if(global->cookie) g_free(global->cookie);
221 		global->cookie = (gchar*)tmp;
222 	}
223 }
224 
225 
226 
227 
xmlparse_gameupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)228 void xmlparse_gameupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
229 	xmlChar *tmp;
230 	struct timeval tv;
231 	gint32 gameid;
232 	game *game;
233 	guint8 newstatus;
234 	(void)c;
235 	(void)doc;
236 
237 	tmp = xmlGetProp(cur, (xmlChar*)"gameid");
238 	if (tmp) {
239 		gameid = atoi((gchar*)tmp);
240 		g_free(tmp);
241 	} else {
242 		return;
243 	}
244 
245 	/* We do not need game templates */
246 	if (gameid < 0) {
247 		return;
248 	}
249 
250 	game = game_find(gameid);
251 	if (!game) {
252 		game = game_new(gameid);
253 		if (!game) {
254 			return;
255 		}
256 	}
257 
258 	tmp = xmlGetProp(cur, (xmlChar*)"status");
259 	if(tmp) {
260 		if(!xmlStrcmp(tmp, (xmlChar*)"config") ) {
261 			newstatus = GAME_STATUS_CONFIG;
262 		}
263 		else if(!xmlStrcmp(tmp, (xmlChar*)"init") ) {
264 			newstatus = GAME_STATUS_INIT;
265 		}
266 		else if(!xmlStrcmp(tmp, (xmlChar*)"run") ) {
267 			newstatus = GAME_STATUS_RUN;
268 		}
269 		else if(!xmlStrcmp(tmp, (xmlChar*)"end") ) {
270 			newstatus = GAME_STATUS_END;
271 		}
272 		else {
273 			g_free(tmp);
274 			return;
275 		}
276 
277 		if (game->status != newstatus) {
278 			game->status = newstatus;
279 
280 			if (newstatus == GAME_STATUS_RUN) {
281 				gettimeofday(&tv, NULL);
282 				game->start_time = tv.tv_sec;
283 			}
284 
285 			if (currentgame == game) {
286 				game_switch_status();
287 			}
288 		}
289 	}
290 	g_free(tmp);
291 
292 	tmp = xmlGetProp(cur, (xmlChar*)"master");
293 	if (tmp)  {
294 		game->master = atoi((gchar*)tmp);
295 		g_free(tmp);
296 
297 		if (game->GameConfigBox) {
298 			GList *list = gtk_container_get_children(GTK_CONTAINER(game->GameConfigBox));
299 			for (list = g_list_first(list); list; list = g_list_next(list)) {
300 				gtk_widget_set_sensitive(GTK_WIDGET(list->data), (global->my_playerid == game->master));
301 			}
302 			g_list_free(list);
303 		}
304 
305 		/* set sensitive mode of start button */
306 		if (currentgame == game && game->status == GAME_STATUS_CONFIG) {
307 			GtkWidget *StartButton = g_object_get_data(G_OBJECT(global->MainVerticalBox), "start_button");
308 			gtk_widget_set_sensitive(StartButton, (global->my_playerid == game->master));
309 		}
310 	}
311 }
312 
313 
xmlparse_deletegame(connection * c,xmlDocPtr doc,xmlNodePtr cur)314 void xmlparse_deletegame(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
315 	xmlChar *tmp;
316 	gint32 gameid;
317 	(void)c;
318 	(void)doc;
319 
320 	tmp = xmlGetProp(cur, (xmlChar*)"gameid");
321 	if (tmp) {
322 		gameid = atoi((gchar*)tmp);
323 		g_free(tmp);
324 	} else {
325 		return;
326 	}
327 
328 	if (!currentgame || currentgame->gameid != gameid) {
329 		game_free(gameid);
330 	}
331 }
332 
333 
xmlparse_message(connection * c,xmlDocPtr doc,xmlNodePtr cur)334 void xmlparse_message(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
335 
336 	gchar *type, *text, *author, *value;
337 	(void)c;
338 	(void)doc;
339 
340 	type = (gchar*)xmlGetProp(cur, (xmlChar*)"type");
341 
342 	if (!g_ascii_strncasecmp(type, "chat", 4)) {
343 
344 		author = (gchar*)xmlGetProp(cur, (xmlChar*)"author");
345 		value = (gchar*)xmlGetProp(cur, (xmlChar*)"value");
346 		if(value && author)  {
347 
348 			if(! strncmp("[ACTION]", value, 8) )
349 				text = g_strdup_printf("* %s%s", author, value + 8);
350 			else if(! strncmp("/me", value, 3) )
351 				text = g_strdup_printf("* %s%s", author, value + 3);
352 			else
353 				text = g_strdup_printf("<%s> %s", author, value);
354 
355 			text_insert_chat(text, strlen(text));
356 			g_free(text);
357 		}
358 		if(value[0] == '!')  parse_specific_chat_message(value);
359 		if(author)  g_free(author);
360 		if(value)  g_free(value);
361 	}
362 	else {
363 		value = (gchar*)xmlGetProp(cur, (xmlChar*)"value");
364 		if (!g_ascii_strncasecmp(type, "error", 5)) {
365 			interface_set_infolabel(value, "b00000", false);
366 		} else {
367 			interface_set_infolabel(value, "808000", false);
368 		}
369 		g_free(value);
370 	}
371 
372 	g_free(type);
373 }
374 
375 
376 
377 
xmlparse_estateupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)378 void xmlparse_estateupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
379 
380 	guint32 color[3], i;
381 	xmlChar *tmp;
382 	eng_obj *pic;
383 	gint32 star, id, t, u;
384 	gboolean refresh = FALSE;
385 	gboolean owner_mortgage_changed = FALSE;
386 	(void)c;
387 	(void)doc;
388 
389 	if (!currentgame) {
390 		return;
391 	}
392 
393 	tmp = xmlGetProp(cur, (xmlChar*)"estateid");
394 	if(!tmp)  return;
395 	id = atoi( (gchar*)tmp );
396 	g_free(tmp);
397 	if(id < 0) return;
398 
399 	tmp = xmlGetProp(cur, (xmlChar*)"name");
400 	if(tmp)  currentgame->estate[id].name = (gchar*)tmp;
401 
402 	tmp = xmlGetProp(cur, (xmlChar*)"color");
403 	if(tmp) {
404 
405 		sscanf((gchar*)tmp, "#%2X%2X%2X", &color[0], &color[1], &color[2]);
406 		currentgame->estate[id].color[0] = color[0];
407 		currentgame->estate[id].color[1] = color[1];
408 		currentgame->estate[id].color[2] = color[2];
409 		g_free(tmp);
410 	}
411 
412 	tmp = xmlGetProp(cur, (xmlChar*)"bgcolor");
413 	if(tmp) {
414 
415 		sscanf((gchar*)tmp, "#%2X%2X%2X", &color[0], &color[1], &color[2]);
416 		currentgame->estate[id].bgcolor[0] = color[0];
417 		currentgame->estate[id].bgcolor[1] = color[1];
418 		currentgame->estate[id].bgcolor[2] = color[2];
419 		g_free(tmp);
420 	}
421 
422 	tmp = xmlGetProp(cur, (xmlChar*)"owner");
423 	if(tmp)  {
424 
425 		t = currentgame->estate[id].owner = atoi((gchar*)tmp);
426 		g_free(tmp);
427 		owner_mortgage_changed = TRUE;
428 	}
429 
430 	tmp = xmlGetProp(cur, (xmlChar*)"mortgaged");
431 	if(tmp)  {
432 
433 		u = currentgame->estate[id].mortgaged = atoi((gchar*)tmp);
434 		g_free(tmp);
435 		owner_mortgage_changed = TRUE;
436 	}
437 
438 	if(owner_mortgage_changed)  {
439 		gint32 cardid = get_playerlistcard_id_with_estate(id);
440 
441 		t = currentgame->estate[id].owner;
442 		u = currentgame->estate[id].mortgaged;
443 
444 		/* reset unowned cards of this estate to all players */
445 		if (cardid >= 0) {
446 			player *p;
447 			for (p = player_h; p; p = p->next) {
448 				if (p->spectator) continue;
449 				if (p->game != currentgame->gameid) continue;
450 
451 				pic = p->playerlist_cards_pic[cardid];
452 				eng_pic_set_alpha(pic, data->playerlist_cards_alphaunowned);
453 			}
454 		}
455 
456 		if(t > 0  &&  !u)  {
457 
458 			/* star */
459 			star = player_from_id(t)->tokenid;
460 
461 			pic = currentgame->estate[id].star_pic;
462 			eng_pic_set_width(pic, data->pngfile_star_width[star]);
463 			eng_pic_set_height(pic, data->pngfile_star_height[star]);
464 			eng_pic_set_pixbuf(pic, data->pngfile_star_buf[star]);
465 			eng_pic_show(pic);
466 
467 			/* playerlist card */
468 			if (cardid >= 0) {
469 				pic = player_from_id(t)->playerlist_cards_pic[cardid];
470 			}
471 
472 			eng_pic_set_bgcolor(pic, data->playerlist_cards_cardbgcolor);
473 			eng_pic_set_alpha(pic, data->playerlist_cards_alphaowned);
474 		}
475 		else  if(t > 0  &&  u)  {
476 
477 			/* star */
478 			star = player_from_id(t)->tokenid;
479 
480 			pic = currentgame->estate[id].star_pic;
481 			eng_pic_set_width(pic, data->pngfile_star_m_width[star]);
482 			eng_pic_set_height(pic, data->pngfile_star_m_height[star]);
483 			eng_pic_set_pixbuf(pic, data->pngfile_star_m_buf[star]);
484 			eng_pic_show(pic);
485 
486 			/* playerlist card */
487 			if (cardid >= 0) {
488 				pic = player_from_id(t)->playerlist_cards_pic[cardid];
489 			}
490 
491 			eng_pic_set_bgcolor(pic, data->playerlist_cards_cardbgcolormortgage);
492 			eng_pic_set_alpha(pic, data->playerlist_cards_alphamortgage);
493 		}
494 		else /* if( t <= 0 ) */ {
495 
496 			/* star */
497 			eng_pic_unshow(currentgame->estate[id].star_pic);
498 		}
499 
500 		/* update estatelist in trade panel */
501 		for(i = 0 ; i < MAX_TRADES ; i++)  {
502 
503 			if(! currentgame->trade[i].open)  continue;
504 			if(currentgame->trade[i].current_component != TRADE_TYPE_ESTATE)  continue;
505 
506 			trade_rebuild_subcomponent(i);
507 		}
508 
509 		refresh = TRUE;
510 	}
511 
512 	tmp = xmlGetProp(cur, (xmlChar*)"houses");
513 	if(tmp)  {
514 
515 		t = currentgame->estate[id].houses = atoi((gchar*)tmp);
516  		g_free(tmp);
517 
518 		if(t <= 0)   {
519 
520 			/* houses */
521 			pic = currentgame->estate[id].house_pic;
522 			eng_pic_unshow(pic);
523 		}
524 		else  if(t > 0  &&  data->estate[id].type_house == TYPE_HOUSE_HORIZONTAL)  {
525 
526 			/* houses */
527 			pic = currentgame->estate[id].house_pic;
528 			eng_pic_set_width(pic, data->pngfile_horiz_house_width[t]);
529 			eng_pic_set_height(pic, data->pngfile_horiz_house_height[t]);
530 			eng_pic_set_pixbuf(pic, data->pngfile_horiz_house_buf[t]);
531 			eng_pic_show(pic);
532 		}
533 		else  if(t > 0  &&  data->estate[id].type_house == TYPE_HOUSE_VERTICAL)  {
534 
535 			/* houses */
536 			pic = currentgame->estate[id].house_pic;
537 			eng_pic_set_width(pic, data->pngfile_vert_house_width[t]);
538 			eng_pic_set_height(pic, data->pngfile_vert_house_height[t]);
539 			eng_pic_set_pixbuf(pic, data->pngfile_vert_house_buf[t]);
540 			eng_pic_show(pic);
541 		}
542 
543 		refresh = TRUE;
544 	}
545 
546 	tmp = xmlGetProp(cur, (xmlChar*)"houseprice");
547 	if(tmp)  {
548 		currentgame->estate[id].houseprice = atoi((gchar*)tmp);
549 		g_free(tmp);
550 	}
551 
552 	tmp = xmlGetProp(cur, (xmlChar*)"sellhouseprice");
553 	if(tmp)  {
554 		currentgame->estate[id].sellhouseprice = atoi((gchar*)tmp);
555 		g_free(tmp);
556 	}
557 
558 	tmp = xmlGetProp(cur, (xmlChar*)"mortgageprice");
559 	if(tmp)  {
560 		currentgame->estate[id].mortgageprice = atoi((gchar*)tmp);
561 		g_free(tmp);
562 	}
563 
564 	tmp = xmlGetProp(cur, (xmlChar*)"unmortgageprice");
565 	if(tmp)  {
566 		currentgame->estate[id].unmortgageprice = atoi((gchar*)tmp);
567 		g_free(tmp);
568 	}
569 
570 	tmp = xmlGetProp(cur, (xmlChar*)"group");
571 	if(tmp)  {
572 		currentgame->estate[id].group = atoi((gchar*)tmp);
573 		g_free(tmp);
574 	}
575 
576 	tmp = xmlGetProp(cur, (xmlChar*)"can_be_owned");
577 	if(tmp)  {
578 		currentgame->estate[id].can_be_owned = atoi((gchar*)tmp);
579 		g_free(tmp);
580 	}
581 
582 	tmp = xmlGetProp(cur, (xmlChar*)"can_toggle_mortgage");
583 	if(tmp)  {
584 		currentgame->estate[id].can_toggle_mortgage = atoi((gchar*)tmp);
585 		g_free(tmp);
586 	}
587 
588 	tmp = xmlGetProp(cur, (xmlChar*)"can_buy_houses");
589 	if(tmp)  {
590 		currentgame->estate[id].can_buy_houses = atoi((gchar*)tmp);
591 		g_free(tmp);
592 	}
593 
594 	tmp = xmlGetProp(cur, (xmlChar*)"can_sell_houses");
595 	if(tmp)  {
596 		currentgame->estate[id].can_sell_houses = atoi((gchar*)tmp);
597 		g_free(tmp);
598 	}
599 
600 	tmp = xmlGetProp(cur, (xmlChar*)"money");
601 	if(tmp)  {
602 		currentgame->estate[id].money = atoi((gchar*)tmp);
603 		g_free(tmp);
604 	}
605 
606 	tmp = xmlGetProp(cur, (xmlChar*)"price");
607 	if(tmp)  {
608 		currentgame->estate[id].price = atoi((gchar*)tmp);
609 		g_free(tmp);
610 	}
611 
612 	for(i = 0 ; i <= 5 ; i++) {
613 
614 		xmlChar *key = (xmlChar*)g_strdup_printf("rent%d", i);
615 		tmp = xmlGetProp(cur, key);
616 
617 		if(tmp)  {
618 			currentgame->estate[id].rent[i] = atoi((gchar*)tmp);
619 			g_free(tmp);
620 		}
621 		g_free(key);
622 	}
623 
624 	if (refresh) {
625 		update_display();
626 	}
627 }
628 
629 
630 
631 
xmlparse_playerupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)632 void xmlparse_playerupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
633 
634 	gint32 id, i;
635 	player *p;
636 	xmlChar *tmp;
637 	gboolean refresh = FALSE;
638 	(void)c;
639 	(void)doc;
640 
641 	tmp = xmlGetProp(cur, (xmlChar*)"playerid");
642 	if(!tmp) return;
643 	id = atoi((gchar*)tmp);
644 	g_free(tmp);
645 	if(!id) return;
646 
647 	/* create new player */
648 	p = player_from_id(id);
649 	if (p == NULL)  {
650 		p = game_new_player(id);
651 		if (!p) {
652 			return;
653 		}
654 	}
655 
656 	tmp = xmlGetProp(cur, (xmlChar*)"game");
657 	if(tmp)  {
658 		p->game = atoi((gchar*)tmp);
659 		g_free(tmp);
660 
661 		if (id == global->my_playerid) {
662 			if (p->game < 0) {
663 				if (currentgame) {
664 					game_quit();
665 				}
666 			} else {
667 				if (!currentgame) {
668 					game *game = game_find(p->game);
669 					if (game) {
670 						currentgame = game;
671 						printf("Current game: %d\n", game->gameid);
672 						game_switch_status();
673 					}
674 				}
675 			}
676 		} else if (p->game < 0) {
677 			interface_gameboard_remove_player(p);
678 			refresh = TRUE;
679 		}
680 	}
681 
682 	tmp = xmlGetProp(cur, (xmlChar*)"host");
683 	if(tmp)  {
684 		if(p->host) g_free(p->host);
685 		p->host = (gchar*)tmp;
686 	}
687 
688 	tmp = xmlGetProp(cur, (xmlChar*)"image");
689 	if(tmp)  {
690 		if(p->image) g_free(p->image);
691 		p->image = (gchar*)tmp;
692 	}
693 
694 	tmp = xmlGetProp(cur, (xmlChar*)"name");
695 	if(tmp)  {
696 		if(p->name) g_free(p->name);
697 		p->name = (char*)tmp;
698 
699 		if (currentgame && p->game == currentgame->gameid) {
700 			/* playerlist name */
701 			/* FIXME: handle hasturn color */
702 			if(p->playerlist_LabelNamePlayer)
703 				gtk_label_set_text(GTK_LABEL(p->playerlist_LabelNamePlayer), p->name);
704 
705 			/* playerlist in trade panel */
706 			for(i = 0 ; i < MAX_TRADES ; i++)  {
707 
708 				if(! currentgame->trade[i].open)  continue;
709 
710 				trade_rebuild_playerlist(i);
711 			}
712 
713 			/* update sub component players in trade panel */
714 			for(i = 0 ; i < MAX_TRADES ; i++)  {
715 
716 				if(! currentgame->trade[i].open)  continue;
717 
718 				trade_rebuild_subcomponent(i);
719 			}
720 		}
721 	}
722 
723 	tmp = xmlGetProp(cur, (xmlChar*)"money");
724 	if(tmp)  {
725 		p->money = atoi((gchar*)tmp);
726 		g_free(tmp);
727 
728 		if (currentgame && p->game == currentgame->gameid) {
729 			if(p->playerlist_LabelMoneyPlayer) {
730 				if(p->hasturn) {
731 					gchar *tmp = g_markup_printf_escaped("<span foreground=\"#ff0000\">%d</span>", p->money);
732 					gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
733 					g_free(tmp);
734 				} else {
735 					gchar *tmp = g_markup_printf_escaped("<span foreground=\"#000000\">%d</span>", p->money);
736 					gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
737 					g_free(tmp);
738 				}
739 			}
740 		}
741 	}
742 
743 	tmp = xmlGetProp(cur, (xmlChar*)"location");
744 	if(tmp)  {
745 		p->location_to = atoi((gchar*)tmp);
746 		g_free(tmp);
747 
748 		tmp = xmlGetProp(cur, (xmlChar*)"directmove");
749 		if (tmp) {
750 			p->directmove = atoi((gchar*)tmp);
751 			g_free(tmp);
752 		}
753 
754 		if (currentgame && p->game == currentgame->gameid) {
755 			refresh = TRUE;
756 		}
757 	}
758 
759 	tmp = xmlGetProp(cur, (xmlChar*)"jailed");
760 	if(tmp)  {
761 		gboolean jailed = atoi((gchar*)tmp);
762 		g_free(tmp);
763 
764 		if (jailed != p->jailed) {
765 			p->jailed = jailed;
766 			p->directmove = TRUE; /* force directmove when player is going to or leaving jail */
767 		}
768 
769 		if (currentgame && p->game == currentgame->gameid) {
770 			refresh = TRUE;
771 		}
772 	}
773 
774 	tmp = xmlGetProp(cur, (xmlChar*)"bankrupt");
775 	if(tmp)  {
776 		p->bankrupt = atoi((gchar*)tmp);
777 		g_free(tmp);
778 
779 		if (currentgame && p->game == currentgame->gameid) {
780 			/* remove token */
781 			if(p->bankrupt) {
782 				eng_pic_unshow(p->token_pic);
783 				refresh = TRUE;
784 			}
785 		}
786 	}
787 
788 	tmp = xmlGetProp(cur, (xmlChar*)"hasturn");
789 	if(tmp)  {
790 		p->hasturn = atoi((gchar*)tmp);
791 		g_free(tmp);
792 
793 		if (currentgame && p->game == currentgame->gameid) {
794 			/* set has turn attributes */
795 			if(p->hasturn)  {
796 
797 				if (p->playerlist_LabelNamePlayer)  {
798 					gchar *tmp = g_markup_printf_escaped("<span foreground=\"#ff0000\">%s</span>", p->name);
799 					gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelNamePlayer), tmp);
800 					g_free(tmp);
801 
802 					tmp = g_markup_printf_escaped("<span foreground=\"#ff0000\">%d</span>", p->money);
803 					gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
804 					g_free(tmp);
805 				}
806 
807 				eng_pic_unset_alpha(p->token_pic);
808 			}
809 			else  {
810 
811 				if (p->playerlist_LabelNamePlayer)  {
812 					gchar *tmp = g_markup_printf_escaped("<span foreground=\"#000000\">%s</span>", p->name);
813 					gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelNamePlayer), tmp);
814 					g_free(tmp);
815 
816 					tmp = g_markup_printf_escaped("<span foreground=\"#000000\">%d</span>", p->money);
817 					gtk_label_set_markup(GTK_LABEL(p->playerlist_LabelMoneyPlayer), tmp);
818 					g_free(tmp);
819 				}
820 
821 				if(config->game_token_transparency)
822 					eng_pic_set_alpha(p->token_pic, 0x7f);
823 			}
824 
825 			refresh = TRUE;
826 		}
827 	}
828 
829 	tmp = xmlGetProp(cur, (xmlChar*)"can_roll");
830 	if(tmp)  {
831 		p->can_roll = atoi((gchar*)tmp);
832 		g_free(tmp);
833 	}
834 
835 	tmp = xmlGetProp(cur, (xmlChar*)"can_buyestate");
836 	if(tmp)  {
837 		p->can_buyestate = atoi((gchar*)tmp);
838 		g_free(tmp);
839 	}
840 
841 	tmp = xmlGetProp(cur, (xmlChar*)"turnorder");
842 	if(tmp)  {
843 		p->turnorder = atoi((gchar*)tmp);
844 		g_free(tmp);
845 	}
846 
847 	tmp = xmlGetProp(cur, (xmlChar*)"spectator");
848 	if(tmp)  {
849 		p->spectator = atoi((gchar*)tmp);
850 		g_free(tmp);
851 		if (currentgame && p->game == currentgame->gameid && !p->spectator) {
852 			/* note: turnorder must be fetched before */
853 			game_sort_playerlist_by_turnorder();
854 			interface_gameboard_add_player(p);
855 			game_update_tokens();
856 		}
857 	}
858 
859 	game_buildplayerlist();
860 	if (refresh) {
861 		game_initiate_token_movement();
862 		update_display();
863 	}
864 }
865 
866 
867 
868 
xmlparse_auctionupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)869 void xmlparse_auctionupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
870 
871 	guint32 auctionid, highbid = 0;
872 	xmlChar *tmp;
873 	(void)c;
874 	(void)doc;
875 
876 	if (!currentgame || currentgame->status != GAME_STATUS_RUN) {
877 		return;
878 	}
879 
880 	tmp = xmlGetProp(cur, (xmlChar*)"auctionid");
881 	if(!tmp) return;
882 	auctionid = atoi((gchar*)tmp);
883 	g_free(tmp);
884 
885 	/* initialise auction */
886 	tmp = xmlGetProp(cur, (xmlChar*)"estateid");
887 	if (tmp && g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auctionbox") == NULL) {
888 		guint32 estateid = atoi((gchar*)tmp);
889 		g_free(tmp);
890 
891 		display_hide();
892 		interface_create_auctionbox(auctionid, estateid);
893 		g_object_set_data(G_OBJECT(currentgame->BoardCenter), "auction_highbid", 0);
894 	}
895 
896 	if (g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auctionbox") == NULL) {
897 		return;
898 	}
899 
900 	/* bid */
901 	tmp = xmlGetProp(cur, (xmlChar*)"highbid");
902 	if(tmp) {
903 		highbid = atoi((gchar*)tmp);
904 		g_object_set_data(G_OBJECT(currentgame->BoardCenter), "auction_highbid", GINT_TO_POINTER(highbid));
905 		g_free(tmp);
906 	}
907 
908 	tmp = xmlGetProp(cur, (xmlChar*)"highbidder");
909 	if(tmp) {
910 		guint32 highbidder = atoi((gchar*)tmp);
911 		g_free(tmp);
912 
913 		GtkListStore *store;
914 		GtkTreeIter iter;
915 		gboolean valid;
916 
917 		store = g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auction_store");
918 		valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
919 		while (valid) {
920 			guint32 eplayerid;
921 
922 			gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, AUCTIONPLAYERLIST_COLUMN_PLAYERID, &eplayerid, -1);
923 			if (eplayerid == highbidder)  {
924 				gtk_list_store_set(store, &iter,
925 					AUCTIONPLAYERLIST_COLUMN_BID, highbid,
926 					AUCTIONPLAYERLIST_WEIGHT, PANGO_WEIGHT_BOLD,
927 					-1);
928 			} else {
929 				gtk_list_store_set(store, &iter,
930 					AUCTIONPLAYERLIST_WEIGHT, PANGO_WEIGHT_NORMAL,
931 					-1);
932 			}
933 
934 			valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
935 		}
936 	}
937 
938 	/* status */
939 	tmp = xmlGetProp(cur, (xmlChar*)"status");
940 	if(tmp) {
941 		guint32 status = atoi((gchar*)tmp);
942 		g_free(tmp);
943 
944 		GtkWidget *label = g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auction_statuslabel");
945 
946 		switch (status) {
947 			case 0:
948 				gtk_label_set_text(GTK_LABEL(label), NULL);
949 				break;
950 
951 			case 1:
952 				gtk_label_set_text(GTK_LABEL(label), "Going once…");
953 				break;
954 
955 			case 2:
956 				gtk_label_set_text(GTK_LABEL(label), "Going twice…");
957 				break;
958 
959 			case 3:
960 				gtk_widget_destroy(g_object_get_data(G_OBJECT(currentgame->BoardCenter), "auctionbox"));
961 				g_object_set_data(G_OBJECT(currentgame->BoardCenter), "auctionbox", NULL);
962 				display_show();
963 				break;
964 		}
965 	}
966 }
967 
968 
969 
970 
xmlparse_display(connection * c,xmlDocPtr doc,xmlNodePtr cur)971 void xmlparse_display(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
972 
973 	xmlNodePtr cur2;
974 	gint32 estateid;
975 	xmlChar *tmp;
976 	gchar *caption, *command;
977 	gboolean enable;
978 	(void)c;
979 	(void)doc;
980 
981 	if (!currentgame || currentgame->status < GAME_STATUS_INIT) {
982 		return;
983 	}
984 
985 	tmp = xmlGetProp(cur, (xmlChar*)"cleartext");
986 	if(tmp)  {
987 		if( atoi((gchar*)tmp) )  display_clear_text();
988 		g_free(tmp);
989 	}
990 
991 	tmp = xmlGetProp(cur, (xmlChar*)"clearbuttons");
992 	if(tmp)  {
993 		if( atoi((gchar*)tmp) )  display_clear_buttons();
994 		g_free(tmp);
995 	}
996 
997 	tmp = xmlGetProp(cur, (xmlChar*)"estateid");
998 	if(tmp)   {
999 		estateid = atoi((gchar*)tmp);
1000 		g_free(tmp);
1001 		display_estate(estateid);
1002 	}
1003 
1004 	tmp = xmlGetProp(cur, (xmlChar*)"text");
1005 	if(tmp)  {
1006 
1007 		if( strlen((gchar*)tmp) > 0)  display_text((gchar*)tmp);
1008 		g_free(tmp);
1009 	}
1010 
1011 	/* buttons */
1012 	for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next)  {
1013 
1014 		if(! xmlStrcmp(cur2->name, (xmlChar*)"button") )  {
1015 
1016 			caption = (gchar*)xmlGetProp(cur2, (xmlChar*)"caption");
1017 			command = (gchar*)xmlGetProp(cur2, (xmlChar*)"command");
1018 
1019 			tmp = xmlGetProp(cur2, (xmlChar*)"enabled");
1020 			enable = atoi((gchar*)tmp);
1021 			g_free(tmp);
1022 
1023 			display_add_button((gchar*)caption, (gchar*)command, enable);
1024 			g_free(caption);
1025 			g_free(command);
1026 		}
1027 	}
1028 }
1029 
1030 
1031 
1032 
xmlparse_configupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1033 void xmlparse_configupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
1034 
1035 	GtkWidget *CButton;
1036 	gchar *description;
1037 	guint32 signalid;
1038 	xmlChar *tmp;
1039 	game *game;
1040 	gint32 id;
1041 	(void)c;
1042 	(void)doc;
1043 
1044 	tmp = xmlGetProp(cur, (xmlChar*)"gameid");
1045 	if (!tmp) {
1046 		return;
1047 	}
1048 
1049 	game = game_find(atoi((gchar*)tmp));
1050 	g_free(tmp);
1051 	if (!game) {
1052 		return;
1053 	}
1054 
1055 	tmp = xmlGetProp(cur, (xmlChar*)"configid");
1056 	if (!tmp) {
1057 		return;
1058 	}
1059 
1060 	id = atoi((gchar*)tmp);
1061 	g_free(tmp);
1062 	if (id <= 0) {
1063 		return;
1064 	}
1065 
1066 	/* We are going to receive <configupdate/> events before we know in which game we are
1067 	 * therefore we create the config box before the config panel is created
1068 	 */
1069 	if (!game->GameConfigBox) {
1070 		game->GameConfigBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
1071 	}
1072 
1073 	/* create it if not created */
1074 	gchar *strid = g_strdup_printf("%d", id);
1075 	if ( !(CButton = g_object_get_data(G_OBJECT(game->GameConfigBox), strid)) ) {
1076 
1077 		/* We only handle boolean type for now */
1078 		tmp = xmlGetProp(cur, (xmlChar*)"type");
1079 		if (!tmp) {
1080 			goto abort;
1081 		}
1082 		if(xmlStrcmp(tmp, (xmlChar*)"bool") )  {
1083 			g_free(tmp);
1084 			goto abort;
1085 		}
1086 		g_free(tmp);
1087 
1088 		description = (gchar*)xmlGetProp(cur, (xmlChar*)"description");
1089 		if (!description) {
1090 			goto abort;
1091 		}
1092 
1093 		CButton = gtk_check_button_new_with_label(description);
1094 		signalid = g_signal_connect(G_OBJECT(CButton), "toggled", G_CALLBACK(Callback_toggle_boolean_gameoption), NULL);
1095 		gtk_widget_set_sensitive(CButton, (global->my_playerid == game->master));
1096 		gtk_box_pack_start(GTK_BOX(game->GameConfigBox), CButton, FALSE, FALSE, 0);
1097 
1098 		/* store signal identifier */
1099 		g_object_set_data(G_OBJECT(CButton), "signal", GINT_TO_POINTER(signalid));
1100 
1101 		/* store id under CButton */
1102 		g_object_set_data(G_OBJECT(CButton), "id", GINT_TO_POINTER(id));
1103 
1104 		/* save the pointer of button to use in the future */
1105 		g_object_set_data(G_OBJECT(game->GameConfigBox), strid, CButton);
1106 
1107 		g_free(description);
1108 	}
1109 
1110 	/* modify */
1111 	tmp = xmlGetProp(cur, (xmlChar*)"value");
1112 	if (tmp) {
1113 
1114 		/* disconnect signal */
1115 		signalid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(CButton), "signal"));
1116 		g_signal_handler_disconnect(G_OBJECT(CButton), signalid);
1117 
1118 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(CButton), (atoi((gchar*)tmp) != 0));
1119 		g_free(tmp);
1120 
1121 		/* reconnect signal */
1122 		signalid = g_signal_connect(G_OBJECT(CButton), "toggled", G_CALLBACK(Callback_toggle_boolean_gameoption), NULL);
1123 		g_object_set_data(G_OBJECT(CButton), "signal", GINT_TO_POINTER(signalid));
1124 	}
1125 
1126 /*	tmp = xmlGetProp(cur, (xmlChar*)"edit");   USELESS */
1127 
1128 abort:
1129 	g_free(strid);
1130 	gtk_widget_show_all(game->GameConfigBox);
1131 }
1132 
1133 
1134 
1135 
xmlparse_tradeupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1136 void xmlparse_tradeupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
1137 
1138 	xmlNodePtr cur2;
1139 	xmlChar *tmp;
1140 	guint32 tradeid = 0, playerid = 0, cardid = 0, estateid = 0;
1141 	guint32 targetplayer = 0, playerfrom = 0, playerto = 0, money = 0;
1142 	gboolean accept = FALSE;
1143 	(void)c;
1144 	(void)doc;
1145 
1146 	if (!currentgame || currentgame->status != GAME_STATUS_RUN) {
1147 		return;
1148 	}
1149 
1150 	tmp = xmlGetProp(cur, (xmlChar*)"tradeid");
1151 	if(tmp)  {
1152 		tradeid = atoi((gchar*)tmp);
1153 		g_free(tmp);
1154 	}
1155 	else  return;
1156 
1157 //	tmp = xmlGetProp(cur, (xmlChar*)"actor");
1158 //	if(tmp)   {
1159 //		actor = atoi((gchar*)tmp);
1160 //		g_free(tmp);
1161 //	}
1162 
1163 	tmp = xmlGetProp(cur, (xmlChar*)"type");
1164 	if(tmp) {
1165 		if (!xmlStrcmp(tmp, (xmlChar*)"rejected") || !xmlStrcmp(tmp, (xmlChar*)"accepted") || !xmlStrcmp(tmp, (xmlChar*)"completed")) {
1166 			trade_destroy(tradeid);
1167 			g_free(tmp);
1168 			return;
1169 		}
1170 
1171 		if (!xmlStrcmp(tmp, (xmlChar*)"new")) {
1172 			trade_initnew(tradeid);
1173 		}
1174 
1175 		g_free(tmp);
1176 	}
1177 
1178 	tmp = xmlGetProp(cur, (xmlChar*)"revision");
1179 	if (tmp) {
1180 		trade_update_revision(tradeid, atoi((gchar*)tmp));
1181 		g_free(tmp);
1182 	}
1183 
1184 	for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next)  {
1185 
1186 		/* -- player -- */
1187 		if(! xmlStrcmp(cur2->name, (xmlChar*)"tradeplayer") )  {
1188 
1189 			tmp = xmlGetProp(cur2, (xmlChar*)"playerid");
1190 			if(tmp)   {
1191 				playerid = atoi((gchar*)tmp);
1192 				g_free(tmp);
1193 			}
1194 
1195 			tmp = xmlGetProp(cur2, (xmlChar*)"accept");
1196 			if(tmp)   {
1197 				accept = atoi((gchar*)tmp);
1198 				g_free(tmp);
1199 			}
1200 
1201 			trade_update_player(tradeid, playerid, accept);
1202 		}
1203 
1204 		/* -- card -- */
1205 		if(! xmlStrcmp(cur2->name, (xmlChar*)"tradecard") )  {
1206 
1207 			tmp = xmlGetProp(cur2, (xmlChar*)"cardid");
1208 			if(tmp)   {
1209 				cardid = atoi((gchar*)tmp);
1210 				g_free(tmp);
1211 			}
1212 
1213 			tmp = xmlGetProp(cur2, (xmlChar*)"targetplayer");
1214 			if(tmp)   {
1215 				targetplayer = atoi((gchar*)tmp);
1216 				g_free(tmp);
1217 			}
1218 
1219 			trade_update_card(tradeid, cardid, targetplayer);
1220 		}
1221 
1222 		/* -- estate -- */
1223 		if(! xmlStrcmp(cur2->name, (xmlChar*)"tradeestate") )  {
1224 
1225 			tmp = xmlGetProp(cur2, (xmlChar*)"estateid");
1226 			if(tmp)   {
1227 				estateid = atoi((gchar*)tmp);
1228 				g_free(tmp);
1229 			}
1230 
1231 			tmp = xmlGetProp(cur2, (xmlChar*)"targetplayer");
1232 			if(tmp)   {
1233 				targetplayer = atoi((gchar*)tmp);
1234 				g_free(tmp);
1235 			}
1236 
1237 			trade_update_estate(tradeid, estateid, targetplayer);
1238 		}
1239 
1240 		/* -- money -- */
1241 		if(! xmlStrcmp(cur2->name, (xmlChar*)"trademoney") )  {
1242 
1243 			tmp = xmlGetProp(cur2, (xmlChar*)"playerfrom");
1244 			if(tmp)   {
1245 				playerfrom = atoi((gchar*)tmp);
1246 				g_free(tmp);
1247 			}
1248 
1249 			tmp = xmlGetProp(cur2, (xmlChar*)"playerto");
1250 			if(tmp)   {
1251 				playerto = atoi((gchar*)tmp);
1252 				g_free(tmp);
1253 			}
1254 
1255 			tmp = xmlGetProp(cur2, (xmlChar*)"money");
1256 			if(tmp)   {
1257 				money = atoi((gchar*)tmp);
1258 				g_free(tmp);
1259 			}
1260 
1261 			trade_update_money(tradeid, playerfrom, playerto, money);
1262 		}
1263 	}
1264 
1265 }
1266 
1267 
1268 
1269 
xmlparse_cardupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1270 void xmlparse_cardupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
1271 
1272 	xmlChar *tmp;
1273 	gint32 cardid, owner, i, cardslot;
1274 	(void)c;
1275 	(void)doc;
1276 
1277 	if (!currentgame || currentgame->status < GAME_STATUS_INIT) {
1278 		return;
1279 	}
1280 
1281 	tmp = xmlGetProp(cur, (xmlChar*)"cardid");
1282 	if (!tmp) {
1283 		return;
1284 	}
1285 	cardid = atoi((gchar*)tmp);
1286 	g_free(tmp);
1287 
1288 	tmp = xmlGetProp(cur, (xmlChar*)"owner");
1289 	if (!tmp) {
1290 		return;
1291 	}
1292 	owner = atoi((gchar*)tmp);
1293 	g_free(tmp);
1294 
1295 	cardslot = get_card_slot_with_cardid(cardid);
1296 
1297 	/* create new or update card slot */
1298 	if (owner >= 0)  {
1299 		if (cardslot < 0 && !game_get_valid_card_slot(&cardslot)) {
1300 			return;
1301 		}
1302 
1303 		currentgame->card[cardslot].cardid = cardid;
1304 		currentgame->card[cardslot].owner = owner;
1305 
1306 		xmlChar *title = xmlGetProp(cur, (xmlChar*)"title");
1307 		if (title) {
1308 			if (currentgame->card[cardslot].title) {
1309 				g_free(currentgame->card[cardslot].title);
1310 			}
1311 			currentgame->card[cardslot].title = (gchar*)title;
1312 		}
1313 	}
1314 
1315 	/* destroy a card slot */
1316 	else {
1317 		if (cardslot < 0) {
1318 			return;
1319 		}
1320 
1321 		currentgame->card[cardslot].cardid = 0;
1322 		currentgame->card[cardslot].owner = 0;
1323 		if (currentgame->card[cardslot].title) {
1324 			g_free(currentgame->card[cardslot].title);
1325 			currentgame->card[cardslot].title = NULL;
1326 		}
1327 
1328 	}
1329 
1330 	/* update component list in trade panel */
1331 	for(i = 0 ; i < MAX_TRADES ; i++)  {
1332 
1333 		if(! currentgame->trade[i].open)  continue;
1334 
1335 		trade_rebuild_component(i);
1336 		trade_rebuild_subcomponent(i);
1337 	}
1338 }
1339 
1340 
1341 
1342 
xmlparse_estategroupupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1343 void xmlparse_estategroupupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
1344 
1345 	xmlChar *tmp;
1346 	gint32 groupid = -1;
1347 	(void)c;
1348 	(void)doc;
1349 
1350 	if (!currentgame) {
1351 		return;
1352 	}
1353 
1354 	tmp = xmlGetProp(cur, (xmlChar*)"groupid");
1355 	if(tmp)  {
1356 		groupid = atoi((gchar*)tmp);
1357 		g_free(tmp);
1358 	}
1359 
1360 	if(groupid < 0)  return;
1361 
1362 	if(currentgame->group[groupid].name)  g_free(currentgame->group[groupid].name);
1363 
1364 	currentgame->group[groupid].name = (gchar*)xmlGetProp(cur, (xmlChar*)"name");
1365 }
1366 
1367 
1368 
1369 
xmlparse_deleteplayer(connection * c,xmlDocPtr doc,xmlNodePtr cur)1370 void xmlparse_deleteplayer(connection *c, xmlDocPtr doc, xmlNodePtr cur)  {
1371 
1372 	xmlChar *tmp;
1373 	gint32 id;
1374 	player *p;
1375 	(void)c;
1376 	(void)doc;
1377 
1378 	tmp = xmlGetProp(cur, (xmlChar*)"playerid");
1379 	if (!tmp) return;
1380 	id = atoi((gchar*)tmp);
1381 	g_free(tmp);
1382 
1383 	if (id < 0) return;
1384 
1385 	p = player_from_id(id);
1386 	if (p == NULL) return;
1387 
1388 	interface_gameboard_remove_player(p);
1389 	update_display();
1390 	game_free_player(p);
1391 	game_buildplayerlist();
1392 }
1393 
1394 
1395 
1396 
xmlparse_gamelist_gameupdate(connection * c,xmlDocPtr doc,xmlNodePtr cur)1397 void xmlparse_gamelist_gameupdate(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1398 	xmlChar *tmp;
1399 	gchar *players = NULL;
1400 	gint32 id;
1401 	GtkTreeIter iter;
1402 	gboolean valid;
1403 	gboolean update = FALSE;
1404 	gchar *status = NULL;
1405 	gint32 canbejoined = -1, canbewatched = -1;
1406 	(void)doc;
1407 
1408 	tmp = xmlGetProp(cur, (xmlChar*)"gameid");
1409 	id = atoi((gchar*)tmp);
1410 	g_free(tmp);
1411 
1412 	/* lookup if gameid on same server already exist */
1413 	if (id > 0) {
1414 		valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1415 		while (valid) {
1416 			gint32 source;
1417 			gint32 eid;
1418 
1419 			gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_GAMEID, &eid, GAMELIST_COLUMN_SOURCE, &source, -1);
1420 			if (eid == id && source == GAMELIST_SOURCE_CUSTOM)  {
1421 				update = TRUE;
1422 				break;
1423 			}
1424 
1425 			valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter);
1426 		}
1427 	}
1428 
1429 	/* ONLY TEMPORARY ! */
1430 	tmp = xmlGetProp(cur, (xmlChar*)"gametype");
1431 	if (tmp && xmlStrcmp(tmp, (xmlChar*)"city") && xmlStrcmp(tmp, (xmlChar*)"french_city") )  {
1432 		g_free(tmp);
1433 		return;
1434 	}
1435 
1436 	tmp = xmlGetProp(cur, (xmlChar*)"turn");
1437 	if(tmp) {
1438 		int turn = atoi((gchar*)tmp);
1439 		g_free(tmp);
1440 
1441 		if (turn >= 1) {
1442 			status = g_strdup_printf("Playing, turn %d", turn);
1443 		}
1444 	}
1445 
1446 	tmp = xmlGetProp(cur, (xmlChar*)"status");
1447 	if(tmp) {
1448 		if (!xmlStrcmp(tmp, (xmlChar*)"config") ) {
1449 			if (status) {
1450 				g_free(status);
1451 			}
1452 			status = g_strdup("Waiting for players");
1453 		}
1454 		else if (!xmlStrcmp(tmp, (xmlChar*)"end") ) {
1455 			if (status) {
1456 				g_free(status);
1457 			}
1458 			status = g_strdup("Finished");
1459 		}
1460 
1461 		g_free(tmp);
1462 	}
1463 
1464 	// game template
1465 	if (id < 0) {
1466 		canbejoined = true;
1467 		canbewatched = false;
1468 	}
1469 	tmp = xmlGetProp(cur, (xmlChar*)"canbejoined");
1470 	if (tmp) {
1471 		canbejoined = atoi((gchar*)tmp);
1472 		g_free(tmp);
1473 	}
1474 
1475 	tmp = xmlGetProp(cur, (xmlChar*)"canbewatched");
1476 	if (tmp) {
1477 		canbewatched = atoi((gchar*)tmp);
1478 		g_free(tmp);
1479 	}
1480 
1481 	players = (gchar*)xmlGetProp(cur, (xmlChar*)"players");
1482 
1483 	if (update) {
1484 		if (status) {
1485 			gtk_list_store_set(global->game_store, &iter,
1486 			GAMELIST_COLUMN_STATUS, status,
1487 			-1);
1488 		}
1489 
1490 		if (players) {
1491 			gtk_list_store_set(global->game_store, &iter,
1492 			GAMELIST_COLUMN_PLAYERS, players,
1493 			-1);
1494 		}
1495 
1496 		if (canbejoined >= 0) {
1497 			gtk_list_store_set(global->game_store, &iter,
1498 			GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1499 			-1);
1500 		}
1501 
1502 		if (canbewatched >= 0) {
1503 			gtk_list_store_set(global->game_store, &iter,
1504 			GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1505 			-1);
1506 		}
1507 
1508 		if (canbejoined >= 0 || canbewatched >= 0) {
1509 			gint32 joined, watched;
1510 
1511 			gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_CANBEJOINED, &joined, GAMELIST_COLUMN_CANBEWATCHED, &watched, -1);
1512 			gtk_list_store_set(global->game_store, &iter,
1513 			GAMELIST_COLUMN_BGCOLOR, (joined || watched) ? global->bg_green : global->bg_red,
1514 			-1);
1515 		}
1516 	}
1517 	else {
1518 		gchar *game = NULL;
1519 		gchar *gametype = (gchar*)xmlGetProp(cur, (xmlChar*)"gametype");
1520 
1521 		tmp = xmlGetProp(cur, (xmlChar*)"name");
1522 		if (tmp) {
1523 			if (id < 0) {
1524 				game = g_strdup_printf("Create new %s game", (gchar*)tmp);
1525 			} else {
1526 				game = g_strdup_printf("%s game %d", (gchar*)tmp, id);
1527 			}
1528 			g_free(tmp);
1529 		}
1530 
1531 		gtk_list_store_append(global->game_store, &iter);
1532 		gtk_list_store_set(global->game_store, &iter,
1533 		GAMELIST_COLUMN_HOST, c->host,
1534 		GAMELIST_COLUMN_VERSION, c->server_version,
1535 		GAMELIST_COLUMN_GAME, game,
1536 		GAMELIST_COLUMN_STATUS, status,
1537 		GAMELIST_COLUMN_PLAYERS, players,
1538 		GAMELIST_COLUMN_PORT, c->port,
1539 		GAMELIST_COLUMN_GAMETYPE, gametype,
1540 		GAMELIST_COLUMN_GAMEID, id,
1541 		GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1542 		GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1543 		GAMELIST_COLUMN_BGCOLOR, (canbejoined || canbewatched) ? global->bg_green : global->bg_red,
1544 		GAMELIST_COLUMN_SOURCE, GAMELIST_SOURCE_CUSTOM,
1545 		-1);
1546 
1547 		g_free(gametype);
1548 		g_free(game);
1549 	}
1550 
1551 	if(players) g_free(players);
1552 	if(status) g_free(status);
1553 }
1554 
1555 
xmlparse_gamelist_deletegame(connection * c,xmlDocPtr doc,xmlNodePtr cur)1556 void xmlparse_gamelist_deletegame(connection *c, xmlDocPtr doc, xmlNodePtr cur) {
1557 	xmlChar *tmp;
1558 	gint32 id;
1559 	GtkTreeIter iter;
1560 	gboolean valid;
1561 	(void)doc;
1562 	(void)c;
1563 
1564 	tmp = xmlGetProp(cur, (xmlChar*)"gameid");
1565 	id = atoi((gchar*)tmp);
1566 	g_free(tmp);
1567 
1568 	valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1569 	while (valid) {
1570 		gint32 source;
1571 		gint32 eid;
1572 		GtkTreeIter curiter = iter;
1573 
1574 		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter); /* get next iter so we can remove the current entry safely */
1575 
1576 		gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &curiter, GAMELIST_COLUMN_GAMEID, &eid, GAMELIST_COLUMN_SOURCE, &source, -1);
1577 		if (eid == id && source == GAMELIST_SOURCE_CUSTOM)  {
1578 			gtk_list_store_remove(global->game_store, &curiter);
1579 		}
1580 	}
1581 }
1582 
1583 
xmlparse_metaserver(connection * c,gchar * buffer)1584 void xmlparse_metaserver(connection *c, gchar *buffer) {
1585 
1586 	xmlChar *tmp;
1587 	xmlDocPtr doc;
1588 	xmlNodePtr cur, cur2;
1589 	(void)c;
1590 
1591 	doc = xmlParseMemory(buffer,  strlen(buffer) );
1592 	if(doc == NULL)  return;
1593 
1594 	cur = xmlDocGetRootElement(doc);
1595 	if (cur == NULL) {
1596 		xmlFreeDoc(doc);
1597 		return;
1598 	}
1599 
1600 	if( xmlStrcmp(cur->name, METASERVER_XMLROOTELEMENT) )  {
1601 		xmlFreeDoc(doc);
1602 		return;
1603 	}
1604 
1605 	for(cur = cur->xmlChildrenNode ; cur != NULL ; cur = cur -> next)  {
1606 
1607 		if(! xmlStrcmp(cur->name, (xmlChar*)"metaserver") )  {
1608 			gchar *text;
1609 
1610 			tmp = xmlGetProp(cur, (xmlChar*)"version");
1611 			text = g_strdup_printf("Atlantic metaserver version %s", tmp);
1612 			g_free(tmp);
1613 			interface_set_infolabel(text, "008000", false);
1614 			g_free(text);
1615 		}
1616 
1617 		if(! xmlStrcmp(cur->name, (xmlChar*)"msg") )  {
1618 			gchar *text;
1619 
1620 			tmp = xmlGetProp(cur, (xmlChar*)"value");
1621 			text = g_strdup_printf("%s", tmp);
1622 			g_free(tmp);
1623 			interface_create_messagewin(text);
1624 			g_free(text);
1625 		}
1626 
1627 		if(!xmlStrcmp(cur->name, (xmlChar*)"server") )  {
1628 			gint32 serverid, users = -1;
1629 			GtkTreeIter serveriter;
1630 			bool valid, update = false;
1631 
1632 			tmp = xmlGetProp(cur, (xmlChar*)"id");
1633 			if (!tmp) {
1634 				continue;
1635 			}
1636 			serverid = atoi((gchar*)tmp);
1637 			g_free(tmp);
1638 
1639 			/* lookup if server already exist */
1640 			valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->server_store), &serveriter);
1641 			while (valid) {
1642 				gint32 eid;
1643 
1644 				gtk_tree_model_get(GTK_TREE_MODEL(global->server_store), &serveriter, SERVERLIST_COLUMN_SERVERID, &eid, -1);
1645 				if (eid == serverid) {
1646 					update = true;
1647 					break;
1648 				}
1649 
1650 				valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->server_store), &serveriter);
1651 			}
1652 
1653 			tmp = xmlGetProp(cur, (xmlChar*)"users");
1654 			if (tmp) {
1655 				users = atoi((gchar*)tmp);
1656 				g_free(tmp);
1657 
1658 				if (update == true) {
1659 					gtk_list_store_set(global->server_store, &serveriter,
1660 					  SERVERLIST_COLUMN_USERS, users,
1661 					  -1);
1662 				}
1663 			}
1664 
1665 			if (update == false) {
1666 				gchar *host, *version;
1667 				gint32 port = -1;
1668 
1669 				host = (gchar*)xmlGetProp(cur, (xmlChar*)"host");
1670 
1671 				tmp = xmlGetProp(cur, (xmlChar*)"port");
1672 				if (tmp) {
1673 					port = atoi((gchar*)tmp);
1674 					g_free(tmp);
1675 				}
1676 				version = (gchar*)xmlGetProp(cur, (xmlChar*)"version");
1677 
1678 				if (! (host && version && port >= 0 && users >= 0)) {
1679 					continue;
1680 				}
1681 
1682 				gtk_list_store_append(global->server_store, &serveriter);
1683 				gtk_list_store_set(global->server_store, &serveriter,
1684 				  SERVERLIST_COLUMN_HOST, host,
1685 				  SERVERLIST_COLUMN_PORT, port,
1686 				  SERVERLIST_COLUMN_VERSION, version,
1687 				  SERVERLIST_COLUMN_USERS, users,
1688 				  SERVERLIST_COLUMN_SERVERID, serverid,
1689 				  -1);
1690 
1691 				g_free(host);
1692 				g_free(version);
1693 			}
1694 
1695 			for(cur2 = cur->xmlChildrenNode ; cur2 != NULL ; cur2 = cur2 -> next )  {
1696 
1697 				if (!xmlStrcmp(cur2->name, (xmlChar*)"game") )  {
1698 					gchar *players;
1699 					gint32 gameid;
1700 					GtkTreeIter iter;
1701 					bool valid, update = false;
1702 					gchar *status = NULL;
1703 					gint32 canbejoined = -1, canbewatched = -1;
1704 
1705 					/* ONLY TEMPORARY ! */
1706 					tmp = xmlGetProp(cur2, (xmlChar*)"gametype");
1707 					if (tmp && xmlStrcmp(tmp, (xmlChar*)"city") && xmlStrcmp(tmp, (xmlChar*)"french_city") )  {
1708 						g_free(tmp);
1709 						continue;
1710 					}
1711 
1712 					tmp = xmlGetProp(cur2, (xmlChar*)"id");
1713 					if (!tmp) {
1714 						continue;
1715 					}
1716 					gameid = atoi((gchar*)tmp);
1717 					g_free(tmp);
1718 
1719 					/* lookup if gameid on same server already exist */
1720 					if (gameid > 0) {
1721 						valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1722 						while (valid) {
1723 							gint32 source;
1724 							gint32 egameid, eserverid;
1725 
1726 							gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_GAMEID, &egameid, GAMELIST_COLUMN_SERVERID, &eserverid, GAMELIST_COLUMN_SOURCE, &source, -1);
1727 							if (source == GAMELIST_SOURCE_METASERVER && egameid == gameid && eserverid == serverid)  {
1728 								update = true;
1729 								break;
1730 							}
1731 
1732 							valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter);
1733 						}
1734 					}
1735 
1736 					tmp = xmlGetProp(cur2, (xmlChar*)"turn");
1737 					if(tmp) {
1738 						int turn = atoi((gchar*)tmp);
1739 						g_free(tmp);
1740 
1741 						if (turn >= 1) {
1742 							status = g_strdup_printf("Playing, turn %d", turn);
1743 						}
1744 					}
1745 
1746 					tmp = xmlGetProp(cur2, (xmlChar*)"status");
1747 					if(tmp) {
1748 						if (!xmlStrcmp(tmp, (xmlChar*)"config") ) {
1749 							if (status) {
1750 								g_free(status);
1751 							}
1752 							status = g_strdup("Waiting for players");
1753 						}
1754 						else if (!xmlStrcmp(tmp, (xmlChar*)"end") ) {
1755 							if (status) {
1756 								g_free(status);
1757 							}
1758 							status = g_strdup("Finished");
1759 						}
1760 
1761 						g_free(tmp);
1762 					}
1763 
1764 					// game template
1765 					if (gameid < 0) {
1766 						canbejoined = true;
1767 						canbewatched = false;
1768 					}
1769 					tmp = xmlGetProp(cur2, (xmlChar*)"canbejoined");
1770 					if (tmp) {
1771 						canbejoined = atoi((gchar*)tmp);
1772 						g_free(tmp);
1773 					}
1774 
1775 					tmp = xmlGetProp(cur2, (xmlChar*)"canbewatched");
1776 					if (tmp) {
1777 						canbewatched = atoi((gchar*)tmp);
1778 						g_free(tmp);
1779 					}
1780 
1781 					players = (gchar*)xmlGetProp(cur2, (xmlChar*)"players");
1782 
1783 					if (update) {
1784 						if (status) {
1785 							gtk_list_store_set(global->game_store, &iter,
1786 							GAMELIST_COLUMN_STATUS, status,
1787 							-1);
1788 						}
1789 
1790 						if (players) {
1791 							gtk_list_store_set(global->game_store, &iter,
1792 							GAMELIST_COLUMN_PLAYERS, players,
1793 							-1);
1794 						}
1795 
1796 						if (canbejoined >= 0) {
1797 							gtk_list_store_set(global->game_store, &iter,
1798 							GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1799 							-1);
1800 						}
1801 
1802 						if (canbewatched >= 0) {
1803 							gtk_list_store_set(global->game_store, &iter,
1804 							GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1805 							-1);
1806 						}
1807 
1808 						if (canbejoined >= 0 || canbewatched >= 0) {
1809 							gint32 joined, watched;
1810 
1811 							gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_CANBEJOINED, &joined, GAMELIST_COLUMN_CANBEWATCHED, &watched, -1);
1812 							gtk_list_store_set(global->game_store, &iter,
1813 							GAMELIST_COLUMN_BGCOLOR, (joined || watched) ? global->bg_green : global->bg_red,
1814 							-1);
1815 						}
1816 					}
1817 					else {
1818 						gchar *host, *version, *game, *gametype;
1819 						gint32 port;
1820 
1821 						tmp = xmlGetProp(cur2, (xmlChar*)"name");
1822 						if (!tmp) {
1823 							continue;
1824 						}
1825 						if(gameid < 0) {
1826 							game = g_strdup_printf("Create new %s game", (gchar*)tmp);
1827 						} else {
1828 							game = g_strdup_printf("%s game %d", (gchar*)tmp, gameid);
1829 						}
1830 						g_free(tmp);
1831 
1832 						gametype = (gchar*)xmlGetProp(cur2, (xmlChar*)"gametype");
1833 
1834 						gtk_tree_model_get(GTK_TREE_MODEL(global->server_store), &serveriter,
1835 						  SERVERLIST_COLUMN_HOST, &host,
1836 						  SERVERLIST_COLUMN_PORT, &port,
1837 						  SERVERLIST_COLUMN_VERSION, &version,
1838 						  -1);
1839 
1840 						gtk_list_store_append(global->game_store, &iter);
1841 						gtk_list_store_set(global->game_store, &iter,
1842 						  GAMELIST_COLUMN_HOST, host,
1843 						  GAMELIST_COLUMN_VERSION, version,
1844 						  GAMELIST_COLUMN_GAME, game,
1845 						  GAMELIST_COLUMN_STATUS, status,
1846 						  GAMELIST_COLUMN_PLAYERS, players,
1847 						  GAMELIST_COLUMN_PORT, port,
1848 						  GAMELIST_COLUMN_GAMETYPE, gametype,
1849 						  GAMELIST_COLUMN_GAMEID, gameid,
1850 						  GAMELIST_COLUMN_SERVERID, serverid,
1851 						  GAMELIST_COLUMN_CANBEJOINED, canbejoined,
1852 						  GAMELIST_COLUMN_CANBEWATCHED, canbewatched,
1853 						  GAMELIST_COLUMN_BGCOLOR, (canbejoined || canbewatched) ? global->bg_green : global->bg_red,
1854 						  GAMELIST_COLUMN_SOURCE, GAMELIST_SOURCE_METASERVER,
1855 						  -1);
1856 
1857 						g_free(host);
1858 						g_free(version);
1859 						g_free(game);
1860 						g_free(gametype);
1861 					}
1862 
1863 					if (players) g_free(players);
1864 					if (status) g_free(status);
1865 				}
1866 				else if (!xmlStrcmp(cur2->name, (xmlChar*)"deletegame") )  {
1867 					gint32 gameid;
1868 					GtkTreeIter iter;
1869 					bool valid;
1870 
1871 					tmp = xmlGetProp(cur2, (xmlChar*)"id");
1872 					if (!tmp) {
1873 						continue;
1874 					}
1875 					gameid = atoi((gchar*)tmp);
1876 					g_free(tmp);
1877 
1878 					valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1879 					while (valid) {
1880 						gint32 source;
1881 						gint32 egameid, eserverid;
1882 
1883 						gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &iter, GAMELIST_COLUMN_GAMEID, &egameid, GAMELIST_COLUMN_SERVERID, &eserverid, GAMELIST_COLUMN_SOURCE, &source, -1);
1884 						if (source == GAMELIST_SOURCE_METASERVER && egameid == gameid && eserverid == serverid)  {
1885 							gtk_list_store_remove(global->game_store, &iter);
1886 							break;
1887 						}
1888 
1889 						valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter);
1890 					}
1891 				}
1892 			}
1893 		}
1894 		else if(!xmlStrcmp(cur->name, (xmlChar*)"deleteserver") )  {
1895 			gint32 id;
1896 			GtkTreeIter iter;
1897 			bool valid;
1898 
1899 			tmp = xmlGetProp(cur, (xmlChar*)"id");
1900 			if (!tmp) {
1901 				continue;
1902 			}
1903 			id = atoi((gchar*)tmp);
1904 			g_free(tmp);
1905 
1906 			valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->server_store), &iter);
1907 			while (valid) {
1908 				gint32 eid;
1909 
1910 				gtk_tree_model_get(GTK_TREE_MODEL(global->server_store), &iter, SERVERLIST_COLUMN_SERVERID, &eid, -1);
1911 				if (eid == id) {
1912 					gtk_list_store_remove(global->server_store, &iter);
1913 					break;
1914 				}
1915 
1916 				valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->server_store), &iter);
1917 			}
1918 
1919 			valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(global->game_store), &iter);
1920 			while (valid) {
1921 				gint32 source;
1922 				gint32 eid;
1923 				GtkTreeIter curiter = iter;
1924 
1925 				valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(global->game_store), &iter); /* get next iter so we can safely remove the current entry */
1926 
1927 				gtk_tree_model_get(GTK_TREE_MODEL(global->game_store), &curiter, GAMELIST_COLUMN_SERVERID, &eid, GAMELIST_COLUMN_SOURCE, &source, -1);
1928 				if (source == GAMELIST_SOURCE_METASERVER && eid == id)  {
1929 					gtk_list_store_remove(global->game_store, &curiter);
1930 				}
1931 			}
1932 		}
1933 
1934 	}
1935 
1936 	xmlFreeDoc(doc);
1937 }
1938