/* Copyright (C) 2000-2003 Markus Lausser (sgop@users.sf.net) This is free software distributed under the terms of the GNU Public License. See the file COPYING for details. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBLCONV_H #include #endif #include "lopster.h" #include "callbacks.h" #include "support.h" #include "connection.h" #include "global.h" #include "commands.h" #include "handler.h" #include "dialog.h" #include "share2.h" #include "hotlist.h" #include "resume.h" #include "search.h" #include "chat.h" #include "log.h" #include "interface.h" #include "whois.h" #include "server.h" #include "irc.h" #include "napster.h" #include "utils.h" #include "buffer.h" static net_group_t* st_ng = NULL; static int napi_busy = 0; static GtkCTree* ctree = NULL; static GList* my_net_list = NULL; // list for net popup GtkWidget* create_user_passwd (net_t* network); int server_check(gpointer data); int napigator_restart_update(gpointer data) { (void)data; if (global.naplist.timer >= 0) gtk_timeout_remove(global.naplist.timer); if (global.naplist.auto_update > 0) { napigator_get_list(); global.naplist.timer = gtk_timeout_add(global.naplist.auto_update * 60 * 1000, napigator_restart_update, NULL); } return 1; } server_t *server_new() { server_t *server; server = g_malloc(sizeof(server_t)); server->address = NULL; server->port = 0; server->users = server->files = server->gigs = 0; server->status = SERVER_OFFLINE; server->flags = 0; server->net = NULL; server->ip = INADDR_NONE; server->timeout = -1; server->linespeed = 0; server->node = NULL; return server; } void server_set_status(server_t* server, int status, char* message) { GtkCTreeNode* node; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); node = server->node; if (!node) return; if (message) gtk_ctree_node_set_text(ctree, node, 2, message); if (server->status != status) { server->status = status; server_update(server); network_update(server->net, 1); net_group_update(server->net->group); } } void on_channel_list(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; channel_list_get(net); } void on_global_list(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; show_global_users(net, NULL); } void on_banned_users(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; show_bans(net, NULL); } void on_client_list(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; show_clients(net); } static void send_usermode(net_t* net) { int i1; char str[1024]; char* pos = str; int mask = 0; if (net->subtype >= 0) mask = ModeMask[net->subtype]; *pos = 0; for (i1 = 0; i1 < MODE_NUMBER; i1++) { if ((mask & (1< 0) *pos++ = ' '; if (global.usermode & (1<subtype != N_OPENNAP_NG && net->subtype != N_OPENNAP) *pos++ = '+'; } else { *pos++ = '-'; } strcpy(pos, ModeNames[i1]); pos += strlen(ModeNames[i1]); } if (*str != 0) command_send(net, CMD_SET_USER_MODE, str); } int network_success(net_t* net) { GList *dlist; hot_t *hot; chat_page_t *page; server_t *server; server = net->active_server; if (!server) { g_warning("network has no active server"); return 0; } net->socket->max_cnt = SERVER_TIMEOUT; server_set_status(server, SERVER_ONLINE, "Online"); global.net_active = g_list_append(global.net_active, net); net->cur_searches = 0; net->skip_search_end = 0; net->user.level = L_USER; net->user.status = STATUS_ACTIVE; if (net->success && !net->success(net)) return 0; // activate some chat pages and printing server join message for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; if (!page->net) continue; if (page->net != net) continue; // only rejoin here, if channel is not in autojoin list // otherwise we would try to join twice if (page->type == P_PUBLIC) { if (global.options.channel_rejoin && !is_string_in_list(net->auto_join, page->name)) join_channel(page->net, page->name); } else if (page->type != P_PRIVATE) { chat_page_set_active(page, 1); } } network_autojoin_channels(net); for (dlist = global.hotlist; dlist; dlist = dlist->next) { hot = dlist->data; command_send(net, CMD_ADD_HOTLIST_SEQ, hot->user); } if (net->subtype != -1) network_go(net); return 1; } void network_reset(net_t* net) { GList *dlist; chat_page_t *page; hot_t *hot; search_t* search; /* user_timestamp_t *stamp; // clear recent list for (dlist = global.appearance; dlist; dlist = dlist->next) { stamp = (user_timestamp_t *) (dlist->data); if (stamp->user) g_free(stamp->user); g_free(stamp); } g_list_free(global.appearance); global.appearance = NULL; for (dlist = global.userstamp; dlist; dlist = dlist->next) { stamp = (user_timestamp_t *) (dlist->data); if (stamp->user) g_free(stamp->user); g_free(stamp); } g_list_free(global.userstamp); global.userstamp = NULL; */ // inactivate chat pages for (dlist = global.chat_pages; dlist; dlist = dlist->next) { page = dlist->data; if (page->net == net) { chat_page_set_active(page, 0); if (page->type == P_PUBLIC) chat_page_set_op(page, 0); } } if (NET_CONNECTED(net)) { // reset hotlist dlist = global.hotlist; while (dlist) { hot = dlist->data; dlist = dlist->next; hotlist_user_offline(net, hot); } // close logs only when connected, otherwise every "server full" // message would trigger a new log session close_logs(net); whois_remove_network(net); speed_remove_network(net); // unsharing library (important to remove server from library) lib_unshare_all_network(global.lib, net); // channel_list_clear(net); // freeing server links network_links_free(net, 0); // finish active searches while (net->active_searches) { search = net->active_searches->data; search_finish(search, net, 0); } net->cur_searches = 0; // no need to, is reset after 60 seconds automatically // net->search_cnt = 0; // deleting queued searches; for (dlist = net->queued_searches; dlist; dlist = dlist->next) { search = dlist->data; search_info_remove(search, net); if (search->resume) ((resume_t*)(search->link))->needs_update = 1; } g_list_free(net->queued_searches); net->queued_searches = NULL; // removing search results from search /* for (dlist = global.searches; dlist; dlist = dlist->next) { search = dlist->data; search_clear_old(search, net); } */ } // clear queues if (net->in_buffer) buffer_clear(net->in_buffer); if (net->out_buffer) buffer_clear(net->out_buffer); if (net->temp_buffer) buffer_clear(net->temp_buffer); set_user_level(net, L_USER); } int server_banned(char* message) { char* pos; if (!message) return 0; // dont try to reconnect if banned. if (!strncmp("You are banned", message, 14)) return 1; pos = strchr(message, ' '); if (pos && !strncmp(pos+1, "banned", 6)) return 1; return 0; } int auto_reconnect(gpointer data) { server_t* server = data; gtk_timeout_remove(server->timeout); server->timeout = -1; server_set_status(server, SERVER_OFFLINE, "Ready to connect"); return 1; } static void server_destroy(server_t* server) { if (server->timeout >= 0) gtk_timeout_remove(server->timeout); if (server->address) g_free(server->address); g_free(server); } static void network_remove_server(net_t* net, server_t* server) { if (!net || !server) return; server_hide(server); net->servers = g_list_remove(net->servers, server); server->net = NULL; } int server_disconnect(server_t* server, char* reason, int relogin) { socket_t* socket; net_t* net; int banned; net_group_t* ng; if (!server || !server->net) return 1; if (server->net->active_server != server) return 0; net = server->net; socket = net->socket; if (!socket) { g_warning("server_disconnect(): net has no socket"); return 0; } global.net_active = g_list_remove(global.net_active, net); network_reset(net); #ifdef HAVE_ZLIB if (net->compress) { /* printf ( "[ZLIB] [%s] destroying compression\n", net->name); */ if (socket->zout && deflateEnd (socket->zout) != Z_OK) { /* printf ("[ZLIB] [%s] deflateEnd: %s\n", net->name, socket->zout->msg); */ } if (socket->zin && inflateEnd (socket->zin) != Z_OK) { /* printf ("[ZLIB] [%s] inflateEnd: %s\n", net->name, socket->zin->msg); */ } if (socket->zin) free(socket->zin); if (socket->zout) free(socket->zout); buffer_destroy(socket->zbuf); buffer_destroy(socket->zcom); socket->zin = NULL; socket->zout = NULL; socket->zbuf = NULL; socket->zcom = NULL; net->compress = 0; } #endif net->sent_compressed = 0; net->sent_uncompressed = 0; net->rcvd_compressed = 0; net->rcvd_uncompressed = 0; net->active_server = NULL; socket_destroy(socket, 0); net->socket = NULL; server_update_stats(); server_set_status(server, SERVER_CANCELED, reason); search_remove_network(net); if (server->timeout >= 0) { gtk_timeout_remove(server->timeout); server->timeout = 0; } banned = server_banned(reason); if (relogin && !banned) { server->timeout = gtk_timeout_add(60000, auto_reconnect, server); } if (banned && strcmp(net->group->name, "Banned Networks")) { ng = net_group_create("Banned Networks", NG_NEVER_CONNECT, 0); network_move(net, ng); } return 0; } #ifdef HAVE_ZLIB static int buffer_compress(buffer_t *b, z_streamp zip, buffer_t* ib) { int n; /* set up the input */ zip->next_in = (unsigned char *) ib->data; zip->avail_in = ib->datasize; zip->next_out = (unsigned char *) b->data + b->datasize; zip->avail_out = b->datamax - b->datasize; // we do not resize the compressed buffer while (zip->avail_in > 0 && zip->avail_out > 0) { n = deflate (zip, Z_SYNC_FLUSH); if (n != Z_OK) { printf ("buffer_compress: deflate: %s (error %d)\n", zip->msg, n); return -1; } } b->datasize = b->datamax - zip->avail_out; buffer_consume(ib, ib->datasize - zip->avail_in); return 0; } #endif static long server_up_calc_max() { long m1; long bytes; int act_limit = global.up_width.limit; bytes = global.up_width.bytes[0] + global.up_width.bytes[1]; // check global limit if (bytes >= act_limit) { return 0; } else { m1 = act_limit - bytes; } // set max bytes if (global.net_active) { act_limit /= g_list_length(global.net_active)*2; } else { // should never happen act_limit /= 2; } if (act_limit > 10240) act_limit = 10240; if (m1 > act_limit) m1 = act_limit; return m1; } static void net_copy_some_unimportant(net_t* net) { int max_copy = 10240; buffer_t* src; buffer_t* dest; src = net->temp_buffer; // cannot be NULL if (!net->out_buffer) net->out_buffer = buffer_new(4048); dest = net->out_buffer; while (max_copy > 0 && src->datasize-src->consumed > 4) { int size; memcpy(&size, src->data+src->consumed, sizeof(size)); buffer_consume_virt(src, sizeof(size)); if (size > src->datasize-src->consumed) { g_warning("internal temp buffer error"); buffer_clear(src); return; } buffer_need_space(dest, size); memcpy(dest->data+dest->datasize, src->data+src->consumed, size); dest->datasize += size; buffer_consume_virt(src, size); max_copy -= size; } buffer_consume(src, src->consumed); // reduce memory usage if (src->datamax > 4096 && src->datasize < 2048) buffer_resize(src, 4096-src->datamax); } gboolean net_has_outgoing(net_t* net) { if (net->out_buffer && net->out_buffer->datasize) return TRUE; if (net->temp_buffer && net->temp_buffer->datasize) return TRUE; return FALSE; } gint server_send(gpointer data, gint source ATTR_UNUSED, GdkInputCondition condition) { int sent = 0; socket_t *socket = data; net_t* net = socket->data; buffer_t* buffer; int real_sent; int dataleft; long maxpush; if (condition != GDK_INPUT_WRITE) { server_disconnect(net->active_server, "Could not send data to server", 1); return 1; } if (!net_has_outgoing(net) || (maxpush = server_up_calc_max()) <= 0) { gtk_input_remove(socket->output); socket->output = -1; return 1; } if (net->out_buffer && net->out_buffer->datasize == 0) { net_copy_some_unimportant(net); } buffer = net->out_buffer; #ifdef HAVE_ZLIB if (net->compress) { sent = buffer->datasize; if (sent > 0 && buffer_compress(socket->zcom, socket->zout, buffer) != 0) { printf("*** [ZLIB] [%s] compression error\n", net->name); server_disconnect(net->active_server, "Compression error", 1); return 1; } if (socket->zcom->datasize > 0) { if (socket->zcom->datasize < maxpush) maxpush = socket->zcom->datasize; real_sent = send_safe(socket->fd, socket->zcom->data, 1, maxpush); if (real_sent < 0) { printf("[to server] could not send command\n"); return 1; } buffer_consume(socket->zcom, real_sent); } else { real_sent = 0; } sent -= buffer->datasize; dataleft = (socket->zcom->datasize>0); } else { #endif if (buffer->datasize > 0) { if (maxpush > buffer->datasize) maxpush = buffer->datasize; real_sent = send_safe(socket->fd, buffer->data, 1, maxpush); if (real_sent < 0) { printf("[to server] could not send command\n"); return 1; } buffer_consume(buffer, real_sent); } else { real_sent = 0; } sent = real_sent; dataleft = 0; #ifdef HAVE_ZLIB } #endif // if (real_sent > 0) socket->cnt = 0; if (buffer->datasize < 4096 && buffer->datamax > 4096) { // free some buffer space buffer_resize(buffer, 4096-buffer->datamax); } net->sent_compressed += real_sent; net->sent_uncompressed += sent; global.up_width.bytes[1] += real_sent; if (!dataleft && !net_has_outgoing(net)) { gtk_input_remove(socket->output); socket->output = -1; } return 1; } void network_go(net_t* net) { GList* dlist; int i1; if (!net->socket) return; if (net->socket->output == -1) { net->socket->output = gdk_input_add(net->socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(server_send), net->socket); } send_usermode(net); update_status_line(0); setup_search_fields(); // try to share 100 files more than the last time was allowed. if (net->max_share > 0) net->max_share += 100; // now do all the sharing stuff lib_share(global.lib, net); search_add_network(net); // search saved searches for (dlist = global.search_pattern; dlist; dlist = dlist->next) { search_pattern_t* pattern = dlist->data; if (pattern->level == PATTERN_SEARCH) { search_pattern_search(pattern, net); } } // updating download/upload counter on server for (i1 = 0; i1 < global.limit.cur_real_downloads; i1++) { command_send(net, CMD_DOWNLOAD_START); } for (i1 = 0; i1 < global.limit.cur_real_uploads; i1++) { command_send(net, CMD_UPLOAD_START); } // search all download files resume_search_all(net, 0); } #ifdef HAVE_ZLIB static int buffer_decompress (buffer_t* b, z_streamp zip, buffer_t* ib) { int n; zip->next_in = (unsigned char *) ib->data; zip->avail_in = ib->datasize; zip->next_out = (unsigned char *) b->data + b->datasize; zip->avail_out = b->datamax - b->datasize; do { /* if there is no more output space left, create some more */ if (zip->avail_out == 0) { if (!buffer_resize(b, 2048)) { printf ("[ZLIB] buffer_decompress: OUT OF MEMORY!!!\n"); return -1; } } zip->next_out = (unsigned char *) b->data + b->datasize; zip->avail_out = b->datamax - b->datasize; n = inflate (zip, Z_SYNC_FLUSH); if (n != Z_OK) { printf ("[ZLIB] buffer_decompress: inflate: %s (error %d)\n", zip->msg, n ); return -1; } // update the output buffer b->datasize = b->datamax - zip->avail_out; } while (zip->avail_in > 0); buffer_consume(ib, ib->datasize - zip->avail_in); return 0; } #endif int server_consume_command(net_t* net) { if (net->c_message) g_free(net->c_message); net->c_message = NULL; if (!net->in_buffer) return 0; if (net->in_buffer->datasize <= net->in_buffer->consumed) return 0; return net->consume_command(net); } static int server_receive(socket_t* socket) { int res; net_t* net = socket->data; buffer_t* buffer; #ifdef HAVE_ZLIB if (net->compress) buffer = socket->zbuf; else #endif buffer = net->in_buffer; res = recv(socket->fd, buffer->data + buffer->datasize, buffer->datamax - buffer->datasize, 0); switch (res) { case 0: server_disconnect(net->active_server, "Remote Close", 1); return 0; break; case -1: g_warning("1 recv error\n"); server_disconnect(net->active_server, strerror(errno), 1); return 0; } global.down_width.bytes[1] += res; buffer->datasize += res; net->rcvd_compressed += res; #ifdef HAVE_ZLIB if (net->compress) { net->rcvd_uncompressed -= net->in_buffer->datasize; if (buffer_decompress( net->in_buffer, socket->zin, buffer ) == -1) { printf("*** decompress error on %s\n", net->name); server_disconnect(net->active_server, "Decompression error", 1); return 0; } net->rcvd_uncompressed += net->in_buffer->datasize; } else { #endif net->rcvd_uncompressed += res; #ifdef HAVE_ZLIB } #endif return 1; } int server_get_input(gpointer data, gint source ATTR_UNUSED, GdkInputCondition condition) { int result; socket_t *socket = data; net_t* net = socket->data; if (condition != GDK_INPUT_READ) { server_disconnect(net->active_server, "Server read error", 1); return 1; } socket->cnt = 0; if (!server_receive(socket)) return 1; while (1) { result = server_consume_command(net); if (result == -1) return 1; // server disconnected else if (result == 0) break; // no command avail #ifdef HAVE_LIBLCONV_H if (global.options.use_iconv) { char* lconv_buf; if (net->codeset && *(net->codeset)) lconv_buf = lconv_strdup_conv(LCONV_SPEC, local_codeset, net->codeset, net->c_message); else lconv_buf = lconv_strdup_conv(LCONV_SPEC, local_codeset, global.options.dest_codeset, net->c_message); /* must copy lconv_buf again, cause c_message must be * allocated with g_malloc since it is freed with g_free() */ g_free(net->c_message); net->c_message = g_strdup(lconv_buf); free(lconv_buf); } #endif net->handle_command(net); // check whether handler disconnected server. // should be unneccesary here, cause server_disconnect() clears // the in_buffer and server_consume_command() would return NULL if (net->socket != socket) return 1; } buffer_consume(net->in_buffer, net->in_buffer->consumed); if (net->in_buffer->datasize >= 4096) { server_disconnect(net->active_server, "Too long command sent by sever", 1); return 1; } return 1; } void server_connect_direct(net_t* net) { socket_t* socket; server_t* server; if (!net || !net->socket) { g_warning("net has no socket\n"); return; } socket = net->socket; server = net->active_server; if (!connect_socket(socket, "TCP", SOCK_STREAM)) { server->ip = INADDR_NONE; server_disconnect(server, "Connection error", 0); return; } socket->cnt = 0; if (!net->in_buffer) net->in_buffer = buffer_new(4069); net->login(socket); } int get_best_server_read(gpointer data, gint source ATTR_UNUSED, GdkInputCondition condition) { int length; socket_t *socket; unsigned char buffer[128]; char *pos; server_t *server; server_t *server2; net_t* net; socket = (socket_t *) data; net = socket->data; server = net->active_server; if (condition != GDK_INPUT_READ) { server->ip = INADDR_NONE; server_disconnect(server, "Connection error", 0); return 1; } gdk_input_remove(socket->input); socket->input = -1; if ((length = recv(socket->fd, buffer, 127, 0)) <= 0) { server_disconnect(server, "Could not get redirect server", 0); return 1; } buffer[length] = '\0'; #ifdef CONNECTION_DEBUG printf("got server %s\n", buffer); #endif pos = strchr(buffer, ':'); if (!pos){ server_disconnect(server, "Could not get redirect server", 0); return 1; } *(pos++) = '\0'; if (strcmp(buffer, "127.0.0.1")) { server2 = network_search_server(net, buffer); if (!server2) { server2 = server_new(); server_set_address(server2, buffer); server2->port = atoi(pos); //server_set_description(server2, "from Metaserver"); network_add_server(net, server2); } else { server2->port = atoi(pos); server_update(server2); } if (!server_disconnect(server, NULL, 0)) // server was not destroyed // need to call server_set_status() cause server_disconnect() // sets status to SERVER_CANCELED server_set_status(server, SERVER_OFFLINE, "Redirect"); #ifdef CONNECTION_DEBUG printf("redirect to %s %d\n", server2->address, server2->port); #endif if (!(server2->flags & SERVER_IGNORE)) server_connect(server2); } else { server_disconnect(server,"All Servers busy",0); } return 1; } void server_connect_redirect(net_t* net) { socket_t* socket; // should never happen, cause caller has to take care // about that stuff, ...so print warning if (!net || !net->socket || !net->active_server) { g_warning("tried to connect to invalid net"); server_disconnect(net->active_server, "Internal Error", 0); return; } socket = net->socket; if (!connect_socket(socket, "TCP", SOCK_STREAM)) { net->active_server->ip = INADDR_NONE; server_disconnect(net->active_server, "Connection error", 0); return; } socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(get_best_server_read), socket); } int server_connect_real(server_t* server) { socket_t* socket; static gboolean warned = FALSE; if (global.up_width.limit <= 0 && !warned) { info_dialog ("You have your upload bandwidth limit set to 0!\n" "The server communication is also limited by this value.\n" "So right now you cannot receive any data from the server\n" "which means that you cannot search, start downloads, etc.\n" "To fix the problem, go the the upload page and click/drag the\n" "bandwidth bar at the bottom to set your upload limit." ); warned = TRUE; } server_set_status(server, SERVER_CONNECTING, "Connecting"); socket = socket_new(S_SERVER); if (!socket) { server_set_status(server, SERVER_OFFLINE, "Could not allocate socket"); return 0; } // now the server is the _active_ server of the network // server_disconnect() has to be used from now on instead of // server_set_status() server->net->socket = socket; server->net->active_server = server; socket->data = server->net; socket->ip_long = server->ip; // network->network socket->port = htons(server->port); // host->network server->net->sent_compressed = 0; server->net->sent_uncompressed = 0; server->net->rcvd_compressed = 0; server->net->rcvd_uncompressed = 0; if (server->flags & SERVER_REDIRECT) { server_connect_redirect(server->net); } else { server_connect_direct(server->net); } return 1; } static gboolean server_is_valid(server_t* server) { GList* dlist1; GList* dlist2; GList* dlist3; net_group_t* ng; net_t* net; for (dlist1 = global.net_groups; dlist1; dlist1 = dlist1->next) { ng = dlist1->data; for (dlist2 = ng->nets; dlist2; dlist2 = dlist2->next) { net = dlist2->data; for (dlist3 = net->servers; dlist3; dlist3 = dlist3->next) { if (server == dlist3->data) return TRUE; } } } return FALSE; } void server_resolver(server_t* server, unsigned long ip_long) { if (!server_is_valid(server)) return; server->ip = ip_long; if (ip_long == INADDR_NONE) { server_set_status(server, SERVER_CANCELED, "Could not resolve address"); if (server->timeout < 0) server->timeout = gtk_timeout_add(300000, auto_reconnect, server); } else { // now ready to connect server_set_status(server, SERVER_OFFLINE, "Successfully resolved address"); } } int server_connect(server_t* server) { if (!server) return 0; if (server->status != SERVER_OFFLINE && server->status != SERVER_CANCELED) { server_set_status(server, server->status, "Server has invalid status"); g_warning("server_connect(): Server has status %d", server->status); } if (server->net->active_server) { g_warning("network has active server"); return 0; } if (server->timeout >= 0) { gtk_timeout_remove(server->timeout); server->timeout = -1; } if (server->status == SERVER_RESOLVING) { return 0; } else if (server->ip == INADDR_NONE) { server_set_status(server, SERVER_RESOLVING, "Resolving"); resolve_address(server->address, (call_func_t)server_resolver, server); } else { server_connect_real(server); } return 1; } void server_set_address(server_t * server, char *address) { if (!server || !address) return; if (server->address) g_free(server->address); server->address = g_strdup(address); } gint server_compare(GtkCList * clist, gconstpointer ptr1, gconstpointer ptr2) { char *text1 = NULL; char *text2 = NULL; long u1, u2; double d1, d2; GtkCListRow *row1 = (GtkCListRow *) ptr1; GtkCListRow *row2 = (GtkCListRow *) ptr2; text1 = GTK_CELL_TEXT(row1->cell[clist->sort_column])->text; text2 = GTK_CELL_TEXT(row2->cell[clist->sort_column])->text; if (!text2) return (text1 != NULL); if (!text1) return -1; if ((clist->sort_column == 0) || (clist->sort_column == 1) || (clist->sort_column == 2)) { return g_strcasecmp(text1, text2); } else if ((clist->sort_column == 3) || (clist->sort_column == 4) || (clist->sort_column == 5) || (clist->sort_column == 6)) { sscanf(text1, "%ld", &u1); sscanf(text2, "%ld", &u2); if (u1 < u2) return -1; if (u1 > u2) return 1; return 0; } else if ((clist->sort_column == 7) || (clist->sort_column == 8) || (clist->sort_column == 9)) { sscanf(text1, "%lf", &d1); sscanf(text2, "%lf", &d2); if (d1 < d2) return -1; if (d1 > d2) return 1; return 0; } else { return 0; } } void server_show(server_t* server) { GtkCTreeNode* node; GtkCTreeNode* node2; net_t* net = server->net; if (!net) return; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); node = net->node; if (!node) return; strcpy(tstr[0], server->address); tstr[1][0] = 0; tstr[2][0] = 0; sprintf(tstr[3], "%s", LineSpeed(server->linespeed)); sprintf(tstr[4], "%d", server->users); sprintf(tstr[5], "%d", server->files); sprintf(tstr[6], "%d", server->gigs); if (server->users > 0) sprintf(tstr[7], "%.1f", (double)server->gigs/(double)server->users); else strcpy(tstr[7], "n/a"); if (server->users > 0) sprintf(tstr[8], "%.1f", (double)server->files/(double)server->users); else strcpy(tstr[8], "n/a"); if (server->files > 0) sprintf(tstr[9], "%.1f", (double)server->gigs/(double)server->files*1024); else strcpy(tstr[9], "n/a"); if (server->flags & SERVER_NO_NAPI) { node2 = gtk_ctree_insert_node(ctree, node, NULL, list, 5, global.pix.server_nnapi, global.pix.server_nnapib, global.pix.server_nnapi, global.pix.server_nnapib, TRUE, FALSE); } else { node2 = gtk_ctree_insert_node(ctree, node, NULL, list, 5, global.pix.server_napi, global.pix.server_napib, global.pix.server_napi, global.pix.server_napib, TRUE, FALSE); } gtk_ctree_node_set_row_data(ctree, node2, server); server->node = node2; if (server->flags & SERVER_IGNORE) gtk_ctree_node_set_pixmap(ctree, node2, 1, global.pix.server_deact, global.pix.server_deactb); else if (server->flags & SERVER_PERMANENT) gtk_ctree_node_set_pixmap(ctree, node2, 1, global.pix.server_perm, global.pix.server_permb); else gtk_ctree_node_set_text(ctree, node, 1, "-"); } void server_hide(server_t* server) { GtkCTreeNode* node; node = server->node; if (!node) return; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); gtk_ctree_remove_node(ctree, node); server->node = NULL; } void server_update(server_t* server) { GtkCTreeNode* node; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); node = server->node; if (!node) return; sprintf(tstr[3], "%s", LineSpeed(server->linespeed)); sprintf(tstr[4], "%d", server->users); sprintf(tstr[5], "%d", server->files); sprintf(tstr[6], "%d", server->gigs); if (server->users > 0) sprintf(tstr[7], "%.1f", (double)server->gigs/(double)server->users); else strcpy(tstr[7], "n/a"); if (server->users > 0) sprintf(tstr[8], "%.1f", (double)server->files/(double)server->users); else strcpy(tstr[8], "n/a"); if (server->files > 0) sprintf(tstr[9], "%.1f", (double)server->gigs/(double)server->files*1024); else strcpy(tstr[9], "n/a"); if (server->status == SERVER_ONLINE) gtk_ctree_node_set_pixmap(ctree, node, 1, global.pix.server_con, global.pix.server_conb); else if (server->flags & SERVER_IGNORE) gtk_ctree_node_set_pixmap(ctree, node, 1, global.pix.server_deact, global.pix.server_deactb); else if (server->flags & SERVER_PERMANENT) gtk_ctree_node_set_pixmap(ctree, node, 1, global.pix.server_perm, global.pix.server_permb); else gtk_ctree_node_set_text(ctree, node, 1, "-"); gtk_ctree_node_set_text(ctree, node, 3, tstr[3]); gtk_ctree_node_set_text(ctree, node, 4, tstr[4]); gtk_ctree_node_set_text(ctree, node, 5, tstr[5]); gtk_ctree_node_set_text(ctree, node, 6, tstr[6]); gtk_ctree_node_set_text(ctree, node, 7, tstr[7]); gtk_ctree_node_set_text(ctree, node, 8, tstr[8]); gtk_ctree_node_set_text(ctree, node, 9, tstr[9]); if (server->flags & SERVER_NO_NAPI) { gtk_ctree_node_set_pixtext(ctree, node, 0, server->address, 5, global.pix.server_nnapi, global.pix.server_nnapib); } else { gtk_ctree_node_set_pixtext(ctree, node, 0, server->address, 5, global.pix.server_napi, global.pix.server_napib); } } net_t* network_new(char* name, int type) { net_t* net; net = g_malloc(sizeof(*net)); strcpy(net->user.username, global.username); strcpy(net->user.password, global.password); net->name = g_strdup(name); net->servers = NULL; net->flags = 0; net->active_server = NULL; net->auto_join = NULL; net->type = type; net->subtype = -1; net->major = net->minor = net->micro = 0; net->codeset = g_strdup(""); net->logs = NULL; net->group = NULL; net->search_stamp = 0; net->search_cnt = 0; net->in_buffer = NULL; net->out_buffer = NULL; net->temp_buffer = NULL; net->node = NULL; net->socket = NULL; net->queued_searches = NULL; net->active_searches = NULL; net->cur_searches = 0; net->max_searches = 1; net->max_share = 0; // unlimited net->links = NULL; net->c_type = 0; net->c_length = 0; net->c_message = NULL; net->temp_list = NULL; #ifdef HAVE_ZLIB net->compress = 0; #endif net->sent_compressed = 0; net->sent_uncompressed = 0; net->rcvd_compressed = 0; net->rcvd_uncompressed = 0; if (NET_IRC(net)) setup_functions_irc(net); else if (NET_NAP(net)) setup_functions_nap(net); else { net->success = NULL; net->consume_command = NULL; net->login = NULL; net->command_pack = NULL; net->channel_setup = NULL; net->handle_command = NULL; } return net; } void network_destroy(net_t* net) { close_logs(net); g_free(net->name); if (net->in_buffer) buffer_destroy(net->in_buffer); if (net->out_buffer) buffer_destroy(net->out_buffer); if (net->temp_buffer) buffer_destroy(net->temp_buffer); if (net->links) network_links_free(net, 0); g_free(net); } server_t* server_create(char* servername, char* ip, int port, char* users, char* files, char* gigs, char* linespeed, int manual) { server_t* server; // no check yet, whether server has valid address server = server_new(); server_set_address(server, servername); if (ip) server->ip = inet_addr(ip); server->port = port; server->users = atoi(users); server->files = atoi(files); server->gigs = atoi(gigs); server->linespeed = atoi(linespeed); if (manual) server->flags |= SERVER_PERMANENT; return server; } void server_all_set_flag(int flag) { GList* dlist1; GList* dlist2; GList* dlist3; net_group_t* ng; net_t* net; server_t* server; for (dlist1 = global.net_groups; dlist1; dlist1 = dlist1->next) { ng = dlist1->data; for (dlist2 = ng->nets; dlist2; dlist2 = dlist2->next) { net = dlist2->data; for (dlist3 = net->servers; dlist3; dlist3 = dlist3->next) { server = dlist3->data; server->flags |= flag; } } } } void server_all_del_flag(int flag) { GList* dlist1; GList* dlist2; GList* dlist3; net_group_t* ng; net_t* net; server_t* server; for (dlist1 = global.net_groups; dlist1; dlist1 = dlist1->next) { ng = dlist1->data; for (dlist2 = ng->nets; dlist2; dlist2 = dlist2->next) { net = dlist2->data; for (dlist3 = net->servers; dlist3; dlist3 = dlist3->next) { server = dlist3->data; server->flags &= ~flag; } } } } int server_load() { FILE *fd; char *fname; char line[2048]; net_group_t* ng = NULL; net_t* net = NULL; server_t* server; char* name; char* ip; char* port; char* nick; char* passwd; char* flags; char* type; char* codeset; char* meta; char* max_share; fname = g_strdup_printf("%s/server.list", global.options.config_dir); if ((fd = fopen(fname, "r")) == NULL) { g_free(fname); return 0; } g_free(fname); while (mfgets(line, sizeof(line), fd)) { name = arg(line, 0); if (!name) continue; if (*name == '+') { name = arg(NULL, 2); flags = arg(NULL, 0); type = arg(NULL, 0); if (!flags) continue; ng = net_group_create(name, atoi(flags) & NG_SAVE_MASK, 10); if (type) ng->how_many = atoi(type); else if (atoi(flags) & 0x1) ng->how_many = -1; // backward } else if (*name == '-') { if (!net) continue; name = arg(NULL, 2); ip = arg(NULL, 2); port = arg(NULL, 2); flags = arg(NULL, 2); if (!flags) continue; server = server_new(); server_set_address(server, name); server->ip = strtoul(ip, NULL, 10); if (server->ip == 0) server->ip = INADDR_NONE; // server->ip = INADDR_NONE; server->port = atoi(port); server->flags = atoi(flags) & SERVER_SAVE_MASK; network_add_server(net, server); } else { flags = arg(NULL, 2); meta = arg(NULL, 2); nick = arg(NULL, 2); passwd = arg(NULL, 2); type = arg(NULL, 2); if (!type) continue; codeset = arg(NULL, 2); max_share = arg(NULL, 2); net = network_new(name, atoi(type)); net->flags = atoi(flags) & NETWORK_SAVE_MASK; make_list_from_string(&(net->auto_join), meta, " "); strncpy(net->user.username, nick, 100); strncpy(net->user.password, passwd, 100); g_free(net->codeset); net->codeset = g_strdup(codeset?codeset:""); if (max_share) net->max_share = atoi(max_share); if (!ng) { ng = net_group_create("Normal Networks", NG_NEVER_CONNECT, 10); net_group_add_net(ng, net); ng = NULL; } else { net_group_add_net(ng, net); } } } fclose(fd); return 1; } int server_save() { GList* dlist; GList* dlist2; GList* dlist3; net_group_t* ng; net_t* net; server_t* server; char *filename_new; char *filename; FILE* file; filename_new = g_strdup_printf("%s/server.list.new", global.options.config_dir); if ((file = fopen(filename_new, "w")) == NULL) { g_free(filename_new); g_warning("could not write server.list %s", filename_new); return 0; } for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; qfprintf(file, "+ %S %d %d\n", ng->name, ng->flags & NG_SAVE_MASK, ng->how_many); for (dlist2 = ng->nets; dlist2; dlist2 = dlist2->next) { net = dlist2->data; qfprintf(file, " %S %d %S %S %S %d %S %d\n", net->name, net->flags & NETWORK_SAVE_MASK, make_string_from_list(net->auto_join, " "), net->user.username, net->user.password, net->type, net->codeset, net->max_share); for (dlist3 = net->servers; dlist3; dlist3 = dlist3->next) { server = dlist3->data; qfprintf(file, " - %S %lu %d %d\n", server->address, server->ip, server->port, server->flags & SERVER_SAVE_MASK); } } } filename = g_strdup_printf("%s/server.list", global.options.config_dir); if (!ferror(file)) { rename(filename_new, filename); g_free(filename); g_free(filename_new); fclose(file); return 1; } else { g_warning("Could not write [%s]\n", filename); g_free(filename); g_free(filename_new); fclose(file); return 0; } return 0; } void server_handle_marked() { GList* dlist1; GList* dlist2; GList* dlist3; net_group_t* ng; net_t* net; server_t* server; dlist1 = global.net_groups; while (dlist1) { ng = dlist1->data; dlist1 = dlist1->next; dlist2 = ng->nets; while (dlist2) { net = dlist2->data; dlist2 = dlist2->next; dlist3 = net->servers; while (dlist3) { server = dlist3->data; dlist3 = dlist3->next; // dont remove server that are in use if (server->flags & SERVER_MARKED) { server->flags &= ~SERVER_MARKED; server->flags |= SERVER_NO_NAPI; if (global.naplist.auto_remove) { if ((server->flags & SERVER_PERMANENT) || net->active_server == server) { server_update(server); } else { network_remove_server(net, server); server_destroy(server); } } else { server_update(server); } } } } } } void on_refresh_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data ATTR_UNUSED) { napigator_get_list(); } void on_remove_server(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { server_t* server = user_data; net_t* net; if (!server) return; if (server->status == SERVER_CONNECTING || server->status == SERVER_ONLINE) { if (server_disconnect(server, "User disconnect", 0)) // server was removed return; } net = server->net; network_remove_server(net, server); server_destroy(server); } void on_network_toggle_message(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; net->flags ^= NETWORK_MESSAGES; server_save(); } void on_network_toggle_global(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; net->flags ^= NETWORK_IGN_GLOBAL; server_save(); } void on_network_toggle_share(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; net->flags ^= NETWORK_DONT_SHARE; server_save(); } void on_network_toggle_winmx(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; if (!net) return; net->flags ^= NETWORK_NO_WINMX; server_save(); } void on_server_toggle_ignore(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { server_t* server = user_data; if (!server) return; server->flags ^= SERVER_IGNORE; server_update(server); server_save(); } void on_server_toggle_perm(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { server_t* server = user_data; if (!server) return; server->flags ^= SERVER_PERMANENT; server_update(server); server_save(); } void on_connect1_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { server_t* server = user_data; server_connect(server); } void on_connect_net_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { GList* nets = user_data; net_t* net; while (nets) { net = nets->data; nets = nets->next; if (net->flags & NETWORK_CONNECTING) network_cancel_connect(net); else network_start_connect(net); } } void on_disconnect_net_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { GList* nets = user_data; net_t* net; while (nets) { net = nets->data; nets = nets->next; if (NET_ONLINE(net)) network_disconnect(net); } } void on_disconnect1_activate(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { server_t* server = user_data; server_disconnect(server, "User disconnect", 0); } void on_change_login_passwd(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* network = user_data; GtkWidget* win; if (!network) return; win = create_user_passwd(network); gtk_widget_show(win); } void on_server_delink(GtkMenuItem * menuitem, gpointer user_data ATTR_UNUSED) { net_t* net = user_data; GtkLabel *label; label = GTK_LABEL(GTK_BIN(menuitem)->child); command_send(net, CMD_SERVER_DISCONNECT, label->label, NULL); } void on_server_shutdown(GtkMenuItem * menuitem, gpointer user_data) { GtkWidget *win; GtkWidget *temp; GtkLabel *label; static guint old_id = 0; win = create_shutdown_win(); temp = lookup_widget(win, "button203"); if (old_id) gtk_signal_disconnect(GTK_OBJECT(temp), old_id); old_id = gtk_signal_connect (GTK_OBJECT (temp), "clicked", GTK_SIGNAL_FUNC (on_button203_clicked), user_data); temp = lookup_widget(win, "label529"); label = GTK_LABEL(GTK_BIN(menuitem)->child); gtk_label_set_text(GTK_LABEL(temp), label->label); gtk_widget_show(win); } void add_server_action(GtkWidget* popup, net_t* net); void add_server_entry(GtkWidget * popup, link_t * link, GtkSignalFunc func, char *action, net_t* net); void add_server_entry2(GtkWidget * popup, net_t* net); static void on_move_to_group(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_group_t* ng = user_data; net_t* net; GList* dlist; for (dlist = my_net_list; dlist; dlist = dlist->next) { net = dlist->data; if (!ng) { net_group_remove_net(net->group, net); network_destroy(net); } else network_move(net, ng); } } GtkWidget* create_network_popup(GtkWidget* popup, GList* nets, int other) { GtkWidget* item; GtkWidget* popup2; GList* dlist; char str[1024]; double size; net_t* net; net_group_t* ng; int cnt; int item_num; if (!popup) popup = gtk_menu_new(); if (!nets) { if (global.net_active) { for (dlist = global.net_active; dlist; dlist = dlist->next) { net = dlist->data; if (my_net_list) g_list_free(my_net_list); my_net_list = g_list_append(NULL, net); sprintf(str, "[%d] %s", g_list_index(global.net_active, net)+1, net->name); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = create_network_popup(NULL, my_net_list, 0); if (popup2) gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); } } else { item = gtk_menu_item_new_with_label("Not connected"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); } return popup; } item_num = g_list_length(nets); net = nets->data; if (net->servers) { if (net->flags & NETWORK_CONNECTING) item = gtk_menu_item_new_with_label("Stop connect"); else item = gtk_menu_item_new_with_label("Start connect"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_connect_net_activate), nets); if (net->active_server) { item = gtk_menu_item_new_with_label("Disconnect"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_disconnect_net_activate), nets); } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); } item = gtk_menu_item_new_with_label("Configure"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = gtk_menu_new(); gtk_widget_show(popup2); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); { item = gtk_check_menu_item_new_with_label("Don't share files"); if (net->flags & NETWORK_DONT_SHARE) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_network_toggle_share), net); item = gtk_check_menu_item_new_with_label("Don't emulate WinMX v2.6"); if (net->flags & NETWORK_NO_WINMX) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_network_toggle_winmx), net); item = gtk_check_menu_item_new_with_label("Own Server/MOTD Page"); if (net->flags & NETWORK_MESSAGES) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_network_toggle_message), net); item = gtk_check_menu_item_new_with_label("Show Global Messages"); if ((net->flags & NETWORK_IGN_GLOBAL) == 0) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_network_toggle_global), net); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Change Login/Password"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_change_login_passwd), net); } my_net_list = nets; if (item_num > 1) sprintf(str, "Move Selected (%d) to Group", item_num); else sprintf(str, "%s", "Move to Group"); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = gtk_menu_new(); gtk_widget_show(popup2); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); if (!net->servers) { item = gtk_menu_item_new_with_label(""); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_widget_show(item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_move_to_group), NULL); } for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; item = gtk_menu_item_new_with_label(ng->name); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_widget_show(item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_move_to_group), ng); if (net->group == ng) gtk_widget_set_sensitive(item, FALSE); } if (NET_CONNECTED(net)) { item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Server Info"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = gtk_menu_new(); gtk_widget_show(popup2); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); network_print_version(str, net); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); sprintf(str, "%d Users, %d Files, %d GB", net->active_server->users, net->active_server->files, net->active_server->gigs); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); sprintf(str, "Nickname: %s", net->user.username); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); sprintf(str, "Searches: %d running, %d queued", g_list_length(net->active_searches), g_list_length(net->queued_searches)); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); size = net->out_buffer?net->out_buffer->datasize:0; size += net->temp_buffer?net->temp_buffer->datasize:0; cnt = sprintf(str, "Send Queue Size: "); print_size(str+cnt, size); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_widget_set_sensitive(item, FALSE); add_server_action(popup, net); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); if (net->links) { add_server_entry(popup, net->links, NULL, "Linked Servers", net); if (net->user.level > L_MOD) { add_server_entry2(popup, net); add_server_entry(popup, net->links, on_server_delink, "Delink Server", net); if (net->user.level > L_ADMIN) { add_server_entry(popup, net->links, on_server_shutdown, "Shutdown Server", net); } } } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Active Server"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); popup2 = create_server_popup(NULL, net->active_server, 1); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); } if (other && g_list_length(global.net_active) > 1) { item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Other Networks"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = create_network_popup(NULL, NULL, 0); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); } return popup; } void on_server_links(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; network_links_get(net); } void on_server_stats(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_t* net = user_data; server_stats_get(net, NULL); } void add_server_action(GtkWidget* popup, net_t* net) { GtkWidget* item1; GtkWidget* item2; GtkWidget* popup2; item1 = gtk_menu_item_new_with_label("Action"); gtk_widget_show(item1); gtk_container_add(GTK_CONTAINER(popup), item1); popup2 = gtk_menu_new(); gtk_widget_show(popup2); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item1), popup2); item2 = gtk_menu_item_new_with_label("Get Channel List"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_channel_list), net); item2 = gtk_menu_item_new_with_label("Get Global User List"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_global_list), net); if (net->user.level < L_MOD) gtk_widget_set_sensitive(item2, FALSE); item2 = gtk_menu_item_new_with_label("Get Banned Users"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_banned_users), net); item2 = gtk_menu_item_new_with_label("Get Client Statistic"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_client_list), net); if (net->user.level < L_MOD) gtk_widget_set_sensitive(item2, FALSE); item2 = gtk_menu_item_new_with_label("Refresh linked servers"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_server_links), net); item2 = gtk_menu_item_new_with_label("Show server stats"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_server_stats), net); } void add_server_entry(GtkWidget * popup, link_t * link, GtkSignalFunc func, char *action, net_t* net) { GtkWidget *menu_entry; GtkWidget *menu; GList *sub; link_t *entry; char *name; if (link->links) { if (action) { menu_entry = gtk_menu_item_new_with_label(action); } else if (link->ping && !func) { name = g_strdup_printf("%s (%s)", link->server, link->ping); menu_entry = gtk_menu_item_new_with_label(name); g_free(name); } else { menu_entry = gtk_menu_item_new_with_label(link->server); } gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(popup), menu_entry); menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_entry), menu); menu_entry = gtk_menu_item_new_with_label(link->server); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(menu), menu_entry); if (func) gtk_signal_connect(GTK_OBJECT(menu_entry), "activate", func, net); menu_entry = gtk_menu_item_new(); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(menu), menu_entry); gtk_widget_set_sensitive(menu_entry, FALSE); for (sub = link->links; sub; sub = sub->next) { entry = sub->data; add_server_entry(menu, entry, func, NULL, net); } } else if (action) { menu_entry = gtk_menu_item_new_with_label(action); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(popup), menu_entry); menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_entry), menu); menu_entry = gtk_menu_item_new_with_label(link->server); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(menu), menu_entry); if (func) gtk_signal_connect(GTK_OBJECT(menu_entry), "activate", func, net); } else { if (link->ping && !func) { name = g_strdup_printf("%s (%s)", link->server, link->ping); menu_entry = gtk_menu_item_new_with_label(name); g_free(name); } else menu_entry = gtk_menu_item_new_with_label(link->server); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(popup), menu_entry); if (func) gtk_signal_connect(GTK_OBJECT(menu_entry), "activate", func, net); } } void on_server_link(GtkMenuItem * menuitem, gpointer user_data) { GtkLabel *label; GtkWidget *temp; char *s1, *s2; char *command; net_t* net = user_data; temp = gtk_object_get_user_data(GTK_OBJECT(menuitem)); if (temp) { label = GTK_LABEL(GTK_BIN(temp)->child); s2 = label->label; } else { s2 = NULL; } label = GTK_LABEL(GTK_BIN(menuitem)->child); s1 = label->label; if (s2) { command = g_strdup_printf("%s %s", s1, s2); command_send(net, CMD_SERVER_CONNECT, command); g_free(command); } else { command_send(net, CMD_SERVER_CONNECT, s1); } } link_t *link_search_rec(link_t * link, char *name) { link_t *result; GList *dlist; link_t *temp; if (!link) { g_warning("link_search_rec: link == NULL"); return NULL; } if (!g_strcasecmp(link->server, name)) return link; for (dlist = link->links; dlist; dlist = dlist->next) { temp = dlist->data; result = link_search_rec(temp, name); if (result) return result; } return NULL; } GList* available_servers(char* net) { GList* dlist; GList* result = NULL; server_link_t* link; for (dlist = global.server_links; dlist; dlist = dlist->next) { link = dlist->data; if (!strcmp(net, link->net)) result = g_list_append(result, link); } return result; } GList* available_links(GList* source, char* server_name, net_t* net) { GList* dlist; GList* result = NULL; server_link_t* link; for (dlist = source; dlist; dlist = dlist->next) { link = dlist->data; if (!strcmp(server_name, link->server1) && !link_search_rec(net->links, link->server2)) { result = g_list_append(result, link->server2); } else if (!strcmp(server_name, link->server2) && !link_search_rec(net->links, link->server1)) { result = g_list_append(result, link->server1); } } return result; } int is_local_server(char* name, net_t* net) { if (!net->links || strcmp(net->links->server, name)) return 0; return 1; } void add_connect(GtkWidget* popup, GList* net_links, link_t* links, net_t* net) { GList* result; GtkWidget* menu; GtkWidget* menu_entry; GtkWidget* menu_entry2; GList* dlist; char* server_name; int cnt = 0; link_t* sublink2; menu_entry = gtk_menu_item_new_with_label(links->server); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(popup), menu_entry); menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_entry), menu); for (dlist = links->links; dlist; dlist = dlist->next) { sublink2 = dlist->data; add_connect(menu, net_links, sublink2, net); } result = available_links(net_links, links->server, net); for (dlist = result; dlist; dlist = dlist->next) { server_name = dlist->data; menu_entry2 = gtk_menu_item_new_with_label(server_name); gtk_widget_show(menu_entry2); gtk_container_add(GTK_CONTAINER(menu), menu_entry2); if (!is_local_server(links->server, net)) gtk_object_set_user_data(GTK_OBJECT(menu_entry2), menu_entry); gtk_signal_connect(GTK_OBJECT(menu_entry2), "activate", on_server_link, net); cnt++; } g_list_free(result); if (cnt == 0) { menu_entry2 = gtk_menu_item_new_with_label("All linked"); gtk_widget_show(menu_entry2); gtk_container_add(GTK_CONTAINER(menu), menu_entry2); gtk_widget_set_sensitive(menu_entry2, FALSE); } } void add_server_entry2(GtkWidget * popup, net_t* net) { GtkWidget *menu_entry; GList* net_links; if (!global.server_links) return; if (!net || !net->links) return; menu_entry = gtk_menu_item_new_with_label("Connect Server"); gtk_widget_show(menu_entry); gtk_container_add(GTK_CONTAINER(popup), menu_entry); popup = gtk_menu_new(); gtk_widget_show(popup); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_entry), popup); net_links = available_servers(net->name); add_connect(popup, net_links, net->links, net); g_list_free(net_links); } char* network_print_version(char* text, net_t* net) { if (net->subtype == N_OPENNAP || net->subtype == N_OPENNAP_NG) { sprintf(text, "%s %d.%d : %s : %s", Network[net->subtype], net->major, net->minor, LevelShort(net->user.level), UserStatus(net->user.status)); } else if (net->subtype == N_SLAVANAP || net->subtype == N_CLEANNAP) { sprintf(text, "%s %d.%d.%d : %s : %s", Network[net->subtype], net->major, net->minor, net->micro, LevelShort(net->user.level), UserStatus(net->user.status)); } else if (net->subtype == N_IRC) { sprintf(text, "%s", Network[net->subtype]); } else if (net->subtype == N_UNKNOWN) { sprintf(text, ": %s : %s", LevelShort(net->user.level), UserStatus(net->user.status)); } else { sprintf(text, ": %s : %s", LevelShort(net->user.level), UserStatus(net->user.status)); } return text; } GtkWidget *create_server_popup(GtkWidget* popup, server_t* server, int name) { GtkWidget *item; int server_status; net_t* net; if (!popup) popup = gtk_menu_new(); net = server->net; server_status = server->status; if (name) { item = gtk_menu_item_new_with_label(net->active_server->address); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); } if (server_status == SERVER_CONNECTING || server_status == SERVER_ONLINE) { item = gtk_menu_item_new_with_label("Disconnect"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_disconnect1_activate), server); } else { item = gtk_menu_item_new_with_label("Connect"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_connect1_activate), server); } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Remove Server"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_remove_server), server); item = gtk_check_menu_item_new_with_label("Deactivated"); if (server->flags & SERVER_IGNORE) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_server_toggle_ignore), server); item = gtk_check_menu_item_new_with_label("Always keep server"); if (server->flags & SERVER_PERMANENT) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_server_toggle_perm), server); return popup; } GtkWidget* create_new_group (); void on_create_group(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data ATTR_UNUSED) { GtkWidget* win; win = create_new_group(); gtk_widget_show(win); } GtkWidget* create_server1_popup(server_t* server) { GtkWidget* popup; GtkWidget* item; popup = gtk_menu_new(); if (napi_busy) { item = gtk_menu_item_new_with_label("Retrieving server list\nWait until finished"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); return popup; } item = gtk_menu_item_new_with_label("Refresh List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_refresh_activate), NULL); item = gtk_menu_item_new_with_label("Create New Group"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_create_group), NULL); if (server) { item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); create_server_popup(popup, server, 0); } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Customize List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_customize_list_activate), NULL); return popup; } GtkWidget* create_network1_popup(net_t* net) { GtkWidget* popup; GtkWidget* item; GtkCTreeNode* node; GtkCTreeNode* node2; net_t* net2; int depth; GList* row_list; popup = gtk_menu_new(); if (napi_busy) { item = gtk_menu_item_new_with_label("Retrieving server list\nWait until finished"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); return popup; } item = gtk_menu_item_new_with_label("Refresh List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_refresh_activate), NULL); item = gtk_menu_item_new_with_label("Create New Group"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_create_group), NULL); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); row_list = GTK_CLIST(global.popup_list)->selection; if (my_net_list) g_list_free(my_net_list); my_net_list = NULL; while (row_list) { node = GTK_CTREE_NODE(row_list->data); row_list = row_list->next; node2 = node; depth = 0; while ((node2 = GTK_CTREE_ROW(node2)->parent)) depth++; if (depth == 1) { net2 = gtk_ctree_node_get_row_data(ctree, node); if (net2 == net) my_net_list = g_list_prepend(my_net_list, net2); else my_net_list = g_list_append(my_net_list, net2); } } create_network_popup(popup, my_net_list, 0); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Customize List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_customize_list_activate), NULL); return popup; } socket_t* network_socket(net_t* net) { GList* dlist; socket_t* socket; for (dlist = global.sockets; dlist; dlist = dlist->next) { socket = dlist->data; if (socket->data == net) return socket; } return NULL; } void server_stats_get(net_t* net, char* server) { char* prefix; chat_page_t* page; page = chat_page_get_printable(); chat_print_time_stamp(page, M_PUBLIC); prefix = cparse(global.scheme->client_prefix); chat_print_colored(page, M_PUBLIC, "message", prefix); chat_print_text(page, M_PUBLIC, "user", "["); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "user", "] "); chat_print_text(page, M_PUBLIC, "message", "Requesting stats"); if (server) { chat_print_text(page, M_PUBLIC, "message", " ("); chat_print_text(page, M_PUBLIC, "text", server); chat_print_text(page, M_PUBLIC, "message", ")"); } chat_print_text(page, M_PUBLIC, "message", "\n"); command_send(net, CMD_USAGE_STATS, server); } void server_update_stats() { GtkWidget *temp; int files, gigs, users; char t[500]; GList* dlist; net_t* net; server_t* server; users = files = gigs = 0; for (dlist = global.net_active; dlist; dlist = dlist->next) { net = dlist->data; if (!NET_CONNECTED(net)) continue; server = net->active_server; users += server->users; files += server->files; gigs += server->gigs; } temp = lookup_widget(global.win, "label1684"); sprintf(t, "%.1fK Users, %.2fM Files, %.1f TB", (double)users/1000, (double)files/1000/1000, (double)gigs/1024); gtk_label_set_text(GTK_LABEL(temp), t); } user_level_t server_get_highest_level() { GList* dlist; user_level_t level = L_USER; net_t* net; for (dlist = global.net_active; dlist; dlist = dlist->next) { net = dlist->data; if (net->user.level > level) level = net->user.level; } return level; } void network_links_get(net_t* net) { if (net->temp_list) return; command_send(net, CMD_LINKS); } void free_links(link_t * link) { GList *dlist; link_t *temp; if (!link) return; g_free(link->server); link->server = NULL; for (dlist = link->links; dlist; dlist = dlist->next) { temp = dlist->data; free_links(temp); } g_list_free(link->links); g_free(link); } void network_links_free(net_t* net, int keep_root) { GList* dlist; link_t* link; if (!net->links) return; if (keep_root) { for (dlist = net->links->links; dlist; dlist = dlist->next) { link = dlist->data; free_links(link); } g_list_free(net->links->links); net->links->links = NULL; } else { free_links(net->links); net->links = NULL; } } void link_message(char *pre, char *server, int depth) { char *prefix; int i1; chat_page_t* page; page = chat_page_get_printable(); chat_print_time_stamp(page, M_PUBLIC); prefix = cparse(global.scheme->client_prefix); chat_print_colored(page, M_PUBLIC, "message", prefix); for (i1 = 0; i1 < depth; i1++) chat_print_text(page, M_PUBLIC, "message", " "); chat_print_text(page, M_PUBLIC, "error", "["); chat_print_text(page, M_PUBLIC, "message", pre); chat_print_text(page, M_PUBLIC, "error", "] "); chat_print_text(page, M_PUBLIC, "message", server); chat_print_text(page, M_PUBLIC, "message", "\n"); } void print_links(chat_page_t* page, link_t * link, int depth) { GList *dlist; link_t *temp; char text[1024]; char t2[100]; static int cnt = 0; int no_links; if (!link) { client_message(NULL, "No Servers Linked"); return; } *text = 0; no_links = g_list_length(link->links); if (no_links > 0) { if (depth == 0) { if (no_links > 1) sprintf(t2, "%2d", no_links); else sprintf(t2, "->"); } else { sprintf(t2, "%2d", no_links + 1); } } else { sprintf(t2, "->"); } link_message(t2, link->server, depth); cnt++; for (dlist = link->links; dlist; dlist = dlist->next) { temp = dlist->data; print_links(page, temp, depth + 1); } if (depth == 0) { client_message("Sum", "%d servers linked!", cnt - 1); cnt = 0; } } void network_links_print(net_t* net) { chat_page_t* page; if (!net) return; if (!net->links) { client_message("Error", "No server link table available"); return; } page = chat_page_get_printable(); chat_print_time_stamp(page, M_PUBLIC); chat_print_text(page, M_PUBLIC, "error", "[Linked servers]"); chat_print_network(page, M_PUBLIC, net, 0, 1); chat_print_text(page, M_PUBLIC, "error", "\n"); print_links(page, net->links, 0); } char *get_s1(char *data) { char result[1024]; char *pos; strcpy(result, data); pos = arg(result, 0); return pos; } char *get_s2(char *data) { char result[1024]; char *pos; strcpy(result, data); pos = arg(result, 0); pos = arg(NULL, 0); pos = arg(NULL, 0); return pos; } link_t *link_search(link_t * link, char *name) { GList *dlist; link_t *temp; for (dlist = link->links; dlist; dlist = dlist->next) { temp = (link_t *) (dlist->data); if (!strcmp(temp->server, name)) return temp; } return NULL; } link_t *link_remove(link_t * link, char *name) { link_t *result; GList *dlist; link_t *temp; if (!strcmp(link->server, name)) return link; for (dlist = link->links; dlist; dlist = dlist->next) { temp = (link_t *) (dlist->data); result = link_remove(temp, name); if (result) { link->links = g_list_remove(link->links, temp); free_links(temp); return NULL; } } return NULL; } static server_link_t* find_allowed_link(char* net, char* server1, char* server2) { GList* dlist; server_link_t* link; for (dlist = global.server_links; dlist; dlist = dlist->next) { link = dlist->data; if (strcmp(link->net, net)) continue; if (!strcmp(link->server1, server1) && !strcmp(link->server2, server2)) return link; if (!strcmp(link->server1, server2) && !strcmp(link->server2, server1)) return link; } return NULL; } static server_link_t* add_allowed_link(char* net, char *server1, char *server2) { server_link_t* link; link = find_allowed_link(net, server1, server2); if (!link) { link = g_malloc(sizeof(*link)); link->net = g_strdup(net); link->server1 = g_strdup(server1); link->server2 = g_strdup(server2); global.server_links = g_list_append(global.server_links, link); } link->link_time = global.current_time; return link; } void network_new_link(net_t* net, char* data) { char *s1, *s2; link_t *new_link; link_t *new_link2; GList *dlist; int cnt; int who; char** pointer; // just save the links if (*data) { s1 = arg(data, 0); s2 = arg(NULL, 0); s2 = arg(NULL, 0); if (s2) { pointer = g_malloc(sizeof(char*)*2); pointer[0] = g_strdup(s1); pointer[1] = g_strdup(s2); net->temp_list = g_list_append(net->temp_list, pointer); } return; } // ok, got end of server links, now build the tree if (!net->temp_list) return; network_links_free(net, 1); while (net->temp_list) { dlist = net->temp_list; cnt = 0; while (dlist) { pointer = dlist->data; dlist = dlist->next; s1 = pointer[0]; s2 = pointer[1]; if (!s2) { net->temp_list = g_list_remove(net->temp_list, data); g_free(data); continue; } new_link = link_search_rec(net->links, s1); if (new_link) { who = 1; } else { new_link = link_search_rec(net->links, s2); if (new_link) who = 2; else who = 0; } if (who) { new_link2 = g_malloc(sizeof(link_t)); if (who == 1) new_link2->server = g_strdup(s2); else new_link2->server = g_strdup(s1); new_link2->links = NULL; new_link2->ping = NULL; new_link->links = g_list_append(new_link->links, new_link2); add_allowed_link(net->name, new_link->server, new_link2->server); net->temp_list = g_list_remove(net->temp_list, pointer); g_free(s1); g_free(s2); g_free(pointer); cnt++; } } // check whether we could add to the tree in this loop if (cnt == 0) break; } if (net->temp_list) { server_message(net, "Could not create link tree"); for (dlist = net->temp_list; dlist; dlist = dlist->next) { pointer = dlist->data; g_free(pointer[0]); g_free(pointer[1]); g_free(pointer); } g_list_free(net->temp_list); net->temp_list = NULL; } } server_t* network_search_server(net_t* net, char* address) { GList* dlist; server_t* server; if (!net) return NULL; for (dlist = net->servers; dlist; dlist = dlist->next) { server = dlist->data; if (!strcasecmp(server->address, address)) return server; } return NULL; } server_t* network_search_link(net_t* net, server_t* server) { GList* dlist; server_t* serv; if (!net) return NULL; for (dlist = net->servers; dlist; dlist = dlist->next) { serv = dlist->data; if (serv == server) return serv; } return NULL; } void network_show(net_t* net) { GtkCTreeNode* node; GList* dlist; net_group_t* ng; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); ng = net->group; if (!ng->node) { printf("group not found %p\n", net->group); return; } strcpy(tstr[0], net->name); strcpy(tstr[1], "-"); if (net->flags & NETWORK_CONNECTING) strcpy(tstr[2], "Ready to connect"); else tstr[2][0] = 0; tstr[3][0] = tstr[4][0] = tstr[5][0] = tstr[6][0] = tstr[7][0] = tstr[8][0] = tstr[9][0] = 0; node = gtk_ctree_insert_node(ctree, ng->node, NULL, list, 5, NULL, NULL, NULL, NULL, FALSE, FALSE); gtk_ctree_node_set_row_data(ctree, node, net); net->node = node; for (dlist = net->servers; dlist; dlist = dlist->next) { server_t* server = dlist->data; server_show(server); server_update(server); } } void network_hide(net_t* net) { GtkCTreeNode* node; node = net->node; if (!node) return; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); gtk_ctree_remove_node(ctree, node); net->node = NULL; } void network_update(net_t* net, int stats) { GtkCTreeNode* node; int gigs = 0; int files = 0; int users = 0; int linespeed = 0; if (!net) return; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); node = net->node; if (!node) return; if (net->active_server) { if (net->active_server->status == SERVER_ONLINE) { gtk_ctree_node_set_pixmap(ctree, node, 1, global.pix.server_con, global.pix.server_conb); gtk_ctree_node_set_text(ctree, node, 2, "Online"); } else { gtk_ctree_node_set_text(ctree, node, 1, "-"); gtk_ctree_node_set_text(ctree, node, 2, "Connecting"); } } else { gtk_ctree_node_set_text(ctree, node, 1, "-"); if (net->flags & NETWORK_CONNECTING) { gtk_ctree_node_set_text(ctree, node, 2, "Ready to connect"); } else { gtk_ctree_node_set_text(ctree, node, 2, ""); } } if (!stats) return; users = network_stats(net, 0); files = network_stats(net, 1); gigs = network_stats(net, 2); linespeed = network_stats(net, 3); sprintf(tstr[3], "%s", LineSpeed(linespeed)); sprintf(tstr[4], "%d", users); sprintf(tstr[5], "%d", files); sprintf(tstr[6], "%d", gigs); if (users > 0) sprintf(tstr[7], "%.1f", (double)gigs/(double)users); else strcpy(tstr[7], "n/a"); if (users > 0) sprintf(tstr[8], "%.1f", (double)files/(double)users); else strcpy(tstr[8], "n/a"); if (gigs > 0) sprintf(tstr[9], "%.1f", (double)gigs/(double)files*1024); else strcpy(tstr[9], "n/a"); gtk_ctree_node_set_text(ctree, node, 3, tstr[3]); gtk_ctree_node_set_text(ctree, node, 4, tstr[4]); gtk_ctree_node_set_text(ctree, node, 5, tstr[5]); gtk_ctree_node_set_text(ctree, node, 6, tstr[6]); gtk_ctree_node_set_text(ctree, node, 7, tstr[7]); gtk_ctree_node_set_text(ctree, node, 8, tstr[8]); gtk_ctree_node_set_text(ctree, node, 9, tstr[9]); } static int net_group_connected(net_group_t* ng, int* cnt) { int result = 0; GList* dlist; net_t* net; if (cnt) *cnt = 0; for (dlist = ng->nets; dlist; dlist = dlist->next) { net = dlist->data; if (NET_CONNECTED(net)) result++; if (cnt) (*cnt)++; } return result; } /* static int net_group_online(net_group_t* ng) { int result = 0; GList* dlist; net_t* net; for (dlist = ng->nets; dlist; dlist = dlist->next) { net = dlist->data; if (NET_ONLINE(net)) result++; } return result; } */ void network_connect_next() { GList* dlist; GList* dlist2; net_t* net; net_group_t* ng; server_t* server; int num1; int num2; if (global.status.exiting != E_NONE) return; if (global_queue_size()/1024. > global.options.autoconnect_sendqueue_limit) { return; } for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; if (!ng->nets_connecting) continue; num1 = net_group_connected(ng, &num2); if (num1 == num2) continue; // all connected if (ng->how_many > 0 && ng->how_many <= num1) continue; // enough connected net = ng->nets_connecting->data; ng->nets_connecting = g_list_remove(ng->nets_connecting, net); ng->nets_connecting = g_list_append(ng->nets_connecting, net); if (net->active_server) continue; for (dlist2 = net->servers; dlist2; dlist2 = dlist2->next) { server = dlist2->data; if (server->flags & SERVER_IGNORE) continue; if (server->status != SERVER_OFFLINE) continue; net->servers = g_list_remove(net->servers, server); net->servers = g_list_append(net->servers, server); server_connect(server); break; } } } void network_start_connect(net_t* net) { if (net) { if (net->flags & NETWORK_CONNECTING) return; net->flags |= NETWORK_CONNECTING; net->group->nets_connecting = g_list_append(net->group->nets_connecting, net); network_update(net, 0); } } void network_cancel_connect(net_t* net) { GList* dlist2; server_t* server; if (!net) return; if (!(net->flags & NETWORK_CONNECTING)) return; net->flags &= ~NETWORK_CONNECTING; net->group->nets_connecting = g_list_remove(net->group->nets_connecting, net); network_update(net, 0); for (dlist2 = net->servers; dlist2; dlist2 = dlist2->next) { server = dlist2->data; if (server->status == SERVER_CANCELED) server->status = SERVER_OFFLINE; if (server->timeout >= 0) { gtk_timeout_remove(server->timeout); server->timeout = -1; } } } void network_disconnect(net_t* net) { if (!net) return; network_cancel_connect(net); if (net->active_server) server_disconnect(net->active_server, "User disconnect", 1); } void napigator_enter() { if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); gtk_clist_freeze(GTK_CLIST(ctree)); napi_busy = 1; } void napigator_leave(int success) { GList* dlist; GList* dlist2; net_t* net; net_group_t* ng; napi_busy = 0; if (!success) { server_all_del_flag(SERVER_MARKED); } else { server_handle_marked(); } server_save(); for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; for (dlist2 = ng->nets; dlist2; dlist2 = dlist2->next) { net = dlist2->data; network_update(net, 1); } } if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); gtk_clist_thaw(GTK_CLIST(ctree)); } void napigator_read(gpointer data, int source, GdkInputCondition condition) { int res; char buf[1025]; char buf2[1025]; char *pos1; char *pos2; char *ip; char *port; char *network; char *users; char *files; char *gigs; char *server; char *linespeed; socket_t *socket = data; net_t* net; net_group_t* ng; server_t* serv; if (condition != GDK_INPUT_READ) { info_dialog("Could not retrieve server list"); socket_destroy(socket, 0); return; } switch (res = recv(source, buf, 1024, MSG_PEEK)) { case -1: info_dialog("Could not read server list"); socket_destroy(socket, 0); return; case 0: napigator_leave(1); socket->data = NULL; socket_destroy(socket, 0); return; default: break; } buf[res] = 0; pos1 = buf; while ((pos2 = strchr(pos1, '\n')) != NULL) { res = pos2 - pos1 + 1; socket->cnt = 0; if (recv_safe(source, buf2, res, res) != res) { socket_destroy(socket, 0); return; } buf2[res - 1] = 0; if (buf2[res - 2] == '\r') buf2[res - 2] = 0; arg(buf2, 0); // unknown ip = arg(NULL, 0); port = arg(NULL, 0); network = arg(NULL, 0); linespeed = arg(NULL, 0); users = arg(NULL, 0); files = arg(NULL, 0); gigs = arg(NULL, 0); server = arg(NULL, 0); if (!server) { if (!network) goto close; users = ip; files = port; gigs = network; } else { if (!strcmp(network, "n/a") || !strcmp(network, "N/A")) network = server; // arg(NULL, 0); // rating?? // arg(NULL, 0); // 0 (unknown) // arg(NULL, 0); // 0 (unknown) // arg(NULL, 0); // E-mail // arg(NULL, 0); // http net = net_group_search_network(network); if (!net) { ng = net_group_create("New Networks", NG_NEVER_CONNECT, 10); net = network_new(network, NETWORK_NAPSTER); net_group_add_net(ng, net); } serv = network_search_server(net, server); if (serv) { serv->flags &= ~(SERVER_NO_NAPI|SERVER_MARKED); serv->port = atoi(port); serv->users = atoi(users); serv->files = atoi(files); serv->gigs = atoi(gigs); serv->ip = inet_addr(ip); serv->linespeed = atoi(linespeed); server_update(serv); } else { serv = server_create(server, ip, atoi(port), users, files, gigs, linespeed, 0); network_add_server(net, serv); } } pos1 = pos2 + 1; } return; close: socket_destroy(socket, 0); } void napigator_read_header(gpointer data, int source, GdkInputCondition condition) { int res; int n; char buf[1025]; char buf2[1025]; char *pos1; char *pos2; socket_t *socket = (socket_t *) data; if (condition != GDK_INPUT_READ) { info_dialog("Could not retrieve header from server list"); socket_destroy(socket, 0); return; } switch (res = recv(source, buf, 1024, MSG_PEEK)) { case -1: info_dialog("Could not read sererlist host"); socket_destroy(socket, 0); return; case 0: info_dialog("Connection hangup"); socket_destroy(socket, 0); return; default: break; } pos1 = buf; while ((pos2 = strchr(pos1, '\n')) != NULL) { n = pos2 - pos1 + 1; if (recv_safe(source, buf2, n, n) != n) { socket_destroy(socket, 0); return; } buf2[n - 2] = 0; if (*buf2 == 0) { gdk_input_remove(socket->input); socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(napigator_read), socket); return; } pos1 = pos2 + 1; } } void napigator_request(gpointer data, int source, GdkInputCondition condition) { socket_t *socket = (socket_t *) data; char* request; char* full_request; if (condition != GDK_INPUT_WRITE) { info_dialog("Could not retrieve server list"); socket_destroy(socket, 0); return; } gdk_input_remove(socket->output); socket->output = -1; request = g_strdup_printf ("/%s HTTP/1.0\r\nHost: %s\r\nConnection: Close\r\n\r\n", global.naplist.document?global.naplist.document:NAPLIST_DOC, global.naplist.host?global.naplist.host:NAPLIST_HOST); if (global.naplist.use_proxy) { full_request = g_strdup_printf ("GET http://%s/%s", global.naplist.host?global.naplist.host:NAPLIST_HOST, request); } else { full_request = g_strdup_printf("GET %s", request); } if (send_safe(source, full_request, strlen(full_request), strlen(full_request)) != (int)strlen(full_request)) { socket_destroy(socket, 0); } else { socket->input = gdk_input_add(source, GDK_INPUT_READ, napigator_read_header, socket); } g_free(request); g_free(full_request); } void napigator_resolver(socket_t* socket, unsigned long ip_long) { // check socket for validity if (!g_list_find(global.sockets, socket)) return; if (ip_long == INADDR_NONE) { info_dialog("Could not resolve napigator url"); socket_destroy(socket, 0); return; } socket->ip_long = ip_long; if (!connect_socket(socket, "TCP", SOCK_STREAM)) { info_dialog("Could not connect to NapList"); socket_destroy(socket, 0); return; } socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(napigator_request), socket); } void napigator_get_list() { socket_t* socket; if (napi_busy) return; napigator_enter(); server_all_set_flag(SERVER_MARKED); socket = socket_new(S_HTTP); socket->data = (void*)(-1); if (global.naplist.use_proxy) { if (!global.naplist.proxy_host || global.naplist.proxy_host[0] == 0) { info_dialog("Please specify a proxy host if you wish to use one"); return; } socket->port = htons(global.naplist.proxy_port); resolve_address(global.naplist.proxy_host, (call_func_t)napigator_resolver, socket); } else { socket->port = htons(80); resolve_address(global.naplist.host?global.naplist.host:NAPLIST_HOST, (call_func_t)napigator_resolver, socket); } } ///////////////////// void read_allowed_links() { char *File; FILE *file; char line[500]; char *net; char *server1; char *server2; char *last; server_link_t* link; time_t tim; File = g_strdup_printf("%s/links.allow", global.options.config_dir); if ((file = fopen(File, "r")) == NULL) { g_free(File); return; } g_free(File); while (mfgets(line, sizeof(line), file)) { if ((line[0] == '#') || (line[0] == ' ')) continue; net = arg(line, 0); server1 = arg(NULL, 0); server2 = arg(NULL, 0); last = arg(NULL, 0); if (!last) continue; tim = strtoul(last, NULL, 10); if (global.current_time - tim > 60*60*24*30) continue; link = add_allowed_link(net, server1, server2); link->link_time = tim; } fclose(file); } void write_allowed_links() { char* File; FILE *file; GList *dlist; server_link_t *link; if (!global.server_links) return; File = g_strdup_printf("%s/links.allow", global.options.config_dir); if ((file = fopen(File, "w")) == NULL) { g_warning("Could not write links.allow"); g_free(File); return; } g_free(File); for (dlist = global.server_links; dlist; dlist = dlist->next) { link = dlist->data; fprintf(file, "%s %s %s %lu\n", link->net, link->server1, link->server2, link->link_time); } fclose(file); } void problems_read(gpointer data, int source, GdkInputCondition condition) { GtkText *text; int res; #ifndef HAVE_LIBLCONV_H char buf[1025]; char buf2[1025]; #else char buf[2047]; char buf2[2047]; char lconv_buf[2047]; #endif char *pos1; char *pos2; socket_t *socket = (socket_t *) data; if (condition != GDK_INPUT_READ) { socket_destroy(socket, 0); return; } switch (res = recv(source, buf, 1024, MSG_PEEK)) { case -1: socket_destroy(socket, 0); return; case 0: socket_destroy(socket, 0); return; default: break; } buf[res] = 0; #ifdef HAVE_LIBLCONV_H if (global.options.use_iconv) { lconv_conv(LCONV_AUTO, local_codeset, global.options.dest_codeset, lconv_buf, buf); strcpy(buf, lconv_buf); } #endif socket->cnt = 0; pos1 = buf; while ((pos2 = strchr(pos1, '\n')) != NULL) { res = pos2 - pos1 + 1; if (recv_safe(source, buf2, res, res) != res) { socket_destroy(socket, 0); return; } buf2[res] = 0; text = GTK_TEXT(socket->data); text_print_text(text, "%s", buf2); pos1 = pos2 + 1; } return; } void problems_read_header(gpointer data, int source, GdkInputCondition condition) { GtkWidget *win; GtkText *text; int res; int n; #ifndef HAVE_LIBLCONV_H char buf[1025]; char buf2[1025]; #else char buf[2047]; char buf2[2047]; char lconv_buf[2047]; #endif char *pos1; char *pos2; socket_t *socket = (socket_t *) data; if (condition != GDK_INPUT_READ) { socket_destroy(socket, 0); return; } switch (res = recv(source, buf, 1024, MSG_PEEK)) { case -1: socket_destroy(socket, 0); return; case 0: socket_destroy(socket, 0); return; default: break; } #ifdef HAVE_LIBLCONV_H if (global.options.use_iconv) { lconv_conv(LCONV_AUTO, local_codeset, global.options.dest_codeset, lconv_buf, buf); strcpy(buf, lconv_buf); } #endif pos1 = buf; while ((pos2 = strchr(pos1, '\n')) != NULL) { n = pos2 - pos1 + 1; if (recv_safe(source, buf2, n, n) != n) { socket_destroy(socket, 0); return; } buf2[n - 2] = 0; if (*buf2 == 0) { win = create_information_win(); // gtk_window_set_default_size(GTK_WINDOW(win), -1, 600); gtk_widget_show(win); gtk_window_set_title(GTK_WINDOW(win), "News"); text = GTK_TEXT(lookup_widget(win, "text15")); gtk_text_set_word_wrap(text, 1); text_print_text(text, "$r-------------------------\n" "$r News ($b"VERSION"$r)\n" "$r-------------------------\n" ); socket->data = text; gdk_input_remove(socket->input); socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(problems_read), socket); return; } pos1 = pos2 + 1; } } void problems_request(gpointer data, int source, GdkInputCondition condition) { socket_t *socket = (socket_t *) data; char t[1024]; client_message(NULL, "Requesting News........"); if (condition != GDK_INPUT_WRITE) { client_message("Error", "Could not connect to lopster.sourceforge.net\n"); socket_destroy(socket, 0); return; } gdk_input_remove(socket->output); socket->output = -1; sprintf(t, "GET /news.php3?version=%s HTTP/1.0\nHost: lopster.sourceforge.net\n\n", VERSION); if (send_safe(source, t, strlen(t), strlen(t)) != (signed)strlen(t)) { socket_destroy(socket, 0); return; } socket->input = gdk_input_add(source, GDK_INPUT_READ, problems_read_header, socket); } void lopster_resolver(socket_t* socket, unsigned long ip_long) { if (!g_list_find(global.sockets, socket)) return; socket->ip_long = ip_long; if (ip_long == INADDR_NONE) { client_message("Error", "Could not resolve lopster.sourceforge.net\n"); socket_destroy(socket, 0); return; } if (!connect_socket(socket, "TCP", SOCK_STREAM)) { client_message("Error", "Could not connect to lopster.sourceforge.net\n"); socket_destroy(socket, 0); return; } socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(problems_request), socket); } void problems_get() { socket_t *socket = socket_new(S_HTTP); socket->port = htons(80); resolve_address("lopster.sourceforge.net", (call_func_t)lopster_resolver, socket); } ///////////////////////////////// void latest_version_read(gpointer data, int source, GdkInputCondition condition) { int res; char buf[1025]; char buf2[1025]; char *pos1; char *pos2; char *version; char *number; socket_t *socket = (socket_t *) data; if (condition != GDK_INPUT_READ) { socket_destroy(socket, 0); return; } switch (res = recv(source, buf, 1024, MSG_PEEK)) { case -1: socket_destroy(socket, 0); return; case 0: socket_destroy(socket, 0); return; default: break; } buf[res] = 0; socket->cnt = 0; pos1 = buf; while ((pos2 = strchr(pos1, '\n')) != NULL) { res = pos2 - pos1 + 1; if (recv_safe(source, buf2, res, res) != res) { socket_destroy(socket, 0); return; } buf2[res - 1] = 0; ///// version = arg(buf2, 0); if (version && !g_strcasecmp(version, "Version")) { version = arg(NULL, 0); number = arg(NULL, 0); if (number) { global.lnumber = atoi(number); set_title(); } if (version) { if (socket->data) { check_version_dialog(version); } else if (version_is_up_to_date(version) == 0) { new_version_dialog(version); } } socket_destroy(socket, 0); return; } ///// pos1 = pos2 + 1; } return; } void latest_version_read_header(gpointer data, int source, GdkInputCondition condition) { int res; int n; char buf[1025]; char buf2[1025]; char *pos1; char *pos2; char *pos3; socket_t *socket = (socket_t *) data; if (condition != GDK_INPUT_READ) { socket_destroy(socket, 0); return; } switch (res = recv(source, buf, 1024, MSG_PEEK)) { case -1: socket_destroy(socket, 0); return; case 0: socket_destroy(socket, 0); return; default: break; } pos1 = buf; while ((pos2 = strchr(pos1, '\n')) != NULL) { n = pos2 - pos1 + 1; if (recv_safe(source, buf2, n, n) != n) { socket_destroy(socket, 0); return; } buf2[n - 2] = 0; if (*buf2 == 0) { gdk_input_remove(socket->input); socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(latest_version_read), socket); return; } if (!strncasecmp(buf2, "HTTP", 4)) { pos3 = arg(buf2, 0); pos3 = arg(NULL, 0); if (!pos3 || strcmp(pos3, "200")) { socket_destroy(socket, 0); return; } } pos1 = pos2 + 1; } } void latest_version_request(gpointer data, int source, GdkInputCondition condition) { socket_t *socket = (socket_t *) data; char t[1024]; static int inc_count = 1; if (condition != GDK_INPUT_WRITE) { socket_destroy(socket, 0); return; } gdk_input_remove(socket->output); socket->output = -1; if (inc_count) { strcpy(t, "GET /LATEST_VERSION.php3?mode=1 HTTP/1.0\nHost: lopster.sourceforge.net\n\n"); inc_count = 0; } else { strcpy(t, "GET /LATEST_VERSION.php3?mode=0 HTTP/1.0\nHost: lopster.sourceforge.net\n\n"); } if (send_safe(source, t, strlen(t), strlen(t)) != (signed)strlen(t)) { socket_destroy(socket, 0); return; } socket->input = gdk_input_add(source, GDK_INPUT_READ, latest_version_read_header, socket); } void lopster_resolver2(socket_t* socket, unsigned long ip_long) { if (!g_list_find(global.sockets, socket)) return; socket->ip_long = ip_long; if (ip_long == INADDR_NONE) { socket_destroy(socket, 0); return; } if (!connect_socket(socket, "TCP", SOCK_STREAM)) { socket_destroy(socket, 0); return; } socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(latest_version_request), socket); } void latest_version_get(int just_check) { socket_t *socket = socket_new(S_HTTP); socket->data = (void *) just_check; socket->port = htons(80); resolve_address("lopster.sourceforge.net", (call_func_t)lopster_resolver2, socket); } GtkWidget* create_stats_popup() { GtkWidget *popup; GtkWidget *item; char str[1024]; GList* dlist; net_t* net; popup = gtk_menu_new(); if (!global.net_active) { item = gtk_menu_item_new_with_label("Not connected"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); } else { for (dlist = global.net_active; dlist; dlist = dlist->next) { net = dlist->data; sprintf(str, "[%s] %d Users, %d Files, %d GB", net->name, net->active_server->users, net->active_server->files, net->active_server->gigs); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); } } return popup; } void network_set_autojoin(char* network, char* channels) { net_t* net; net = net_group_search_network(network); if (!net) return; make_list_from_string(&(net->auto_join), channels, " "); } void network_add_autojoin(net_t* network, char* channel) { if (channel && *channel) network->auto_join = g_list_append(network->auto_join, g_strdup(channel)); } void network_autojoin_channels(net_t* net) { GList* dlist; char* channel; if (!net) return; for (dlist = net->auto_join; dlist; dlist = dlist->next) { channel = dlist->data; join_channel(net, channel); } } void on_name_pass_clicked(GtkButton *button, gpointer user_data) { net_t* network = user_data; GtkWidget* entry; char* name; char* passwd; char* name1; char* passwd1; if (!network) return; entry = gtk_object_get_data(GTK_OBJECT(button), "entry_name"); name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); entry = gtk_object_get_data(GTK_OBJECT(button), "entry_pass"); passwd = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); name1 = arg(name, 0); passwd1 = arg(passwd, 0); if (name1 && passwd1) { if (strcmp(network->user.username, name1)) { strcpy(network->user.username, name1); command_send(network, CMD_CHANGE_NICK, name1); } if (strcmp(network->user.password, passwd1)) { strcpy(network->user.password, passwd1); command_send(network, CMD_CHANGE_PASS, passwd1); } entry = gtk_object_get_data(GTK_OBJECT(button), "window"); gtk_widget_destroy(entry); server_save(); } g_free(name); g_free(passwd); } void on_reset_clicked(GtkButton *button, gpointer user_data ATTR_UNUSED) { GtkWidget* entry; if (global.username && global.password) { entry = gtk_object_get_data(GTK_OBJECT(button), "entry_name"); gtk_entry_set_text(GTK_ENTRY(entry), global.username); entry = gtk_object_get_data(GTK_OBJECT(button), "entry_pass"); gtk_entry_set_text(GTK_ENTRY(entry), global.password); } } void on_change_cancel_clicked(GtkButton *button ATTR_UNUSED, gpointer user_data) { GtkWidget* window = user_data; gtk_widget_destroy(window); } GtkWidget* create_user_passwd (net_t* network) { GtkWidget *window; GtkWidget *frame; GtkWidget *vbox1; GtkWidget *vbox2; GtkWidget *hbox1; GtkWidget *label; GtkWidget *table; GtkWidget *entry1; GtkWidget *entry2; GtkWidget *hseparator; GtkWidget *button; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Change Username and Password"); frame = gtk_frame_new (NULL); gtk_widget_show (frame); gtk_container_add (GTK_CONTAINER (window), frame); gtk_container_set_border_width (GTK_CONTAINER (frame), 5); vbox1 = gtk_vbox_new (FALSE, 5); gtk_widget_show (vbox1); gtk_container_add (GTK_CONTAINER (frame), vbox1); gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); vbox2 = gtk_vbox_new (FALSE, 5); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0); hbox1 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox1); gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 0); label = gtk_label_new ("Network: "); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0); label = gtk_label_new (network->name); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0); gtk_widget_set_style(label, global.styles[STYLE_PREF]); table = gtk_table_new (2, 2, FALSE); gtk_widget_show (table); gtk_box_pack_start (GTK_BOX (vbox2), table, TRUE, TRUE, 0); gtk_table_set_col_spacings (GTK_TABLE (table), 5); hbox1 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox1); gtk_table_attach (GTK_TABLE (table), hbox1, 0, 1, 1, 2, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); label = gtk_label_new ("Password"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0); hbox1 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox1); gtk_table_attach (GTK_TABLE (table), hbox1, 0, 1, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); label = gtk_label_new ("Username"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0); entry1 = gtk_entry_new (); gtk_widget_show (entry1); gtk_table_attach (GTK_TABLE (table), entry1, 1, 2, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_entry_set_text(GTK_ENTRY(entry1), network->user.username); entry2 = gtk_entry_new (); gtk_widget_show (entry2); gtk_table_attach (GTK_TABLE (table), entry2, 1, 2, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_entry_set_visibility (GTK_ENTRY (entry2), FALSE); gtk_entry_set_text(GTK_ENTRY(entry2), network->user.password); hseparator = gtk_hseparator_new (); gtk_widget_show (hseparator); gtk_box_pack_start (GTK_BOX (vbox1), hseparator, FALSE, FALSE, 0); frame = gtk_frame_new (NULL); gtk_widget_show (frame); gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 0); gtk_widget_set_usize (frame, -2, 41); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); hbox1 = gtk_hbox_new (TRUE, 5); gtk_widget_show (hbox1); gtk_container_add (GTK_CONTAINER (frame), hbox1); gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); button = gtk_button_new_with_label ("Ok"); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox1), button, TRUE, TRUE, 0); gtk_object_set_data (GTK_OBJECT (button), "entry_name", entry1); gtk_object_set_data (GTK_OBJECT (button), "entry_pass", entry2); gtk_object_set_data (GTK_OBJECT (button), "window", window); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_name_pass_clicked), network); button = gtk_button_new_with_label ("Reset to Default"); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox1), button, TRUE, TRUE, 0); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_reset_clicked), network); gtk_object_set_data (GTK_OBJECT (button), "entry_name", entry1); gtk_object_set_data (GTK_OBJECT (button), "entry_pass", entry2); gtk_object_set_data (GTK_OBJECT (button), "window", window); button = gtk_button_new_with_label ("Cancel"); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox1), button, TRUE, TRUE, 0); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_change_cancel_clicked), window); gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (gtk_widget_destroy), window); return window; } void on_how_many(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_group_t* ng = st_ng; if (!ng) return; ng->how_many = (int)user_data; server_save(); } void on_ng_startconnect(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_group_t* ng = user_data; if (!ng) return; ng->flags ^= NG_STARTUP_CONNECT; server_save(); } void on_ng_autoconnect(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_group_t* ng = user_data; if (!ng) return; ng->flags ^= NG_NEVER_CONNECT; server_save(); } void on_ng_connect(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_group_t* ng = user_data; if (!ng) return; net_group_start_connect(ng); } void on_ng_remove(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { net_group_t* ng = user_data; if (!ng) return; net_group_hide(ng); net_group_destroy(ng); } void on_group_new_clicked(GtkButton * button ATTR_UNUSED, gpointer user_data) { GtkWidget* win; GtkWidget* temp; char *text; win = GTK_WIDGET(user_data); temp = lookup_widget(win, "entry"); if (!temp) return; text = gtk_entry_get_text(GTK_ENTRY(temp)); net_group_create(text, NG_NEVER_CONNECT, 10); gtk_widget_destroy(win); } void on_group_cancel_clicked(GtkButton * button ATTR_UNUSED, gpointer user_data) { GtkWidget* win; win = GTK_WIDGET(user_data); gtk_widget_destroy(win); } GtkWidget* create_new_group () { GtkWidget *win; GtkWidget *frame; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *entry; GtkWidget *hseparator; GtkWidget *button; win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), "Create new Network Group"); gtk_window_set_policy(GTK_WINDOW(win), FALSE, FALSE, FALSE); frame = gtk_frame_new(NULL); gtk_widget_show(frame); gtk_container_add(GTK_CONTAINER(win), frame); gtk_container_set_border_width(GTK_CONTAINER(frame), 5); vbox = gtk_vbox_new(FALSE, 5); gtk_widget_show(vbox); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); entry = gtk_entry_new(); gtk_object_set_data(GTK_OBJECT(win), "entry", entry); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0); hseparator = gtk_hseparator_new(); gtk_widget_show(hseparator); gtk_box_pack_start(GTK_BOX(vbox), hseparator, FALSE, FALSE, 0); frame = gtk_frame_new(NULL); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); gtk_widget_set_usize(frame, -2, 41); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); hbox = gtk_hbox_new(TRUE, 5); gtk_widget_show(hbox); gtk_container_add(GTK_CONTAINER(frame), hbox); gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); button = gtk_button_new_with_label("Add"); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT(button), "clicked", on_group_new_clicked, win); button = gtk_button_new_with_label("Cancel"); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_signal_connect(GTK_OBJECT(button), "clicked", on_group_cancel_clicked, win); gtk_signal_connect(GTK_OBJECT(win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroy), NULL); return win; } #define SUB_LEN 20 GtkWidget *create_netgroup_popup(GtkWidget* popup, net_group_t* ng) { GtkWidget *item; GtkWidget *popup2; GtkWidget *popup3; int i1; GtkWidget* items[SUB_LEN+1]; int no_nets, inc; char str[128]; if (!popup) popup = gtk_menu_new(); st_ng = ng; no_nets = g_list_length(ng->nets); inc = (no_nets+SUB_LEN-1)/SUB_LEN; if (ng->nets) { item = gtk_menu_item_new_with_label("Connect"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_ng_connect), ng); } else { item = gtk_menu_item_new_with_label("Remove Group"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_ng_remove), ng); } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Configure"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = gtk_menu_new(); gtk_widget_show(popup2); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); { item = gtk_menu_item_new_with_label("Stay connected to"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); popup3 = gtk_menu_new(); gtk_widget_show(popup3); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup3); if (ng->how_many == -1) strcpy(str, "All networks"); else sprintf(str, "%d networks", ng->how_many); item = gtk_menu_item_new_with_label(str); gtk_widget_show(item); gtk_widget_set_sensitive(item, FALSE); gtk_container_add(GTK_CONTAINER(popup3), item); item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup3), item); items[0] = gtk_menu_item_new_with_label ("All networks"); gtk_widget_show (items[0]); gtk_container_add (GTK_CONTAINER (popup3), items[0]); for (i1 = 0; i1*inc < no_nets; i1++) { sprintf(str, "%d networks", i1*inc); items[i1+1] = gtk_menu_item_new_with_label (str); gtk_widget_show(items[i1+1]); gtk_container_add(GTK_CONTAINER(popup3), items[i1+1]); } gtk_signal_connect(GTK_OBJECT(items[0]), "activate", GTK_SIGNAL_FUNC(on_how_many), (void*)-1); for (i1 = 0; i1*inc < no_nets; i1++) { gtk_signal_connect(GTK_OBJECT(items[i1+1]), "activate", GTK_SIGNAL_FUNC(on_how_many), (void*)(i1*inc)); } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_check_menu_item_new_with_label("Connect on Startup"); if (ng->flags & NG_STARTUP_CONNECT) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_ng_startconnect), ng); item = gtk_check_menu_item_new_with_label("Exclude from Autoconnect"); if (ng->flags & NG_NEVER_CONNECT) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup2), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_ng_autoconnect), ng); } return popup; } GtkWidget* create_netgroup1_popup(net_group_t* ng) { GtkWidget* popup; GtkWidget* item; popup = gtk_menu_new(); if (napi_busy) { item = gtk_menu_item_new_with_label("Retrieving server list\nWait until finished"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); return popup; } item = gtk_menu_item_new_with_label("Refresh List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_refresh_activate), NULL); item = gtk_menu_item_new_with_label("Create New Group"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_create_group), NULL); if (ng) { item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); create_netgroup_popup(popup, ng); } item = gtk_menu_item_new(); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Customize List"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_customize_list_activate), NULL); return popup; } void network_add_server(net_t* net, server_t* server) { if (!net || !server) return; server->net = net; net->servers = g_list_append(net->servers, server); server_show(server); } net_group_t* net_group_new(char* name) { net_group_t* ng; ng = g_malloc(sizeof(*ng)); ng->name = g_strdup(name); ng->flags = 0; ng->nets = NULL; ng->nets_connecting = NULL; ng->how_many = 0; ng->node = NULL; global.net_groups = g_list_append(global.net_groups, ng); return ng; } void net_group_destroy(net_group_t* ng) { if (!ng) return; global.net_groups = g_list_remove(global.net_groups, ng); g_free(ng->name); g_free(ng); } void net_group_show(net_group_t* ng) { GtkCTreeNode* node; GList* dlist; if (!ng) return; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); strcpy(tstr[0], ng->name); tstr[1][0] = 0; tstr[2][0] = 0; tstr[3][0] = 0; tstr[4][0] = 0; tstr[5][0] = 0; tstr[6][0] = 0; tstr[7][0] = 0; tstr[8][0] = 0; node = gtk_ctree_insert_node(ctree, NULL, NULL, list, 5, NULL, NULL, NULL, NULL, FALSE, (ng->how_many==1)?TRUE:FALSE); ng->node = node; gtk_ctree_node_set_row_data(ctree, node, ng); for (dlist = ng->nets; dlist; dlist = dlist->next) { net_t* net = dlist->data; network_show(net); network_update(net, 1); } net_group_update(ng); } void net_group_hide(net_group_t* ng) { GtkCTreeNode* node; node = ng->node; if (!node) g_warning("net group not shown"); if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); gtk_ctree_remove_node(ctree, node); ng->node = NULL; } net_group_t* net_group_search(char* name) { GList* dlist; net_group_t* ng; for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; if (!strcmp(name, ng->name)) return ng; } return NULL; } void net_group_remove_net(net_group_t* ng, net_t* net) { if (!ng || !net) return; ng->nets = g_list_remove(ng->nets, net); if (net->flags & NETWORK_CONNECTING) ng->nets_connecting = g_list_remove(ng->nets_connecting, net); net->group = NULL; network_hide(net); } void net_group_add_net(net_group_t* ng, net_t* net) { if (!ng || !net) return; net->group = ng; ng->nets = g_list_append(ng->nets, net); if (net->flags & NETWORK_CONNECTING) ng->nets_connecting = g_list_remove(ng->nets_connecting, net); network_show(net); } void network_move(net_t* net, net_group_t* to) { /* need to store old group as net_group_add_net changes it... */ net_group_t* from = net->group; net_group_remove_net(from, net); net_group_add_net(to, net); network_update(net, 1); net_group_update(from); net_group_update(to); } net_t* net_group_search_network(char* name) { GList* dlist; GList* dlist2; net_group_t* ng; net_t* net; for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; for (dlist2 = ng->nets; dlist2; dlist2 = dlist2->next) { net = dlist2->data; if (!strcasecmp(net->name, name)) return net; } } return NULL; } int network_stats(net_t* net, int mode) { int cnt; GList* dlist; server_t* server; int result; if (NET_CONNECTED(net)) { switch (mode) { case 0: return net->active_server->users; case 1: return net->active_server->files; case 2: return net->active_server->gigs; case 3: return net->active_server->linespeed; default: return 0; } } else { result = cnt = 0; for (dlist = net->servers; dlist; dlist = dlist->next) { server = dlist->data; if (server->users <= 0) continue; cnt++; switch (mode) { case 0: result += server->users; break; case 1: result += server->files; break; case 2: result += server->gigs; break; case 3: if (server->linespeed > result) result = server->linespeed; break; } } if (mode != 3) { if (cnt > 0) result /= cnt; else result = 0; } return result; } } int net_group_stats(net_group_t* ng, int mode) { GList* dlist; net_t* net; int result = 0; for (dlist = ng->nets; dlist; dlist = dlist->next) { net = dlist->data; if (!NET_CONNECTED(net)) continue; result += network_stats(net, mode); } return result; } net_group_t* net_group_create(char* name, int flags, int hm) { net_group_t* ng; ng = net_group_search(name); if (!ng) { ng = net_group_new(name); ng->flags = flags; ng->how_many = hm; net_group_show(ng); } return ng; } void net_group_start_connect(net_group_t* ng) { GList* dlist; net_t* net; if (ng) { for (dlist = ng->nets; dlist; dlist = dlist->next) { net = dlist->data; network_start_connect(net); } } else { for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; if (ng->flags & NG_NEVER_CONNECT) continue; net_group_start_connect(ng); } } } void net_group_startup_connect() { GList* dlist; net_group_t* ng; for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; if (ng->flags & NG_STARTUP_CONNECT) net_group_start_connect(ng); } } void net_group_disconnect(net_group_t* ng) { GList* dlist; net_t* net; if (ng) { for (dlist = ng->nets; dlist; dlist = dlist->next) { net = dlist->data; network_disconnect(net); } } else { for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; net_group_disconnect(ng); } } } void net_group_cancel_connect(net_group_t* ng) { GList* dlist; net_t* net; if (ng) { for (dlist = ng->nets; dlist; dlist = dlist->next) { net = dlist->data; network_cancel_connect(net); } } else { for (dlist = global.net_groups; dlist; dlist = dlist->next) { ng = dlist->data; net_group_cancel_connect(ng); } } } void net_group_update(net_group_t* ng) { GtkCTreeNode* node; int gigs = 0; int files = 0; int users = 0; int cnt = 0; if (!ng) return; if (!ctree) ctree = GTK_CTREE(lookup_widget(global.win, "ctree10")); node = ng->node; if (!node) return; cnt = net_group_connected(ng, NULL); if (cnt == 0) { tstr[2][0] = 0; tstr[4][0] = 0; tstr[5][0] = 0; tstr[6][0] = 0; tstr[7][0] = 0; tstr[8][0] = 0; tstr[8][0] = 0; } else { users = net_group_stats(ng, 0); files = net_group_stats(ng, 1); gigs = net_group_stats(ng, 2); sprintf(tstr[2], "%d Networks connected", cnt); sprintf(tstr[4], "%d", users); sprintf(tstr[5], "%d", files); sprintf(tstr[6], "%d", gigs); if (users > 0) sprintf(tstr[7], "%.1f", (double)gigs/(double)users); else strcpy(tstr[7], "n/a"); if (users > 0) sprintf(tstr[8], "%.1f", (double)files/(double)users); else strcpy(tstr[8], "n/a"); if (files > 0) sprintf(tstr[9], "%.1f", (double)gigs/(double)files*1024); else strcpy(tstr[9], "n/a"); } gtk_ctree_node_set_text(ctree, node, 2, tstr[2]); gtk_ctree_node_set_text(ctree, node, 4, tstr[4]); gtk_ctree_node_set_text(ctree, node, 5, tstr[5]); gtk_ctree_node_set_text(ctree, node, 6, tstr[6]); gtk_ctree_node_set_text(ctree, node, 7, tstr[7]); gtk_ctree_node_set_text(ctree, node, 8, tstr[8]); gtk_ctree_node_set_text(ctree, node, 9, tstr[9]); }