diff options
Diffstat (limited to 'plugins/checksum/checksum.c')
-rw-r--r-- | plugins/checksum/checksum.c | 201 |
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); |