summary refs log tree commit diff stats
path: root/plugins/fishlim
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/fishlim')
-rw-r--r--plugins/fishlim/Makefile.am8
-rw-r--r--plugins/fishlim/fish.c44
-rw-r--r--plugins/fishlim/fish.h3
-rw-r--r--plugins/fishlim/fishlim.vcxproj66
-rw-r--r--plugins/fishlim/fishlim.vcxproj.filters6
-rw-r--r--plugins/fishlim/irc.c54
-rw-r--r--plugins/fishlim/irc.h5
-rw-r--r--plugins/fishlim/keystore.c92
-rw-r--r--plugins/fishlim/keystore.h9
-rw-r--r--plugins/fishlim/misc.c54
-rw-r--r--plugins/fishlim/misc.h36
-rw-r--r--plugins/fishlim/plugin_hexchat.c137
-rw-r--r--plugins/fishlim/plugin_hexchat.h1
-rw-r--r--plugins/fishlim/test.c94
14 files changed, 172 insertions, 437 deletions
diff --git a/plugins/fishlim/Makefile.am b/plugins/fishlim/Makefile.am
index 255ea0c3..df541396 100644
--- a/plugins/fishlim/Makefile.am
+++ b/plugins/fishlim/Makefile.am
@@ -3,7 +3,7 @@ EXTRA_DIST = INSTALL LICENSE
 libdir = $(hexchatlibdir)
 
 lib_LTLIBRARIES = fishlim.la
-fishlim_la_SOURCES = fish.c irc.c keystore.c misc.c plugin_hexchat.c
-fishlim_la_LDFLAGS = -avoid-version -module 
-fishlim_la_LIBADD = 
-AM_CPPFLAGS = $(COMMON_CFLAGS) -I$(srcdir)/../../src/common
+fishlim_la_SOURCES = fish.c irc.c keystore.c plugin_hexchat.c
+fishlim_la_LDFLAGS = $(PLUGIN_LDFLAGS) -module
+fishlim_la_LIBADD = $(GLIB_LIBS) $(OPENSSL_LIBS)
+fishlim_la_CFLAGS = $(GLIB_CFLAGS) $(OPENSSL_CFLAGS) -I$(top_srcdir)/src/common
diff --git a/plugins/fishlim/fish.c b/plugins/fishlim/fish.c
index 93420f23..00ecfbfa 100644
--- a/plugins/fishlim/fish.c
+++ b/plugins/fishlim/fish.c
@@ -39,17 +39,17 @@ static const char fish_base64[64] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDE
 static const signed char fish_unbase64[256] = {
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB,IB,IB,
-//      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  /
+/*      !  "  #  $  %  &  '  (    )  *  +  ,  -  .  / */
     IB,IB,IB,IB,IB,IB,IB,IB,  IB,IB,IB,IB,IB,IB, 0, 1,
-//   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ?
+/*   0  1  2  3  4  5  6  7    8  9  :  ;  <  =  >  ? */
      2, 3, 4, 5, 6, 7, 8, 9,  10,11,IB,IB,IB,IB,IB,IB,
-//   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O
+/*   @  A  B  C  D  E  F  G    H  I  J  K  L  M  N  O */
     IB,38,39,40,41,42,43,44,  45,46,47,48,49,50,51,52,
-//   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _
+/*   P  Q  R  S  T  U  V  W    X  Y  Z  [  \  ]  ^  _*/
     53,54,55,56,57,58,59,60,  61,62,63,IB,IB,IB,IB,IB,
-//   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o
+/*   `  a  b  c  d  e  f  g    h  i  j  k  l  m  n  o */
     IB,12,13,14,15,16,17,18,  19,20,21,22,23,24,25,26,
-//   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del>
+/*   p  q  r  s  t  u  v  w    x  y  z  {  |  }  ~  <del> */
     27,28,29,30,31,32,33,34,  35,36,37,IB,IB,IB,IB,IB,
 };
 
@@ -75,12 +75,11 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
     
     messagelen = strlen(message);
     if (messagelen == 0) return NULL;
-    encrypted = malloc(((messagelen-1)/8)*12 + 12 + 1); // each 8-byte block becomes 12 bytes
+    encrypted = g_malloc(((messagelen - 1) / 8) * 12 + 12 + 1); /* each 8-byte block becomes 12 bytes */
     end = encrypted;
