diff options
Diffstat (limited to 'plugins/checksum')
-rw-r--r-- | plugins/checksum/checksum.c | 264 | ||||
-rw-r--r-- | plugins/checksum/checksum.def | 3 | ||||
-rw-r--r-- | plugins/checksum/checksum.vcxproj | 110 | ||||
-rw-r--r-- | plugins/checksum/checksum.vcxproj.filters | 23 | ||||
-rw-r--r-- | plugins/checksum/checksum.vcxproj.user | 3 | ||||
-rw-r--r-- | plugins/checksum/makefile.mak | 18 |
6 files changed, 421 insertions, 0 deletions
diff --git a/plugins/checksum/checksum.c b/plugins/checksum/checksum.c new file mode 100644 index 00000000..79f64982 --- /dev/null +++ b/plugins/checksum/checksum.c @@ -0,0 +1,264 @@ +/* XChat-WDK + * 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. + */ + +#include <stdio.h> +#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_LIMIT 256 /* default size is 256 MiB */ + +#ifndef snprintf +#define snprintf _snprintf +#endif +#ifndef stat64 +#define stat64 _stat64 +#endif + +static xchat_plugin *ph; /* plugin handle */ +static const char name[] = "Checksum"; +static const char desc[] = "Calculate checksum for DCC file transfers"; +static const char version[] = "3.0"; + +/* 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; +} + +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; +} + +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) + { + 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 (xchat_pluginpref_set_int (ph, "limit", buffer)) + { + xchat_printf (ph, "File size limit has successfully been set to: %d MiB\n", buffer); + } + else + { + xchat_printf (ph, "File access error while saving!\n"); + } + } + else + { + xchat_printf (ph, "Invalid input!\n"); + } +} + +static int +get_limit () +{ + int size = xchat_pluginpref_get_int (ph, "limit"); + + if (size <= -1 || size >= INT_MAX) + { + return DEFAULT_LIMIT; + } + else + { + return size; + } +} + +static void +print_limit () +{ + xchat_printf (ph, "File size limit for checksums: %d MiB", get_limit ()); +} + +static int +dccrecv_cb (char *word[], void *userdata) +{ + int result; + struct stat64 buffer; /* buffer for storing file info */ + char sum[65]; /* buffer for checksum */ + + result = stat64 (word[2], &buffer); + if (result == 0) /* stat returns 0 on success */ + { + if (buffer.st_size <= (unsigned long long) get_limit () * 1048576) + { + 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!\n"); + } + + return XCHAT_EAT_NONE; +} + +static int +dccoffer_cb (char *word[], void *userdata) +{ + int result; + struct stat64 buffer; /* buffer for storing file info */ + char sum[65]; /* buffer for checksum */ + + result = stat64 (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 */ + 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, "quote PRIVMSG %s :SHA-256 checksum for %s (remote): (size limit reached, no checksum calculated)", word[2], word[1]); + } + } + else + { + xchat_printf (ph, "File access error!\n"); + } + + return XCHAT_EAT_NONE; +} + +static void +checksum (char *word[], void *userdata) +{ + if (!stricmp ("GET", word[2])) + { + print_limit (); + } + else if (!stricmp ("SET", word[2])) + { + set_limit (word[3]); + } + else + { + xchat_printf (ph, "Usage: /CHECKSUM GET|INC|DEC\n"); + xchat_printf (ph, " GET - print the maximum file size (in MiB) to be hashed\n"); + xchat_printf (ph, " SET <filesize> - set the maximum file size (in MiB) to be hashed\n"); + } +} + +int +xchat_plugin_init (xchat_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 (xchat_pluginpref_get_int (ph, "limit") == -1) + { + xchat_pluginpref_set_int (ph, "limit", DEFAULT_LIMIT); + } + + xchat_hook_command (ph, "CHECKSUM", XCHAT_PRI_NORM, checksum, "Usage: /CHECKSUM GET|SET", 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); + + xchat_printf (ph, "%s plugin loaded\n", name); + return 1; +} + +int +xchat_plugin_deinit (void) +{ + xchat_printf (ph, "%s plugin unloaded\n", name); + return 1; +} diff --git a/plugins/checksum/checksum.def b/plugins/checksum/checksum.def new file mode 100644 index 00000000..77670bf2 --- /dev/null +++ b/plugins/checksum/checksum.def @@ -0,0 +1,3 @@ +EXPORTS +xchat_plugin_init +xchat_plugin_deinit diff --git a/plugins/checksum/checksum.vcxproj b/plugins/checksum/checksum.vcxproj new file mode 100644 index 00000000..753ca10e --- /dev/null +++ b/plugins/checksum/checksum.vcxproj @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{5EF7F47D-D09C-43C4-BF64-B28B11A0FF91}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>checksum</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>WDK7</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>WDK7</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\win32\xchat.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\win32\xchat.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <TargetName>xcchecksum</TargetName> + <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir> + <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <TargetName>xcchecksum</TargetName> + <OutDir>$(SolutionDir)build\$(PlatformName)\bin</OutDir> + <IntDir>$(SolutionDir)build\$(PlatformName)\obj\$(ProjectName)</IntDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level1</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(DepsRoot)\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <ModuleDefinitionFile>checksum.def</ModuleDefinitionFile> + <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level1</WarningLevel> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;_WIN64;NDEBUG;_WINDOWS;_USRDLL;CHECKSUM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>$(DepsRoot)\include;..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <ModuleDefinitionFile>checksum.def</ModuleDefinitionFile> + <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="checksum.c" /> + </ItemGroup> + <ItemGroup> + <None Include="checksum.def" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/plugins/checksum/checksum.vcxproj.filters b/plugins/checksum/checksum.vcxproj.filters new file mode 100644 index 00000000..e6ef5e81 --- /dev/null +++ b/plugins/checksum/checksum.vcxproj.filters @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="checksum.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <None Include="checksum.def"> + <Filter>Resource Files</Filter> + </None> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/plugins/checksum/checksum.vcxproj.user b/plugins/checksum/checksum.vcxproj.user new file mode 100644 index 00000000..695b5c78 --- /dev/null +++ b/plugins/checksum/checksum.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +</Project> \ No newline at end of file diff --git a/plugins/checksum/makefile.mak b/plugins/checksum/makefile.mak new file mode 100644 index 00000000..ec8e0455 --- /dev/null +++ b/plugins/checksum/makefile.mak @@ -0,0 +1,18 @@ +include "..\..\src\makeinc.mak" + +all: checksum.obj checksum.def + link $(LDFLAGS) $(LIBS) /dll /out:xcchecksum.dll /def:checksum.def checksum.obj + +checksum.def: + echo EXPORTS > checksum.def + echo xchat_plugin_init >> checksum.def + echo xchat_plugin_deinit >> checksum.def + +checksum.obj: checksum.c makefile.mak + cl $(CFLAGS) /I.. checksum.c + +clean: + del *.obj + del *.dll + del *.exp + del *.lib |