📄 toc.c
字号:
{ struct file_transfer *ft = data; if (src == -1) { purple_notify_error(ft->gc, NULL, _("Could not connect for transfer."), NULL); g_free(ft->filename); g_free(ft->cookie); g_free(ft->user); g_free(ft->ip); g_free(ft); return; } ft->inpa = purple_input_add(src, PURPLE_INPUT_READ, toc_send_file_callback, ft);}static void toc_send_file(gpointer a, struct file_transfer *old_ft){ struct file_transfer *ft; const char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window)); PurpleAccount *account; char buf[BUF_LEN * 2]; if (purple_gtk_check_if_dir(dirname, GTK_FILE_SELECTION(old_ft->window))) return; ft = g_new0(struct file_transfer, 1); if (old_ft->files == 1) ft->filename = g_strdup(dirname); else ft->filename = g_path_get_dirname(dirname); ft->cookie = g_strdup(old_ft->cookie); ft->user = g_strdup(old_ft->user); ft->ip = g_strdup(old_ft->ip); ft->files = old_ft->files; ft->port = old_ft->port; ft->gc = old_ft->gc; account = ft->gc->account; gtk_widget_destroy(old_ft->window); g_snprintf(buf, sizeof(buf), "toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_SEND_UID); sflap_send(ft->gc, buf, -1, TYPE_DATA); if (purple_proxy_connect(ft->gc, account, ft->ip, ft->port, toc_send_file_connect, ft) != 0) { purple_notify_error(ft->gc, NULL, _("Could not connect for transfer."), NULL); g_free(ft->filename); g_free(ft->cookie); g_free(ft->user); g_free(ft->ip); g_free(ft); return; }}static void toc_get_file_callback(gpointer data, gint source, PurpleInputCondition cond){ char buf[BUF_LONG]; struct file_transfer *ft = data; if (cond & PURPLE_INPUT_WRITE) { int remain = MIN(ntohl(ft->hdr.totsize) - ft->recvsize, 1024); int i; for (i = 0; i < remain; i++) fscanf(ft->file, "%c", &buf[i]); write(source, buf, remain); ft->recvsize += remain; if (ft->recvsize == ntohl(ft->hdr.totsize)) { purple_input_remove(ft->inpa); ft->inpa = purple_input_add(source, PURPLE_INPUT_READ, toc_get_file_callback, ft); } return; } if (ft->hdr.hdrtype == htons(0x1108)) { struct tm *fortime; struct stat st; char *basename; read(source, ft, 8); read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); debug_header(ft); g_stat(ft->filename, &st); fortime = localtime(&st.st_mtime); basename = g_path_get_basename(ft->filename); g_snprintf(buf, sizeof(buf), "%2d/%2d/%4d %2d:%2d %8ld %s\r\n", fortime->tm_mon + 1, fortime->tm_mday, fortime->tm_year + 1900, fortime->tm_hour + 1, fortime->tm_min + 1, (long)st.st_size, basename); write(source, buf, ntohl(ft->hdr.size)); g_free(basename); return; } if (ft->hdr.hdrtype == htons(0x1209)) { read(source, ft, 8); read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); debug_header(ft); return; } if (ft->hdr.hdrtype == htons(0x120b)) { read(source, ft, 8); read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); debug_header(ft); if (ft->hdr.hdrtype != htons(0x120c)) { g_snprintf(buf, sizeof(buf), "%s decided to cancel the transfer", ft->user); purple_notify_error(ft->gc, NULL, buf, NULL); purple_input_remove(ft->inpa); close(source); g_free(ft->filename); g_free(ft->user); g_free(ft->ip); g_free(ft->cookie); if (ft->file) fclose(ft->file); g_free(ft); return; } ft->hdr.hdrtype = 0x0101; ft->hdr.totfiles = htons(1); ft->hdr.filesleft = htons(1); ft->hdr.flags = 0x20; write(source, ft, 256); return; } if (ft->hdr.hdrtype == 0x0101) { read(source, ft, 8); read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); debug_header(ft); purple_input_remove(ft->inpa); ft->inpa = purple_input_add(source, PURPLE_INPUT_WRITE, toc_get_file_callback, ft); return; } if (ft->hdr.hdrtype == 0x0202) { read(source, ft, 8); read(source, &ft->hdr.bcookie, MIN(256 - 8, ntohs(ft->hdr.hdrlen) - 8)); debug_header(ft); purple_input_remove(ft->inpa); close(source); g_free(ft->filename); g_free(ft->user); g_free(ft->ip); g_free(ft->cookie); if (ft->file) fclose(ft->file); g_free(ft); return; }}static void toc_get_file_connect(gpointer data, gint src, PurpleInputCondition cond){ struct file_transfer *ft = data; struct file_header *hdr; char *buf; char *basename; if (src == -1) { purple_notify_error(ft->gc, NULL, _("Could not connect for transfer."), NULL); fclose(ft->file); g_free(ft->filename); g_free(ft->cookie); g_free(ft->user); g_free(ft->ip); g_free(ft); return; } hdr = (struct file_header *)ft; hdr->magic[0] = 'O'; hdr->magic[1] = 'F'; hdr->magic[2] = 'T'; hdr->magic[3] = '2'; hdr->hdrlen = htons(256); hdr->hdrtype = htons(0x1108); rombase64(ft->cookie, &buf, NULL); g_snprintf(hdr->bcookie, 8, "%s", buf); g_free(buf); hdr->totfiles = htons(1); hdr->filesleft = htons(1); hdr->totparts = htons(1); hdr->partsleft = htons(1); hdr->totsize = htonl((long)ft->st.st_size); /* combined size of all files */ /* size = strlen("mm/dd/yyyy hh:mm sizesize 'name'\r\n") */ basename = g_path_get_basename(ft->filename); hdr->size = htonl(28 + strlen(basename)); /* size of listing.txt */ g_free(basename); hdr->modtime = htonl(ft->st.st_mtime); hdr->checksum = htonl(0x89f70000); /* uh... */ g_snprintf(hdr->idstring, 32, "OFT_Windows ICBMFT V1.1 32"); hdr->flags = 0x02; hdr->lnameoffset = 0x1A; hdr->lsizeoffset = 0x10; g_snprintf(hdr->name, 64, "listing.txt"); if (write(src, hdr, 256) < 0) { purple_notify_error(ft->gc, NULL, _("Could not write file header. The file will " "not be transferred."), NULL); fclose(ft->file); g_free(ft->filename); g_free(ft->cookie); g_free(ft->user); g_free(ft->ip); g_free(ft); return; } ft->inpa = purple_input_add(src, PURPLE_INPUT_READ, toc_get_file_callback, ft);}static void toc_get_file(gpointer a, struct file_transfer *old_ft){ struct file_transfer *ft; const char *dirname = gtk_file_selection_get_filename(GTK_FILE_SELECTION(old_ft->window)); PurpleAccount *account; char *buf, buf2[BUF_LEN * 2]; if (purple_gtk_check_if_dir(dirname, GTK_FILE_SELECTION(old_ft->window))) return; ft = g_new0(struct file_transfer, 1); ft->filename = g_strdup(dirname); ft->file = g_fopen(ft->filename, "r"); if (!ft->file) { buf = g_strdup_printf("Unable to open %s for transfer.", ft->filename); purple_notify_error(ft->gc, NULL, buf, NULL); g_free(buf); g_free(ft->filename); g_free(ft); return; } if (g_stat(dirname, &ft->st)) { buf = g_strdup_printf("Unable to examine %s.", dirname); purple_notify_error(ft->gc, NULL, buf, NULL); g_free(buf); g_free(ft->filename); g_free(ft); return; } ft->cookie = g_strdup(old_ft->cookie); ft->user = g_strdup(old_ft->user); ft->ip = g_strdup(old_ft->ip); ft->port = old_ft->port; ft->gc = old_ft->gc; account = ft->gc->account; gtk_widget_destroy(old_ft->window); g_snprintf(buf2, sizeof(buf2), "toc_rvous_accept %s %s %s", ft->user, ft->cookie, FILE_GET_UID); sflap_send(ft->gc, buf2, -1, TYPE_DATA); if (purple_proxy_connect(ft->gc, account, ft->ip, ft->port, toc_get_file_connect, ft) < 0) { purple_notify_error(ft->gc, NULL, _("Could not connect for transfer."), NULL); fclose(ft->file); g_free(ft->filename); g_free(ft->cookie); g_free(ft->user); g_free(ft->ip); g_free(ft); return; }}static void cancel_callback(gpointer a, struct file_transfer *ft) { gtk_widget_destroy(ft->window); if (a == ft->window) { g_free(ft->cookie); g_free(ft->user); g_free(ft->ip); g_free(ft); }}static void toc_reject_ft(struct ft_request *ft) { g_free(ft->user); g_free(ft->filename); g_free(ft->ip); g_free(ft->cookie); if (ft->message) g_free(ft->message); g_free(ft);}static void toc_accept_ft(struct ft_request *fr) { if(g_list_find(purple_connections_get_all(), fr->gc)) { GtkWidget *window; char buf[BUF_LEN]; struct file_transfer *ft = g_new0(struct file_transfer, 1); ft->gc = fr->gc; ft->user = g_strdup(fr->user); ft->cookie = g_strdup(fr->cookie); ft->ip = g_strdup(fr->ip); ft->port = fr->port; ft->files = fr->files; ft->window = window = gtk_file_selection_new(_("Save As...")); g_snprintf(buf, sizeof(buf), "%s/%s", purple_home_dir(), fr->filename ? fr->filename : ""); gtk_file_selection_set_filename(GTK_FILE_SELECTION(window), buf); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(cancel_callback), ft); g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(ft->window)->cancel_button), "clicked", G_CALLBACK(cancel_callback), ft); if (!strcmp(fr->UID, FILE_SEND_UID)) g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", G_CALLBACK(toc_send_file), ft); else g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", G_CALLBACK(toc_get_file), ft); gtk_widget_show(window); } toc_reject_ft(fr);}static void accept_file_dialog(struct ft_request *ft) { char buf[BUF_LONG]; if (!strcmp(ft->UID, FILE_SEND_UID)) { /* holy crap. who the fuck would transfer gigabytes through AIM?! */ static char *sizes[4] = { "bytes", "KB", "MB", "GB" }; float size = ft->size; int index = 0; while ((index < 4) && (size > 1024)) { size /= 1024; index++; } g_snprintf(buf, sizeof(buf), dngettext(PACKAGE, "%s requests %s to accept %d file: %s (%.2f %s)%s%s", "%s requests %s to accept %d files: %s (%.2f %s)%s%s", ft->files), ft->user, purple_account_get_username(ft->gc->account), ft->files, ft->filename, size, sizes[index], (ft->message) ? "\n" : "", (ft->message) ? ft->message : ""); } else { g_snprintf(buf, sizeof(buf), _("%s requests you to send them a file"), ft->user); } purple_request_accept_cancel(ft->gc, NULL, buf, NULL, PURPLE_DEFAULT_ACTION_NONE, ft, G_CALLBACK(toc_accept_ft), G_CALLBACK(toc_reject_ft));}#endifstatic PurplePluginProtocolInfo prpl_info ={ 0, NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */ toc_list_icon, /* list_icon */ toc_list_emblem, /* list_emblems */ NULL, /* status_text */ NULL, /* tooltip_text */ toc_away_states, /* away_states */ toc_blist_node_menu, /* blist_node_menu */ toc_chat_info, /* chat_info */ toc_chat_info_defaults, /* chat_info_defaults */ toc_login, /* login */ toc_close, /* close */ toc_send_im, /* send_im */ toc_set_info, /* set_info */ NULL, /* send_typing */ toc_get_info, /* get_info */ toc_set_status, /* set_away */ toc_set_idle, /* set_idle */ toc_change_passwd, /* change_passwd */ toc_add_buddy, /* add_buddy */ toc_add_buddies, /* add_buddies */ toc_remove_buddy, /* remove_buddy */ toc_remove_buddies, /* remove_buddies */ toc_add_permit, /* add_permit */ toc_add_deny, /* add_deny */ toc_rem_permit, /* rem_permit */ toc_rem_deny, /* rem_deny */ toc_set_permit_deny, /* set_permit_deny */ toc_join_chat, /* join_chat */ NULL, /* reject_chat */ NULL, /* get_chat_name */ toc_chat_invite, /* chat_invite */ toc_chat_leave, /* chat_leave */ toc_chat_whisper, /* chat_whisper */ toc_chat_send, /* chat_send */ toc_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ NULL, /* buddy_free */ NULL, /* convo_closed */ toc_normalize, /* normalize */ NULL, /* set_buddy_icon */ NULL, /* remove_group */ NULL, /* get_cb_real_name */ NULL, /* set_chat_topic */ NULL, /* find_blist_chat */ NULL, /* roomlist_get_list */ NULL, /* roomlist_cancel */ NULL, /* roomlist_expand_category */ NULL, /* can_receive_file */ NULL, /* send_file */ NULL, /* new_xfer */ NULL, /* offline_message */ NULL, /* whiteboard_prpl_ops */ toc_send_raw, /* send_raw */};static PurplePluginInfo info ={ PURPLE_PLUGIN_MAGIC, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_PLUGIN_PROTOCOL, /**< type */ NULL, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ PURPLE_PRIORITY_DEFAULT, /**< priority */ "prpl-toc", /**< id */ "TOC", /**< name */ VERSION, /**< version */ /** summary */ N_("TOC Protocol Plugin"), /** description */ N_("TOC Protocol Plugin"), NULL, /**< author */ PURPLE_WEBSITE, /**< homepage */ NULL, /**< load */ NULL, /**< unload */ NULL, /**< destroy */ NULL, /**< ui_info */ &prpl_info, /**< extra_info */ NULL, toc_actions};static voidinit_plugin(PurplePlugin *plugin){ PurpleAccountOption *option; option = purple_account_option_string_new(_("Server"), "server", TOC_HOST); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_int_new(_("Port"), "port", TOC_PORT); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); my_protocol = plugin;}PURPLE_INIT_PLUGIN(toc, init_plugin, info);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -