Commit Diff
Diff:
ce736fc15bd80044f3206ae36c7c0462decaf1be
222ecbffbb5f0c21e64002c95fe9447b4f6b6320
Commit:
222ecbffbb5f0c21e64002c95fe9447b4f6b6320
Tree:
eb5bcdbfe0d6dbb7fa86e2c82663de672bc67a9a
Author:
Alexander Barton <alex@barton.de>
Committer:
Alexander Barton <alex@barton.de>
Date:
Sun Sep 16 22:56:36 2012 UTC
Message:
Implement new IRC+ "CHARCONV" command See bug 109 and doc/Protocol.txt for details and documentation.
blob - 5b47e9da7ac277b4baf8411013dff10bc2611f76
blob + a25d88617705646a25d38b56ebde1c62d5cea9ed
--- contrib/MacOSX/config.h
+++ contrib/MacOSX/config.h
@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
+ * 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
@@ -51,6 +51,9 @@
/* Define if PAM should be used */
#define PAM 1
+/* Define if libiconv can be used, e.g. for CHARCONV */
+#define ICONV 1
+
/* -- Supported features -- */
/* Define if SSP C support is enabled. */
@@ -76,6 +79,8 @@
/* Define to 1 if you have the `gai_strerror' function. */
#define HAVE_GAI_STRERROR 1
+/* Define to 1 if you have the `iconv_open' function. */
+#define HAVE_ICONV_OPEN 1
/* Define to 1 if you have the `kqueue' function. */
#define HAVE_KQUEUE 1
/* Define to 1 if you have the `inet_ntoa' function. */
blob - ac3f6235381cea4879e4b0c09a1fee324ee93777
blob + b904c763003be5868cc3ff934c4135374ddb54f6
--- contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj
+++ contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj
@@ -36,6 +36,9 @@
FA322DBE0CEF7766001761B3 /* tool.c in Sources */ = {isa = PBXBuildFile; fileRef = FA322D330CEF74B1001761B3 /* tool.c */; };
FA322DC10CEF77CB001761B3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FA322DC00CEF77CB001761B3 /* libz.dylib */; };
FA407F2E0DB159F400271AF1 /* ng_ipaddr.c in Sources */ = {isa = PBXBuildFile; fileRef = FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */; };
+ FA6BBC631605F0AC0004247A /* conn-encoding.c in Sources */ = {isa = PBXBuildFile; fileRef = FA6BBC5F1605F0AB0004247A /* conn-encoding.c */; };
+ FA6BBC641605F0AC0004247A /* irc-encoding.c in Sources */ = {isa = PBXBuildFile; fileRef = FA6BBC611605F0AC0004247A /* irc-encoding.c */; };
+ FA6BBC661605F6D60004247A /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FA6BBC651605F6D60004247A /* libiconv.dylib */; };
FA85178C0FA061EC006A1F5A /* op.c in Sources */ = {isa = PBXBuildFile; fileRef = FA85178B0FA061EC006A1F5A /* op.c */; };
FA99428C10E82A27007F27ED /* proc.c in Sources */ = {isa = PBXBuildFile; fileRef = FA99428B10E82A27007F27ED /* proc.c */; };
FAA3D27B0F139CDC00B2447E /* conn-ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA3D2790F139CDC00B2447E /* conn-ssl.c */; };
@@ -203,6 +206,11 @@
FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "ngIRCd-Logo.gif"; sourceTree = "<group>"; };
FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "ngircd-redhat.init"; sourceTree = "<group>"; };
FA4B08E813E7F91C00765BA3 /* platformtest.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = platformtest.sh; sourceTree = "<group>"; };
+ FA6BBC5F1605F0AB0004247A /* conn-encoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "conn-encoding.c"; sourceTree = "<group>"; };
+ FA6BBC601605F0AC0004247A /* conn-encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "conn-encoding.h"; sourceTree = "<group>"; };
+ FA6BBC611605F0AC0004247A /* irc-encoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "irc-encoding.c"; sourceTree = "<group>"; };
+ FA6BBC621605F0AC0004247A /* irc-encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "irc-encoding.h"; sourceTree = "<group>"; };
+ FA6BBC651605F6D60004247A /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = ../../../../../../../usr/lib/libiconv.dylib; sourceTree = "<group>"; };
FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "sample-ngircd.conf.tmpl"; sourceTree = "<group>"; };
FA85178A0FA061EC006A1F5A /* op.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = op.h; sourceTree = "<group>"; };
FA85178B0FA061EC006A1F5A /* op.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = op.c; sourceTree = "<group>"; };
@@ -258,6 +266,7 @@
files = (
FA322DC10CEF77CB001761B3 /* libz.dylib in Frameworks */,
FA2D567B11EA1AB300D37A35 /* libpam.dylib in Frameworks */,
+ FA6BBC661605F6D60004247A /* libiconv.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -283,8 +292,9 @@
FA322D600CEF750F001761B3 /* configure.in */,
FA322D630CEF750F001761B3 /* Makefile.am */,
1AB674ADFE9D54B511CA2CBB /* Products */,
- FA322DC00CEF77CB001761B3 /* libz.dylib */,
+ FA6BBC651605F6D60004247A /* libiconv.dylib */,
FA2D567A11EA1AB300D37A35 /* libpam.dylib */,
+ FA322DC00CEF77CB001761B3 /* libz.dylib */,
);
name = ngIRCd;
sourceTree = "<group>";
@@ -328,12 +338,14 @@
FA322CDF0CEF74B1001761B3 /* conf.c */,
FA322CE00CEF74B1001761B3 /* conf.h */,
FAA3D2780F139CDC00B2447E /* conf-ssl.h */,
+ FA322CE50CEF74B1001761B3 /* conn.c */,
+ FA322CE60CEF74B1001761B3 /* conn.h */,
+ FA6BBC5F1605F0AB0004247A /* conn-encoding.c */,
+ FA6BBC601605F0AC0004247A /* conn-encoding.h */,
FA322CE10CEF74B1001761B3 /* conn-func.c */,
FA322CE20CEF74B1001761B3 /* conn-func.h */,
FA322CE30CEF74B1001761B3 /* conn-zip.c */,
FA322CE40CEF74B1001761B3 /* conn-zip.h */,
- FA322CE50CEF74B1001761B3 /* conn.c */,
- FA322CE60CEF74B1001761B3 /* conn.h */,
FAA3D2790F139CDC00B2447E /* conn-ssl.c */,
FAA3D27A0F139CDC00B2447E /* conn-ssl.h */,
FA322CE70CEF74B1001761B3 /* defines.h */,
@@ -341,10 +353,14 @@
FA322CE90CEF74B1001761B3 /* hash.h */,
FA322CEA0CEF74B1001761B3 /* io.c */,
FA322CEB0CEF74B1001761B3 /* io.h */,
+ FA322CFC0CEF74B1001761B3 /* irc.c */,
+ FA322CFD0CEF74B1001761B3 /* irc.h */,
FAD5853315271AB800328741 /* irc-cap.c */,
FAD5853415271AB800328741 /* irc-cap.h */,
FA322CEC0CEF74B1001761B3 /* irc-channel.c */,
FA322CED0CEF74B1001761B3 /* irc-channel.h */,
+ FA6BBC611605F0AC0004247A /* irc-encoding.c */,
+ FA6BBC621605F0AC0004247A /* irc-encoding.h */,
FA322CEE0CEF74B1001761B3 /* irc-info.c */,
FA322CEF0CEF74B1001761B3 /* irc-info.h */,
FA322CF00CEF74B1001761B3 /* irc-login.c */,
@@ -359,8 +375,6 @@
FA322CF90CEF74B1001761B3 /* irc-server.h */,
FA322CFA0CEF74B1001761B3 /* irc-write.c */,
FA322CFB0CEF74B1001761B3 /* irc-write.h */,
- FA322CFC0CEF74B1001761B3 /* irc.c */,
- FA322CFD0CEF74B1001761B3 /* irc.h */,
FA322CFE0CEF74B1001761B3 /* lists.c */,
FA322CFF0CEF74B1001761B3 /* lists.h */,
FA322D000CEF74B1001761B3 /* log.c */,
@@ -750,6 +764,8 @@
FAD5853215271AAB00328741 /* client-cap.c in Sources */,
FAD5853515271AB800328741 /* irc-cap.c in Sources */,
FAD5853815272C2600328741 /* login.c in Sources */,
+ FA6BBC631605F0AC0004247A /* conn-encoding.c in Sources */,
+ FA6BBC641605F0AC0004247A /* irc-encoding.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
blob - 5093eea9f3ace44b40b5c6388f0395dcc66f4693
blob + 3d2cda6cb23f8bdd33dee20bc643dbfd59dec19c
--- doc/Protocol.txt
+++ doc/Protocol.txt
@@ -1,9 +1,8 @@
ngIRCd - Next Generation IRC Server
+ http://ngircd.barton.de/
- (c)2001-2008 Alexander Barton,
- alex@barton.de, http://www.barton.de/
-
+ (c)2001-2012 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
@@ -181,3 +180,34 @@ first command sent to the server, even before USER and
The <password> must be set in the server configuration file to prevent
unauthorized clients to fake their identity; it is an arbitrary string.
+
+II.5 Client character encoding conversion
+
+ Command: CHARCONV
+ Parameters: <client-charset>
+ Used by: registered clients
+ Replies: RPL_IP_CHARCONV_MSG, ERR_IP_CHARCONV_MSG
+
+
+III. Numerics used by IRC+ Protocol
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The IRC+ protocol uses numerics in the range 800-899 which aren't used by
+RFC 2812 and hopefully don't clash with other implementations ...
+
+Numerics 800-849 are used for status and success messages, and numerics
+850-899 are failure and error messages.
+
+
+III.1 IRC+ status and success numerics
+
+800 - RPL_IP_CHARCONV_MSG
+ %1 :Client encoding set"
+
+ %1 client character set
+
+
+III.2 IRC+ failure and error numerics
+
+850 - ERR_IP_CHARCONV_MSG
+ :Can't initialize client encoding
blob - 3a411a964b266a2ab9874342ee618018c953ba86
blob + c1fd42409dbb1b24b57492e6dc9e9d161ca8c481
--- src/ngircd/Makefile.am
+++ src/ngircd/Makefile.am
@@ -27,6 +27,7 @@ ngircd_SOURCES = \
client-cap.c \
conf.c \
conn.c \
+ conn-encoding.c \
conn-func.c \
conn-ssl.c \
conn-zip.c \
@@ -35,6 +36,7 @@ ngircd_SOURCES = \
irc.c \
irc-cap.c \
irc-channel.c \
+ irc-encoding.c \
irc-info.c \
irc-login.c \
irc-mode.c \
@@ -68,6 +70,7 @@ noinst_HEADERS = \
conf.h \
conf-ssl.h \
conn.h \
+ conn-encoding.h \
conn-func.h \
conn-ssl.h \
conn-zip.h \
@@ -77,6 +80,7 @@ noinst_HEADERS = \
irc.h \
irc-cap.h \
irc-channel.h \
+ irc-encoding.h \
irc-info.h \
irc-login.h \
irc-mode.h \
blob - /dev/null
blob + 71ab58848a5aa87d258f85156ab98021d5c0cd7a (mode 644)
--- /dev/null
+++ src/ngircd/conn-encoding.c
@@ -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- */
blob - /dev/null
blob + 7b50ed654b4662b53b1c3e0dbd7bb7c234582896 (mode 644)
--- /dev/null
+++ src/ngircd/conn-encoding.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef __conn_encoding_h__
+#define __conn_encoding_h__
+
+/**
+ * @file
+ * Functions to deal with character encodings and conversions (header)
+ */
+
+#ifdef ICONV
+
+GLOBAL bool Conn_SetEncoding PARAMS((CONN_ID Idx, const char *ClientEnc));
+GLOBAL void Conn_UnsetEncoding PARAMS((CONN_ID Idx));
+
+#endif /* ICONV */
+
+GLOBAL char* Conn_EncodingFrom PARAMS((CONN_ID Idx, char *Message));
+GLOBAL char* Conn_EncodingTo PARAMS((CONN_ID Idx, char *Message));
+
+#endif
blob - f4511642c7c7b309c0e302de58cd7e184c172166
blob + 5d086857dcd2f634ab4ec5b506d57ddf3f9d3ce2
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
@@ -63,6 +63,7 @@
#include "client.h"
#include "class.h"
#include "conf.h"
+#include "conn-encoding.h"
#include "conn-ssl.h"
#include "conn-zip.h"
#include "conn-func.h"
@@ -861,6 +862,9 @@ va_dcl
#endif
{
char buffer[COMMAND_LEN];
+#ifdef ICONV
+ char *ptr, *message;
+#endif
size_t len;
bool ok;
va_list ap;
@@ -901,6 +905,16 @@ va_dcl
CUT_TXTSUFFIX);
}
+#ifdef ICONV
+ ptr = strchr(buffer + 1, ':');
+ if (ptr) {
+ ptr++;
+ message = Conn_EncodingTo(Idx, ptr);
+ if (message != ptr)
+ strlcpy(ptr, message, sizeof(buffer) - (ptr - buffer));
+ }
+#endif
+
#ifdef SNIFFER
if (NGIRCd_Sniffer)
Log(LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer);
@@ -2105,6 +2119,11 @@ Init_Conn_Struct(CONN_ID Idx)
My_Connections[Idx].lastdata = now;
My_Connections[Idx].lastprivmsg = now;
Proc_InitStruct(&My_Connections[Idx].proc_stat);
+
+#ifdef ICONV
+ My_Connections[Idx].iconv_from = (iconv_t)(-1);
+ My_Connections[Idx].iconv_to = (iconv_t)(-1);
+#endif
} /* Init_Conn_Struct */
blob - e42a2ae6a7ac1c1466ade3a8124650a489e61715
blob + 9236c58ba7767a7be858a6a331abeedc78e02221
--- src/ngircd/conn.h
+++ src/ngircd/conn.h
@@ -54,6 +54,10 @@ typedef int CONN_ID;
#include "tool.h"
#include "ng_ipaddr.h"
+#ifdef ICONV
+# include <iconv.h>
+#endif
+
#ifdef ZLIB
#include <zlib.h>
typedef struct _ZipData
@@ -95,6 +99,10 @@ typedef struct _Connection
#ifndef STRICT_RFC
long auth_ping; /** PING response expected on login */
#endif
+#ifdef ICONV
+ iconv_t iconv_from; /** iconv: convert from client to server */
+ iconv_t iconv_to; /** iconv: convert from server to client */
+#endif
} CONNECTION;
GLOBAL CONNECTION *My_Connections;
blob - /dev/null
blob + b1d3a697ca0b55c0e3f9bc858fe5b0c3c534d8a1 (mode 644)
--- /dev/null
+++ src/ngircd/irc-encoding.c
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#include "portab.h"
+
+/**
+ * @file
+ * IRC encoding commands
+ */
+
+#include "imp.h"
+#include <assert.h>
+#include <string.h>
+
+#include "conn-func.h"
+#include "channel.h"
+#include "conn-encoding.h"
+#include "irc-write.h"
+#include "messages.h"
+#include "parse.h"
+#include "tool.h"
+
+#include "exp.h"
+#include "irc-encoding.h"
+
+#ifdef ICONV
+
+/**
+ * Handler for the IRC+ "CHARCONV" command.
+ *
+ * @param Client The client from which this command has been received.
+ * @param Req Request structure with prefix and all parameters.
+ * @returns CONNECTED or DISCONNECTED.
+ */
+GLOBAL bool
+IRC_CHARCONV(CLIENT *Client, REQUEST *Req)
+{
+ char encoding[20];
+
+ assert (Client != NULL);
+ assert (Req != NULL);
+
+ if (Req->argc != 1)
+ return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+ Client_ID(Client), Req->command);
+
+ strlcpy(encoding, Req->argv[0], sizeof(encoding));
+ ngt_UpperStr(encoding);
+
+ if (!Conn_SetEncoding(Client_Conn(Client), encoding))
+ return IRC_WriteStrClient(Client, ERR_IP_CHARCONV_MSG,
+ Client_ID(Client), encoding);
+
+ return IRC_WriteStrClient(Client, RPL_IP_CHARCONV_MSG,
+ Client_ID(Client), encoding);
+} /* IRC_CHARCONV */
+
+#endif
+
+/* -eof- */
blob - /dev/null
blob + 4349c91043fd4d3339fb022ba0b815e847416cc6 (mode 644)
--- /dev/null
+++ src/ngircd/irc-encoding.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#ifndef __irc_encoding_h__
+#define __irc_encoding_h__
+
+/**
+ * @file
+ * IRC encoding commands (header)
+ */
+
+GLOBAL bool IRC_CHARCONV PARAMS((CLIENT *Client, REQUEST *Req));
+
+#endif
+
+/* -eof- */
blob - efc34d4b2e087f8e3742c1d44ea6a820e2073f92
blob + ceb649ecf350159d1db1bc969d0a5bb496372a2a
--- src/ngircd/irc.c
+++ src/ngircd/irc.c
@@ -25,6 +25,7 @@
#include "conn-func.h"
#include "conf.h"
#include "channel.h"
+#include "conn-encoding.h"
#include "defines.h"
#include "irc-write.h"
#include "log.h"
@@ -359,6 +360,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
CHANNEL *chan;
char *currentTarget = Req->argv[0];
char *lastCurrentTarget = NULL;
+ char *message = NULL;
assert(Client != NULL);
assert(Req != NULL);
@@ -390,6 +392,13 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
+#ifdef ICONV
+ if (Client_Conn(Client) > NONE)
+ message = Conn_EncodingFrom(Client_Conn(Client), Req->argv[1]);
+ else
+#endif
+ message = Req->argv[1];
+
/* handle msgtarget = msgto *("," msgto) */
currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget);
ngt_UpperStr(Req->command);
@@ -523,12 +532,12 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
}
if (!IRC_WriteStrClientPrefix(cl, from, "%s %s :%s",
Req->command, Client_ID(cl),
- Req->argv[1]))
+ message))
return DISCONNECTED;
} else if (ForceType != CLIENT_SERVICE
&& (chan = Channel_Search(currentTarget))) {
if (!Channel_Write(chan, from, Client, Req->command,
- SendErrors, Req->argv[1]))
+ SendErrors, message))
return DISCONNECTED;
} else if (ForceType != CLIENT_SERVICE
/* $#: server/target mask, RFC 2812, sec. 3.3.1 */
@@ -536,7 +545,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int Force
&& strchr(currentTarget, '.')) {
/* targetmask */
if (!Send_Message_Mask(from, Req->command, currentTarget,
- Req->argv[1], SendErrors))
+ message, SendErrors))
return DISCONNECTED;
} else {
if (!SendErrors)
blob - 4f3a397b2647eabc6fd6ed21f9aa31d776df69e9
blob + 99d258284eb4624e173b0e8576959f1ff368e2ee
--- src/ngircd/messages.h
+++ src/ngircd/messages.h
@@ -21,7 +21,7 @@
#define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
#define RPL_CREATED_MSG "003 %s :This server has been started %s"
#define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s"
-#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
+#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server"
#define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d"
@@ -34,7 +34,6 @@
#define RPL_UMODEIS_MSG "221 %s +%s"
#define RPL_SERVLIST_MSG "234 %s %s %s %s %d %d :%s"
#define RPL_SERVLISTEND_MSG "235 %s %s %s :End of service listing"
-
#define RPL_STATSUPTIME "242 %s :Server Up %u days %u:%02u:%02u"
#define RPL_LUSERCLIENT_MSG "251 %s :There are %ld users and %ld services on %ld servers"
#define RPL_LUSEROP_MSG "252 %s %lu :operator(s) online"
@@ -149,9 +148,17 @@
#define ERR_USERSDONTMATCH_MSG "502 %s :Can't set/get mode for other users"
#ifdef ZLIB
-#define RPL_STATSLINKINFOZIP_MSG "211 %s %s %d %ld %ld/%ld %ld %ld/%ld :%ld"
+# define RPL_STATSLINKINFOZIP_MSG "211 %s %s %d %ld %ld/%ld %ld %ld/%ld :%ld"
#endif
+#ifdef IRCPLUS
+
+# define RPL_IP_CHARCONV_MSG "801 %s %s :Client encoding set"
+
+# define ERR_IP_CHARCONV_MSG "851 %s :Can't initialize client encoding"
+
+#endif /* IRCPLUS */
+
#endif
/* -eof- */
blob - e9c5d53a3f584bc2fda3a13cc5625e63ca37e3c7
blob + f3b04d0c2ee8617ceb21d32ce919859e640b55f4
--- src/ngircd/parse.c
+++ src/ngircd/parse.c
@@ -38,6 +38,7 @@
#include "irc.h"
#include "irc-cap.h"
#include "irc-channel.h"
+#include "irc-encoding.h"
#include "irc-info.h"
#include "irc-login.h"
#include "irc-mode.h"
@@ -114,6 +115,9 @@ static COMMAND My_Commands[] =
#ifdef IRCPLUS
{ "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 },
+# ifdef ICONV
+ { "CHARCONV", IRC_CHARCONV, CLIENT_USER, 0, 0, 0 },
+# endif
#endif
#ifndef STRICT_RFC
IRCNow