]> arthur.barton.de Git - ngircd-alex.git/commitdiff
Merge branch 'bug141-ModesQq'
authorAlexander Barton <alex@barton.de>
Sat, 6 Oct 2012 20:37:57 +0000 (22:37 +0200)
committerAlexander Barton <alex@barton.de>
Sat, 6 Oct 2012 20:37:57 +0000 (22:37 +0200)
This closes bug #141.

* bug141-ModesQq:
  KICK-protect IRC services
  Implement channel mode "Q" and user mode "q"

Conflicts:
src/ngircd/defines.h
src/ngircd/messages.h

22 files changed:
configure.ng
contrib/Debian/control
contrib/Debian/rules
contrib/MacOSX/config.h
contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj
doc/Modes.txt
doc/Protocol.txt
src/ngircd/Makefile.ng
src/ngircd/conn-encoding.c [new file with mode: 0644]
src/ngircd/conn-encoding.h [new file with mode: 0644]
src/ngircd/conn.c
src/ngircd/conn.h
src/ngircd/defines.h
src/ngircd/irc-encoding.c [new file with mode: 0644]
src/ngircd/irc-encoding.h [new file with mode: 0644]
src/ngircd/irc-info.c
src/ngircd/irc-mode.c
src/ngircd/irc-op.c
src/ngircd/irc.c
src/ngircd/messages.h
src/ngircd/ngircd.c
src/ngircd/parse.c

index 8b47ad15dfdded9638be714f46df4b150c099522..a3cab6aee2a77b31cc901aa92ca5795ea5b5e415 100644 (file)
@@ -39,6 +39,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 AH_TEMPLATE([DEBUG], [Define if debug-mode should be enabled])
 AH_TEMPLATE([HAVE_sockaddr_in_len], [Define if sockaddr_in.sin_len exists])
 AH_TEMPLATE([HAVE_socklen_t], [Define if socklen_t exists])
+AH_TEMPLATE([ICONV], [Define if libiconv can be used, e.g. for CHARCONV])
 AH_TEMPLATE([IDENTAUTH], [Define if the server should do IDENT requests])
 AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used])
 AH_TEMPLATE([PAM], [Define if PAM should be used])
@@ -511,6 +512,29 @@ AC_ARG_ENABLE(ircplus,
 )
 if test "$x_ircplus_on" = "yes"; then
        AC_DEFINE(IRCPLUS, 1)