-    if (!encrypted) return NULL;
      
     while (*message) {
-        // Read 8 bytes (a Blowfish block)
+        /* Read 8 bytes (a Blowfish block) */
         BF_LONG binary[2] = { 0, 0 };
         unsigned char c;
         for (i = 0; i < 8; i++) {
@@ -90,10 +89,10 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
         }
         message += 8;
         
-        // Encrypt block
+        /* Encrypt block */
         BF_encrypt(binary, &bfkey);
         
-        // Emit FiSH-BASE64
+        /* Emit FiSH-BASE64 */
         bit = 0;
         word = 1;
         for (j = 0; j < 12; j++) {
@@ -106,7 +105,7 @@ char *fish_encrypt(const char *key, size_t keylen, const char *message) {
             }
         }
         
-        // Stop if a null terminator was found
+        /* Stop if a null terminator was found */
         if (c == '\0') break;
     }
     *end = '\0';
@@ -124,12 +123,11 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
     unsigned char d;
     BF_set_key(&bfkey, keylen, (const unsigned char*)key);
     
-    decrypted = malloc(strlen(data)+1);
+    decrypted = g_malloc(strlen(data) + 1);
     end = decrypted;
-    if (!decrypted) return NULL;
     
     while (*data) {
-        // Convert from FiSH-BASE64
+        /* Convert from FiSH-BASE64 */
         BF_LONG binary[2] = { 0, 0 };
         bit = 0;
         word = 1;
@@ -144,10 +142,10 @@ char *fish_decrypt(const char *key, size_t keylen, const char *data) {
             }
         }
         
-        // Decrypt block
+        /* Decrypt block */
         BF_decrypt(binary, &bfkey);
         
-        // Copy to buffer
+        /* Copy to buffer */
         GET_BYTES(end, binary[0]);
         GET_BYTES(end, binary[1]);
     }
@@ -165,14 +163,14 @@ char *fish_encrypt_for_nick(const char *nick, const char *data) {
     char *key;
     char *encrypted;
 
-    // Look for key
+    /* Look for key */
     key = keystore_get_key(nick);
     if (!key) return NULL;
     
-    // Encrypt
+    /* Encrypt */
     encrypted = fish_encrypt(key, strlen(key), data);
     
-    free(key);
+    g_free(key);
     return encrypted;
 }
 
