diff --git a/Changes b/Changes index 7556b6d0e..d8b13d5d7 100644 --- a/Changes +++ b/Changes @@ -607,3 +607,16 @@ - Fixed a small doc bug regarding shun in spamfilter, reported by KnuX (#0002338). - Added greek docs, translator: GSF. - Some help.conf/005.txt updates, reported by Ron2K (#0002354). +- No longer cutoff nick upon illegal character -- just reject the whole nick. The nick is + still cutoff if the nick is too long. Basically this is the same way as Hybrid does it + so it should work ok :). +- Added nick character system. This allows you to choose which (additional) characters + to allow in nicks via set::allowed-nickchars. See unreal32docs.html -> section 3.16 + for a list of available languages and more info on how to use it. + Current list: dutch, french, german, italian, spanish, euro-west, chinese-trad, + chinese-simp, chinese-ja, chinese. + If you wonder why your language is not yet included or why a certain mistake is present, + then please understand that we are most likely not experienced (at all) in your language. + If you are a native of your language (or know the language well), and your language + is not included yet or you have some corrections, then contact syzop@vulnscan.org or + report it as a bug on http://bugs.unrealircd.org/ diff --git a/doc/unreal32docs.html b/doc/unreal32docs.html index 036a4eb25..afd817598 100644 --- a/doc/unreal32docs.html +++ b/doc/unreal32docs.html @@ -69,7 +69,8 @@ English | German | -- 3.13. Ban types
-- 3.14. Spamfilter
-- 3.15. CIDR
- -- 3.16. Other features
+ -- 3.16. Nick Character Sets
+ -- 3.17. Other features
4. Configuring your unrealircd.conf file
---4.1. Configuration file explained
@@ -558,7 +559,34 @@ and except tkl::mask (for gzline, gline, and shun). Additionally, CIDR can be us 127.0.0.0/8 (matches 127.0.0.0 - 127.255.255.255), and fe80:0:0:123::/64 (matches fe80:0:0:123:0:0:0:0 - fe80:0:0:123:ffff:ffff:ffff:ffff).

-

3.16 - Other features

+

3.16 - Nick Character Sets

+

UnrealIRCd has now the ability to specify which charsets/languages should be allowed +in nicknames. You do this in set::allowed-nickchars.
+A table of all possible choices:
+ + + + + + + + + + + + +
Name:Description:Character set/encoding:
dutchDutch characterslatin1
frenchFrench characters: accents, ..latin1
germanGerman characters: umlauts, eszet, ..latin1
italianItalian characters: accents, ..latin1
spanishSpanish characterslatin1
euro-westdutch, french, german, spanish, italianlatin1
chinese-simpSimplified ChineseMultibyte: GBK/GB2312
chinese-tradTradditional ChineseMultibyte: GBK
chinese-jaJapanese-alike ChineseMultibyte: GBK
chinesechinese-*Multibyte: GBK
+Please note that some combinations are not allowed (especially multi-region), +such as (one of) euro-west and chinese-*, because they can cause display conflicts. +UnrealIRCd will print out an error if you try to do so.

+ +Example 1, for people of western europe:
+

set { allowed-nickchars { euro-west; }; };
+Example 2, if you have mainly chinese users:
+
set { allowed-nickchars { chinese-simp; chinese-trad; }; };
+

+ +

3.17 - Other features

UnrealIRCd has a lot of features so not everything is covered here... You'll find that out by yourself.

@@ -2152,6 +2180,8 @@ set { Specifies the prefix characters for services "in channel commands". Messages starting with any of the specified characters will still be sent even if the client is +d. The default value is "`".

+

set::allowed-nickchars { <list> };
+ Character sets / languages to allow in nicks, see Nick Character Sets.

set::allow-userhost-change [never|always|not-on-channels|force-rejoin]
Specifies what happens when the user@host changes (+x/-x/chghost/chgident/setident/vhost/etc).
never disables all the commands, always does always allow it even when in channels diff --git a/include/common.h b/include/common.h index c369f8adb..d031a18fc 100644 --- a/include/common.h +++ b/include/common.h @@ -184,6 +184,7 @@ extern MODVAR unsigned char char_atribs[]; #define DIGIT 16 #define SPACE 32 #define ALLOW 64 +#define ALLOWN 128 #ifndef KLINE_TEMP #define KLINE_PERM 0 diff --git a/include/h.h b/include/h.h index ab0a12bdf..69a9a985d 100644 --- a/include/h.h +++ b/include/h.h @@ -746,3 +746,7 @@ void cmodej_delentry(aJFlood *e); void cmodej_deluserentries(aClient *cptr); void cmodej_delchannelentries(aChannel *chptr); #endif +extern void charsys_reset(void); +extern void charsys_addmultibyterange(char s1, char e1, char s2, char e2); +extern void charsys_addallowed(char *s); +extern void charsys_reset(void); diff --git a/include/struct.h b/include/struct.h index 4ce7b2cd4..6ca5eb95d 100644 --- a/include/struct.h +++ b/include/struct.h @@ -1636,7 +1636,8 @@ struct liststruct { #define BadPtr(x) (!(x) || (*(x) == '\0')) -#define isvalid(c) (((c) >= 'A' && (c) <= '~') || isdigit(c) || (c) == '-') +/** Is valid character in nick? [not for external usage, use do_check_nickname instead!] */ +#define isvalid(c) (char_atribs[(u_char)(c)]&ALLOWN) /* remote fds are set to -256, else its a local fd (a local fd * can get -1 or -2 in case it has been closed). -- Syzop diff --git a/makefile.win32 b/makefile.win32 index b47da6517..eaa3ad333 100644 --- a/makefile.win32 +++ b/makefile.win32 @@ -133,7 +133,7 @@ EXP_OBJ_FILES=SRC/CHANNEL.OBJ SRC/SEND.OBJ SRC/SOCKET.OBJ \ SRC/HELP.OBJ SRC/S_MISC.OBJ SRC/MATCH.OBJ SRC/CRULE.OBJ \ SRC/S_DEBUG.OBJ SRC/SUPPORT.OBJ SRC/LIST.OBJ \ SRC/S_ERR.OBJ SRC/PACKET.OBJ SRC/S_BSD.OBJ \ - SRC/S_SERV.OBJ SRC/S_USER.OBJ \ + SRC/S_SERV.OBJ SRC/S_USER.OBJ SRC/CHARSYS.OBJ \ SRC/VERSION.OBJ SRC/RES_INIT.OBJ SRC/RES_COMP.OBJ SRC/RES_MKQUERY.OBJ SRC/RES_SKIPNAME.OBJ \ SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ SRC/IRCSPRINTF.OBJ SRC/LUSERS.OBJ \ SRC/SCACHE.OBJ SRC/ALN.OBJ SRC/BADWORDS.OBJ SRC/WEBTV.OBJ SRC/RES.OBJ SRC/MODULES.OBJ \ @@ -352,6 +352,10 @@ src/s_user.obj: src/s_user.c $(INCLUDES) ./include/dbuf.h \ ./include/channel.h ./include/whowas.h $(CC) $(CFLAGS) src/s_user.c +src/charsys.obj: src/charsys.c $(INCLUDES) ./include/dbuf.h \ + ./include/channel.h ./include/whowas.h + $(CC) $(CFLAGS) src/charsys.c + src/s_extra.obj: src/s_extra.c $(INCLUDES) ./include/dbuf.h \ ./include/channel.h ./include/whowas.h $(CC) $(CFLAGS) src/s_extra.c diff --git a/src/Makefile b/src/Makefile index 10507687f..c5c206e06 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,7 +27,7 @@ OBJS=auth.o aln.o badwords.o channel.o cloak.o crule.o dbuf.o \ res_init.o res_comp.o res_mkquery.o res_skipname.o s_auth.o \ s_bsd.o s_conf.o s_debug.o s_err.o s_extra.o s_kline.o \ s_misc.o s_numeric.o s_serv.o s_svs.o $(STRTOUL) socket.o \ - ssl.o s_user.o scache.o send.o support.o umodes.o \ + ssl.o s_user.o charsys.o scache.o send.o support.o umodes.o \ version.o webtv.o whowas.o zip.o cidr.o random.o extcmodes.o \ extbans.o md5.o api-isupport.o api-command.o $(URL) @@ -211,6 +211,10 @@ s_user.o: s_user.c $(INCLUDES) \ ../include/dbuf.h ../include/channel.h ../include/whowas.h $(CC) $(CFLAGS) -c s_user.c +charsys.o: charsys.c $(INCLUDES) \ + ../include/dbuf.h ../include/channel.h ../include/whowas.h + $(CC) $(CFLAGS) -c charsys.c + s_extra.o: s_extra.c $(INCLUDES) \ s_numeric.c ../include/dbuf.h ../include/channel.h ../include/whowas.h $(CC) $(CFLAGS) -c s_extra.c diff --git a/src/charsys.c b/src/charsys.c new file mode 100644 index 000000000..c84a1607a --- /dev/null +++ b/src/charsys.c @@ -0,0 +1,306 @@ +/* + * Unreal Internet Relay Chat Daemon, src/charsys.c + * (C) Copyright 2005 Bram Matthys and The UnrealIRCd Team. + * + * Character system: This subsystem deals with finding out wheter a + * character should be allowed or not in nicks (nicks only for now). + * + * 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 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "config.h" +#include "struct.h" +#include "common.h" +#include "sys.h" +#include "macros.h" +#include "numeric.h" +#include "msg.h" +#include "channel.h" +#include +#include +#include +#include +#include +#ifdef _WIN32 +#include +#endif +#include +#include "h.h" +#include "proto.h" +#ifdef STRIPBADWORDS +#include "badwords.h" +#endif + +#ifdef _WIN32 +#include "version.h" +#endif + +/* NOTE: it is guaranteed that char is unsigned by compiling options + * (-funsigned-char @ gcc, /J @ MSVC) + * NOTE2: Original credit for supplying the correct chinese + * coderanges goes to: RexHsu, Mr.WebBar and Xuefer + */ + +/** Our multibyte structure */ +typedef struct _mblist MBList; +struct _mblist +{ + MBList *next; + char s1, e1, s2, e2; +}; +MBList *mblist = NULL, *mblist_tail = NULL; + +static int do_nick_name_multibyte(char *nick); +static int do_nick_name_standard(char *nick); + +/* Use this to prevent mixing of certain combinations + * (such as GBK & high-ascii, etc) + */ +static int langav; +/* bitmasks: */ +#define LANGAV_ASCII 1 /* 8 bit ascii */ +#define LANGAV_GBK 2 /* (Chinese) GBK encoding */ + +/** Called on boot and just before config run */ +void charsys_reset(void) +{ +int i; +MBList *m, *m_next; + + /* First, reset everything */ + for (i=0; i < 256; i++) + char_atribs[i] &= ~ALLOWN; + for (m=mblist; m; m=m_next) + { + m_next = m->next; + MyFree(m); + } + mblist=mblist_tail=NULL; + /* Then add the default which will always be allowed */ + charsys_addallowed("0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyzy{|}"); + langav = 0; +} + +void charsys_reset_pretest(void) +{ + langav = 0; +} + +/** Add a character range to the multibyte list. + * @param s1 Start of highest byte + * @param e1 End of highest byte + * @param s2 Start of lowest byte + * @param e2 End of lowest byte + * @example charsys_addmultibyterange(0xaa, 0xbb, 0x00, 0xff) for 0xaa00-0xbbff + */ +void charsys_addmultibyterange(char s1, char e1, char s2, char e2) +{ +MBList *m = MyMallocEx(sizeof(m)); + + m->s1 = s1; + m->e1 = e1; + m->s2 = s2; + m->e2 = e2; + + if (mblist_tail) + mblist_tail->next = m; + else + mblist = m; + mblist_tail = m; +} + +/** Adds all characters in the specified string to the allowed list. */ +void charsys_addallowed(char *s) +{ + for (; *s; s++) + char_atribs[(unsigned int)*s] |= ALLOWN; +} + +int do_nick_name(char *nick) +{ + if (mblist) + return do_nick_name_multibyte(nick); + else + return do_nick_name_standard(nick); +} + +static int do_nick_name_standard(char *nick) +{ +int len; +char *ch; + + if ((*nick == '-') || isdigit(*nick)) + return 0; + + for (ch=nick,len=0; *ch && len <= NICKLEN; ch++, len++) + if (!isvalid(*ch)) + return 0; /* reject the full nick */ + *ch = '\0'; + return len; +} + +static int isvalidmbyte(unsigned char c1, unsigned char c2) +{ +MBList *m; + + for (m=mblist; m; m=m->next) + { + if ((c1 >= m->s1) && (c1 <= m->e1) && + (c2 >= m->s2) && (c2 <= m->e2)) + return 1; + } + return 0; +} + +/* hmmm.. there must be some problems with multibyte & + * other high ascii characters I think (such as german etc). + * Not sure if this can be solved? I don't think so... -- Syzop. + */ +static int do_nick_name_multibyte(char *nick) +{ +int len; +char *ch; +MBList *m; +int firstmbchar = 0; + + if ((*nick == '-') || isdigit(*nick)) + return 0; + + for (ch=nick,len=0; *ch && len <= NICKLEN; ch++, len++) + { + if (firstmbchar) + { + if (!isvalidmbyte(ch[-1], *ch)) + return 0; + firstmbchar = 0; + } else if ((*ch) & 0x80) + firstmbchar = 1; + else if (!isvalid(*ch)) + return 0; + } + if (firstmbchar) + ch--; + *ch = '\0'; + return len; +} + +/** Check if the specified charsets during the TESTING phase can be + * premitted without getting into problems. + * RETURNS: -1 in case of failure, 1 if ok + */ +int charsys_postconftest(void) +{ + if ((langav & LANGAV_ASCII) && (langav & LANGAV_GBK)) + { + config_error("ERROR: set::accept-language specifies incorrect combination " + "of languages: high-ascii languages (such as german, french, etc) " + "cannot be mixed with chinese/.."); + return -1; + } + return 1; +} + +/** Check if language is available. */ +int charsys_test_language(char *name) +{ + if (!strcmp(name, "euro-west") || + !strcmp(name, "german") || !strcmp(name, "dutch") || + !strcmp(name, "french") || !strcmp(name, "spanish")) + { + langav |= LANGAV_ASCII; + return 1; + } + if (!strcmp(name, "chinese") || !strcmp(name, "chinese-trad") || + !strcmp(name, "chinese-simp") || !strcmp(name, "chinese-ja")) + { + langav |= LANGAV_GBK; + return 1; + } + return 0; +} + +void charsys_add_language(char *name) +{ +char euro_west=0, chinese=0; + + /** Note: there could well be some characters missing in the lists below. + * While I've seen other altnernatives that just allow pretty much + * every accent that exists even for dutch (where we rarely use + * accents except for like 3 types), I rather prefer to use a bit more + * reasonable aproach ;). That said, anyone is welcome to make + * suggestions about characters that should be added (or removed) + * of course. -- Syzop + */ + + /* GROUPS */ + if (!strcmp(name, "euro-west")) + euro_west = 1; + if (!strcmp(name, "chinese")) + chinese = 1; + + /* INDIVIDUAL CHARSETS */ + + if (euro_west || !strcmp(name, "german")) + { + /* a", A", e', o", O", u", U" and es-zett */ + charsys_addallowed("äÄéöÖüÜß"); + } + if (euro_west || !strcmp(name, "dutch")) + { + /* Ok, even though I'm Dutch myself, I've trouble getting + * a proper list of this ;). I think I got them all now, but + * I did not include "borrow-words" like words we use in Dutch + * that are literal French. So if you really want to use them all, + * I suggest you to use just euro-west :P. + */ + /* e', e", o", i", u", e`. */ + charsys_addallowed("éëöïüè"); + } + if (euro_west || !strcmp(name, "french")) + { + /* A`, A^, a`, a^, weird-C, weird-c, E`, E', E^, E", e`, e', e^, e", + * I^, I", i^, i", O^, o^, U`, U^, U", u`, u", u`, y" [not in that order, sry] + * Hmm.. there might be more, but I'm not sure how common they are + * and I don't think they are always displayed correctly (?). + */ + charsys_addallowed("ÀÂàâÇçÈÉÊËèéêëÎÏîïÔôÙÛÜùûüÿ"); + } + if (euro_west || !strcmp(name, "spanish")) + { + /* a', A', e', E', i', I', o', O', u', U', u", U", n~, N~ */ + charsys_addallowed("áÁéÉíÍóÓúÚüÜñÑ"); + } + if (euro_west || !strcmp(name, "italian")) + { + /* A`, E`, E', I`, I', O`, O', U`, U', a`, e`, e', i`, i', o`, o', u`, u' */ + charsys_addallowed("ÀÈÉÌÍÒÓÙÚàèéìíòóùú"); + } + if (chinese || !strcmp(name, "chinese-ja")) + { + charsys_addmultibyterange(0xa4, 0xa4, 0xa1, 0xf3); /* JIS_PIN */ + charsys_addmultibyterange(0xa5, 0xa5, 0xa1, 0xf6); /* JIS_PIN */ + } + if (chinese || !strcmp(name, "chinese-simp")) + { + charsys_addmultibyterange(0xb0, 0xd6, 0xa1, 0xfe); /* GBK/2 BC with GB2312 */ + charsys_addmultibyterange(0xd7, 0xd7, 0xa1, 0xf9); /* GBK/2 BC with GB2312 */ + charsys_addmultibyterange(0xd8, 0xf7, 0xa1, 0xfe); /* GBK/2 BC with GB2312 */ + } + if (chinese || !strcmp(name, "chinese-trad")) + { + charsys_addmultibyterange(0x81, 0xa0, 0x40, 0xfe); /* GBK/3 */ + charsys_addmultibyterange(0xaa, 0xfe, 0x40, 0xa0); /* GBK/4 */ + } +} diff --git a/src/ircd.c b/src/ircd.c index 1ca752234..5da7aa7d2 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -1006,6 +1006,7 @@ int InitwIRCD(int argc, char *argv[]) bzero((char *)&me, sizeof(me)); bzero(&StatsZ, sizeof(StatsZ)); setup_signals(); + charsys_reset(); init_ircstats(); #ifdef USE_LIBCURL url_init(); diff --git a/src/match.c b/src/match.c index de1dea944..654f92cc6 100644 --- a/src/match.c +++ b/src/match.c @@ -378,8 +378,8 @@ u_char char_atribs[] = { PRINT | ALPHA | ALLOW, /* VWX */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, -/* YZ[ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA, -/* \]^ */ PRINT | ALPHA, PRINT | ALPHA, PRINT | ALPHA, +/* YZ[ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT, +/* \]^ */ PRINT, PRINT, PRINT, /* _` */ PRINT | ALLOW, PRINT, /* abc */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, @@ -397,8 +397,8 @@ u_char char_atribs[] = { PRINT | ALPHA | ALLOW, /* vwx */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, -/* yz{ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA, -/* |}~ */ PRINT | ALPHA, PRINT | ALPHA, PRINT | ALPHA, +/* yz{ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT, +/* |}~ */ PRINT, PRINT, PRINT, /* del */ 0, /* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/s_conf.c b/src/s_conf.c index a08ee5cb7..fed1074ea 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -331,6 +331,11 @@ extern void add_entropy_configfile(struct stat st, char *buf); extern void unload_all_unused_snomasks(); extern void unload_all_unused_umodes(); +extern int charsys_test_language(char *name); +extern void charsys_add_language(char *name); +extern void charsys_reset_pretest(void); +int charsys_postconftest(void); + /* Stuff we only need here for spamfilter, so not in h.h... */ extern aTKline *tklines[TKLISTLEN]; extern inline int tkl_hash(char c); @@ -1595,7 +1600,9 @@ int init_conf(char *rootconf, int rehash) config_setdefaultsettings(&tempiConf); if (load_conf(rootconf) > 0) { - if ((config_test() < 0) || (callbacks_check() < 0) || (efunctions_check() < 0)) + charsys_reset_pretest(); + if ((config_test() < 0) || (callbacks_check() < 0) || (efunctions_check() < 0) || + (charsys_postconftest() < 0)) { config_error("IRCd configuration failed to pass testing"); #ifdef _WIN32 @@ -1647,6 +1654,7 @@ int init_conf(char *rootconf, int rehash) l_commands_Init(&ModCoreInfo); } #endif + charsys_reset(); if (config_run() < 0) { config_error("Bad case of config errors. Server will now die. This really shouldn't happen"); @@ -6400,6 +6408,10 @@ int _conf_set(ConfigFile *conf, ConfigEntry *ce) else tempiConf.userhost_allowed = UHALLOW_REJOIN; } + else if (!strcmp(cep->ce_varname, "allowed-nickchars")) { + for (cepp = cep->ce_entries; cepp; cepp=cepp->ce_next) + charsys_add_language(cepp->ce_varname); + } else if (!strcmp(cep->ce_varname, "channel-command-prefix")) { ircstrdup(tempiConf.channel_command_prefix, cep->ce_vardata); } @@ -6914,6 +6926,25 @@ int _test_set(ConfigFile *conf, ConfigEntry *ce) continue; } } + else if (!strcmp(cep->ce_varname, "allowed-nickchars")) { + if (cep->ce_vardata) + { + config_error("%s:%i: set::allow-nickchars: please use 'allowed-nickchars { name; };' " + "and not 'allowed-nickchars name;'", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum); + errors++; + continue; + } + for (cepp = cep->ce_entries; cepp; cepp=cepp->ce_next) + { + if (!charsys_test_language(cepp->ce_varname)) + { + config_error("%s:%i: set::allow-nickchars: Unknown (sub)language '%s'", + cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cepp->ce_varname); + errors++; + } + } + } else if (!strcmp(cep->ce_varname, "anti-spam-quit-message-time")) { CheckNull(cep); CheckDuplicate(cep, anti_spam_quit_message_time, "anti-spam-quit-message-time"); diff --git a/src/s_user.c b/src/s_user.c index 1a06e5bf3..26b214b12 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -657,157 +657,6 @@ int check_for_target_limit(aClient *sptr, void *target, const char *name) return 0; } - - - -/* -** 'do_nick_name' ensures that the given parameter (nick) is -** really a proper string for a nickname (note, the 'nick' -** may be modified in the process...) -** -** RETURNS the length of the final NICKNAME (0, if -** nickname is illegal) -** -** Nickname characters are in range -** 'A'..'}', '_', '-', '0'..'9' -** anything outside the above set will terminate nickname. -** In addition, the first character cannot be '-' -** or a Digit. -** -** Note: -** '~'-character should be allowed, but -** a change should be global, some confusion would -** result if only few servers allowed it... -*/ - -#if defined(NICK_GB2312) || defined(NICK_GBK) || defined(NICK_GBK_JAP) -#define NICK_MULTIBYTE -#endif - -#ifdef NICK_MULTIBYTE -/* Chinese Nick Verification Code - Added by RexHsu on 08/09/00 (beta2) - * Now Support All GBK Words,Thanks to Mr.WebBar ! - * Special Char Bugs Fixed by RexHsu 09/01/00 I dont know whether it is - * okay now?May I am right ;p - * Thanks dilly for providing me Japanese code range! - * Now I am meeting a nickname conflicting problem.... - * - * GBK Libary Reference: - * 1. GBK2312·Çºº×Ö·ûºÅÇø(A1A1----A9FE) - * 2. GBK2312ºº×ÖÇø(B0A1----F7FE) - * 3. GBKÀ©³äºº×ÖÇø(8140----A0FE) - * 4. GBKÀ©³äºº×ÖÇø(AA40----FEA0) - * 5. GBKÀ©³ä·Çºº×ÖÇø(A840----A9A0) - * 6. ÈÕÎÄÆ½¼ÙÃû±àÂëÇø(a4a1-a4f3) -->work correctly?maybe... - * 7. ÈÕÎÄÆ¬¼ÙÃû±àÂëÇø(a5a1-a5f7) -->work correctly?maybe... - * 8. º«ÎıàÂëÇø(xxxx-yyyy) - * - * isvalidChinese() rewritten by Xuefer (2004-10-10), - * this will probably be the last time we do it this way, - * in 3.2.3 we are gonna try a more generic aproach. -- Syzop - */ - -int isvalidChinese(const unsigned char c1, const unsigned char c2) -{ - unsigned int w = (((unsigned int)c1) << 8) | c2; - -/* rang of w/c1/c2 (rw never used) */ -#define rw(s, e) (w >= ((unsigned int )s) && w <= ((unsigned int )e)) -#define r1(s, e) (c1 >= ((unsigned char)s) && c1 <= ((unsigned char)e)) -#define r2(s, e) (c2 >= ((unsigned char)s) && c2 <= ((unsigned char)e)) -#define e1(e) (c1 == (unsigned char)e) - -#ifdef NICK_GBK_JAP - /* GBK/1 */ - /* JIS_PIN part 1 */ - if (e1(0xA4) && r2(0xA1, 0xF3)) return 1; - /* JIS_PIN part 2 */ - if (e1(0xA5) && r2(0xA1, 0xF6)) return 1; -#endif -#if defined(NICK_GB2312) || defined(NICK_GBK) - /* GBK/2 BC with GB2312 */ - if (r2(0xA1, 0xFE)) - { - /* Block 16-55, ordered by Chinese Spelling(PinYin) 3755 chars */ - if (r1(0xB0, 0xD6)) return 1; - /* Block 55 is NOT full (w <= 0xd7f9) */ - if (e1(0xD7) && c2 <= (unsigned char)0xF9 /* r2(0xA1, 0xF9)*/) return 1; - /* Block 56-87 is level 2 chars, ordered by writing 3008 chars */ - if (r1(0xD8, 0xF7)) return 1; - } -#endif - -#ifdef NICK_GBK - /* GBK/3 */ - if (r1(0x81, 0xA0) && r2(0x40, 0xFE)) return 1; - /* GBK/4 */ - if (r2(0x40, 0xA0) && r1(0xAA, 0xFE)) return 1; -#endif - - /* all failed */ - return 0; - -#undef rw -#undef r1 -#undef r2 -#undef e1 -} - -/* Chinese Nick Supporting Code (Switch Mode) - Modified by RexHsu on 08/09/00 */ -int do_nick_name(char *pnick) -{ - unsigned char *ch; - unsigned char *nick = pnick; - int firstChineseChar = 0; - char lastChar; - - if (*nick == '-' || isdigit(*nick)) /* first character in [0..9-] */ - return 0; - - for (ch = nick; *ch && (ch - nick) < NICKLEN; ch++) - { - if ((!isvalid(*ch) && !((*ch) & 0x80)) || isspace(*ch) - || (*ch) == '@' || (*ch) == '!' || (*ch) == ':' - || (*ch) == ' ') - break; - if (firstChineseChar) - { - if (!isvalidChinese(lastChar, *ch)) - break; - firstChineseChar = 0; - } - else if ((*ch) & 0x80) - firstChineseChar = 1; - lastChar = *ch; - } - - if (firstChineseChar) - ch--; - - *ch = '\0'; - - return (ch - nick); -} - - -#else -int do_nick_name(char *nick) -{ - char *ch; - - if (*nick == '-' || isdigit(*nick)) /* first character in [0..9-] */ - return 0; - - for (ch = nick; *ch && (ch - nick) < NICKLEN; ch++) - if (!isvalid(*ch) || isspace(*ch)) - break; - - *ch = '\0'; - - return (ch - nick); -} -#endif - /* ** canonize **