+
+       # Compile in iconv support?
+       # We only check for it when IRC+ is enabled, because the IRC+ command
+       # CHARCONV is the only function depending on it.
+       x_iconv_on=no
+       AC_ARG_WITH(iconv,
+               [  --with-iconv            enable character conversation using libiconv],
+               [ if test "$withval" != "no"; then
+                       if test "$withval" != "yes"; then
+                               CFLAGS="-I$withval/include $CFLAGS"
+                               CPPFLAGS="-I$withval/include $CPPFLAGS"
+                               LDFLAGS="-L$withval/lib $LDFLAGS"
+                       fi
+                       AC_CHECK_LIB(iconv, iconv_open)
+                       AC_CHECK_FUNCS(iconv_open, x_iconv_on=yes,
+                               AC_MSG_ERROR([Can't enable libiconv support!])
+                       )
+                 fi
+               ]
+       )
+       if test "$x_iconv_on" = "yes"; then
+               AC_DEFINE(ICONV, 1)
+       fi
 fi
 
 # enable support for IPv6?
@@ -683,6 +707,9 @@ test "$x_pam_on" = "yes" \
 echo $ECHO_N "        SSL support: $ECHO_C"
 echo "$x_ssl_lib"
 
+echo $ECHO_N "   libiconv support: $ECHO_C"
+       echo "$x_iconv_on"
+
 echo
 
 if ! grep "^AUTOMAKE_OPTIONS = ../portab/ansi2knr" src/ngircd/Makefile.am >/dev/null 2>&1; then
index d6cf418c15202f1227eb337fe6df94237ae49758..59a74ab5b4af7c18b505bf66d40576ce3d236866 100644 (file)
@@ -10,7 +10,7 @@ Build-Depends: debhelper (>> 4.0.0),
     libident-dev,
     libgnutls-dev,
     libpam0g-dev,
-    telnet,
+    telnet | telnet-ssl,
 Standards-Version: 3.9.1
 
 Package: ngircd
index 868a04250a09d70d37a952c24d5cff545b268a3a..0aecde56e00ee6640b5155eab2c2a3974a908fb2 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/make -f
 #
 # ngIRCd -- The Next Generation IRC Daemon
-# Copyright (c)2001-2009 Alexander Barton <alex@barton.de>
+# 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
@@ -53,7 +53,8 @@ configure-ngircd-full: configure
          --sysconfdir=/etc/ngircd \
          --mandir=\$${prefix}/share/man \
          --with-syslog --with-zlib \
-         --with-gnutls --with-ident --with-tcp-wrappers --with-pam \
+         --with-gnutls --with-iconv --with-ident --with-tcp-wrappers \
+         --with-pam \
          --enable-ipv6
 
 configure-ngircd-full-dbg: configure
@@ -66,7 +67,8 @@ configure-ngircd-full-dbg: configure
          --mandir=\$${prefix}/share/man \
          --enable-debug --enable-sniffer \
          --with-syslog --with-zlib \
-         --with-gnutls --with-ident --with-tcp-wrappers --with-pam \
+         --with-gnutls --with-iconv --with-ident --with-tcp-wrappers \
+         --with-pam \
          --enable-ipv6
 
 build:
index 5a71278486231654103dfd208f1184a3dab5c455..bf94d327fb337e024eeb8c44501c8821e827863d 100644 (file)
@@ -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. */
index ac3f6235381cea4879e4b0c09a1fee324ee93777..b904c763003be5868cc3ff934c4135374ddb54f6 100644 (file)
@@ -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 */; };
                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>"; };
                        files = (
                                FA322DC10CEF77CB001761B3 /* libz.dylib in Frameworks */,
                                FA2D567B11EA1AB300D37A35 /* libpam.dylib in Frameworks */,
+                               FA6BBC661605F6D60004247A /* libiconv.dylib in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                FA322D600CEF750F001761B3 /* configure.in */,
                                FA322D630CEF750F001761B3 /* Makefile.am */,
                                1AB674ADFE9D54B511CA2CBB /* Products */,
-                               FA322DC00CEF77CB001761B3 /* libz.dylib */,
+                               FA6BBC651605F6D60004247A /* libiconv.dylib */,
                                FA2D567A11EA1AB300D37A35 /* libpam.dylib */,
+                               FA322DC00CEF77CB001761B3 /* libz.dylib */,
                        );
                        name = ngIRCd;
                        sourceTree = "<group>";
                                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 */,
                                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 */,
                                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 */,
                                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;
                };
index fb7845112c960268c6a96b4aed2d9d61fae6f1b3..8d7cdd70714d62d85844c68c28539615da33baef 100644 (file)
@@ -60,6 +60,7 @@ users to lists (e.g. "invite list", "ban list"), others have parameters
   R    19      Only registered users are allowed to join this channel.
   s    0.9.0   Channel is "secret".
   t    0.3.0   Only ChanOps are allowed to modify the channel topic.
+  V    20      Channel doesn't allow invites.
   z    16      Only users connected via SSL are allowed to join the channel.
 
 III. Channel User Modes
index 5093eea9f3ace44b40b5c6388f0395dcc66f4693..3d2cda6cb23f8bdd33dee20bc643dbfd59dec19c 100644 (file)
@@ -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 NICK commands!
 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
index dec6db7c0c9ba81a28b3f91590cb11040cd288d3..27b5c40837a6244dac0c2ff8d375997afc91edbb 100644 (file)
@@ -29,6 +29,7 @@ ngircd_SOURCES = \
        client-cap.c \
        conf.c \
        conn.c \
