diff options
Diffstat (limited to 'plugins/xdcc')
-rw-r--r-- | plugins/xdcc/Makefile.am | 7 | ||||
-rw-r--r-- | plugins/xdcc/xdcc.c | 327 |
2 files changed, 334 insertions, 0 deletions
diff --git a/plugins/xdcc/Makefile.am b/plugins/xdcc/Makefile.am new file mode 100644 index 00000000..24f93f16 --- /dev/null +++ b/plugins/xdcc/Makefile.am @@ -0,0 +1,7 @@ +libdir = $(xchatdir)/plugins + +lib_LTLIBRARIES = xdcc.la +xdcc_la_SOURCES = xdcc.c +xdcc_la_LDFLAGS = -avoid-version -module +INCLUDES = $(COMMON_CFLAGS) -I$(srcdir)/.. + diff --git a/plugins/xdcc/xdcc.c b/plugins/xdcc/xdcc.c new file mode 100644 index 00000000..147a3c33 --- /dev/null +++ b/plugins/xdcc/xdcc.c @@ -0,0 +1,327 @@ +/* xchat 2.0 plugin: simple xdcc server example */ + +#include <glib.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> + +#include "xchat-plugin.h" + +static xchat_plugin *ph; /* plugin handle */ + +static int xdcc_on = 1; +static int xdcc_slots = 3; +static GSList *file_list = 0; + +typedef struct fileoffer +{ + char *file; + char *fullpath; + char *desc; + int downloads; +} fileoffer; + + +/* find the number of open dccs */ + +static int num_open_dccs(void) +{ + xchat_list *list; + int num = 0; + + list = xchat_list_get(ph, "dcc"); + if(!list) + return 0; + + while(xchat_list_next(ph, list)) + { + /* check only ACTIVE dccs */ + if(xchat_list_int(ph, list, "status") == 1) + { + /* check only SEND dccs */ + if(xchat_list_int(ph, list, "type") == 0) + num++; + } + } + + xchat_list_free(ph, list); + + return num; +} + +static void xdcc_get(char *nick, char *host, char *arg) +{ + int num; + GSList *list; + fileoffer *offer; + + if(arg[0] == '#') + arg++; + + num = atoi(arg); + list = g_slist_nth(file_list, num - 1); + if(!list) + { + xchat_commandf(ph, "quote NOTICE %s :No such file number #%d!", nick, num); + return; + } + + if(num_open_dccs() >= xdcc_slots) + { + xchat_commandf(ph, "quote NOTICE %s :All slots full. Try again later.", nick); + return; + } + + offer = (fileoffer *) list->data; + offer->downloads++; + xchat_commandf(ph, "quote NOTICE %s :Sending offer #%d %s", nick, num, offer->file); + xchat_commandf(ph, "dcc send %s %s", nick, offer->fullpath); +} + +static void xdcc_del(char *name) +{ + GSList *list; + fileoffer *offer; + + list = file_list; + while(list) + { + offer = (fileoffer *) list->data; + if(strcasecmp(name, offer->file) == 0) + { + file_list = g_slist_remove(file_list, offer); + xchat_printf(ph, "%s [%s] removed.\n", offer->file, offer->fullpath); + free(offer->file); + free(offer->desc); + free(offer->fullpath); + free(offer); + return; + } + list = list->next; + } +} + +static void xdcc_add(char *name, char *fullpath, char *desc, int dl) +{ + fileoffer *offer; + + offer = (fileoffer *) malloc(sizeof(fileoffer)); + offer->file = strdup(name); + offer->desc = strdup(desc); + offer->fullpath = strdup(fullpath); + offer->downloads = dl; + + file_list = g_slist_append(file_list, offer); +} + +static void xdcc_list(char *nick, char *host, char *arg, char *cmd) +{ + GSList *list; + int i = 0; + fileoffer *offer; + + xchat_commandf(ph, "%s %s :XDCC List:", cmd, nick); + list = file_list; + while(list) + { + i++; + offer = (fileoffer *) list->data; + xchat_commandf(ph, "%s %s :[#%d] %s - %s [%d dl]", cmd, + nick, i, offer->file, offer->desc, offer->downloads); + list = list->next; + } + + if(i == 0) + xchat_commandf(ph, "%s %s :- list empty.", cmd, nick); + else + xchat_commandf(ph, "%s %s :%d files listed.", cmd, nick, i); +} + +static int xdcc_command(char *word[], char *word_eol[], void *userdata) +{ + if(strcasecmp(word[2], "ADD") == 0) + { + if(!word_eol[5][0]) + xchat_print(ph, "Syntax: /XDCC ADD <name> <path> <description>\n"); + else + { + if(access(word[4], R_OK) == 0) + { + xdcc_add(word[3], word[4], word_eol[5], 0); + xchat_printf(ph, "%s [%s] added.\n", word[3], word[4]); + } + else + xchat_printf(ph, "Cannot read %s\n", word[4]); + } + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "DEL") == 0) + { + xdcc_del(word[3]); + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "SLOTS") == 0) + { + if(word[3][0]) + { + xdcc_slots = atoi(word[3]); + xchat_printf(ph, "XDCC slots set to %d\n", xdcc_slots); + } else + { + xchat_printf(ph, "XDCC slots: %d\n", xdcc_slots); + } + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "ON") == 0) + { + xdcc_on = TRUE; + xchat_print(ph, "XDCC now ON\n"); + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "LIST") == 0) + { + xdcc_list("", "", "", "echo"); + return XCHAT_EAT_XCHAT; + } + + if(strcasecmp(word[2], "OFF") == 0) + { + xdcc_on = FALSE; + xchat_print(ph, "XDCC now OFF\n"); + return XCHAT_EAT_XCHAT; + } + + xchat_print(ph, "Syntax: XDCC ADD <name> <fullpath> <description>\n" + " XDCC DEL <name>\n" + " XDCC SLOTS <number>\n" + " XDCC LIST\n" + " XDCC ON\n" + " XDCC OFF\n\n"); + + return XCHAT_EAT_XCHAT; +} + +static void xdcc_remote(char *from, char *msg) +{ + char *ex, *nick, *host; + + ex = strchr(from, '!'); + if(!ex) + return; + ex[0] = 0; + nick = from; + host = ex + 1; + + if(xdcc_on == 0) + { + xchat_commandf(ph, "notice %s XDCC is turned OFF!", from); + return; + } + + if(strncasecmp(msg, "LIST", 4) == 0) + xdcc_list(nick, host, msg + 4, "quote notice"); + else if(strncasecmp(msg, "GET ", 4) == 0) + xdcc_get(nick, host, msg + 4); + else + xchat_commandf(ph, "notice %s Unknown XDCC command!", from); +} + +static int ctcp_cb(char *word[], void *userdata) +{ + char *msg = word[1]; + char *from = word[2]; + + if(strncasecmp(msg, "XDCC ", 5) == 0) + xdcc_remote(from, msg + 5); + + return XCHAT_EAT_NONE; +} + +static void xdcc_save(void) +{ + char buf[512]; + FILE *fp; + GSList *list; + fileoffer *offer; + + snprintf(buf, sizeof(buf), "%s/xdcclist.conf", xchat_get_info(ph, "xchatdir")); + + fp = fopen(buf, "w"); + if(!fp) + return; + + list = file_list; + while(list) + { + offer = (fileoffer *) list->data; + fprintf(fp, "%s\n%s\n%s\n%d\n\n\n", offer->file, offer->fullpath, + offer->desc, offer->downloads); + list = list->next; + } + + fclose(fp); +} + +static void xdcc_load(void) +{ + char buf[512]; + char file[128]; + char path[128]; + char desc[128]; + char dl[128]; + FILE *fp; + + snprintf(buf, sizeof(buf), "%s/xdcclist.conf", xchat_get_info(ph, "xchatdir")); + + fp = fopen(buf, "r"); + if(!fp) + return; + + while(fgets(file, sizeof(file), fp)) + { + file[strlen(file)-1] = 0; + fgets(path, sizeof(path), fp); + path[strlen(path)-1] = 0; + fgets(desc, sizeof(desc), fp); + desc[strlen(desc)-1] = 0; + fgets(dl, sizeof(dl), fp); + dl[strlen(dl)-1] = 0; + fgets(buf, sizeof(buf), fp); + fgets(buf, sizeof(buf), fp); + xdcc_add(file, path, desc, atoi(dl)); + } + + fclose(fp); +} + +int xchat_plugin_deinit(void) +{ + xdcc_save(); + xchat_print(ph, "XDCC List saved\n"); + return 1; +} + +int xchat_plugin_init(xchat_plugin *plugin_handle, + char **plugin_name, char **plugin_desc, char **plugin_version, + char *arg) +{ + ph = plugin_handle; + + *plugin_name = "XDCC"; + *plugin_desc = "Very simple XDCC server"; + *plugin_version = "0.1"; + + xchat_hook_command(ph, "XDCC", XCHAT_PRI_NORM, xdcc_command, 0, 0); + xchat_hook_print(ph, "CTCP Generic", XCHAT_PRI_NORM, ctcp_cb, 0); + xchat_hook_print(ph, "CTCP Generic to Channel", XCHAT_PRI_NORM, ctcp_cb, 0); + + xdcc_load(); + xchat_print(ph, "XDCC loaded. Type /XDCC for help.\n"); + + return 1; +} |