]> arthur.barton.de Git - ngircd.git/blobdiff - src/ngircd/conn-encoding.c
Implement new IRC+ "CHARCONV" command
[ngircd.git] / src / ngircd / conn-encoding.c
diff --git a/src/ngircd/conn-encoding.c b/src/ngircd/conn-encoding.c
new file mode 100644 (file)
index 0000000..71ab588
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * ngIRCd -- The Next Generation IRC Daemon
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * Please read the file COPYING, README and AUTHORS for more information.
+ */
+
+#define __conn_encoding_c__
+
+#define CONN_MODULE
+
+#include "portab.h"
+
+/**
+ * @file
+ * Functions to deal with character encodings and conversions
+ */
+
+#include "imp.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "defines.h"
+#include "conn.h"
+#include "log.h"
+
+#include "exp.h"
+#include "conn-encoding.h"
+
+#ifdef ICONV
+
+char Encoding_Buffer[COMMAND_LEN];
+
+char *Convert_Message PARAMS((iconv_t Handle, char *Message));
+
+
+/**
+ * Set client character encoding on a connection.
+ *
+ * @param Conn Connection identifier.
+ * @param ClientEnc Client encoding (for example "ASCII", "MacRoman", ...).
+ * @return true on success, false otherwise.
+ */
+GLOBAL bool
+Conn_SetEncoding(CONN_ID Conn, const char *ClientEnc)
+{
+       char client_enc[25], server_enc[25];
+
+       assert(Conn > NONE);
+       assert(ClientEnc != NULL);
+
+       Conn_UnsetEncoding(Conn);
+
+       /* Is the client character set identical to server character set? */
+       if (strcasecmp(ClientEnc, "UTF-8") == 0)
+               return true;
+
+       snprintf(client_enc, sizeof(client_enc), "%s//TRANSLIT", ClientEnc);
+       snprintf(server_enc, sizeof(server_enc), "%s//TRANSLIT", "UTF-8");
+
+       My_Connections[Conn].iconv_from = iconv_open(server_enc, client_enc);
+       if (My_Connections[Conn].iconv_from == (iconv_t)(-1)) {
+               Conn_UnsetEncoding(Conn);
+               return false;
+       }
+       My_Connections[Conn].iconv_to = iconv_open(client_enc, server_enc);
+       if (My_Connections[Conn].iconv_to == (iconv_t)(-1)) {
+               Conn_UnsetEncoding(Conn);
+               return false;
+       }
+
+       LogDebug("Set client character set of connection \"%d\" to \"%s\".",
+                Conn, client_enc);
+       return true;
+}
+
+/**
+ * Remove client character encoding conversion on a connection.
+ *
+ * @param Conn Connection identifier.
+ */
+GLOBAL void
+Conn_UnsetEncoding(CONN_ID Conn)
+{
+       assert(Conn > NONE);
+
+       if (My_Connections[Conn].iconv_from != (iconv_t)(-1))
+               iconv_close(My_Connections[Conn].iconv_from);
+       if (My_Connections[Conn].iconv_to != (iconv_t)(-1))
+               iconv_close(My_Connections[Conn].iconv_to);
+
+       My_Connections[Conn].iconv_from = (iconv_t)(-1);
+       My_Connections[Conn].iconv_to = (iconv_t)(-1);
+
+       LogDebug("Unset character conversion of connection %d.", Conn);
+}
+
+/**
+ * Convert the encoding of a given message.
+ *
+ * This function uses a static buffer for the result of the encoding
+ * conversion which is overwritten by subsequent calls to this function!
+ *
+ * @param Handle libiconv handle.
+ * @param Message The message to convert.
+ * @return Pointer to the result.
+ */
+char *
+Convert_Message(iconv_t Handle, char *Message)
+{
+       size_t in_left, out_left;
+       char *out = Encoding_Buffer;
+
+       assert (Handle != (iconv_t)(-1));
+       assert (Message != NULL);
+
+       in_left = strlen(Message);
+       out_left = sizeof(Encoding_Buffer) - 1;
+
+       if (iconv(Handle, &Message, &in_left, &out, &out_left) == (size_t)(-1)) {
+               /* An error occured! */
+               LogDebug("Error converting message encoding!");
+               strlcpy(Encoding_Buffer, Message, sizeof(Encoding_Buffer));
+               iconv(Handle, NULL, NULL, NULL, NULL);
+       } else
+               *out = '\0';
+
+       return Encoding_Buffer;
+}
+
+#endif
+
+/**
+ * Convert encoding of a message received from a connection.
+ *
+ * Note 1: If no conversion is required, this function returns the original
+ * pointer to the message.
+ *
+ * Note 2: This function uses Convert_Message(), so subsequent calls to this
+ * function will overwrite the earlier results.
+ *
+ * @param Conn Connection identifier.
+ * @param Message The message to convert.
+ * @return Pointer to the result.
+ * @see Convert_Message
+ */
+GLOBAL char *
+Conn_EncodingFrom(UNUSED CONN_ID Conn, char *Message)
+{
+       assert(Conn > NONE);
+       assert (Message != NULL);
+
+#ifdef ICONV
+       if (My_Connections[Conn].iconv_from != (iconv_t)(-1))
+               return Convert_Message(My_Connections[Conn].iconv_from, Message);
+#endif
+       return Message;
+}
+
+/**
+ * Convert encoding of a message for sending on a connection.
+ *
+ * Note 1: If no conversion is required, this function returns the original
+ * pointer to the message.
+ *
+ * Note 2: This function uses Convert_Message(), so subsequent calls to this
+ * function will overwrite the earlier results.
+ *
+ * @param Conn Connection identifier.
+ * @param Message The message to convert.
+ * @return Pointer to the result.
+ * @see Convert_Message
+ */
+GLOBAL char *
+Conn_EncodingTo(UNUSED CONN_ID Conn, char *Message)
+{
+       assert(Conn > NONE);
+       assert (Message != NULL);
+
+#ifdef ICONV
+       if (My_Connections[Conn].iconv_to != (iconv_t)(-1))
+               return Convert_Message(My_Connections[Conn].iconv_to, Message);
+#endif
+       return Message;
+}
+
+/* -eof- */