rework checksum plugin, add option for limiting file size
This commit is contained in:
parent
04faeae4f3
commit
522c6c9f16
@ -30,15 +30,26 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
#include "xchat-plugin.h"
|
#include "xchat-plugin.h"
|
||||||
|
|
||||||
#define BUFSIZE 32768
|
#define BUFSIZE 32768
|
||||||
|
#define DEFAULT_MAX_HASH_SIZE 4294967296 /* default size is 4 GB */
|
||||||
|
|
||||||
|
#ifndef snprintf
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
#ifndef stat64
|
||||||
|
#define stat64 _stat64
|
||||||
|
#endif
|
||||||
|
|
||||||
static xchat_plugin *ph; /* plugin handle */
|
static xchat_plugin *ph; /* plugin handle */
|
||||||
|
static int config_fail; /* variable for config availability */
|
||||||
|
|
||||||
void
|
static void
|
||||||
sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
|
sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -49,7 +60,7 @@ sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[
|
|||||||
outputBuffer[64] = 0;
|
outputBuffer[64] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
sha256 (char *string, char outputBuffer[65])
|
sha256 (char *string, char outputBuffer[65])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -67,7 +78,7 @@ sha256 (char *string, char outputBuffer[65])
|
|||||||
outputBuffer[64] = 0;
|
outputBuffer[64] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
sha256_file (char *path, char outputBuffer[65])
|
sha256_file (char *path, char outputBuffer[65])
|
||||||
{
|
{
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
@ -103,30 +114,185 @@ sha256_file (char *path, char outputBuffer[65])
|
|||||||
return 0;
|
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)
|
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);
|
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 */
|
/* try to print the checksum in the privmsg tab of the sender */
|
||||||
xchat_set_context (ph, xchat_find_context (ph, NULL, word[3]));
|
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);
|
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;
|
return XCHAT_EAT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
dccoffer_cb (char *word[], void *userdata)
|
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);
|
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);
|
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;
|
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
|
int
|
||||||
xchat_plugin_init (xchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
|
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_name = "Checksum";
|
||||||
*plugin_desc = "Calculate checksum for DCC file transfers";
|
*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 RECV Complete", XCHAT_PRI_NORM, dccrecv_cb, NULL);
|
||||||
xchat_hook_print (ph, "DCC Offer", XCHAT_PRI_NORM, dccoffer_cb, NULL);
|
xchat_hook_print (ph, "DCC Offer", XCHAT_PRI_NORM, dccoffer_cb, NULL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user