summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorberkeviktor@aol.com <berkeviktor@aol.com>2011-01-12 06:58:54 +0100
committerberkeviktor@aol.com <berkeviktor@aol.com>2011-01-12 06:58:54 +0100
commit522c6c9f16ed0f8837e897e9e67d62a6f7a11fd0 (patch)
treed9e05ab539747e688982d2a343d21b88894539b4
parent04faeae4f3a0e893a014fc0cd747b617e6987f7c (diff)
rework checksum plugin, add option for limiting file size
-rw-r--r--plugins/checksum/checksum.c201
1 files changed, 185 insertions, 16 deletions
diff --git a/plugins/checksum/checksum.c b/plugins/checksum/checksum.c
index ea6d9a42..dcc54eb4 100644
--- a/plugins/checksum/checksum.c
+++ b/plugins/checksum/checksum.c
@@ -30,15 +30,26 @@
 #include <string.h>
 #include <malloc.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <openssl/sha.h>
 
 #include "xchat-plugin.h"
 
 #define BUFSIZE 32768
+#define DEFAULT_MAX_HASH_SIZE 4294967296					/* default size is 4 GB */
 
-static xchat_plugin *ph;   /* plugin handle */
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
+#ifndef stat64
+#define stat64 _stat64
+#endif
 
