/************************************************************************** Returns a string which list all available plugins. You don't have to free the string. **************************************************************************/ const char *audio_get_all_plugin_names() { static char buffer[100]; int i; sz_strlcpy(buffer, "["); for (i = 0; i < num_plugins_used; i++) { sz_strlcat(buffer, plugins[i].name); if (i != num_plugins_used - 1) { sz_strlcat(buffer, ", "); } } sz_strlcat(buffer, "]"); return buffer; }
/**************************************************************** if the client is capable of 'wanting hack', then the server will send the client a filename in the packet_join_game_reply packet. this function creates the file with a suitably random string in it and then sends the string to the server. If the server can open and read the string, then the client is given hack access. *****************************************************************/ void send_client_wants_hack(const char *filename) { if (filename[0] != '\0') { struct packet_single_want_hack_req req; struct section_file *file; if (!is_safe_filename(filename)) { return; } /* get the full filename path */ interpret_tilde(challenge_fullname, sizeof(challenge_fullname), "~/.freeciv/"); make_dir(challenge_fullname); sz_strlcat(challenge_fullname, filename); /* generate an authentication token */ randomize_string(req.token, sizeof(req.token)); file = secfile_new(FALSE); secfile_insert_str(file, req.token, "challenge.token"); if (!secfile_save(file, challenge_fullname, 0, FZ_PLAIN)) { log_error("Couldn't write token to temporary file: %s", challenge_fullname); } secfile_destroy(file); /* tell the server what we put into the file */ send_packet_single_want_hack_req(&client.conn, &req); } }
/************************************************************************* Writes buf to socket and returns the response in an fz_FILE. Use only on blocking sockets. *************************************************************************/ fz_FILE *fc_querysocket(int sock, void *buf, size_t size) { FILE *fp; #ifdef HAVE_FDOPEN fp = fdopen(sock, "r+b"); if (fwrite(buf, 1, size, fp) != size) { log_error("socket %d: write error", sock); } fflush(fp); /* we don't use fc_closesocket on sock here since when fp is closed * sock will also be closed. fdopen doesn't dup the socket descriptor. */ #else /* HAVE_FDOPEN */ { char tmp[4096]; int n; #ifdef WIN32_NATIVE /* tmpfile() in mingw attempts to make a temp file in the root directory * of the current drive, which we may not have write access to. */ { char filename[MAX_PATH]; GetTempPath(sizeof(filename), filename); sz_strlcat(filename, "fctmp"); fp = fc_fopen(filename, "w+b"); } #else /* WIN32_NATIVE */ fp = tmpfile(); #endif /* WIN32_NATIVE */ if (fp == NULL) { return NULL; } fc_writesocket(sock, buf, size); while ((n = fc_readsocket(sock, tmp, sizeof(tmp))) > 0) { if (fwrite(tmp, 1, n, fp) != n) { log_error("socket %d: write error", sock); } } fflush(fp); fc_closesocket(sock); rewind(fp); } #endif /* HAVE_FDOPEN */ return fz_from_stream(fp); }
/**************************************************************************** Give technologies to players with EFT_TECH_PARASITE (traditionally from the Great Library). ****************************************************************************/ void do_tech_parasite_effect(struct player *pplayer) { int mod; struct effect_list *plist = effect_list_new(); /* Note that two EFT_TECH_PARASITE effects will combine into a single, * much worse effect. */ if ((mod = get_player_bonus_effects(plist, pplayer, EFT_TECH_PARASITE)) > 0) { char buf[512]; buf[0] = '\0'; effect_list_iterate(plist, peffect) { if (buf[0] != '\0') { sz_strlcat(buf, ", "); } get_effect_req_text(peffect, buf, sizeof(buf)); } effect_list_iterate_end; advance_index_iterate(A_FIRST, i) { if (player_invention_reachable(pplayer, i) && player_invention_state(pplayer, i) != TECH_KNOWN) { int num_players = 0; players_iterate(aplayer) { if (player_invention_state(aplayer, i) == TECH_KNOWN) { num_players++; } } players_iterate_end; if (num_players >= mod) { notify_player(pplayer, NULL, E_TECH_GAIN, FTC_SERVER_INFO, NULL, _("%s acquired from %s!"), advance_name_for_player(pplayer, i), buf); notify_embassies(pplayer, NULL, NULL, E_TECH_GAIN, FTC_SERVER_INFO, NULL, _("The %s have acquired %s from %s."), nation_plural_for_player(pplayer), advance_name_for_player(pplayer, i), buf); do_free_cost(pplayer, i); found_new_tech(pplayer, i, FALSE, TRUE); script_signal_emit("tech_researched", 3, API_TYPE_TECH_TYPE, advance_by_number(i), API_TYPE_PLAYER, pplayer, API_TYPE_STRING, "stolen"); break; } } } advance_index_iterate_end;
/************************************************************************** Refresh info label **************************************************************************/ void update_info_label(void) { GtkWidget *label; const struct player *pplayer = client.conn.playing; label = gtk_frame_get_label_widget(GTK_FRAME(main_frame_civ_name)); if (pplayer != NULL) { const gchar *name; gunichar c; /* Capitalize the first character of the translated nation * plural name so that the frame label looks good. */ name = nation_plural_for_player(pplayer); c = g_utf8_get_char_validated(name, -1); if ((gunichar) -1 != c && (gunichar) -2 != c) { gchar nation[MAX_LEN_NAME]; gchar *next; gint len; len = g_unichar_to_utf8(g_unichar_toupper(c), nation); nation[len] = '\0'; next = g_utf8_find_next_char(name, NULL); if (NULL != next) { sz_strlcat(nation, next); } gtk_label_set_text(GTK_LABEL(label), nation); } else { gtk_label_set_text(GTK_LABEL(label), name); } } else { gtk_label_set_text(GTK_LABEL(label), "-"); } gtk_label_set_text(GTK_LABEL(main_label_info), get_info_label_text(!gui_gtk3_small_display_layout)); set_indicator_icons(client_research_sprite(), client_warming_sprite(), client_cooling_sprite(), client_government_sprite()); if (NULL != client.conn.playing) { int d = 0; for (; d < client.conn.playing->economic.luxury /10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_LUXURY); gtk_pixcomm_set_from_sprite(GTK_PIXCOMM(econ_label[d]), sprite); } for (; d < (client.conn.playing->economic.science + client.conn.playing->economic.luxury) / 10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_SCIENCE); gtk_pixcomm_set_from_sprite(GTK_PIXCOMM(econ_label[d]), sprite); } for (; d < 10; d++) { struct sprite *sprite = get_tax_sprite(tileset, O_GOLD); gtk_pixcomm_set_from_sprite(GTK_PIXCOMM(econ_label[d]), sprite); } } update_timeout_label(); /* update tooltips. */ gtk_widget_set_tooltip_text(econ_ebox, _("Shows your current luxury/science/tax rates; " "click to toggle them.")); gtk_widget_set_tooltip_text(bulb_ebox, get_bulb_tooltip()); gtk_widget_set_tooltip_text(sun_ebox, get_global_warming_tooltip()); gtk_widget_set_tooltip_text(flake_ebox, get_nuclear_winter_tooltip()); gtk_widget_set_tooltip_text(government_ebox, get_government_tooltip()); }