summary refs log tree commit diff stats
path: root/src/common/cfgfiles.c
AgeCommit message (Expand)Author
2013-09-19Add fullscreen to to view menuTingPing
2013-09-15Replace search window with a searchbarTingPing
2013-06-28Added preferences options to enable the server-time extension when available.Diogo Sousa
2013-06-08Minor cosmetic changesDiogo Sousa
2013-06-08Now the default configuration tries to set the language from the systemDiogo Sousa
2013-06-07Change default irc_ban_type to 1TingPing
2013-05-24Merge pull request #590 from orium/run-as-root-589-504TingPing
2013-05-20Temporary workaround for reconnect crashes on win32Berke Viktor
2013-05-17Increase default irc_join_delay to 5TingPing
2013-05-13Restructured a fair bit of cfgfiles.c. Besides making the code cleaner this a...Diogo Sousa
2013-05-12Removed unnecessary call to check_prefs_dir() in load_config().Diogo Sousa
2013-05-12Now hexchat doesn't abnormally terminal when started as root.Diogo Sousa
2013-05-11CosmeticsBerke Viktor
2013-05-11Make logmask consistent with scrollback maskBerke Viktor
2013-05-04Replace g_strdup_printf with g_build_filename where possibleBerke Viktor
2013-04-28Remove away announceTingPing
2013-04-28Store just the filename if the sound file comes from the default sound dirBerke Viktor
2013-04-28Remove dead code for sound_commandBerke Viktor
2013-04-27Get rid of bundled beepBerke Viktor
2013-04-27Reverts commit d964af81428a6d768aeb96906eb0538a30d919caTingPing
2013-04-16Move beep to proper placeBerke Viktor
2013-04-14Use bundled beep file for beep alertsBerke Viktor
2013-04-14Remove sound_dir, it's pointlessBerke Viktor
2013-04-14Add default beep sound, deploy on WindowsBerke Viktor
2013-04-13Add option for omitting alerts while focusedTingPing
2013-04-05Fix root user warning running before g_type_initTingPing
2013-04-03renable irc_who_join by defaultTingPing
2013-03-24Merge pull request #445 from TingPing/ulistcolorsTingPing
2013-03-09Add option to color nicknames in the userlist to match the chatTingPing
2013-03-09Add irc_notice_pos settingTingPing
2013-02-18Fallback to $HOME/Downloads for dcc_dirTingPing
2013-02-16follow XDG for default download directoryTingPing
2013-02-16Try to create the addons folder initiallyBerke Viktor
2013-01-04Merge pull request #337 from TingPing/trayRichardHitt
2013-01-02use g_get_user_config_dirTingPing
2012-12-29default irc_whois_front onTingPing
2012-12-23fix incorrect FSF addressDan Mashal
2012-12-20allow tray blinks to be static iconsTingPing
2012-12-20Add auto-away to plugin-trayTingPing
2012-12-01rename pane height variableTingPing
2012-11-30Save pane height and restore on startTingPing
2012-11-12Make sure g_strconcat() result is NULL terminatedBerke Viktor
2012-11-12utf8-everywhere: Forgot the g_free's and the g_unlink / g_rename.Arnav Singh
2012-11-12Fix g_strdup_printf() call causing removal of hexchat.confBerke Viktor
2012-11-11utf8-everywhere: Fixed some remaining C file I/O API calls to use the glib API.Arnav Singh
2012-11-11Disable one instance code coz it's really buggyBerke Viktor
2012-11-11Copy-paste fixBerke Viktor
2012-11-10Explode gui_tray_flagsBerke Viktor
2012-11-10Eliminate some more warnings and hide less warnings in VSBerke Viktor
2012-11-04Some more platform unificationBerke Viktor
umber.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 */
/* HexChat
 * Copyright (c) 2010-2012 Berke Viktor.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifdef __APPLE__
#define __AVAILABILITYMACROS__
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/sha.h>
#include <glib.h>

#ifdef WIN32
#ifndef snprintf
#define snprintf _snprintf
#endif
#define stat _stat64
#else
/* for INT_MAX */
#include <limits.h>
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#endif

#include "hexchat-plugin.h"

#define BUFSIZE 32768
#define DEFAULT_LIMIT 256									/* default size is 256 MiB */

static hexchat_plugin *ph;									/* plugin handle */
static char name[] = "Checksum";
static char desc[] = "Calculate checksum for DCC file transfers";
static char version[] = "3.1";

/* Use of OpenSSL SHA256 interface: http://adamlamers.com/?p=5 */
static void
sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
{
	int i;
	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
	{
		sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
	}
	outputBuffer[64] = 0;
}

#if 0
static void
sha256 (char *string, char outputBuffer[65])
{
	int i;
	unsigned char hash[SHA256_DIGEST_LENGTH];
	SHA256_CTX sha256;

	SHA256_Init (&sha256);
	SHA256_Update (&sha256, string, strlen (string));
	SHA256_Final (hash, &sha256);

	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
	{
		sprintf (outputBuffer + (i * 2), "%02x", hash[i]);
	}
	outputBuffer[64] = 0;
}
#endif