-void
+static xchat_plugin *ph;									/* plugin handle */
+static int config_fail;										/* variable for config availability */
+
+static void
 sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
 {
 	int i;
@@ -49,7 +60,7 @@ sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[
 	outputBuffer[64] = 0;
 }
 
-void
+static void
 sha256 (char *string, char outputBuffer[65])
 {
 	int i;
@@ -67,7 +78,7 @@ sha256 (char *string, char outputBuffer[65])
 	outputBuffer[64] = 0;
 }
 
-int
+static int
 sha256_file (char *path, char outputBuffer[65])
 {
 	int bytesRead;
@@ -103,30 +114,185 @@ sha256_file (char *path, char outputBuffer[65])
 	return 0;
 }
 
-int
+static void
+init ()
+{
+	/* check whether the config file exists, if it doesn't, try to create it */
+	FILE * file_in;
+	FILE * file_out;
+	char buffer[1024];
+
+	snprintf (buffer, sizeof (buffer), "%s/checksum.conf", xchat_get_info (ph, "xchatdirfs"));
+
+	if ((file_in = fopen (buffer, "r")) == NULL)
+	{
+		if ((file_out = fopen (buffer, "w")) == NULL)
+		{
+			config_fail = 1;
+		} else
+		{
+			config_fail = 0;
+			fprintf (file_out, "%llu\n", DEFAULT_MAX_HASH_SIZE);
+		}
+	}
+
+	fclose (file_in);
+	fclose (file_out);
+}
+
+static unsigned long long
+get_max_hash_size ()
+{
+	FILE * file_in;
+	char buffer[1024];
+	unsigned long long max_hash_size;
+
+	if (config_fail)
+	{
+		return DEFAULT_MAX_HASH_SIZE;
+	} else
+	{
+		snprintf (buffer, sizeof (buffer), "%s/checksum.conf", xchat_get_info (ph, "xchatdirfs"));
+		file_in = fopen (buffer, "r");
+		fscanf (file_in, "%llu", &max_hash_size);
+
+		fclose (file_in);
+		return max_hash_size;
+	}
+}
+
+void
+print_size ()
+{
+	xchat_printf (ph, "File size limit for checksums (in bytes): %llu", get_max_hash_size ());
+}
+
+static void
+increase_max_hash_size ()
+{
+	unsigned long long size;
+	FILE * file_out;
+	char buffer[1024];
+
+	if (config_fail)
+	{
+		xchat_printf (ph, "Config file is unavailable, defaulting to 4 GB");
+	} else
+	{
+		size = get_max_hash_size ();
+		if (size <= ULLONG_MAX/2)
+		{
+			size *= 2;
+		}
+		
+		snprintf (buffer, sizeof (buffer), "%s/checksum.conf", xchat_get_info (ph, "xchatdirfs"));
+		file_out = fopen (buffer, "w");
+		fprintf (file_out, "%llu\n", size);
+		fclose (file_out);
+		xchat_printf (ph, "New file size limit for checksums (in bytes): %llu", size);
+	}
+}
+
+static void
+decrease_max_hash_size ()
+{
+	unsigned long long size;
+	FILE * file_out;
+	char buffer[1024];
+
+	if (config_fail)
+	{
+		xchat_printf (ph, "Config file is unavailable, defaulting to 4 GB");
+	} else
+	{
+		size = get_max_hash_size ();
+		if (size >= 2)
+		{
+			size /= 2;
+		}
+		
+		snprintf (buffer, sizeof (buffer), "%s/checksum.conf", xchat_get_info (ph, "xchatdirfs"));
+		file_out = fopen (buffer, "w");
+		fprintf (file_out, "%llu\n", size);
+		fclose (file_out);
+		xchat_printf (ph, "New file size limit for checksums (in bytes): %llu", size);
+	}
+}
+
+static int
 dccrecv_cb (char *word[], void *userdata)
 {
-	char sum[65];
+	int result;
+	struct stat64 buffer;									/* buffer for storing file info */
+	char sum[65];											/* buffer for checksum */
 
-	sha256_file (word[2], sum);
-	/* try to print the checksum in the privmsg tab of the sender */
-	xchat_set_context (ph, xchat_find_context (ph, NULL, word[3]));
-	xchat_printf (ph, "SHA-256 checksum for %s (local):  %s\n", word[1], sum);
+	result = stat64 (word[2], &buffer);
+	if (result == 0)										/* stat returns 0 on success */
+	{
+		if (buffer.st_size <= get_max_hash_size ())
+		{
+			sha256_file (word[2], sum);						/* word[2] is the full filename */
+			/* try to print the checksum in the privmsg tab of the sender */
+			xchat_set_context (ph, xchat_find_context (ph, NULL, word[3]));
+			xchat_printf (ph, "SHA-256 checksum for %s (local):  %s\n", word[1], sum);
+		} else
+		{
+			xchat_set_context (ph, xchat_find_context (ph, NULL, word[3]));
+			xchat_printf (ph, "SHA-256 checksum for %s (local):  (size limit reached, no checksum calculated, you can increase it with /CHECKSUM_INC)\n", word[1]);
+		}
+	} else
+	{
+		xchat_printf (ph, "File access error");
+	}
 
 	return XCHAT_EAT_NONE;
 }
 
-int
+static int
 dccoffer_cb (char *word[], void *userdata)
 {
-	char sum[65];
+	int result;
+	struct stat64 buffer;									/* buffer for storing file info */
+	char sum[65];											/* buffer for checksum */
 
-	sha256_file (word[3], sum);
-	xchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], sum);
+	result = stat64 (word[2], &buffer);
+	if (result == 0)										/* stat returns 0 on success */
+	{
+		if (buffer.st_size <= get_max_hash_size ())
+		{
+			sha256_file (word[3], sum);						/* word[3] is the full filename */
+			xchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], sum);
+		} else
+		{
+			xchat_set_context (ph, xchat_find_context (ph, NULL, word[3]));
+			xchat_printf (ph, "SHA-256 checksum for %s (local):  (size limit reached, no checksum calculated, you can increase it with /CHECKSUM_INC)\n", word[1]);
+		}
+	} else
+	{
+		xchat_printf (ph, "File access error");
+	}
 
 	return XCHAT_EAT_NONE;
 }
 
+static void
+checksum (char *userdata[])
+{
+	if (!stricmp("GET", userdata[2]))
+	{
+		print_size ();
+	} else if (!stricmp("INC", userdata[2]))
+	{
+		increase_max_hash_size ();
+	} else if (!stricmp("DEC", userdata[2]))
+	{
+		decrease_max_hash_size ();
+	} else
+	{
+		xchat_printf (ph, "Usage: /CHECKSUM GET|INC|DEC");
+	}
+}
+
 int
 xchat_plugin_init (xchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
 {
@@ -134,8 +300,11 @@ xchat_plugin_init (xchat_plugin *plugin_handle, char **plugin_name, char **plugi
 
 	*plugin_name = "Checksum";
 	*plugin_desc = "Calculate checksum for DCC file transfers";
-	*plugin_version = "1.2";
-	
+	*plugin_version = "2.0";
+
+	init ();
+
+	xchat_hook_command (ph, "CHECKSUM", XCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|INC|DEC", 0);
 	xchat_hook_print (ph, "DCC RECV Complete", XCHAT_PRI_NORM, dccrecv_cb, NULL);
 	xchat_hook_print (ph, "DCC Offer", XCHAT_PRI_NORM, dccoffer_cb, NULL);