summary refs log tree commit diff stats
path: root/plugins/xdcc
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/xdcc')
-rw-r--r--plugins/xdcc/Makefile.am7
-rw-r--r--plugins/xdcc/xdcc.c327
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;
+}