/* 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 #ifdef HAVE_LIBLCONV_H #include #endif #include "lopster.h" #include "callbacks.h" #include "connection.h" #include "transfer.h" #include "global.h" #include "search.h" #include "hotlist.h" #include "resume.h" #include "support.h" #include "chat.h" #include "share2.h" #include "handler.h" #include "browse.h" #include "userinfo.h" #include "clist_rename.h" #include "file_tree.h" #include "string_list.h" #include "utils.h" #include "scheme.h" #include "files.h" #include "log.h" static int browse_version = 0; static server_t* share_server = NULL; static browse_t* popup_browse = NULL; static browse_node_t* popup_node = NULL; gint await_conn_ack2(gpointer data, gint source, GdkInputCondition condition); gint send_browse_get(gpointer data, gint source, GdkInputCondition condition); void share_fill_buffer(share_t* share) { buffer_t* buffer; int added; file_node_t* node; file_t* file; if (share->buffer) buffer_destroy(share->buffer); share->buffer = buffer_new(1024); if (!global.lib) node = NULL; else node = FILE_TREE(global.lib)->files; buffer = share->buffer; while (node) { if (!node->file || !(node->flags & LIB_SHARED)) { node = file_node_next(node); continue; } file = node->file; if (buffer->datamax - buffer->datasize < 1024) buffer_resize(buffer, 1024); added = sprintf(buffer->data + buffer->datasize, "\"%s\" %s %lu %d %d %d\n", file->winname, file->md5, file->size, file->bitrate, file->frequency, file->duration); #ifdef HAVE_LIBLCONV_H if (global.options.use_iconv) { char* lconv_buf = lconv_strdup_conv(LCONV_SPEC, global.options.dest_codeset, local_codeset, buffer->data + buffer->datasize); added = strlen(lconv_buf); // replace the original buffer strcpy(buffer->data + buffer->datasize, lconv_buf); free(lconv_buf); } #endif buffer->datasize += added; node = file_node_next(node); } added = sprintf(buffer->data + buffer->datasize, "\n"); #ifdef HAVE_LIBLCONV_H if (global.options.use_iconv) { char* lconv_buf = lconv_strdup_conv(LCONV_SPEC, global.options.dest_codeset, local_codeset, buffer->data + buffer->datasize); added = strlen(lconv_buf); // replace the original buffer strcpy(buffer->data + buffer->datasize, lconv_buf); free(lconv_buf); } #endif buffer->datasize += added; } share_t *share_new(net_t* net, char* user) { share_t *share; share = g_malloc(sizeof(share_t)); transfer_init(TRANS(share), S_QUEUED); TRANS(share)->user_info = user_info_detect(net, user); share->nu.net = net; share->nu.user = g_strdup(user); share->buffer = NULL; return share; } void share_end(socket_t * socket, int mode) { share_t *share = socket->data; transfer_t* trans = TRANS(share); if (!share) return; share_status_set(socket, mode); if (share->buffer) { buffer_destroy(share->buffer); share->buffer = NULL; trans->timeleft = trans->stop_time - trans->start_time; if (trans->timeleft > 0) trans->rate = trans->transferred / trans->timeleft; else trans->rate = 0; } share_update(socket); } void share_hide(socket_t * socket) { GtkCList *clist; int row; if (!socket) return; if (socket->type != S_SHARE) return; clist = GTK_CLIST(lookup_widget(global.win, "transfer_up")); row = gtk_clist_find_row_from_data(clist, socket); if (row < 0) { g_warning("upload_hide(): transfer not found"); return; } gtk_clist_remove(clist, row); } void share_destroy(share_t *share) { if (!share) return; if (share->buffer) buffer_destroy(share->buffer); transfer_destroy(TRANS(share)); } gint share_push_output(gpointer data, gint source, GdkInputCondition condition) { socket_t *socket = data; share_t* share = socket->data; buffer_t* buffer = share->buffer; long maxpush; int sent; if (condition != GDK_INPUT_WRITE) { socket_destroy(socket, 0); return 1; } maxpush = upload_calc_max(TRANS(share)->user_info); if (!maxpush) { gdk_input_remove(socket->output); socket->output = -1; return 1; } if (maxpush > buffer->datasize - buffer->consumed) maxpush = buffer->datasize - buffer->consumed; if (maxpush > 0) { if ((sent = send_safe(source, buffer->data+buffer->consumed, 1, maxpush)) == -1) { socket_end(socket, S_INCOMPLETE); return 1; } else { socket->cnt = 0; buffer_consume_virt(buffer, sent); } global.up_width.bytes[0] += sent; TRANS(share)->user_info->bytes[1] += sent; TRANS(share)->transferred += sent; } if (buffer->consumed == buffer->datasize) { socket_end(socket, S_FINISHED); } return 1; } gint share_send_nick(gpointer data, gint source, GdkInputCondition condition) { socket_t *socket = data; share_t* share = socket->data; char *temp_str; if ((condition & GDK_INPUT_WRITE) == 0) { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->output); socket->output = -1; temp_str = g_strdup_printf("%s\n", share->nu.net->user.username); if (send_safe(source, temp_str, strlen(temp_str), strlen(temp_str)) == -1) { g_free(temp_str); socket_destroy(socket, 0); return 1; } g_free(temp_str); share_fill_buffer(share); share_status_set(socket, S_UPLOADING); socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(share_push_output), socket); return 1; } socket_t *share_search_mapable() { socket_t *socket; share_t *share; GList *dlist; for (dlist = global.sockets; dlist; dlist = dlist->next) { socket = (socket_t *) (dlist->data); if (socket->type != S_SHARE) continue; share = socket->data; if (!share) continue; if (TRANS(share)->status == S_WAITING) return socket; } return NULL; } gint share_fw_get_info(gpointer data, gint source ATTR_UNUSED, GdkInputCondition condition) { socket_t *socket = data; socket_t *socket2; share_t* share; if (condition != GDK_INPUT_WRITE) { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->output); socket->output = -1; socket2 = share_search_mapable(); if (socket2) { share = socket2->data; if (string_list_search(LIST_ENEMY, TRANS(share)->user_info->nick)) { socket_destroy(socket, S_DELETE); return 1; } // make sure to reset the destination transfer first if (socket2->fd >= 0) close(socket2->fd); socket2->fd = socket->fd; // should be -1 socket->fd = -1; socket2->ip_long = socket->ip_long; socket2->port = socket->port; socket_destroy(socket, S_DELETE); socket = socket2; socket->cnt = 0; } else { socket_destroy(socket, S_DELETE); return 1; } share_status_set(socket, S_INFO); socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(share_send_nick), socket); return 1; } static gint share_send_send(gpointer data, gint source, GdkInputCondition condition) { socket_t *socket = (socket_t *) data; if ((condition & GDK_INPUT_WRITE) == 0) { socket_destroy(socket, 0); return 1; } if (send_safe(source, "SENDLIST", 8, 8) != 8) { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->output); socket->output = -1; socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(share_send_nick), socket); return 1; } void print_transfer_prefix(chat_page_t* page, int down, char* text2, char* text3, char* nick, net_t* net, char* longname, char* shortname, char* nick2, net_t* net2); void share_status_set(socket_t * socket, int status) { share_t *share; int add; style_t *style; double val; char str[1024]; chat_page_t *page; GtkCList *clist; int row; transfer_t* trans; if (!socket) return; share = socket->data; if (!share) return; trans = TRANS(share); add = transfer_status_dist(trans->status, status); if (add < 0) check_uploads_again(); if (trans->user_info) trans->user_info->cur[1] += add; global.limit.cur_uploads += add; if (status == S_UPLOADING) { global.limit.cur_real_uploads++; trans->user_info->real_cur[1]++; trans->start_time = global.current_time; trans->transferred = 0; } else if (add > 0) trans->start_time = global.current_time; if (trans->status == S_UPLOADING) { global.limit.cur_real_uploads--; trans->user_info->real_cur[1]--; trans->stop_time = global.current_time; } if (status == S_UPLOADING) { l_log(NULL, "uploads", LOG_OTHER, "Uploading [Shared List] to [%s]\n", trans->user_info->nick); if ((global.options.no_piping & NOPIPE_UPLOAD) == 0) { if (global.options.piping & PIPE_UPLOAD) { page = chat_page_search(NULL, "Uploads", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Uploads", "Uploads"); } else { page = chat_page_get_printable();; } print_size(str, share->buffer->datasize); print_transfer_prefix(page, 0, "start", str, share->nu.user, share->nu.net, "Shared List", "Shared List", NULL, NULL); } } else if (trans->status == S_UPLOADING) { if (trans->stop_time - trans->start_time > 0) val = trans->transferred / (trans->stop_time - trans->start_time); else val = 0; print_speed(str, val, 1); l_log(NULL, "uploads", LOG_OTHER, "Ending [Shared List] to [%s] :%s: [%ld] (%s)\n", trans->user_info->nick, status_names(status), share->buffer->consumed, str); if ((global.options.no_piping & NOPIPE_UPLOAD) == 0) { if (global.options.piping & PIPE_UPLOAD) { page = chat_page_search(NULL, "Uploads", P_OTHER, 3); if (!page) page = create_other_page(NULL, "Uploads", "Uploads"); } else { page = chat_page_get_printable(); } print_transfer_prefix(page, 0, status_names(status), str, share->nu.user, share->nu.net, "Shared List", "Shared List", NULL, NULL); } } trans->status = status; share_update(socket); clist = GTK_CLIST(lookup_widget(global.win, "transfer_up")); row = gtk_clist_find_row_from_data(clist, socket); if (row < 0) return; if (status == S_UPLOADING) { style = style_get(global.scheme, "transfer_running"); if (style) { gtk_clist_set_background(clist, row, style->back); gtk_clist_set_foreground(clist, row, style->fore); } } else { gtk_clist_set_background(clist, row, NULL); gtk_clist_set_foreground(clist, row, NULL); } } void share_update(socket_t * socket) { GtkCList *clist; int row; char str[200]; GdkPixmap *pixmap = NULL; GdkBitmap *bitmap = NULL; share_t *share; transfer_t* trans; if (!socket) return; share = socket->data; trans = TRANS(share); clist = GTK_CLIST(lookup_widget(global.win, "transfer_up")); row = gtk_clist_find_row_from_data(clist, socket); if (row < 0) return; strcpy(str, LineSpeed(trans->user_info->linespeed)); gtk_clist_set_text(clist, row, 4, str); // filesize if (share->buffer) sprintf(str, "%s [%.1f%%]", print_size(tstr[1], share->buffer->datasize), (double)(share->buffer->consumed)*100/ (double)(share->buffer->datasize)); else *str = 0; gtk_clist_set_text(clist, row, 1, str); // status if (trans->status == S_WAITING) sprintf(str, "%d Waiting", (socket->max_cnt - socket->cnt)); else strcpy(str, status_names(trans->status)); gtk_clist_set_text(clist, row, 3, str); // progress if ((trans->status == S_UPLOADING) && (share->buffer)) { gtk_clist_get_pixmap(clist, row, 5, &pixmap, &bitmap); pixmap = transfer_draw_progress(clist, pixmap, 0, share->buffer->consumed, share->buffer->datasize, share->buffer->datasize, 0, clist->column[5].width); gtk_clist_set_pixmap(clist, row, 5, pixmap, NULL); } else { gtk_clist_set_text(clist, row, 5, ""); } if (trans->rate > 0 || trans->status == S_UPLOADING) { print_speed(str, (int) trans->rate, 1); up_speed_pixs(trans->rate, &pixmap, &bitmap); gtk_clist_set_pixtext(clist, row, 6, str, 5, pixmap, bitmap); } else { gtk_clist_set_text(clist, row, 6, ""); } if (trans->rate > 0) { print_time_unit(str, trans->timeleft); } else if (trans->status == S_UPLOADING) { sprintf(str, "stalled"); } else { *str = 0; } gtk_clist_set_text(clist, row, 7, str); return; } void share_show(socket_t* socket) { GtkCList *temp; int row; share_t *share = socket->data; transfer_t* trans = TRANS(share); temp = GTK_CLIST(lookup_widget(global.win, "transfer_up")); row = gtk_clist_find_row_from_data(temp, socket); if (row >= 0) return; strcpy(tstr[0], "Library upload"); print_size(tstr[1], 0); sprintf(tstr[2], "[%s] %s", share->nu.net?NetType[share->nu.net->type]:"?", trans->user_info->nick); strcpy(tstr[4], LineSpeed(trans->user_info->linespeed)); tstr[3][0] = tstr[5][0] = tstr[6][0] = 0; row = gtk_clist_append(temp, list); gtk_clist_set_row_data(temp, row, (gpointer) socket); share_update(socket); } gint await_conn_ack3(gpointer data, gint source, GdkInputCondition condition) { char c; socket_t *socket = (socket_t *) data; if ((condition & GDK_INPUT_READ) == 0) { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->input); socket->input = -1; if (recv_safe(source, &c, 1, 1) != 1) { socket_destroy(socket, 0); return 1; } if (c != '1') { socket_destroy(socket, 0); return 1; } share_status_set(socket, S_INFO); socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(share_send_send), socket); return 1; } static int browse_node_status(file_tree_t* tree, file_node_t* node) { int result = 0; if (!node->file) return 0; if (BROWSE_NODE(node)->first_seen == tree->last_refreshed) result |= (1<<2); // its a new shared file if (BROWSE_NODE(node)->last_seen == tree->last_refreshed) result |= (1<<1); // its an shared file else result |= (1<<0); // its unshared return result; } static void browse_update_user(file_tree_t* tree) { GtkWidget* area = NULL; char str[1024]; double percent; int width, height; int posx; int posy; browse_t* browse = BROWSE_TREE(tree); GtkStyle* style; int dx, dy; if (!browse) return; area = tree->progress; if (!area) return; if (!area->window) return; if (!GTK_WIDGET_REALIZED(global.progressbar)) gtk_widget_realize(global.progressbar); style = global.progressbar->style; dx = style->klass->xthickness; dy = style->klass->ythickness; width = area->allocation.width; height = area->allocation.height; gtk_paint_box (style, area->window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, area, "trough", 0, 0, width, height); if (browse->status < 0) percent = 100.; else if (browse->userinfo && browse->userinfo->shares > 0) percent = (double)browse->status/(double)(browse->userinfo->shares); else percent = 100.; posx = (width - 2*dx) * percent; if (posx > width-2*dx) posx = width-2*dx; if (posx > 0) gtk_paint_box(style, area->window, browse->status<0?GTK_STATE_NORMAL:GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, NULL, area, "bar", dx, dy, posx, height-2*dy); if (browse->status < 0) { strcpy(str, "Done"); } else if (browse->userinfo) { sprintf(str, "%d / %d", browse->status, browse->userinfo->shares); } else { sprintf(str, "%d / ??", browse->status); } posx = (width - 2*dx - gdk_string_width(style->font, str)) / 2; posy = (height + style->font->ascent)/2 - dy +1; gdk_draw_text (area->window, style->font, style->fg_gc[GTK_STATE_NORMAL], posx, posy, str, strlen (str)); } static void browse_save_node(FILE* fd, file_node_t* node, int indent) { file_t* file; while (node) { file = node->file; if (file) { fprintf(fd, "%*s", indent, ""); qfprintf(fd, "FILE %S %s %ld %d %d %d %lu %lu\n", file->filename, file->md5, file->size, file->bitrate, file->frequency, file->duration, BROWSE_NODE(node)->first_seen, BROWSE_NODE(node)->last_seen); } else if (node->child) { fprintf(fd, "%*s", indent, ""); qfprintf(fd, "DIR %S {\n", node->name); browse_save_node(fd, node->child, indent+2); fprintf(fd, "%*s}\n", indent, ""); } node = node->next; } } //////// void browse_insert_file(browse_t* browse, file_t* file) { file_node_t* node; node = file_tree_insert_file(FILE_TREE(browse), file); if (node) BROWSE_NODE(node)->last_seen = 0; browse->status++; } HANDLER(nap_browse_end); gint get_browse_files(gpointer data, gint source, GdkInputCondition condition) { int res; char buf[2049]; char *filename; char *md5; char *size; char *bitrate; char *frequency; char *duration; socket_t *socket = data; file_t *file; char *pos1; char *pos2; browse_t *browse = socket->data; buffer_t* buffer = browse->buffer; if ((condition & GDK_INPUT_READ) == 0) { socket_destroy(socket, 0); return 1; } if ((res = recv_safe(source, buffer->data + buffer->datasize, 0, buffer->datamax - buffer->datasize - 1)) == -1) { socket_destroy(socket, 0); return 1; } buffer->data[buffer->datasize + res] = 0; #ifdef HAVE_LIBLCONV_H if (global.options.use_iconv) { char* lconv_buf = lconv_strdup_conv(LCONV_SPEC, local_codeset, global.options.dest_codeset, buffer->data + buffer->datasize); res = strlen(lconv_buf); if (res >= buffer->datamax - buffer->datasize -1) buffer_resize(buffer, res); strcpy(buffer->data+buffer->datasize, lconv_buf); free(lconv_buf); } #endif buffer->datasize += res; global.down_width.bytes[0] += res; buffer->data[buffer->datasize] = 0; pos1 = buffer->data; while ((pos2 = strchr(pos1, '\n'))) { *pos2 = 0; if (!(filename = arg(pos1, 0))) goto close; if (!(md5 = arg(NULL, 0))) goto close; if (!(size = arg(NULL, 0))) goto close; if (!(bitrate = arg(NULL, 0))) goto close; if (!(frequency = arg(NULL, 0))) goto close; if (!(duration = arg(NULL, 0))) goto close; file = file_new(); file_set_winname(file, filename); file->user = g_strdup(FILE_TREE(browse)->name); file->md5 = g_strdup(md5); file->size = strtoul(size, NULL, 10); file->bitrate = atoi(bitrate); file->frequency = atoi(frequency); file->duration = atoi(duration); file->net = browse->net; browse_insert_file(browse, file); socket->cnt = 0; pos1 = pos2 + 1; } res = pos1 - buffer->data; buffer_consume(buffer, res); return 1; close: sprintf(buf, "%s %lu", FILE_TREE(browse)->name, socket->ip_long); nap_browse_end(browse->net, buf); socket_destroy(socket, 1); return 1; } gint get_browse_nick(gpointer data, gint source, GdkInputCondition condition) { unsigned char buffer[1025]; int res; int cnt; char *pos; socket_t *socket = data; socket_t *socket2; if ((condition & GDK_INPUT_READ) == 0) { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->input); socket->input = -1; switch (res = recv(source, buffer, 1024, MSG_PEEK)) { case -1: case 0: socket_destroy(socket, 0); return 1; default: break; } buffer[res] = 0; // printf("[BROWSE] got [%s]\n", buffer); pos = strchr(buffer, '\n'); if (!pos) { socket_destroy(socket, 0); return 1; } cnt = (long) pos - (long) buffer; if (recv_safe(source, buffer, cnt+1, cnt+1) != cnt+1) { socket_destroy(socket, 0); return 1; } buffer[cnt] = 0; pos = buffer; /* Originally there should be no space between SENDLIST and the nick * (invented by the original napster client) but the * opennap/slavanap protocol specs say there is one (which is not * correct). XNap sends one space before the nick, lopster and other * clients dont. So get rid of the XNap space here. */ while (*pos == ' ') pos++; socket2 = browse_search_socket(pos); if (!socket2) { socket_destroy(socket, 0); return 1; } else if (socket != socket2) { // socket is an incoming connection, mapping to found one browse_t *browse; browse = socket2->data; if (!browse) { // printf("[BROWSE] socket has no data\n"); socket_destroy(socket, 0); return 1; } socket_destroy(socket2, 1); socket->data = browse; socket2 = socket; } socket2->cnt = 0; socket2->input = gdk_input_add(socket2->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(get_browse_files), socket2); return 1; } /////////////// void browse_connect_and_start(socket_t * socket) { if (!connect_socket(socket, "TCP", SOCK_STREAM)) { socket_destroy(socket, 0); return; } socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(await_conn_ack2), socket); } gint await_conn_ack2(gpointer data, gint source, GdkInputCondition condition) { char c; socket_t *socket = data; if ((condition & GDK_INPUT_READ) == 0) { socket_destroy(socket, 0); return 1; } if (recv_safe(source, &c, 1, 1) != 1) { socket_destroy(socket, 0); return 1; } // printf("[BROWSE] got [%c]\n", c); if (c != '1') { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->input); socket->input = -1; socket->output = gdk_input_add(socket->fd, GDK_INPUT_WRITE, GTK_SIGNAL_FUNC(send_browse_get), socket); return 1; } gint send_browse_get(gpointer data, gint source, GdkInputCondition condition) { socket_t *socket = data; if ((condition & GDK_INPUT_WRITE) == 0) { socket_destroy(socket, 0); return 1; } gdk_input_remove(socket->output); socket->output = -1; // printf("[BROWSE] send [GETLIST]\n"); if (send_safe(source, "GETLIST", 7, 7) != 7) { socket_destroy(socket, 0); return 1; } socket->input = gdk_input_add(socket->fd, GDK_INPUT_READ, GTK_SIGNAL_FUNC(get_browse_nick), socket); return 1; } //////////// socket_t *browse_search_socket(char* user) { GList *dlist; socket_t *socket; file_tree_t* browse2; for (dlist = global.sockets; dlist; dlist = dlist->next) { socket = dlist->data; if (socket->type != S_BROWSE) continue; browse2 = socket->data; if (browse2 && !g_strcasecmp(browse2->name, user)) return socket; } return NULL; } void browse_direct(browse_t* browse) { socket_t *socket; socket = browse_search_socket(FILE_TREE(browse)->name); if (socket) return; // already direct browsing socket = socket_new(S_BROWSE); browse->buffer->datasize = 0; browse->buffer->data[0] = 0; // uneccessary socket->data = browse; command_send(browse->net, CMD_BROWSE_DIRECT, FILE_TREE(browse)->name); } static gboolean on_remove_browse_activate(GtkWidget *widget ATTR_UNUSED, GdkEventButton *event ATTR_UNUSED, gpointer user_data) { browse_t *browse = user_data; if (browse) browse_remove(browse, 0); return TRUE; } static void on_delete_browse_activate(GtkWidget *source ATTR_UNUSED, gpointer user_data) { browse_t *browse = user_data; if (browse) browse_remove(browse, 1); } GtkWidget *create_browse_popup(browse_t* browse, browse_node_t* node) { GtkWidget *popup; file_t* file; int item_num; char* text; GList* resume_list; GtkCList* clist; GtkWidget* user_popup; GtkWidget* item; GList* dlist; resume_t* resume; static net_user_t nu; popup = gtk_menu_new(); clist = FILE_TREE(browse)->clist; if (!node) { file = NULL; item_num = 0; } else { file = FILE_NODE(node)->file; item_num = g_list_length(clist->selection); } if (file) { if (item_num > 1) text = g_strdup_printf("Download Selected (%d)", item_num); else text = g_strdup("Download File"); item = gtk_menu_item_new_with_label(text); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_download2_activate), GINT_TO_POINTER(0)); if (item_num > 1) text = g_strdup_printf("Download with Foldername (%d)", item_num); else text = g_strdup("Download with Foldername"); item = gtk_menu_item_new_with_label(text); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_download2_activate), GINT_TO_POINTER(1)); if ((resume_list = resume_search_size(file->size)) != NULL) { item = gtk_menu_item_new_with_label("Resume File"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); user_popup = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), user_popup); for (dlist = resume_list; dlist; dlist = dlist->next) { resume = dlist->data; item = gtk_menu_item_new_with_label(get_file_name(resume->filename)); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(user_popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_download_resume_activate), (gpointer)resume); } g_list_free(resume_list); } 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 Browse"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_remove_browse_activate), browse); item = gtk_menu_item_new_with_label("Delete Browse"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_delete_browse_activate), browse); nu.net = browse->net; nu.user = FILE_TREE(browse)->name; item = gtk_menu_item_new_with_label("Refresh Files"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_browse_files_activate), &nu); 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("User Menu"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); user_popup = create_user_popup(M_BROWSE, browse); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), user_popup); 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), GINT_TO_POINTER(2)); return popup; } static file_node_t* browse_node_new(char* name) { browse_node_t* node; if (!name) return NULL; node = g_malloc(sizeof(browse_node_t)); if (!node) return NULL; file_node_init(FILE_NODE(node), name); node->first_seen = 0; node->last_seen = 0; return FILE_NODE(node); } static void browse_load_saved(browse_t* browse); static browse_t* browse_search_nick(char *nick) { GList *dlist; file_tree_t *browse; for (dlist = global.browses; dlist; dlist = dlist->next) { browse = dlist->data; if (!g_strcasecmp(nick, browse->name)) return BROWSE_TREE(browse); } return NULL; } void browse_user_files(net_t* net, char *nick) { browse_t *browse; if (!net || !nick || !(*nick)) return; browse = browse_search_nick(nick); if (browse) { if (!FILE_TREE(browse)->files) { browse_load_saved(browse); browse_create_page(browse); file_tree_show(FILE_TREE(browse), MEDIA_SIZE, 3); } browse->net = net; } else { browse = browse_create_new(net, nick); } browse->userinfo = user_info_detect(net, nick); browse->status = 0; // mark as in progress browse_direct(browse); browse_update_user(FILE_TREE(browse)); } ///// browse_t *browse_search_user_net(char* user, net_t* net) { GList *dlist; browse_t *browse; if (!user || !net) return NULL; for (dlist = global.browses; dlist; dlist = dlist->next) { browse = dlist->data; if (!user || !net || net != browse->net || browse->status < 0) continue; if (!g_strcasecmp(user, FILE_TREE(browse)->name)) return browse; } return NULL; } static browse_t* browse_new(char* nick, char* des) { browse_t *browse; browse = g_malloc(sizeof(browse_t)); file_tree_init(FILE_TREE(browse), nick, des); FILE_TREE(browse)->node_new = browse_node_new; FILE_TREE(browse)->node_status = browse_node_status; FILE_TREE(browse)->update_user = browse_update_user; // FILE_TREE(browse)->node_free = NULL; // FILE_TREE(browse)->node_init = NULL; // FILE_TREE(browse)->next_mark = browse_next_mark; browse->net = NULL; browse->userinfo = NULL; browse->buffer = buffer_new(4096); browse->status = -1; global.browses = g_list_append(global.browses, browse); return browse; } /** this function is used to browse a _new_ user */ browse_t *browse_create_new(net_t* net, char *nick) { browse_t *browse; browse = browse_new(nick, NULL); if (!browse) return NULL; browse->net = net; browse_create_page(browse); browse_update_user(FILE_TREE(browse)); return browse; } static gboolean on_browse_expose_event(GtkWidget * widget ATTR_UNUSED, GdkEventExpose * event ATTR_UNUSED, gpointer user_data) { browse_t* browse = user_data; browse_update_user(FILE_TREE(browse)); return TRUE; } static void on_browse_expand(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { file_tree_t* tree = FILE_TREE(popup_browse); file_node_t* node = FILE_NODE(popup_node); GtkCTree* ctree; GtkCTreeNode* tnode; int levels = GPOINTER_TO_INT(user_data); file_node_t* parent; if (!tree || !node || !tree->ctree) return; ctree = tree->ctree; tnode = gtk_ctree_find_by_row_data(ctree, NULL, node); if (!tnode) return; switch (levels) { case 0: gtk_ctree_expand_recursive(ctree, tnode); break; default: parent = node->parent; while (parent) { levels++; parent = parent->parent; } gtk_ctree_expand_to_depth(ctree, tnode, levels); break; } } static void on_browse_collapse(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { file_tree_t* tree = FILE_TREE(popup_browse); file_node_t* node = FILE_NODE(popup_node); GtkCTree* ctree; GtkCTreeNode* tnode; int levels = GPOINTER_TO_INT(user_data); file_node_t* parent; if (!tree || !node || !tree->ctree) return; ctree = tree->ctree; tnode = gtk_ctree_find_by_row_data(ctree, NULL, node); if (!tnode) return; switch (levels) { case 0: gtk_ctree_collapse_recursive(ctree, tnode); break; default: parent = node->parent; while (parent) { levels++; parent = parent->parent; } gtk_ctree_collapse_to_depth(ctree, tnode, levels); break; } } static void on_browse_download(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { file_tree_t* tree = FILE_TREE(popup_browse); file_node_t* node = FILE_NODE(popup_node); if (user_data) download_file_node(tree, node, NULL, 1); else download_file_node(tree, node, NULL, 0); } GtkWidget* create_browse2_popup(browse_t* browse, browse_node_t* node) { GtkWidget *popup; GtkWidget *item; GtkWidget *popup2; GtkWidget *item2; char* item_str; char str[100]; file_tree_t* tree = FILE_TREE(browse); file_node_t* fnode = FILE_NODE(node); if (!browse || !node) return NULL; popup = gtk_menu_new(); popup_browse = browse; popup_node = node; item_str = g_strdup_printf("%d files = %s", fnode->fci[tree->show_mime][tree->show_time], print_size(str, fnode->fsi[tree->show_mime][tree->show_time])); item = gtk_menu_item_new_with_label(item_str); g_free(item_str); 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_with_label("Download subtree (flat)"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_browse_download), NULL); item = gtk_menu_item_new_with_label("Download subtree (structure)"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_browse_download), GINT_TO_POINTER(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("Expand subtree"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); item2 = gtk_menu_item_new_with_label("Depth 1"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_expand), GINT_TO_POINTER(1)); item2 = gtk_menu_item_new_with_label("Depth 2"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_expand), GINT_TO_POINTER(2)); item2 = gtk_menu_item_new_with_label("Depth 3"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_expand), GINT_TO_POINTER(3)); item2 = gtk_menu_item_new_with_label("Completely"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_expand), GINT_TO_POINTER(0)); item = gtk_menu_item_new_with_label("Collapse subtree"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); popup2 = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), popup2); item2 = gtk_menu_item_new_with_label("Depth 1"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_collapse), GINT_TO_POINTER(2)); item2 = gtk_menu_item_new_with_label("Depth 2"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_collapse), GINT_TO_POINTER(3)); item2 = gtk_menu_item_new_with_label("Depth 3"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_collapse), GINT_TO_POINTER(4)); item2 = gtk_menu_item_new_with_label("Completely"); gtk_widget_show(item2); gtk_container_add(GTK_CONTAINER(popup2), item2); gtk_signal_connect(GTK_OBJECT(item2), "activate", GTK_SIGNAL_FUNC(on_browse_collapse), GINT_TO_POINTER(0)); return popup; } void on_browse_resize_column(GtkCList *clist, gint column, gint width, gpointer user_data ATTR_UNUSED) { GList* dlist; file_tree_t* browse; if (global.browse_width[column] == width) return; global.browse_width[column] = width; for (dlist = global.browses; dlist; dlist = dlist->next) { browse = dlist->data; if (!browse->clist) continue; if (clist == browse->clist) continue; gtk_clist_set_column_width (browse->clist, column, width); } } static void browse_add_saved(browse_t* browse) { GtkCList* clist; int row; file_tree_t* tree = FILE_TREE(browse); clist = GTK_CLIST(lookup_widget(global.win, "clist43")); row = gtk_clist_find_row_from_data(clist, tree); if (row >= 0) { sprintf(tstr[1], "%d", tree->fci[MEDIA_SIZE][3]); gtk_clist_set_text(clist, row, 1, tstr[1]); strcpy(tstr[2], ctime(&tree->last_refreshed)); tstr[2][strlen(tstr[2])-1] = 0; gtk_clist_set_text(clist, row, 2, tstr[2]); strcpy(tstr[3], tree->description?tree->description:""); gtk_clist_set_text(clist, row, 3, tstr[3]); } else { strcpy(tstr[0], tree->name); sprintf(tstr[1], "%d", tree->fci[MEDIA_SIZE][3]); strcpy(tstr[2], ctime(&tree->last_refreshed)); tstr[2][strlen(tstr[2])-1] = 0; strcpy(tstr[3], tree->description?tree->description:""); row = gtk_clist_append(clist, list); gtk_clist_set_row_data(clist, row, tree); } } static void browse_save(browse_t* browse) { char filename[2048]; file_tree_t* tree = FILE_TREE(browse); FILE *file; if (!browse) return; sprintf(filename, "%s%cbrowse%c%s", global.options.config_dir, DIR_SEP, DIR_SEP, tree->name); if ((file = fopen(filename, "w")) == NULL) { client_message("Error", "Could not save browse [%s]", tree->name); return; } qfprintf(file, "SAVED_BROWSE 1 %S %d %ld %S\n", tree->name, tree->fci[MEDIA_SIZE][3], tree->last_refreshed, tree->description?tree->description:""); browse_save_node(file, tree->files, 0); fclose(file); browse_add_saved(browse); } static int on_file_tree_search_change_frombutton(GtkWidget * widget, void* user_data) { GtkWidget* item = widget; file_tree_t* tree = user_data; char* text; if (!tree || !tree->search_entry || !tree->ctree || !tree->clist) return 0; gtk_label_get(GTK_LABEL(GTK_BIN(item)->child), &text); gtk_entry_set_text(GTK_ENTRY(tree->search_entry), text); return 0; } void popup_position(GtkMenu * menu, gint * x, gint * y, gpointer user_data); static void on_browse_quicker_clicked(GtkButton * button ATTR_UNUSED, gpointer user_data) { GtkWidget *popup; GtkWidget* item; file_tree_t* tree = user_data; char* text; GList* dlist; deactivate_auto_afk(); popup = gtk_menu_new(); if (global.string_list[LIST_QSEARCH]) { for (dlist = global.string_list[LIST_QSEARCH]; dlist; dlist = dlist->next) { text = dlist->data; item = gtk_menu_item_new_with_label(text); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_file_tree_search_change_frombutton), tree); } } else { item = gtk_menu_item_new_with_label("No saved search items"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_widget_set_sensitive(item, FALSE); } gtk_menu_popup(GTK_MENU(popup), NULL, NULL, (GtkMenuPositionFunc) popup_position, button, 1, 0); } static void on_browse_quicker_add(GtkButton * button ATTR_UNUSED, gpointer user_data) { GtkWidget *popup; file_tree_t* tree = user_data; char* text; deactivate_auto_afk(); if (!tree || !tree->search_entry) return; popup = gtk_menu_new(); text = gtk_entry_get_text(GTK_ENTRY(tree->search_entry)); if (!text || *text == 0) return; qsearch_add(text); } GtkWidget *browse_create_page(browse_t* browse) { GtkWidget *vbox; GtkWidget *scrolledwindow; GtkWidget *ctree; GtkWidget *clist; GtkWidget *label; GtkWidget *tab_label; GtkWidget *frame; GtkWidget *hbox; GtkWidget *hbox2; GtkWidget *hbox3; GtkWidget *entry; GtkWidget *button; GtkWidget *sep; GtkWidget *drawingarea; GtkNotebook *notebook; GtkWidget* pixmap; GtkWidget* hpaned; GtkWidget* eventbox; GtkTooltips *tooltips; file_tree_t* tree = FILE_TREE(browse); if (tree->ctree) return NULL; if (global.options.switch_browse) switch_to_page(4); tooltips = gtk_tooltips_new(); hpaned = gtk_hpaned_new (); tree->main_link = hpaned; gtk_widget_show (hpaned); gtk_paned_set_gutter_size (GTK_PANED (hpaned), 10); gtk_paned_set_position (GTK_PANED (hpaned), 300); // left side vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_paned_pack1 (GTK_PANED (hpaned), vbox, FALSE, TRUE); scrolledwindow = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (scrolledwindow); gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); ctree = gtk_ctree_new (1, 0); tree->ctree = GTK_CTREE(ctree); gtk_widget_show (ctree); gtk_container_add (GTK_CONTAINER (scrolledwindow), ctree); gtk_clist_set_column_width (GTK_CLIST (ctree), 0, 80); gtk_clist_column_titles_show (GTK_CLIST (ctree)); gtk_clist_set_sort_column(GTK_CLIST(ctree), 0); gtk_clist_set_auto_sort(GTK_CLIST(ctree), TRUE); gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED); tree->signal[0] = gtk_signal_connect (GTK_OBJECT (ctree), "tree_select_row", GTK_SIGNAL_FUNC (on_file_tree_select_row), tree); gtk_signal_connect (GTK_OBJECT (ctree), "button_press_event", GTK_SIGNAL_FUNC (on_browse_tree_button_event), browse); label = gtk_label_new ("Folder"); gtk_widget_show (label); gtk_clist_set_column_widget (GTK_CLIST (ctree), 0, label); hbox2 = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox2); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); label = gtk_label_new("Search"); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 5); entry = gtk_entry_new(); // gtk_entry_set_text(GTK_ENTRY(entry), "not functional yet"); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox2), entry, TRUE, TRUE, 0); // gtk_widget_set_sensitive(entry, FALSE); tree->signal[1] = gtk_signal_connect (GTK_OBJECT (entry), "changed", GTK_SIGNAL_FUNC (on_file_tree_search_changed), tree); tree->search_entry = entry; // quicker_search_button button = gtk_button_new (); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_HALF); hbox3 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox3); gtk_container_add (GTK_CONTAINER (button), hbox3); pixmap = create_pixmap (global.win, "arrowr.xpm"); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX (hbox3), pixmap, FALSE, FALSE, 3); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_browse_quicker_add), tree); button = gtk_button_new (); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_HALF); hbox3 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox3); gtk_container_add (GTK_CONTAINER (button), hbox3); pixmap = create_pixmap (global.win, "arrowu.xpm"); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX (hbox3), pixmap, FALSE, FALSE, 3); /*ev. not necessary: */ sep = gtk_vseparator_new (); gtk_widget_show (sep); gtk_box_pack_start (GTK_BOX (hbox3), sep, FALSE, FALSE, 0); label = gtk_label_new ("quicker"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox3), label, FALSE, FALSE, 3); /**/ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_browse_quicker_clicked), tree); // right side. vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_paned_pack2 (GTK_PANED (hpaned), vbox, FALSE, TRUE); scrolledwindow = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolledwindow); gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); clist = gtk_clist_new(5); tree->clist = GTK_CLIST(clist); gtk_clist_set_sort_column(GTK_CLIST(clist), 0); gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING); gtk_clist_set_auto_sort(GTK_CLIST(clist), 1); gtk_widget_show(clist); gtk_widget_set_events(clist, GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_container_add(GTK_CONTAINER(scrolledwindow), clist); gtk_clist_set_column_width(tree->clist, 0, global.browse_width[0]); gtk_clist_set_column_width(tree->clist, 1, global.browse_width[1]); gtk_clist_set_column_width(tree->clist, 2, global.browse_width[2]); gtk_clist_set_column_width(tree->clist, 3, global.browse_width[3]); gtk_clist_set_column_width(tree->clist, 4, global.browse_width[4]); gtk_clist_set_column_visibility(tree->clist, 0, global.browse_show[0]); gtk_clist_set_column_visibility(tree->clist, 1, global.browse_show[1]); gtk_clist_set_column_visibility(tree->clist, 2, global.browse_show[2]); gtk_clist_set_column_visibility(tree->clist, 3, global.browse_show[3]); gtk_clist_set_column_visibility(tree->clist, 4, global.browse_show[4]); gtk_signal_connect (GTK_OBJECT (clist), "resize_column", GTK_SIGNAL_FUNC (on_browse_resize_column), browse); gtk_signal_connect (GTK_OBJECT (clist), "button_press_event", GTK_SIGNAL_FUNC (on_browse_list_button_event), browse); gtk_signal_connect (GTK_OBJECT (clist), "click_column", GTK_SIGNAL_FUNC (on_list_click_column), NULL); gtk_clist_set_selection_mode(tree->clist, GTK_SELECTION_EXTENDED); gtk_clist_column_titles_show(tree->clist); gtk_clist_set_compare_func(tree->clist, browse_compare); label = gtk_label_new("Filename"); gtk_widget_show(label); gtk_clist_set_column_widget(tree->clist, 0, label); label = gtk_label_new("Size"); gtk_widget_show(label); gtk_clist_set_column_widget(tree->clist, 1, label); label = gtk_label_new("Bitrate"); gtk_widget_show(label); gtk_clist_set_column_widget(tree->clist, 2, label); label = gtk_label_new("Frequency"); gtk_widget_show(label); gtk_clist_set_column_widget(tree->clist, 3, label); label = gtk_label_new("Duration"); gtk_widget_show(label); gtk_clist_set_column_widget(tree->clist, 4, label); hbox2 = gtk_hbox_new(FALSE, 5); gtk_widget_show(hbox2); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); tree->resize_cont = hbox2; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(hbox2), hbox, FALSE, FALSE, 0); /// button1 button = gtk_button_new (); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_HALF); tree->signal[5] = gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_file_tree_files1_clicked), browse); hbox3 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox3); gtk_container_add (GTK_CONTAINER (button), hbox3); pixmap = create_pixmap (global.win, "arrowu.xpm"); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX (hbox3), pixmap, FALSE, FALSE, 3); sep = gtk_vseparator_new (); gtk_widget_show (sep); gtk_box_pack_start (GTK_BOX (hbox3), sep, FALSE, FALSE, 0); label = gtk_label_new ("Show all"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox3), label, FALSE, FALSE, 3); tree->button[0] = button; tree->blabel[0] = label; /// button2 button = gtk_button_new (); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_HALF); tree->signal[6] = gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (on_file_tree_files2_clicked), browse); hbox3 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox3); gtk_container_add (GTK_CONTAINER (button), hbox3); label = gtk_label_new ("Files"); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox3), label, FALSE, FALSE, 3); tree->button[1] = button; tree->blabel[1] = label; sep = gtk_vseparator_new (); gtk_widget_show (sep); gtk_box_pack_start (GTK_BOX (hbox3), sep, FALSE, FALSE, 0); pixmap = create_pixmap (global.win, "arrowu.xpm"); gtk_widget_show (pixmap); gtk_box_pack_start (GTK_BOX (hbox3), pixmap, FALSE, FALSE, 3); // label frame = gtk_frame_new(NULL); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(hbox2), frame, TRUE, TRUE, 0); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); hbox = gtk_hbox_new(TRUE, 0); gtk_widget_show(hbox); gtk_container_add (GTK_CONTAINER (frame), hbox); label = gtk_label_new (""); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 5); tree->label = label; drawingarea = gtk_drawing_area_new (); gtk_widget_show (drawingarea); gtk_box_pack_start(GTK_BOX(hbox2), drawingarea, FALSE, FALSE, 0); // gtk_widget_set_events (drawingarea12, GDK_EXPOSURE_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_usize (drawingarea, 120, -2); gtk_signal_connect (GTK_OBJECT (drawingarea), "expose_event", GTK_SIGNAL_FUNC (on_browse_expose_event), browse); tree->progress = drawingarea; tree->signal[2] = gtk_signal_connect(GTK_OBJECT(tree->clist), "motion_notify_event", GTK_SIGNAL_FUNC(on_tree_motion_notify_event), NULL); tree->signal[3] = gtk_signal_connect(GTK_OBJECT(tree->clist), "leave_notify_event", GTK_SIGNAL_FUNC(on_tree_leave_notify_event), NULL); tree->signal[4] = gtk_signal_connect (GTK_OBJECT (tree->clist), "select_row", GTK_SIGNAL_FUNC (on_file_select_row), tree); tab_label = gtk_hbox_new (FALSE, 2); gtk_widget_show (tab_label); label = gtk_label_new(tree->name); gtk_widget_show(label); gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0); /* button = gtk_button_new(); gtk_widget_show(button); gtk_box_pack_start (GTK_BOX (tab_label), button, FALSE, FALSE, 0); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS); gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); */ // gtk_widget_set_sensitive(button, FALSE); eventbox = gtk_event_box_new (); gtk_widget_show (eventbox); gtk_container_add (GTK_CONTAINER (tab_label), eventbox); gtk_widget_set_events (eventbox, GDK_BUTTON_RELEASE_MASK); pixmap = create_pixmap (global.win, "close.xpm"); gtk_widget_show (pixmap); gtk_container_add (GTK_CONTAINER (eventbox), pixmap); gtk_signal_connect (GTK_OBJECT (eventbox), "button_release_event", GTK_SIGNAL_FUNC(on_remove_browse_activate), browse); /* gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(on_remove_browse_activate), browse); */ notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook6")); gtk_notebook_append_page(notebook, hpaned, tab_label); if (global.options.switch_browse) { gtk_notebook_set_page (notebook, gtk_notebook_page_num(GTK_NOTEBOOK(notebook), hpaned)); } gtk_widget_realize(hpaned); return ctree; } void browse_remove(browse_t *browse, int del) { GtkNotebook *notebook; int i1; socket_t* socket; file_tree_t* tree = FILE_TREE(browse); GtkCList* clist; int row; char* fname; if (!browse) return; // clearing file list file_tree_clear_files(tree); // removing browse page if (tree->main_link) { notebook = GTK_NOTEBOOK(lookup_widget(global.win, "notebook6")); i1 = gtk_notebook_page_num(notebook, tree->main_link); gtk_notebook_remove_page(notebook, i1); } socket = browse_search_socket(tree->name); if (socket) socket_destroy(socket, 1); tree->main_link = NULL; tree->progress = NULL; tree->ctree = NULL; tree->clist = NULL; tree->search_entry = NULL; tree->button[0] = NULL; tree->button[1] = NULL; tree->blabel[0] = NULL; tree->blabel[1] = NULL; tree->resize_cont = NULL; tree->label = NULL; tree->current_node = NULL; clist = GTK_CLIST(lookup_widget(global.win, "clist43")); row = gtk_clist_find_row_from_data(clist, tree); if (row < 0) { // not saved, destroy browse global.browses = g_list_remove(global.browses, browse); buffer_destroy(browse->buffer); file_tree_destroy(FILE_TREE(browse)); } else if (del) { gtk_clist_remove(clist, row); fname = g_strdup_printf("%s%cbrowse%c%s", global.options.config_dir, DIR_SEP, DIR_SEP, tree->name); unlink(fname); g_free(fname); global.browses = g_list_remove(global.browses, browse); buffer_destroy(browse->buffer); file_tree_destroy(FILE_TREE(browse)); } } /////////// void browse_do_search(search_t * search) { file_tree_t *tree; GList *dlist; int cnt = 0; for (dlist = global.browses; dlist; dlist = dlist->next) { tree = dlist->data; file_tree_search(tree, search, &cnt); if (search->pattern->max_results && (cnt >= search->pattern->max_results)) break;; } search_finish(search, NULL, 0); } void share_set_server(server_t* server) { share_server = server; } static file_node_t* set_finish_cb(file_node_t* node, void* ip) { if (node->file) node->file->ip = *((unsigned long*)(ip)); if (!BROWSE_NODE(node)->last_seen) BROWSE_NODE(node)->last_seen = global.current_time; if (!BROWSE_NODE(node)->first_seen) BROWSE_NODE(node)->first_seen = global.current_time; return NULL; } void browse_finish(browse_t* browse, unsigned long ip) { file_tree_t* tree = FILE_TREE(browse); if (!browse) return; browse->status = -1; tree->last_refreshed = global.current_time; file_node_action(tree, NULL, set_finish_cb, &ip); file_tree_calc_matrix(tree); browse_update_user(tree); file_tree_show(tree, MEDIA_SIZE, 1); browse_save(browse); } static browse_t* browse_preload_saved(char *name) { struct stat st; FILE *file; char temp[2048]; char* user; char* files; char* lbrowsed; char* des; browse_t* browse; sprintf(temp, "%s%cbrowse%c%s", global.options.config_dir, DIR_SEP, DIR_SEP, name); if (stat(temp, &st) < 0) return NULL; if ((file = fopen(temp, "r")) == NULL) return NULL; fgets(temp, sizeof(temp), file); if (strncmp(temp, "SAVED_BROWSE ", 13)) { fclose(file); return NULL; } user = arg(temp, 0); user = arg(NULL, 0); if (isdigit((int)(*user))) user = arg(NULL, 0); files = arg(NULL, 0); lbrowsed = arg(NULL, 0); des = arg(NULL, 0); if (!des) { fclose(file); return NULL; } browse = browse_new(user, des); FILE_TREE(browse)->last_refreshed = strtoul(lbrowsed, NULL, 10); FILE_TREE(browse)->fci[MEDIA_SIZE][3] = atoi(files); browse_add_saved(browse); fclose(file); return browse; } void browse_load_saved_list() { char dirname[2048]; GList *list2; struct dirent *entry; struct stat buf; char filename[2048]; DIR *dir; sprintf(dirname, "%s%cbrowse", global.options.config_dir, DIR_SEP); list2 = NULL; if ((dir = opendir(dirname)) == NULL) { g_warning("could not open dir [%s]", dirname); } else { while ((entry = readdir(dir)) != NULL) { // if (!strncmp(entry->d_name, ".", 1)) continue; // if (!strncmp(entry->d_name, "..", 2)) continue; sprintf(filename, "%s%c%s", dirname, DIR_SEP, entry->d_name); stat(filename, &buf); if (S_ISREG(buf.st_mode)) { browse_preload_saved(entry->d_name); } } closedir(dir); } } static void browse_load_folder_0(browse_t* browse, FILE* fd, browse_node_t* parent) { char* token; char* wname; char* md5; char* size; char* brate; char* freq; char* duration; char* tstamp; char* tstamp2; browse_node_t* child; char temp[2048]; file_t* file; file_tree_t* tree = FILE_TREE(browse); while (mfgets(temp, sizeof(temp), fd)) { token = arg(temp, 0); if (!strcmp(token, "FILE")) { wname = arg(NULL, 2); md5 = arg(NULL, 0); size = arg(NULL, 0); brate = arg(NULL, 0); freq = arg(NULL, 0); duration = arg(NULL, 0); tstamp = arg(NULL, 0); tstamp2 = arg(NULL, 0); if (tstamp2) { // create the file file = file_new(); file_set_winname(file, wname); file->user = g_strdup(tree->name); file->md5 = g_strdup(md5); file->size = strtol(size, NULL, 0); file->bitrate = atoi(brate); file->frequency = atoi(freq); file->duration = atoi(duration); child = BROWSE_NODE (file_node_insert_file(tree, FILE_NODE(parent), file, FALSE)); child->first_seen = strtoul(tstamp, NULL, 10); child->last_seen = strtoul(tstamp2, NULL, 10); } } else if (!strcmp(token, "DIR")) { wname = arg(NULL, 2); if (wname) { child = BROWSE_NODE (file_tree_insert_folder(tree, FILE_NODE(parent), wname, 1)); browse_load_folder_0(browse, fd, child); } } else if (!strcmp(token, "}")) { return; } else { // ignore line } } } static void browse_load_folder_1(browse_t* browse, FILE* fd, browse_node_t* parent) { char* token; char* filename; char* md5; char* size; char* brate; char* freq; char* duration; char* tstamp; char* tstamp2; int pos; browse_node_t* child; char temp[2048]; file_t* file; file_tree_t* tree = FILE_TREE(browse); while (mfgets(temp, sizeof(temp), fd)) { token = arg(temp, 0); if (!strcmp(token, "FILE")) { filename = arg(NULL, 2); md5 = arg(NULL, 0); size = arg(NULL, 0); brate = arg(NULL, 0); freq = arg(NULL, 0); duration = arg(NULL, 0); tstamp = arg(NULL, 0); tstamp2 = arg(NULL, 0); if (tstamp2) { // create the file file = file_new(); pos = strlen(filename); file->longname = file_node_get_folder(FILE_NODE(parent), &pos); strcpy(file->longname+pos, filename); file->shortname = get_short_name(file->longname); file->filename = get_file_name(file->shortname); file->winname = g_strdup(file->longname); local_to_napster(file->winname); file->media_type = mtype_get(file->filename); file->user = g_strdup(tree->name); file->md5 = g_strdup(md5); file->size = strtol(size, NULL, 0); file->bitrate = atoi(brate); file->frequency = atoi(freq); file->duration = atoi(duration); child = BROWSE_NODE (file_node_insert_file(tree, FILE_NODE(parent), file, FALSE)); child->first_seen = strtoul(tstamp, NULL, 10); child->last_seen = strtoul(tstamp2, NULL, 10); } } else if (!strcmp(token, "DIR")) { filename = arg(NULL, 2); if (filename) { child = BROWSE_NODE (file_tree_insert_folder(tree, FILE_NODE(parent), filename, 1)); browse_load_folder_1(browse, fd, child); } } else if (!strcmp(token, "}")) { return; } else { // ignore line } } } static void browse_load_saved(browse_t* browse) { struct stat st; FILE *file; char temp[2048]; file_tree_t* tree = FILE_TREE(browse); char* string; if (tree->files) return; sprintf(temp, "%s%cbrowse%c%s", global.options.config_dir, DIR_SEP, DIR_SEP, tree->name); if (stat(temp, &st) < 0) return; if ((file = fopen(temp, "r")) == NULL) return; // skip the first line. mfgets(temp, sizeof(temp), file); string = arg(temp, 0); string = arg(NULL, 0); if (string && isdigit((int)(*string))) browse_version = atoi(string); else browse_version = 0; if (browse_version == 0) browse_load_folder_0(browse, file, NULL); else if (browse_version == 1) browse_load_folder_1(browse, file, NULL); file_tree_calc_matrix(tree); fclose(file); return; } static void on_show_browse_files_activate(GtkMenuItem* menuitem ATTR_UNUSED, gpointer user_data) { browse_t* browse = user_data; if (!FILE_TREE(browse)->files) { browse_load_saved(browse); browse_create_page(browse); file_tree_show(FILE_TREE(browse), MEDIA_SIZE, 3); } } static int browse_description_func(clist_rename_t* cr) { int row; file_tree_t* tree; if (!cr || !cr->new_text || !cr->data) return 0; row = gtk_clist_find_row_from_data(cr->clist, cr->data); if (row < 0) return 0; tree = cr->data; if (tree->description) g_free(tree->description); tree->description = g_strdup(cr->new_text); gtk_clist_set_text(cr->clist, row, cr->col, tree->description); if (!tree->files) { browse_load_saved(BROWSE_TREE(tree)); browse_save(BROWSE_TREE(tree)); file_tree_clear_files(tree); } else { browse_save(BROWSE_TREE(tree)); } return 1; } static void on_enter_description2(GtkMenuItem * menuitem ATTR_UNUSED, gpointer user_data) { file_tree_t* tree = user_data; GtkCList* clist; if (!tree) return; clist = GTK_CLIST(lookup_widget(global.win, "clist43")); clist_rename(clist, 3, browse_description_func, tree, tree->description); } GtkWidget *create_saved_browse_popup(browse_t* browse) { GtkWidget *popup; GtkWidget* user_popup; GtkWidget* item; file_tree_t* tree = FILE_TREE(browse); static net_user_t nu; if (!browse) return NULL; popup = gtk_menu_new(); nu.net = browse->net; nu.user = tree->name; item = gtk_menu_item_new_with_label("Show Browse"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_show_browse_files_activate), browse); if (tree->files) gtk_widget_set_sensitive(item, FALSE); item = gtk_menu_item_new_with_label("Browse Files again"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_browse_files_activate), &nu); if (!NET_CONNECTED(nu.net)) 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); item = gtk_menu_item_new_with_label("Delete Browse"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_delete_browse_activate), browse); 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("Enter description"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(on_enter_description2), browse); 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("User Menu"); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(popup), item); user_popup = create_user_popup(M_BROWSE, browse); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), user_popup); 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; }