+       conn-encoding.c \
        conn-func.c \
        conn-ssl.c \
        conn-zip.c \
@@ -37,6 +38,7 @@ ngircd_SOURCES = \
        irc.c \
        irc-cap.c \
        irc-channel.c \
+       irc-encoding.c \
        irc-info.c \
        irc-login.c \
        irc-mode.c \
@@ -70,6 +72,7 @@ noinst_HEADERS = \
        conf.h \
        conf-ssl.h \
        conn.h \
+       conn-encoding.h \
        conn-func.h \
        conn-ssl.h \
        conn-zip.h \
@@ -79,6 +82,7 @@ noinst_HEADERS = \
        irc.h \
        irc-cap.h \
        irc-channel.h \
+       irc-encoding.h \
        irc-info.h \
        irc-login.h \
        irc-mode.h \
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- */
diff --git a/src/ngircd/conn-encoding.h b/src/ngircd/conn-encoding.h
new file mode 100644 (file)
index 0000000..7b50ed6
--- /dev/null
@@ -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
index f4511642c7c7b309c0e302de58cd7e184c172166..5d086857dcd2f634ab4ec5b506d57ddf3f9d3ce2 100644 (file)
@@ -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 */
 
 
index e42a2ae6a7ac1c1466ade3a8124650a489e61715..9236c58ba7767a7be858a6a331abeedc78e02221 100644 (file)
@@ -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;
index c0be813a60f74ffec8821fcdff2535394d2a9414..37ca67640331d1aaef54181a7038e8f7b4cfa2ca 100644 (file)
 #define USERMODES "aBcCioqrRswx"
 
 /** Supported channel modes. */
-#define CHANMODES "abehiIklmMnoOPqQrRstvz"
+#define CHANMODES "abehiIklmMnoOPqQrRstvVz"
 
 /** Away message for users connected to linked servers. */
 #define DEFAULT_AWAY_MSG "Away"
diff --git a/src/ngircd/irc-encoding.c b/src/ngircd/irc-encoding.c
new file mode 100644 (file)
index 0000000..b1d3a69
--- /dev/null
@@ -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- */
diff --git a/src/ngircd/irc-encoding.h b/src/ngircd/irc-encoding.h
new file mode 100644 (file)
index 0000000..4349c91
--- /dev/null
@@ -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- */
index 4909a96a063a3a9940be0e52d9b9e070925a28c9..89defc3829ffaf4bba4e05cbcb25377e87ec7a22 100644 (file)
@@ -1156,6 +1156,12 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
                                Client_ID(from), Client_ID(c)))
                return DISCONNECTED;
 