static int
sha256_file (char *path, char outputBuffer[65])
{
	int bytesRead;
	unsigned char *buffer;
	unsigned char hash[SHA256_DIGEST_LENGTH];
	SHA256_CTX sha256;

	FILE *file = fopen (path, "rb");
	if (!file)
	{
		return -534;
	}

	SHA256_Init (&sha256);
	buffer = malloc (BUFSIZE);
	bytesRead = 0;

	if (!buffer)
	{
		fclose (file);
		return ENOMEM;
	}

	while ((bytesRead = fread (buffer, 1, BUFSIZE, file)))
	{
		SHA256_Update (&sha256, buffer, bytesRead);
	}

	SHA256_Final (hash, &sha256);
	sha256_hash_string (hash, outputBuffer);

	fclose (file);
	free (buffer);
	return 0;
}

static void
set_limit (char* size)
{
	int buffer = atoi (size);

	if (buffer > 0 && buffer < INT_MAX)
	{
		if (hexchat_pluginpref_set_int (ph, "limit", buffer))
		{
			hexchat_printf (ph, "File size limit has successfully been set to: %d MiB\n", buffer);
		}
		else
		{
			hexchat_printf (ph, "File access error while saving!\n");
		}
	}
	else
	{
		hexchat_printf (ph, "Invalid input!\n");
	}
}

static int
get_limit ()
{
	int size = hexchat_pluginpref_get_int (ph, "limit");

	if (size <= -1 || size >= INT_MAX)
	{
		return DEFAULT_LIMIT;
	}
	else
	{
		return size;
	}
}

static void
print_limit ()
{
	hexchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ());
}

static int
dccrecv_cb (char *word[], void *userdata)
{
	int result;
	struct stat buffer;									/* buffer for storing file info */
	char sum[65];											/* buffer for checksum */
	const char *file;
	char *cfile;

	if (hexchat_get_prefs (ph, "dcc_completed_dir", &file, NULL) == 1 && file[0] != 0)
	{
		cfile = g_strconcat (file, G_DIR_SEPARATOR_S, word[1], NULL);
	}
	else
	{
		cfile = g_strdup(word[2]);
	}

	result = stat (cfile, &buffer);
	if (result == 0)										/* stat returns 0 on success */
	{
		if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
		{
			sha256_file (cfile, sum);						/* file is the full filename even if completed dir set */
			/* try to print the checksum in the privmsg tab of the sender */
			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
			hexchat_printf (ph, "SHA-256 checksum for %s (local):  %s\n", word[1], sum);
		}
		else
		{
			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
			hexchat_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
	{
		hexchat_printf (ph, "File access error!\n");
	}

	g_free (cfile);
	return HEXCHAT_EAT_NONE;
}

static int
dccoffer_cb (char *word[], void *userdata)
{
	int result;
	struct stat buffer;									/* buffer for storing file info */
	char sum[65];											/* buffer for checksum */

	result = stat (word[3], &buffer);
	if (result == 0)										/* stat returns 0 on success */
	{
		if (buffer.st_size <= (unsigned long long) get_limit () * 1048576)
		{
			sha256_file (word[3], sum);						/* word[3] is the full filename */
			hexchat_commandf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): %s", word[2], word[1], sum);
		}
		else
		{
			hexchat_set_context (ph, hexchat_find_context (ph, NULL, word[3]));
			hexchat_printf (ph, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): (size limit reached, no checksum calculated)", word[2], word[1]);
		}
	}
	else
	{
		hexchat_printf (ph, "File access error!\n");
	}

	return HEXCHAT_EAT_NONE;
}

static int
checksum (char *word[], char *word_eol[], void *userdata)
{
	if (!g_ascii_strcasecmp ("GET", word[2]))
	{
		print_limit ();
	}
	else if (!g_ascii_strcasecmp ("SET", word[2]))
	{
		set_limit (word[3]);
	}
	else
	{
		hexchat_printf (ph, "Usage: /CHECKSUM GET|SET\n");
		hexchat_printf (ph, "  GET - print the maximum file size (in MiB) to be hashed\n");
		hexchat_printf (ph, "  SET <filesize> - set the maximum file size (in MiB) to be hashed\n");
	}

	return HEXCHAT_EAT_NONE;
}

int
hexchat_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
{
	ph = plugin_handle;

	*plugin_name = name;
	*plugin_desc = desc;
	*plugin_version = version;

	/* this is required for the very first run */
	if (hexchat_pluginpref_get_int (ph, "limit") == -1)
	{
		hexchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT);
	}

	hexchat_hook_command (ph, "CHECKSUM", HEXCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", 0);
	hexchat_hook_print (ph, "DCC RECV Complete", HEXCHAT_PRI_NORM, dccrecv_cb, NULL);
	hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_NORM, dccoffer_cb, NULL);

	hexchat_printf (ph, "%s plugin loaded\n", name);
	return 1;
}

int
hexchat_plugin_deinit (void)
{
	hexchat_printf (ph, "%s plugin unloaded\n", name);
	return 1;
}