summary refs log tree commit diff stats
path: root/plugins/xdcc/xdcc.c
blob: 85d277329bd24a9f33fd90edee5c8ca183b555a7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
diff -ruN --strip-trailing-cr libxml2-2.7.8.orig/libxml.h libxml2-2.7.8/libxml.h
--- libxml2-2.7.8.orig/libxml.h	2010-10-12 08:25:32 +0200
+++ libxml2-2.7.8/libxml.h	2011-08-07 09:12:07 +0200
@@ -94,3 +94,7 @@
 #  define LIBXML_STATIC
 #endif
 #endif /* ! __XML_LIBXML_H__ */
+
+#ifndef vsnprintf
+#define vsnprintf _vsnprintf
+#endif
diff -ruN --strip-trailing-cr libxml2-2.7.8.orig/win32/Makefile.msvc libxml2-2.7.8/win32/Makefile.msvc
--- libxml2-2.7.8.orig/win32/Makefile.msvc	2010-11-04 14:58:44 +0100
+++ libxml2-2.7.8/win32/Makefile.msvc	2011-08-07 09:23:47 +0200
@@ -58,12 +58,20 @@
 !if "$(WITH_ZLIB)" == "1"
 CFLAGS = $(CFLAGS) /D "HAVE_ZLIB_H"
 !endif
-CFLAGS = $(CFLAGS) /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS = $(CFLAGS)
 
 # The linker and its options.
 LD = link.exe
 LDFLAGS = /nologo /VERSION:$(LIBXML_MAJOR_VERSION).$(LIBXML_MINOR_VERSION)
 LDFLAGS = $(LDFLAGS) /LIBPATH:$(BINDIR) /LIBPATH:$(LIBPREFIX)
+
+!ifdef X64
+CFLAGS = $(CFLAGS) /favor:AMD64
+LDFLAGS = $(LDFLAGS) msvcrt_win2003.obj
+!else
+LDFLAGS = $(LDFLAGS) msvcrt_winxp.obj
+!endif
+
 LIBS =
 !if "$(WITH_FTP)" == "1" || "$(WITH_HTTP)" == "1"
 LIBS = $(LIBS) wsock32.lib ws2_32.lib
@@ -71,9 +79,9 @@
 !if "$(WITH_ICONV)" == "1"
 LIBS = $(LIBS) iconv.lib
 !endif 
-+!if "$(WITH_ICU)" == "1"
+!if "$(WITH_ICU)" == "1"
 +LIBS = $(LIBS) icu.lib
-+!endif
+!endif
 !if "$(WITH_ZLIB)" == "1"
 LIBS = $(LIBS) zdll.lib
 !endif
@@ -94,7 +102,7 @@
 LDFLAGS = $(LDFLAGS) /DEBUG
 !else
 CFLAGS = $(CFLAGS) /D "NDEBUG" /O2 
-LDFLAGS = $(LDFLAGS) /OPT:NOWIN98
+LDFLAGS = $(LDFLAGS)
 !endif
 
 # Libxml object files.
0 331
/* HexChat 2.0 plugin: simple XDCC server example */

#include <glib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#ifndef WIN32
#include <unistd.h>
#endif

#include "hexchat-plugin.h"
#include "../../src/common/hexchat.h"

static hexchat_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)
{
	hexchat_list *list;
	int num = 0;

	list = hexchat_list_get(ph, "dcc");
	if(!list)
		return 0;

	while(hexchat_list_next(ph, list))
	{
		/* check only ACTIVE dccs */
		if(hexchat_list_int(ph, list, "status") == 1)
		{
			/* check only SEND dccs */
			if(hexchat_list_int(ph, list, "type") == 0)
				num++;
		}
	}

	hexchat_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)
	{
		hexchat_commandf(ph, "quote NOTICE %s :No such file number #%d!", nick, num);
		return;
	}

	if(num_open_dccs() >= xdcc_slots)
	{
		hexchat_commandf(ph, "quote NOTICE %s :All slots full. Try again later.", nick);
		return;
	}

	offer = (fileoffer *) list->data;
	offer->downloads++;
	hexchat_commandf(ph, "quote NOTICE %s :Sending offer #%d %s", nick, num, offer->file);
	hexchat_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);
			hexchat_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;

	hexchat_commandf(ph, "%s %s :XDCC List:", cmd, nick);
	list = file_list;
	while(list)
	{
		i++;
		offer = (fileoffer *) list->data;
		hexchat_commandf(ph, "%s %s :[#%d] %s - %s [%d dl]", cmd,
							nick, i, offer->file, offer->desc, offer->downloads);
		list = list->next;
	}

	if(i == 0)
		hexchat_commandf(ph, "%s %s :- list empty.", cmd, nick);
	else
		hexchat_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])
			hexchat_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);
				hexchat_printf(ph, "%s [%s] added.\n", word[3], word[4]);
			}
			else
				hexchat_printf(ph, "Cannot read %s\n", word[4]);
		}
		return HEXCHAT_EAT_HEXCHAT;
	}

	if(strcasecmp(word[2], "DEL") == 0)
	{
		xdcc_del(word[3]);
		return HEXCHAT_EAT_HEXCHAT;
	}

	if(strcasecmp(word[2], "SLOTS") == 0)
	{
		if(word[3][0])
		{
			xdcc_slots = atoi(word[3]);
			hexchat_printf(ph, "XDCC slots set to %d\n", xdcc_slots);
		} else
		{
			hexchat_printf(ph, "XDCC slots: %d\n", xdcc_slots);
		}
		return HEXCHAT_EAT_HEXCHAT;
	}

	if(strcasecmp(word[2], "ON") == 0)
	{
		xdcc_on = TRUE;
		hexchat_print(ph, "XDCC now ON\n");
		return HEXCHAT_EAT_HEXCHAT;
	}

	if(strcasecmp(word[2], "LIST") == 0)
	{
		xdcc_list("", "", "", "echo");
		return HEXCHAT_EAT_HEXCHAT;
	}

	if(strcasecmp(word[2], "OFF") == 0)
	{
		xdcc_on = FALSE;
		hexchat_print(ph, "XDCC now OFF\n");
		return HEXCHAT_EAT_HEXCHAT;
	}

	hexchat_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 HEXCHAT_EAT_HEXCHAT;
}

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)
	{
		hexchat_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
		hexchat_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 HEXCHAT_EAT_NONE;
}

static void xdcc_save(void)
{
	char buf[512];
	FILE *fp;
	GSList *list;
	fileoffer *offer;

	snprintf(buf, sizeof(buf), "%s/xdcclist.conf", hexchat_get_info(ph, "configdir"));

	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", hexchat_get_info(ph, "configdir"));

	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 hexchat_plugin_deinit(void)
{
	xdcc_save();
	hexchat_print(ph, "XDCC List saved\n");
	return 1;
}

int hexchat_plugin_init(hexchat_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";

	hexchat_hook_command(ph, "XDCC", HEXCHAT_PRI_NORM, xdcc_command, 0, 0);
	hexchat_hook_print(ph, "CTCP Generic", HEXCHAT_PRI_NORM, ctcp_cb, 0);
	hexchat_hook_print(ph, "CTCP Generic to Channel", HEXCHAT_PRI_NORM, ctcp_cb, 0);

	xdcc_load();
	hexchat_print(ph, "XDCC loaded. Type /XDCC for help.\n");

	return 1;
}