+       if (Client_Conn(c) > NONE &&
+           (from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o'))) &&
+           !IRC_WriteStrClient(from, RPL_WHOISMODES_MSG, Client_ID(from),
+                               Client_ID(c), Client_Modes(c)))
+               return DISCONNECTED;
+
        if (Client_Conn(c) > NONE && (Client_OperByMe(from) || from == c) &&
            !IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, Client_ID(from),
                                Client_ID(c), Client_Hostname(c),
index 7f04e9c5b867b51d92df2c6fd2d4b4ef4a51582e..c7d02c9101e224fe14d787ff2938e4cf165c0853 100644 (file)
@@ -575,6 +575,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                                goto chan_exit;
                        }
                case 'i': /* Invite only */
+               case 'V': /* Invite disallow */
                case 'M': /* Only identified nicks can write */
                case 'm': /* Moderated */
                case 'n': /* Only members can write */
@@ -707,9 +708,9 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
                /* --- Channel user modes --- */
                case 'q': /* Owner */
                case 'a': /* Channel admin */
-                       if(!is_oper && !is_machine && !is_owner) {
+                       if(!is_oper && !is_machine && !is_owner && !is_admin) {
                                connected = IRC_WriteStrClient(Origin,
-                                       ERR_CHANOPRIVSNEEDED_MSG,
+                                       ERR_CHANOPPRIVTOOLOW_MSG,
                                        Client_ID(Origin),
                                        Channel_Name(Channel));
                                goto chan_exit;
index 08495475f60520c7dd899d7cef9e10b4f4852550..5c12faf78022ac8929d239029a4e7d2e8ff2fe47 100644 (file)
@@ -164,6 +164,11 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req)
                if (!Channel_IsMemberOf(chan, from))
                        return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, Client_ID(Client), Req->argv[1]);
 
+               /* Is the channel "invite-disallow"? */
+               if (strchr(Channel_Modes(chan), 'V'))
+                       return IRC_WriteStrClient(from, ERR_NOINVITE_MSG,
+                               Client_ID(from), Channel_Name(chan));
+
                /* Is the channel "invite-only"? */
                if (strchr(Channel_Modes(chan), 'i')) {
                        /* Yes. The user must be channel owner/admin/operator/halfop! */
index efc34d4b2e087f8e3742c1d44ea6a820e2073f92..ceb649ecf350159d1db1bc969d0a5bb496372a2a 100644 (file)
@@ -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 ForceType, bool SendErrors)
        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 ForceType, bool SendErrors)
                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 ForceType, bool SendErrors)
                        }
                        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 ForceType, bool SendErrors)
                           && strchr(currentTarget, '.')) {
                        /* targetmask */
                        if (!Send_Message_Mask(from, Req->command, currentTarget,
-                                              Req->argv[1], SendErrors))
+                                              message, SendErrors))
                                return DISCONNECTED;
                } else {
                        if (!SendErrors)
index ea24b2eb92708fabbcb4898cf03f3216ae5cf7f0..b94a999a1575102685fbd55373fe76e78434d17d 100644 (file)
@@ -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=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstz CHANLIMIT=#&+:%d :are supported on this server"
+#define RPL_ISUPPORT1_MSG              "005 %s RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstVz 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"
@@ -93,6 +92,7 @@
 #define RPL_MOTDSTART_MSG              "375 %s :- %s message of the day"
 #define RPL_ENDOFMOTD_MSG              "376 %s :End of MOTD command"
 #define RPL_WHOISHOST_MSG              "378 %s %s :is connecting from *@%s %s"
+#define RPL_WHOISMODES_MSG             "379 %s %s :is using modes +%s"
 #define RPL_YOUREOPER_MSG              "381 %s :You are now an IRC Operator"
 #define RPL_REHASHING_MSG              "382 %s :Rehashing"
 #define RPL_YOURESERVICE_MSG           "383 %s :You are service %s"
 #define ERR_UMODEUNKNOWNFLAG_MSG       "501 %s :Unknown mode"
 #define ERR_UMODEUNKNOWNFLAG2_MSG      "501 %s :Unknown mode \"%c%c\""
 #define ERR_USERSDONTMATCH_MSG         "502 %s :Can't set/get mode for other users"
+#define ERR_NOINVITE_MSG               "518 %s :Cannot invite to %s (+V)"
 
 #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- */
index a4c2fe8aabc07c72ff5fa00b21330ea087612856..50d91ce8e2dbff20c87e9dc54505e0bac3406019 100644 (file)
@@ -351,6 +351,13 @@ Fill_Version(void)
 {
        NGIRCd_VersionAddition[0] = '\0';
 
+#ifdef ICONV
+       if (NGIRCd_VersionAddition[0])
+               strlcat(NGIRCd_VersionAddition, "+",
+                       sizeof NGIRCd_VersionAddition);
+       strlcat(NGIRCd_VersionAddition, "CHARCONV",
+               sizeof NGIRCd_VersionAddition);
+#endif
 #ifdef DEBUG
        if (NGIRCd_VersionAddition[0])
                strlcat(NGIRCd_VersionAddition, "+",
index e9c5d53a3f584bc2fda3a13cc5625e63ca37e3c7..f3b04d0c2ee8617ceb21d32ce919859e640b55f4 100644 (file)
@@ -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