@@ -183,14 +181,14 @@ char *fish_encrypt_for_nick(const char *nick, const char *data) {
 char *fish_decrypt_from_nick(const char *nick, const char *data) {
     char *key;
     char *decrypted;
-    // Look for key
+    /* Look for key */
     key = keystore_get_key(nick);
     if (!key) return NULL;
     
-    // Decrypt
+    /* Decrypt */
     decrypted = fish_decrypt(key, strlen(key), data);
     
-    free(key);
+    g_free(key);
     return decrypted;
 }
 
diff --git a/plugins/fishlim/fish.h b/plugins/fishlim/fish.h
index db471326..238f52e7 100644
--- a/plugins/fishlim/fish.h
+++ b/plugins/fishlim/fish.h
@@ -25,9 +25,10 @@
 #ifndef FISH_H
 #define FISH_H
 
-#include <stdbool.h>
 #include <stddef.h>
 
+#include <glib.h>
+
 char *fish_encrypt(const char *key, size_t keylen, const char *message);
 char *fish_decrypt(const char *key, size_t keylen, const char *data);
 char *fish_encrypt_for_nick(const char *nick, const char *data);
diff --git a/plugins/fishlim/fishlim.vcxproj b/plugins/fishlim/fishlim.vcxproj
index f1eb95ba..25492a82 100644
--- a/plugins/fishlim/fishlim.vcxproj
+++ b/plugins/fishlim/fishlim.vcxproj
@@ -2,6 +2,7 @@
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <PropertyGroup Label="Configuration">

     <PlatformToolset>v120</PlatformToolset>

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

   </PropertyGroup>

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Release|Win32">

@@ -19,57 +20,19 @@
     <RootNamespace>fishlim</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>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>MultiByte</CharacterSet>

-  </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\hexchat.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\hexchat.props" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <LinkIncremental>false</LinkIncremental>

-    <TargetName>hcfishlim</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <LinkIncremental>false</LinkIncremental>

+  <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  <Import Project="..\..\win32\hexchat.props" />

+  <PropertyGroup>

     <TargetName>hcfishlim</TargetName>

-    <OutDir>$(HexChatBin)</OutDir>

-    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <OutDir>$(HexChatRel)plugins\</OutDir>

   </PropertyGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>

       <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -77,19 +40,10 @@
   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

     <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;_USRDLL;FISHLIM_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(DepsRoot)\include;$(Glib);..\..\src\common;$(HexChatLib);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

-      <SubSystem>Windows</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

       <ModuleDefinitionFile>fishlim.def</ModuleDefinitionFile>

       <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(DepLibs);%(AdditionalDependencies)</AdditionalDependencies>

@@ -103,17 +57,13 @@
     <ClInclude Include="fish.h" />

     <ClInclude Include="irc.h" />

     <ClInclude Include="keystore.h" />

-    <ClInclude Include="misc.h" />

     <ClInclude Include="plugin_hexchat.h" />

   </ItemGroup>

   <ItemGroup>

     <ClCompile Include="fish.c" />

     <ClCompile Include="irc.c" />

     <ClCompile Include="keystore.c" />

-    <ClCompile Include="misc.c" />

     <ClCompile Include="plugin_hexchat.c" />

   </ItemGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>
\ No newline at end of file
+</Project>

diff --git a/plugins/fishlim/fishlim.vcxproj.filters b/plugins/fishlim/fishlim.vcxproj.filters
index 7c13733b..d8fbf454 100644
--- a/plugins/fishlim/fishlim.vcxproj.filters
+++ b/plugins/fishlim/fishlim.vcxproj.filters
@@ -32,9 +32,6 @@
     <ClInclude Include="keystore.h">

       <Filter>Header Files</Filter>

     </ClInclude>

-    <ClInclude Include="misc.h">

-      <Filter>Header Files</Filter>

-    </ClInclude>

     <ClInclude Include="plugin_hexchat.h">

       <Filter>Header Files</Filter>

     </ClInclude>

@@ -49,9 +46,6 @@
     <ClCompile Include="keystore.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="misc.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="plugin_hexchat.c">

       <Filter>Source Files</Filter>

     </ClCompile>

diff --git a/plugins/fishlim/irc.c b/plugins/fishlim/irc.c
index 3586921b..deba545b 100644
--- a/plugins/fishlim/irc.c
+++ b/plugins/fishlim/irc.c
@@ -22,8 +22,9 @@
 
 */
 
-#include <stdlib.h>
-#include <string.h>
+#include "config.h"
+
+#include <glib.h>
 #include "irc.h"
 
 /**
@@ -31,26 +32,26 @@
  * at spaces. The prefix and command is extracted from the message, and
  * parameters_offset is set to the index of the first parameter.
  */
-bool irc_parse_message(const char *words[],
+gboolean irc_parse_message(const char *words[],
                        const char **prefix, const char **command,
                        size_t *parameters_offset) {
     size_t w = 1;
     if (prefix) *prefix = NULL;
     if (command) *command = NULL;
     
-    // See if the message starts with a prefix (sender user)
+    /* See if the message starts with a prefix (sender user) */
     if (words[w][0] == ':') {
         if (prefix) *prefix = &words[w][1];
         w++;
     }
     
-    // Check command
-    if (words[w][0] == '\0') return false;
+    /* Check command */
+    if (words[w][0] == '\0') return FALSE;
     if (command) *command = words[w];
     w++;
     
     *parameters_offset = w;
-    return true;
+    return TRUE;
 }
 
 
@@ -65,48 +66,15 @@ bool irc_parse_message(const char *words[],
  */
 char *irc_prefix_get_nick(const char *prefix) {
     const char *end;
-    char *nick;
     size_t length;
     
     if (!prefix) return NULL;
     
-    // Find end of nick
+    /* Find end of nick */
     end = prefix;
     while (*end != '\0' && *end != '!' && *end != '@') end++;
     
-    // Allocate string
+    /* Allocate string */
     length = end - prefix;
-    nick = malloc(length+1);
-    if (!nick) return NULL;
-    
-    // Copy to string
-    memcpy(nick, prefix, length);
-    nick[length] = '\0';
-    return nick;
-}
-
-
-/**
- * Compares two nick names. Return 0 if equal. Otherwise the return value is
- * less than zero if a is less than b or greater than zero if a is greater
- * than b.
- */
-int irc_nick_cmp(const char *a, const char *b) {
-    char ac;
-    char bc;
-    char diff;
-    for (;;) {
-        ac = *(a++);
-        bc = *(b++);
-        
-        // Change into IRC uppercase (see RFC 2812 section 2.2)
-        if (ac >= 'a' && ac <= '~') ac &= ~0x20;
-        if (bc >= 'a' && bc <= '~') bc &= ~0x20;
-        
-        diff = ac - bc;
-        if (diff) return diff;
-        if (!ac) return 0;
-    }
+    return g_strndup (prefix, length);
 }
-
-
diff --git a/plugins/fishlim/irc.h b/plugins/fishlim/irc.h
index 87317130..c5649233 100644
--- a/plugins/fishlim/irc.h
+++ b/plugins/fishlim/irc.h
@@ -25,14 +25,13 @@
 #ifndef IRC_H
 #define IRC_H
 
-#include <stdbool.h>
 #include <stddef.h>
+#include <glib.h>
 
-bool irc_parse_message(const char *words[],
+gboolean irc_parse_message(const char *words[],
                        const char **prefix, const char **command,
                        size_t *parameters_offset);
 char *irc_prefix_get_nick(const char *prefix);
-int irc_nick_cmp(const char *a, const char *b);
 
 #endif
 
diff --git a/plugins/fishlim/keystore.c b/plugins/fishlim/keystore.c
index 9f1c446e..84373996 100644
--- a/plugins/fishlim/keystore.c
+++ b/plugins/fishlim/keystore.c
@@ -22,12 +22,13 @@
 
 */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 #include "irc.h"
 #include "fish.h"
-#include "misc.h"
 #include "keystore.h"
 #include "plugin_hexchat.h"
 
@@ -57,7 +58,7 @@ static GKeyFile *getConfigFile() {
 static const char *get_keystore_password() {
     return (keystore_password != NULL ?
         keystore_password :
-        // Silly default value...
+        /* Silly default value... */
         "blowinikey");
 }
 
@@ -87,17 +88,17 @@ static gchar *get_nick_value(GKeyFile *keyfile, const char *nick, const char *it
  * Extracts a key from the key store file.
  */
 char *keystore_get_key(const char *nick) {
-    // Get the key
+    /* Get the key */
     GKeyFile *keyfile = getConfigFile();
     gchar *value = get_nick_value(keyfile, nick, "key");
     g_key_file_free(keyfile);
     if (!value) return NULL;
     
     if (strncmp(value, "+OK ", 4) != 0) {
-        // Key is stored in plaintext
-        return import_glib_string(value);
+        /* Key is stored in plaintext */
+        return value;
     } else {
-        // Key is encrypted
+        /* Key is encrypted */
         const char *encrypted = value+4;
         const char *password = get_keystore_password();
         char *decrypted = fish_decrypt(password, strlen(password), encrypted);
@@ -109,10 +110,10 @@ char *keystore_get_key(const char *nick) {
 /**
  * Deletes a nick and the associated key in the key store file.
  */
-static bool delete_nick(GKeyFile *keyfile, const char *nick) {
+static gboolean delete_nick(GKeyFile *keyfile, const char *nick) {
     gchar **group;
     gchar **groups = g_key_file_get_groups(keyfile, NULL);
-    bool ok = false;
+    gboolean ok = FALSE;
     
     for (group = groups; *group != NULL; group++) {
         if (!irc_nick_cmp(*group, nick)) {
@@ -125,58 +126,77 @@ static bool delete_nick(GKeyFile *keyfile, const char *nick) {
     return ok;
 }
 
+#if !GLIB_CHECK_VERSION(2,40,0)
 /**
  * Writes the key store file to disk.
  */
-static bool save_keystore(GKeyFile *keyfile) {
-    char *filename;
-    bool ok;
-    // Serialize
+static gboolean keyfile_save_to_file (GKeyFile *keyfile, char *filename) {
+    gboolean ok;
+
+    /* Serialize */
     gsize file_length;
     gchar *file_data = g_key_file_to_data(keyfile, &file_length, NULL);
-    if (!file_data) return false;
-    
-    // Write to file
-    filename = get_config_filename();
-    ok = g_file_set_contents(filename, file_data, file_length, NULL);
-    g_free(filename);
+    if (!file_data)
+        return FALSE;
+
+    /* Write to file */
+    ok = g_file_set_contents (filename, file_data, file_length, NULL);
     g_free(file_data);
     return ok;
 }
+#endif
+
+/**
+ * Writes the key store file to disk.
+ */
+static gboolean save_keystore(GKeyFile *keyfile) {
+    char *filename;
+    gboolean ok;
+
+    filename = get_config_filename();
+#if !GLIB_CHECK_VERSION(2,40,0)
+    ok = keyfile_save_to_file (keyfile, filename);
+#else
+    ok = g_key_file_save_to_file (keyfile, filename, NULL);
+#endif
+    g_free (filename);
+
+    return ok;
+}
 
 /**
  * Sets a key in the key store file.
  */
-bool keystore_store_key(const char *nick, const char *key) {
+gboolean keystore_store_key(const char *nick, const char *key) {
     const char *password;
     char *encrypted;
     char *wrapped;
-    bool ok = false;
+    gboolean ok = FALSE;
     GKeyFile *keyfile = getConfigFile();
     
-    // Remove old key
+    /* Remove old key */
     delete_nick(keyfile, nick);
     
-    // Add new key
+    /* Add new key */
     password = get_keystore_password();
     if (password) {
-        // Encrypt the password
+        /* Encrypt the password */
         encrypted = fish_encrypt(password, strlen(password), key);
         if (!encrypted) goto end;
         
-        // Prepend "+OK "
+        /* Prepend "+OK " */
         wrapped = g_strconcat("+OK ", encrypted, NULL);
         g_free(encrypted);
         
-        // Store encrypted in file
+        /* Store encrypted in file */
         g_key_file_set_string(keyfile, nick, "key", wrapped);
-        free(wrapped);
+        g_free(wrapped);
     } else {
-        // Store unencrypted in file
+        /* Store unencrypted in file */
         g_key_file_set_string(keyfile, nick, "key", key);
     }
     
-    // Save key store file
+    /* Save key store file */
     ok = save_keystore(keyfile);
     
   end:
@@ -187,23 +207,15 @@ bool keystore_store_key(const char *nick, const char *key) {
 /**
  * Deletes a nick from the key store.
  */
-bool keystore_delete_nick(const char *nick) {
+gboolean keystore_delete_nick(const char *nick) {
     GKeyFile *keyfile = getConfigFile();
     
-    // Delete entry
-    bool ok = delete_nick(keyfile, nick);
+    /* Delete entry */
+    gboolean ok = delete_nick(keyfile, nick);
     
-    // Save
+    /* Save */
     if (ok) save_keystore(keyfile);
     
     g_key_file_free(keyfile);
     return ok;
 }
-
-
-void keystore_secure_free(void *ptr, size_t size) {
-    secure_erase(ptr, size);
-    free(ptr);
-}
-
-
diff --git a/plugins/fishlim/keystore.h b/plugins/fishlim/keystore.h
index a2c33f02..3d90606a 100644
--- a/plugins/fishlim/keystore.h
+++ b/plugins/fishlim/keystore.h
@@ -25,14 +25,13 @@
 #ifndef KEYSTORE_H
 #define KEYSTORE_H
 
-#include <stdbool.h>
 #include <stddef.h>
 
-char *keystore_get_key(const char *nick);
-bool keystore_store_key(const char *nick, const char *key);
-bool keystore_delete_nick(const char *nick);
+#include <glib.h>
 
-void keystore_secure_free(void *ptr, size_t size);
+char *keystore_get_key(const char *nick);
+gboolean keystore_store_key(const char *nick, const char *key);
+gboolean keystore_delete_nick(const char *nick);
 
 #endif
 
diff --git a/plugins/fishlim/misc.c b/plugins/fishlim/misc.c
deleted file mode 100644
index 2b78961d..00000000
--- a/plugins/fishlim/misc.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  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 <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include "misc.h"
-
-
-void secure_erase(void *ptr, size_t size) {
-    // "volatile" prevents this code from being optimized away
-    volatile char* volptr = ptr;
-    while (size--) *volptr++ = 0;
-}
-
-/**
- * Re-allocates a string with the native allocator.
- */
-char *import_glib_string(gchar *gstr) {
-    size_t size;
-    char *native;
-    if (g_mem_is_system_malloc()) return gstr;
-    
-    size = strlen(gstr)+1;
-    native = malloc(size);
-    memcpy(native, gstr, size);
-    
-    secure_erase(gstr, size);
-    g_free(gstr);
-    return native;
-}
-
-
diff --git a/plugins/fishlim/misc.h b/plugins/fishlim/misc.h
deleted file mode 100644
index ee4fc5b8..00000000
--- a/plugins/fishlim/misc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  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.
-
-*/
-
-#ifndef MISC_H
-#define MISC_H
-
-void secure_erase(void *ptr, size_t size);
-
-#ifdef __G_LIB_H__
-char *import_glib_string(gchar *gstr);
-#endif
-
-#endif
-
-
diff --git a/plugins/fishlim/plugin_hexchat.c b/plugins/fishlim/plugin_hexchat.c
index f200ea8c..556a2f51 100644
--- a/plugins/fishlim/plugin_hexchat.c
+++ b/plugins/fishlim/plugin_hexchat.c
@@ -22,17 +22,14 @@
 
 */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 
-// #pragma GCC visibility push(default)
 #include "hexchat-plugin.h"
 #define HEXCHAT_MAX_WORDS 32
-// #pragma GCC visibility pop
-
-//#define EXPORT __attribute((visibility("default")))
-//#define EXPORT
 
 #include "fish.h"
 #include "keystore.h"
@@ -52,26 +49,18 @@ static hexchat_plugin *ph;
  * Returns the path to the key store file.
  */
 gchar *get_config_filename() {
-    return g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
-}
+    char *filename_fs, *filename_utf8;
 
-/**
- * Appends data to a string. Returns true if there was sufficient memory.
- * Frees *s and returns false if an error occurs.
- */
-static bool append(char **s, size_t *length, const char *data) {
-    size_t datalen = strlen(data);
-    char *extended = realloc(*s, *length + datalen + 1);
-    if (!extended) {
-        free(*s);
-        return false;
-    }
-    memcpy(extended + *length, data, datalen + 1);
-    *s = extended;
-    *length += datalen;
-    return true;
+    filename_utf8 = g_build_filename(hexchat_get_info(ph, "configdir"), "addon_fishlim.conf", NULL);
+    filename_fs = g_filename_from_utf8 (filename_utf8, -1, NULL, NULL, NULL);
+
+    g_free (filename_utf8);
+    return filename_fs;
 }
 
+int irc_nick_cmp(const char *a, const char *b) {
+	return hexchat_nickcmp (ph, a, b);
+}
 
 /*static int handle_debug(char *word[], char *word_eol[], void *userdata) {
     hexchat_printf(ph, "debug incoming: ");
@@ -87,26 +76,26 @@ static bool append(char **s, size_t *length, const char *data) {
  */
 static int handle_outgoing(char *word[], char *word_eol[], void *userdata) {
     const char *own_nick;
-    // Encrypt the message if possible
+    /* Encrypt the message if possible */
     const char *channel = hexchat_get_info(ph, "channel");
     char *encrypted = fish_encrypt_for_nick(channel, word_eol[1]);
     if (!encrypted) return HEXCHAT_EAT_NONE;
     
-    // Display message
+    /* Display message */
     own_nick = hexchat_get_info(ph, "nick");
     hexchat_emit_print(ph, "Your Message", own_nick, word_eol[1], NULL);
     
-    // Send message
+    /* Send message */
     hexchat_commandf(ph, "PRIVMSG %s :+OK %s", channel, encrypted);
     
-    free(encrypted);
+    g_free(encrypted);
     return HEXCHAT_EAT_HEXCHAT;
 }
 
 /**
  * Called when a channel message or private message is received.
  */
-static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
+static int handle_incoming(char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *userdata) {
     const char *prefix;
     const char *command;
     const char *recipient;
@@ -114,20 +103,19 @@ static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
     const char *peice;
     char *sender_nick;
     char *decrypted;
-    char *message;
     size_t w;
     size_t ew;
     size_t uw;
-    size_t length;
     char prefix_char = 0;
+    GString *message;
 
     if (!irc_parse_message((const char **)word, &prefix, &command, &w))
         return HEXCHAT_EAT_NONE;
     
-    // Topic (command 332) has an extra parameter
+    /* Topic (command 332) has an extra parameter */
     if (!strcmp(command, "332")) w++;
     
-    // Look for encrypted data
+    /* Look for encrypted data */
     for (ew = w+1; ew < HEXCHAT_MAX_WORDS-1; ew++) {
         const char *s = (ew == w+1 ? word[ew]+1 : word[ew]);
         if (*s && (s[1] == '+' || s[1] == 'm')) { prefix_char = *(s++); }
@@ -136,61 +124,70 @@ static int handle_incoming(char *word[], char *word_eol[], void *userdata) {
     }
     return HEXCHAT_EAT_NONE;
   has_encrypted_data: ;
-    // Extract sender nick and recipient nick/channel
+    /* Extract sender nick and recipient nick/channel */
     sender_nick = irc_prefix_get_nick(prefix);
     recipient = word[w];
     
-    // Try to decrypt with these (the keys are searched for in the key store)
+    /* Try to decrypt with these (the keys are searched for in the key store) */
     encrypted = word[ew+1];
     decrypted = fish_decrypt_from_nick(recipient, encrypted);
     if (!decrypted) decrypted = fish_decrypt_from_nick(sender_nick, encrypted);
     
-    // Check for error
+    /* Check for error */
     if (!decrypted) goto decrypt_error;
     
-    // Build unecrypted message
-    message = NULL;
-    length = 0;
-    if (!append(&message, &length, "RECV")) goto decrypt_error;
-    
+    /* Build unecrypted message */
+    message = g_string_sized_new (100); /* TODO: more accurate estimation of size */
+    g_string_append (message, "RECV");
+
+    if (attrs->server_time_utc)
+    {
+        GTimeVal tv = { (glong)attrs->server_time_utc, 0 };
+        char *timestamp = g_time_val_to_iso8601 (&tv);
+
+       g_string_append (message, " @time=");
+       g_string_append (message, timestamp);
+       g_free (timestamp);
+    }
+
     for (uw = 1; uw < HEXCHAT_MAX_WORDS; uw++) {
-        if (word[uw][0] != '\0' && !append(&message, &length, " ")) goto decrypt_error;
+        if (word[uw][0] != '\0')
+            g_string_append_c (message, ' ');
         
         if (uw == ew) {
-            // Add the encrypted data
+            /* Add the encrypted data */
             peice = decrypted;
-            uw++; // Skip "OK+"
+            uw++; /* Skip "OK+" */
             
             if (ew == w+1) {
-                // Prefix with colon, which gets stripped out otherwise
-                if (!append(&message, &length, ":")) goto decrypt_error;
+                /* Prefix with colon, which gets stripped out otherwise */
+                g_string_append_c (message, ':');
             }
             
             if (prefix_char) {
-                char prefix_str[2] = { prefix_char, '\0' };
-                if (!append(&message, &length, prefix_str)) goto decrypt_error;
+                g_string_append_c (message, prefix_char);
             }
             
         } else {
-            // Add unencrypted data (for example, a prefix from a bouncer or bot)
+            /* Add unencrypted data (for example, a prefix from a bouncer or bot) */
             peice = word[uw];
         }
-        
-        if (!append(&message, &length, peice)) goto decrypt_error;
+
+        g_string_append (message, peice);
     }
-    free(decrypted);
+    g_free(decrypted);
     
-    // Simulate unencrypted message
-    //hexchat_printf(ph, "simulating: %s\n", message);
-    hexchat_command(ph, message);
-    
-    free(message);
-    free(sender_nick);
+    /* Simulate unencrypted message */
+    /* hexchat_printf(ph, "simulating: %s\n", message->str); */
+    hexchat_command(ph, message->str);
+
+    g_string_free (message, TRUE);
+    g_free(sender_nick);
     return HEXCHAT_EAT_HEXCHAT;
   
   decrypt_error:
-    free(decrypted);
-    free(sender_nick);
+    g_free(decrypted);
+    g_free(sender_nick);
     return HEXCHAT_EAT_NONE;
 }
 
@@ -201,23 +198,23 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
     const char *nick;
     const char *key;
     
-    // Check syntax
+    /* Check syntax */
     if (*word[2] == '\0') {
         hexchat_printf(ph, "%s\n", usage_setkey);
         return HEXCHAT_EAT_HEXCHAT;
     }
     
     if (*word[3] == '\0') {
-        // /setkey password
+        /* /setkey password */
         nick = hexchat_get_info(ph, "channel");
         key = word_eol[2];
     } else {
-        // /setkey #channel password
+        /* /setkey #channel password */
         nick = word[2];
         key = word_eol[3];
     }
     
-    // Set password
+    /* Set password */
     if (keystore_store_key(nick, key)) {
         hexchat_printf(ph, "Stored key for %s\n", nick);
     } else {
@@ -233,15 +230,15 @@ static int handle_setkey(char *word[], char *word_eol[], void *userdata) {
 static int handle_delkey(char *word[], char *word_eol[], void *userdata) {
     const char *nick;
     
-    // Check syntax
+    /* Check syntax */
     if (*word[2] == '\0' || *word[3] != '\0') {
         hexchat_printf(ph, "%s\n", usage_delkey);
         return HEXCHAT_EAT_HEXCHAT;
     }
     
-    nick = word_eol[2];
+    nick = g_strstrip (word_eol[2]);
     
-    // Delete the given nick from the key store
+    /* Delete the given nick from the key store */
     if (keystore_delete_nick(nick)) {
         hexchat_printf(ph, "Deleted key for %s\n", nick);
     } else {
@@ -282,11 +279,11 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
     
     /* Add handlers */
     hexchat_hook_command(ph, "", HEXCHAT_PRI_NORM, handle_outgoing, NULL, NULL);
-    hexchat_hook_server(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    hexchat_hook_server(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    //hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL);
-    hexchat_hook_server(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
-    hexchat_hook_server(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "NOTICE", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "PRIVMSG", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    /* hexchat_hook_server(ph, "RAW LINE", HEXCHAT_PRI_NORM, handle_debug, NULL); */
+    hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
+    hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
     
     hexchat_printf(ph, "%s plugin loaded\n", plugin_name);
     /* Return success */
diff --git a/plugins/fishlim/plugin_hexchat.h b/plugins/fishlim/plugin_hexchat.h
index 04a1f4ff..f60522e6 100644
--- a/plugins/fishlim/plugin_hexchat.h
+++ b/plugins/fishlim/plugin_hexchat.h
@@ -26,6 +26,7 @@
 #define PLUGIN_HEXCHAT_H
 
 gchar *get_config_filename();
+int irc_nick_cmp (const char *, const char *);
 
 #endif
 
diff --git a/plugins/fishlim/test.c b/plugins/fishlim/test.c
deleted file mode 100644
index b4dc8d91..00000000
--- a/plugins/fishlim/test.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-
-  Copyright (c) 2010 Samuel Lidén Borell <samuel@kodafritt.se>
-
-  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 <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "fish.h"
-
-// We can't use the HexChat plugin API from here...
-gchar *get_config_filename() {
-    const gchar *homedir = g_get_home_dir();
-    return g_build_filename(homedir, ".config", "hexchat", "blow.ini", NULL);
-}
-
-
-static int decrypt(int nick_count, char *nicks[]) {
-    char encrypted[8192];
-    while (fgets(encrypted, sizeof(encrypted), stdin)) {
-        char *msg;
-        for (int i = 0; i < nick_count; i++) {
-            msg = fish_decrypt_from_nick(nicks[i], encrypted);
-            if (msg) goto success;
-        }
-        fprintf(stderr, "None of the recipients were found in the key store!\n");
-        return 1;
-      success:
-        fprintf(stderr, "Decrypted text >>>%s<<<\n", msg);
-        free(msg);
-    }
-    return 0;
-}
-
-static int encrypt(int nick_count, char *nicks[]) {
-    char message[8192];
-    while (fgets(message, sizeof(message), stdin)) {
-        // Remove newline character
-        char *newline = strchr(message, '\n');
-        if (newline) *newline = '\0';
-        
-        bool error = false;
-        for (int i = 0; i < nick_count; i++) {
-            char *encrypted = fish_encrypt_for_nick(nicks[i], message);
-            if (encrypted) {
-                fprintf(stderr, "Encrypted [%s]:  >>>%s<<<\n", nicks[i], encrypted);
-                free(encrypted);
-            } else {
-                error = true;
-            }
-        }
-        
-        if (error) {
-            fprintf(stderr, "Some of the recipients were't found in the key store!\n");
-            return 1;
-        }
-    }
-    return 0;
-}
-
-int main(int argc, char *argv[]) {
-    if (argc < 2) {
-        fprintf(stderr, "usage: %s [-e] nick...\n", argv[0]);
-        return 2;
-    }
-    
-    if (strcmp(argv[1], "-e") == 0) {
-        return encrypt(argc-2, &argv[2]);
-    } else {
-        return decrypt(argc-1, &argv[1]);
-    }
-}
-
-