rpms/eggdrop/EL-5 eggdrop-1.6.18-suzi_sp0007.patch, NONE, 1.1 eggdrop.spec, 1.10, 1.11

Robert Scheck (robert) fedora-extras-commits at redhat.com
Sun Feb 10 22:05:30 UTC 2008


Author: robert

Update of /cvs/extras/rpms/eggdrop/EL-5
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv23623/EL-5

Modified Files:
	eggdrop.spec 
Added Files:
	eggdrop-1.6.18-suzi_sp0007.patch 
Log Message:
Added patch to provide better non-latin support (#429621)

eggdrop-1.6.18-suzi_sp0007.patch:

--- NEW FILE eggdrop-1.6.18-suzi_sp0007.patch ---
--- eggdrop1.6.18/UTF-8						1970-01-01 01:00:00.000000000 +0100
+++ eggdrop1.6.18/UTF-8.suzi_sp0007				2008-02-10 20:57:30.000000000 +0100
@@ -0,0 +1,237 @@
+        Eggdrop and non-latin characters.
+
+Introduction.
+
+  It is known that popular irc-bot eggdrop (http://eggheads.org) has some troubles with non-latin characters. You can see a lot of messages on www.egghelp.org forum (http://forum.egghelp.org) under titles like "Some characters aren't correctly handled by the eggdrop".
+  Also I asked eggdrop's users, whose alphabet in general has Latin characters and in addition has Latin characters with diacritic signs (cedilla, diaeresis, caron, acute, etc.), about problem with these characters (for example: there are 'ÁČĎÉĚÍŇÓŘŠŤÚŮÝŽáčďéěíňóřšťúůýž' characters in Czech alphabet). Many of them said that they don't have any problems, because they can easily replace these characters with Latin characters without diacritic signs. One french-speaking friend said that the word 'garçon' (boy, fr.) can be written as 'garcon'. On the other hand, many people, whose native alphabet is Cyrillic or Greek answered positively. They have some problems with case sensitive binds that contains non-latin characters and sometimes bot even outputs 'trash' instead of expected characters.
+
+1. Suzi project patch.
+
+The patch intends to avoid problems listed below:
+  - problem with get/send/process strings which contain non-Latin characters in TCL interpreter when encoding system is not iso8859-1 (also there are problems even if encoding system is iso8859-1)
+  - problem with 'case sensitive' and 'not matching' binds, which contains non-Latin characters in match part
+  - problem with 'set nick "non-Latin-characters"'
+  - problem with stripping characters with code 255 in party line or DCC chat
+  - problem with DCC commands '.chhandle' and '.handle' and their TCL analogs
+  - problem with detecting locale encoding
+
+Although, this problems have the relationship between themselves and if you fix one also will be fixed the other, I've separated and sorted them by 'severity'.
+
+Of course, the patch is not revolutionary, ideas implemented by the patch were discussed many times in various forums. But I've not seen the realization yet. This patch replaces calls TCL API function which requires well formed utf-8 strings as input/output arguments to wrappers that convert strings which come in locale encoding to utf-8 and back.
+
+After applying patch you avoid ALL problems described below and your bots will work as expected at any test.
+
+2. Problem details
+
+So, if you haven't believed me yet, follow the detailed explanation of each problem.
+
+I have bot installed in '~/eggdrop' compiled from original sources (without any patch). Version of eggdrop is 1.8.16, TCL is 8.4.13.
+
+2.1. Problem with get/send/process strings which contain non-Latin characters.
+
+  This problem has long history, but it's not still solved. There is a particular solution for some languages, but I haven't seen really universal one. Problem has appeared when TCL's developers changed internal and external API of TCL library to Unicode (since version 8.1.0, but I'm not sure). Now functions of TCL library require well formed utf-8 strings as input argument and return also utf-8 encoded string (with some exception). Alas, eggdrop internals do not meet this requirement. It has been changed partially, but not at all.
+  Let users on some IRC server use cp1251 encoding for chat. We have configured the bot connected to an IRC server and a small script for testing purposes that was loaded via 'source scripts/test.cp1251.tcl' command in eggdrop’s configuration file:
+
+  'scripts/test.cp1251.tcl' (script contains characters in cp1251 encoding):
+  +-------
+  | bind pub -|- {!test} test_handler
+  | bind pub -|- {!тест} test_handler
+  | proc test_handler { unick uhost uhandle uchannel utext } {
+  |   set text [string toupper "$unick on $uchannel, you said (ты сказал): $utext ([encoding system])"]
+  |   putserv "PRIVMSG $channel :$text"
+  | }
+
+  Test it on channel #eggtes (bot run in locale en_US.iso8859-1)
+  +------
+  | < lynxy> !test abcd абвг
+  | <eggbot> LYNXY ON #EGGTEST, YOU SAID (ТЫ СКАЗАЛ): ABCD абвг (ISO8859-1)
+  | < lynxy> !tEsT abcd абвг
+  | <eggbot> LYNXY ON #EGGTEST, YOU SAID (ТЫ СКАЗАЛ): ABCD абвг (ISO8859-1)
+  | < lynxy> !тест abcd абвг
+  | < lynxy> !тЕсТ abcd абвг
+
+  There are two problems. The first problem is that 'bind' for '!тест' does not work and the second one is that 'string toupper' converts both Latin and Cyrillic characters which are in the body of the script, but Cyrillic characters in the input string are left unchanged.
+
+  Why does 'bind' not work?
+  Go to bot's party line and type '.binds'
+  +------
+  | .binds
+  | [13:26] tcl: builtin dcc call: *dcc:binds lynxy 7
+  | [13:26] #lynxy# binds
+  | Command bindings:
+  | TYPE FLGS     COMMAND              HITS BINDING (TCL)
+  |   evnt -|-      init-server             1 evnt:init_server
+  |   pub  -|-      !B5AB                   0 test_handler
+  |   pub  -|-      !test                   2 test_handler
+
+  Wow! The second bind is wrong! I wrote '!тест' for match, but I've got strange '!B5AB' sequence. Look at the table below: the first two columns are Cyrillic letter and corresponding Unicode code, the second two columns are Latin letter and its Unicode code:
+
+  +---+------+---+------+
+  | 1 | uni  | 2 | uni  |
+  +---+------+---+------+
+  | Ñ‚ | 0442 | B | 0042 |
+  | е | 0435 | 5 | 0035 |
+  | с | 0441 | A | 0041 |
+  | Ñ‚ | 0442 | B | 0042 |
+  +---+------+---+------+
+
+  Seems that 'bind' just takes only the lower byte of each Unicode character.
+
+  Why 'string toupper' does not work properly with non-Latin characters?
+  The string is received from IRC server in cp1251 encoding and when eggdrop's core sets values of TCL variables and calls the handler it does not convert this string from cp1251 to utf-8 (as required by TCL API) and TCL function 'string toupper' can't process these characters properly.
+  Ok, now I know why it happens. Let's change the script by applying 'encoding convertfrom' to string that is passed to TCL interpreter by eggdrop's C-code and 'encoding convertto' to string that is sent to C-code.
+  Also we must run bot in locale with proper encoding, because eggdrop uses functions from C library like 'strcasecmp()', 'tolower()', 'toupper()' with locale depended behaviour.
+
+  'scripts/test.cp1251.tcl':
+  +-------
+  | bind pub -|- {!test} test_handler
+  | bind pub -|- [encoding convertto {!тест}] test_handler
+  | proc test_handler { unick uhost uhandle uchannel utext } {
+  |   set nick      [encoding convertfrom $unick]
+  |   set channel   [encoding convertfrom $uchannel]
+  |   set text      [encoding convertfrom $utext]
+  |   set str [string toupper "$nick on $channel, you said (ты сказал): $text ([encoding system])"]
+  |   putserv [encoding convertto "PRIVMSG $channel :$text"]
+  | }
+
+  And run bot in locale with cp1251 encoding:
+  +-------
+  | user at sys:~/eggdrop> LANG=ru_RU.cp1251 ./eggdrop
+
+  Test:
+  +-------
+  | < lynxy> !test SoMe TeXt нЕкИй ТеКсТ
+  | <eggbot> LYNXY ON #EGGTEST, YOU SAID (ТЫ СКАЗАЛ): SOME TEXT НЕКИЙ ТЕКСТ (CP1251)
+  | < lynxy> !tEsT SoMe TeXt нЕкИй ТеКсТ
+  | <eggbot> LYNXY ON #EGGTEST, YOU SAID (ТЫ СКАЗАЛ): SOME TEXT НЕКИЙ ТЕКСТ (CP1251)
+  | < lynxy> !тест SoMe TeXt нЕкИй ТеКсТ
+  | <eggbot> LYNXY ON #EGGTEST, YOU SAID (ТЫ СКАЗАЛ): SOME TEXT НЕКИЙ ТЕКСТ (CP1251)
+  | <lynxy> !тЕсТ SoMe TeXt нЕкИй ТеКсТ
+  | <eggbot> LYNXY ON #EGGTEST, YOU SAID (ТЫ СКАЗАЛ): SOME TEXT НЕКИЙ ТЕКСТ (CP1251)
+
+  Wow! It works! But the body of handler proc generally contains 'encoding ...' lines, of course I could write an alias for 'bind', 'putserv' and other functions like this:
+  +-------
+  | proc i18bind {type flags name handler} {
+  |   bind $type $flag [encoding convertto $name] $handler
+  | }
+
+  It solves many encoding problems, but not them all.
+  
+  I think that passing locale encoded string as byte array to TCL interpreter and getting back was intended by eggdrop's developers, but this idea seems a bit useless. I haven't seen any scripts yet that required byte array rather than a string. Why I must use 'encoding ...' in scripts when it is task of eggdrop's C-code? You can use Suzi project patch and forget about 'encoding ...' hell or do not use patch and use 'encoding ...' everywhere. It is your choice.
+
+  Problem with 'set nick "non-Latin-chars"' has similar solution.
+
+2.2. Problem with stripping characters with code 255 in party line or DCC chat.
+
+  There are two types of clients which can connect to bot:
+  1. IRC clients working via DCC chat
+  2. Telnet clients
+
+  Telnet protocol has some control sequences which starts with code 255 and eggdrop silently strips it from incoming strings:
+
+  encoding system is cp1251
+  +-------
+  | .say #eggtest меня зовут Настя
+  | [14:20] tcl: builtin dcc call: *dcc:say lynxy 7 #eggtest мен зовут Наст
+  | [14:20] #lynxy# (#eggtest) say мен зовут Наст
+  | Said to #eggtest: мен зовут Наст
+
+  Stripped letter 'я' (code 255 in cp1251), this letter very often appears in Russian words.
+
+  encoding system iso8859-1 (letter 'ÿ' has code 255 in iso8859-1)
+  +-------
+  | .say #eggtest saÿ ÿo-ÿo
+  | [14:24] tcl: builtin dcc call: *dcc:say lynxy 7 #eggtest sa o-o
+  | [14:24] #lynxy# (#eggtest) say sa o-o
+  | Said to #eggtest: sa o-o
+
+  Also stripped (I don't know how often this letter is used, but it is stripped!)
+
+  There is a solution. Telnet clients send some control sequences while establishing the connection, but IRC clients do not. If control sequences are sent while the connection establishes stripping will be enabled and if there are no any control sequences, stripping will be disabled. This allows to avoid the problem.
+
+2.3. Problem with DCC commands '.chhandle' and '.handle' and their TCL analogs
+  Bugs in DCC commands 'chhandle','handle' lead to substitution of non-Latin characters by '?'. Although you can add handle with non-Latin characters, but DCC commands 'chhandle', 'handle' and their analogs for TCL replace all the characters of the code above 127 to '?' (question mark)
+  
+  +-------
+  | .+user LamoЮзер
+  | [14:37] tcl: builtin dcc call: *dcc:+user lynxy 7 LamoЮзер
+  | [14:37] #lynxy# +user LamoЮзер
+  | Added LamoЮзер (no host) with no password and no flags.
+  | .chhandle LamoЮзер ЛамоЮзер
+  | [14:37] tcl: builtin dcc call: *dcc:chhandle lynxy 7 LamoЮзер ЛамоЮзер
+  | [14:37] Switched 0 notes from LamoЮзер to ????????.
+  | [14:37] #lynxy# chhandle LamoЮзер ????????
+  | Changed.
+
+  The problem is located in 'cmd_handle', 'cmd_chhandle' and 'tcl_chhandle' functions, that treat all the characters with code not in range from 32 to 127 as bad. Other procedures related to user handles don't have such problems.
+
+2.4. Problem with detecting locale encoding.
+  This problem has very low severity, but I'll describe it.
+
+  Create small configuration file 'eggenc.conf':
+  +-------
+  | user at sys:~/eggdrop> echo -e "putlog \"eggdrop encoding: [encoding system]\"; die;" > eggenc.conf
+
+  And test:
+  +-------
+  | user at sys:~/eggdrop> echo $LANG
+  | ru_RU.cp1251
+  | user at sys:~/eggdrop> ./eggdrop eggenc.conf
+  | Eggdrop v1.6.18 (C) 1997 Robey Pointer (C) 2006 Eggheads
+  | [10:48] --- Loading eggdrop v1.6.18 (Sat Jul 22 2006)
+  | [10:48] eggdrop encoding: cp1251
+  | [10:48] * EXIT
+
+  Ok.
+
+  Now run in locale ru_RU.koi8-r:
+  +-------
+  | user at sys:~/eggdrop> LANG=ru_RU.koi8-r ./eggdrop eggenc.conf
+  | Eggdrop v1.6.18 (C) 1997 Robey Pointer (C) 2006 Eggheads
+  | [10:57] --- Loading eggdrop v1.6.18 (Sat Jul 22 2006)
+  | [10:57] eggdrop encoding: iso8859-1
+  | [10:57] * EXIT
+
+  Wrong.
+
+  Next:
+  +-------
+  | user at sys:~/eggdrop> LANG=ko_KR.euckr ./eggdrop eggenc.conf
+  | Eggdrop v1.6.18 (C) 1997 Robey Pointer (C) 2006 Eggheads
+  | [10:58] --- Loading eggdrop v1.6.18 (Sat Jul 22 2006)
+  | [10:58] eggdrop encoding: iso8859-1
+  | [10:58] * EXIT
+  
+  Wrong again!
+
+  You can force setting appropriate locale encoding by placing at the begin of eggdrop's configuration file something like this:
+  +-------
+  | encoding system koi8-r
+
+  Or:
+  +-------
+  | encoding system euc-kr
+
+  But if I run 'tclsh', it detects locale encoding properly:
+  +-------
+  | user at sys:~/eggdrop> LANG=ru_RU.koi8r tclsh
+  | % encoding system; exit
+  | koi8-r
+  | user at sys:~/eggdrop> LANG=ko_KR.euckr tclsh
+  | % encoding system; exit
+  | euc-kr
+
+  When eggdrop initializes TCL interpreter it also tries to detect locale encoding and then set it for the interpreter. But eggdrop's code has some errors in encoding detection and doesn't always detect encoding properly. In comments written to this code in 'src/tcl.c' is said that the code is grabbed from TCL sources, but it seems to be very old. Furthermore now there is no need of this code because TCL library detects locale encoding while perform self-initialization. Patch just removes this strange code from eggdrop and now it detects ALL the encodings that I have on my system.
+
+3. Windows and Eggdrop
+
+  Eggdrop compiled with Cygwin environment (also known as Windrop) has the same problems and even more.
+  As I know Cygwin does not support any locale encoding except ASCII and UTF-8, but it is useless in many cases. So case insensetive binds does not work with non-latin characters (see test 2.1). I also include separate patch to make Windrop use Windows API locale depended routines for case of insensetive string comparision instead their Cygwin's analogs.
+
+P.S. Sorry for bad english.
+
+-----
+Date:           2006-Jul-26
+Author:         Anastasia Zemina a.k.a. lynxy (WeNet irc.wenet.ru:6667, #eggtest), Suzi project team
+Thanks to:      ZemIn, Buster, Yxaaaaaaa.
+URL:            Forum (russian): http://xirc.ru/plugins/forum/forum_viewforum.php?15
--- eggdrop1.6.18/src/cmds.c					2006-03-28 06:35:49.000000000 +0400
+++ eggdrop1.6.18/src/cmds.c.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -859,7 +859,7 @@
     return;
   }
   for (i = 0; i < strlen(newhand); i++)
-    if ((newhand[i] <= 32) || (newhand[i] >= 127) || (newhand[i] == '@'))
+    if ((((unsigned char *)newhand)[i] <= 32) || (newhand[i] == '@'))
       newhand[i] = '?';
   if (strchr(BADHANDCHARS, newhand[0]) != NULL)
     dprintf(idx, "Bizarre quantum forces prevent nicknames from starting with "
@@ -902,8 +902,9 @@
     dprintf(idx, "Usage: handle <new-handle>\n");
     return;
   }
+
   for (i = 0; i < strlen(newhandle); i++)
-    if ((newhandle[i] <= 32) || (newhandle[i] >= 127) || (newhandle[i] == '@'))
+    if ((((unsigned char *)newhandle)[i] <= 32) || (newhandle[i] == '@'))
       newhandle[i] = '?';
   if (strchr(BADHANDCHARS, newhandle[0]) != NULL)
     dprintf(idx,
--- eggdrop1.6.18/src/dcc.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/dcc.c.suzi_sp0007				2006-07-27 21:19:02.000000000 +0400
@@ -108,6 +108,10 @@
         /* response is: "hell yes!" */
         write(sock, "\r\nHell, yes!\r\n", 14);
       }
+      if (*p == TLN_IAC) {
+        *o++ = *p++;
+        mark = 1;
+      }
       /* Anything else can probably be ignored */
       p += mark - 1;
       *len = *len - mark;
@@ -317,6 +321,9 @@
   struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
   char *code;
 
+  if (((unsigned char) *buf == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &x);
   code = newsplit(&buf);
   if (!egg_strcasecmp(code, "*hello!"))
@@ -401,6 +408,9 @@
   char *msg;
   int f;
 
+  if (((unsigned char) *code == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, code, &i);
   if (raw_log) {
     if (code[0] == 's')
@@ -537,6 +547,9 @@
 {
   if (!atr)
     return;
+  if (((unsigned char) *buf == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &atr);
   atr = dcc[idx].user ? dcc[idx].user->flags : 0;
 
@@ -861,6 +874,7 @@
   int nathan = 0, doron = 0, fixed = 0;
   char *v, *d, filtbuf[2048];
 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &i);
   if (buf[0] && (buf[0] != '.') &&
       detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx))
@@ -1319,6 +1333,9 @@
   int ok = 0;
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
 
+  if (((unsigned char) *buf == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &atr);
   buf[HANDLEN] = 0;
   /* Toss out bad nicknames */
@@ -1521,6 +1538,9 @@
   char work[1024], *p, *q, *r;
 
   buf[HANDLEN] = 0;
+  if (((unsigned char) *buf == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &x);
   dcc[idx].timeval = now;
   for (x = 0; x < strlen(buf); x++)
@@ -1586,6 +1606,9 @@
   char *newpass;
   int ok;
 
+  if (((unsigned char) *buf == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &x);
   buf[16] = 0;
   ok = 1;
@@ -1714,6 +1737,9 @@
 {
   long oldsock;
 
+  if (((unsigned char) *buf == TLN_IAC) && (dcc[idx].status & STAT_TELNET)) 
+        dcc[idx].status |= STAT_STRIP_TELNET; 
+  if (dcc[idx].status & STAT_STRIP_TELNET)
   strip_telnet(dcc[idx].sock, buf, &len);
   if (!len)
     return;
--- eggdrop1.6.18/src/dccutil.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/dccutil.c.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -116,6 +116,23 @@
   return WBUF;
 }
 
+/* fix code 255, Replace TLN_IAC to double TLN_IAC */
+char *fix_TLN_IAC(char *buf)
+{
+  static unsigned char buftln[1024];
+  unsigned char *src = (unsigned char *) buf, *dst; 
+  dst = buftln;
+
+  while (*src) {
+    if ((*src == TLN_IAC) && (src[2] != '\01')){
+      *dst++ = *src;
+    }
+    *dst++ = *src++;
+  }
+  *dst = 0;
+  return buftln;
+}
+
 extern void (*qserver) (int, char *, int);
 
 void dprintf EGG_VARARGS_DEF(int, arg1)
@@ -174,8 +191,15 @@
       char *p = add_cr(buf);
 
       tputs(dcc[idx].sock, p, strlen(p));
-    } else if (dcc[idx].type && dcc[idx].type->output)
-      dcc[idx].type->output(idx, buf, dcc[idx].u.other);
+    } else if (dcc[idx].type && dcc[idx].type->output) {
+
+      /* fix code 255 - TLN_IAC */
+      if (dcc[idx].status & STAT_STRIP_TELNET) {
+        char *p = fix_TLN_IAC(buf);
+        dcc[idx].type->output(idx, p, dcc[idx].u.other);
+      } else 
+        dcc[idx].type->output(idx, buf, dcc[idx].u.other);
+    }
     else
       tputs(dcc[idx].sock, buf, len);
   }
--- eggdrop1.6.18/src/eggdrop.h					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/eggdrop.h.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -471,6 +471,9 @@
 #define STAT_BOTONLY 0x00020    /* telnet on bots-only connect          */
 #define STAT_USRONLY 0x00040    /* telnet on users-only connect         */
 #define STAT_PAGE    0x00080    /* page output to the user              */
+#define STAT_STRIP_TELNET 0x00100 /* This connection supports managing  *
+          *  codes of the protocol 
+          * a telnet  - TLN_IAC                */
 
 /* For stripping out mIRC codes. */
 #define STRIP_COLOR  0x00001    /* remove mIRC color codes              */
--- eggdrop1.6.18/src/main.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/main.c.suzi_sp0007			2006-07-27 22:36:49.000000000 +0400
@@ -129,6 +129,11 @@
 int resolve_timeout = 15; /* Hostname/address lookup timeout        */
 char quit_msg[1024];      /* Quit message                           */
 
+#ifdef USE_TCL_EVENTS
+int max_tcl_events = 1;
+#endif /* USE_TCL_EVENTS */
+int select_timeout = 1000;
+
 /* Traffic stats */
 unsigned long otraffic_irc = 0;
 unsigned long otraffic_irc_today = 0;
@@ -935,8 +940,14 @@
     int socket_cleanup = 0;
 
 #ifdef USE_TCL_EVENTS
-    /* Process a single tcl event */
-    Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
+    /* Process tcl events, but no more than max_tcl_events */
+    {
+      int i;
+      for (i = 0; i < max_tcl_events; i ++) {
+        if (!Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT))
+          break;
+      }
+    }
 #endif /* USE_TCL_EVENTS */
 
     /* Lets move some of this here, reducing the numer of actual
--- eggdrop1.6.18/src/mod/irc.mod/cmdsirc.c			2006-03-28 06:35:51.000000000 +0400
+++ eggdrop1.6.18/src/mod/irc.mod/cmdsirc.c.suzi_sp0007		2006-07-27 21:19:02.000000000 +0400
@@ -1001,7 +1001,7 @@
     int ok = 1;
 
     for (p = par; *p; p++)
-      if ((*p <= 32) || (*p >= 127))
+      if (*((unsigned char *)p) <= 32) 
         ok = 0;
     if (!ok) {
       dprintf(idx, "You can't have strange characters in a nick.\n");
--- eggdrop1.6.18/src/mod/module.h				2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/mod/module.h.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -479,6 +479,18 @@
 #define str_isdigit ((int (*) (const char *))global[292])
 #define remove_crlf ((void (*)(char **))global[293])
 
+#ifdef USE_TCL_BYTE_ARRAYS
+#define Tcl_EggSetVar ((CONST char *(*) (Tcl_Interp *, CONST char *, CONST char *newValue, int))global[294])
+#define Tcl_EggSetVar2 ((CONST char *(*) (Tcl_Interp *, CONST char *, CONST char *, CONST char *, int))global[295])
+#define Tcl_EggAppendResult ((void (*) TCL_VARARGS_DEF(Tcl_Interp *,arg1))global[296])
+#define Tcl_EggAppendElement ((void (*) (Tcl_Interp *, CONST char *))global[297])
+
+#define Tcl_EggEval ((int (*) (Tcl_Interp *interp, CONST char *script))global[298])
+#define Tcl_EggGlobalEval ((int (*) (Tcl_Interp *interp, CONST char *script))global[299])
+#define Tcl_EggNewStringObj ((Tcl_Obj *(*) (CONST char *bytes, int length))global[300])
+
+#endif /* USE_TCL_BYTE_ARRAYS */
+
 /* hostmasking */
 #define maskhost(a,b) _maskhost((a),(b),1)
 #define maskban(a,b) _maskhost((a),(b),0)
--- eggdrop1.6.18/src/mod/server.mod/server.c			2006-03-28 06:35:51.000000000 +0400
+++ eggdrop1.6.18/src/mod/server.mod/server.c.suzi_sp0007	2006-07-27 22:51:19.000000000 +0400
@@ -1145,7 +1145,20 @@
       Tcl_TraceVar(irp, name1, TCL_TRACE_READS | TCL_TRACE_WRITES |
                    TCL_TRACE_UNSETS, nick_change, cdata);
   } else {                        /* writes */
+
+#ifdef USE_TCL_ENCODING
+    Tcl_DString dstr;
+#endif
+    
     new = Tcl_GetVar2(interp, name1, name2, TCL_GLOBAL_ONLY);
+
+#ifdef USE_TCL_ENCODING
+  /* properly convert string to system encoding. */
+  Tcl_DStringInit(&dstr);
+  Tcl_UtfToExternalDString(NULL, new, -1, &dstr);
+  new = Tcl_DStringValue(&dstr);
+#endif
+
     if (strcmp(origbotname, (char *) new)) {
       if (origbotname[0]) {
         putlog(LOG_MISC, "*", "* IRC NICK CHANGE: %s -> %s", origbotname, new);
@@ -1154,7 +1167,13 @@
       strncpyz(origbotname, new, NICKLEN);
       if (server_online)
         dprintf(DP_SERVER, "NICK %s\n", origbotname);
+        
     }
+
+#ifdef USE_TCL_ENCODING
+  Tcl_DStringFree(&dstr);
+#endif
+    
   }
   return NULL;
 }
@@ -1837,6 +1856,9 @@
 char *server_start(Function *global_funcs)
 {
   EGG_CONST char *s;
+#ifdef USE_TCL_ENCODING
+  Tcl_DString dstr;
+#endif
 
   global = global_funcs;
 
@@ -1906,9 +1928,24 @@
   /* Fool bot in reading the values. */
   tcl_eggserver(NULL, interp, "servers", NULL, 0);
   tcl_traceserver("servers", NULL);
+
   s = Tcl_GetVar(interp, "nick", TCL_GLOBAL_ONLY);
+
+#ifdef USE_TCL_ENCODING
+  /* properly convert string to system encoding. */
+  Tcl_DStringInit(&dstr);
+  Tcl_UtfToExternalDString(NULL, s, -1, &dstr);
+  s = Tcl_DStringValue(&dstr);
+#endif
+
   if (s)
     strncpyz(origbotname, s, NICKLEN);
+
+#ifdef USE_TCL_ENCODING
+  Tcl_DStringFree(&dstr);
+#endif
+    
+    
   Tcl_TraceVar(interp, "nick",
                TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,
                nick_change, NULL);
--- eggdrop1.6.18/src/modules.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/modules.c.suzi_sp0007			2006-07-27 22:40:10.000000000 +0400
@@ -570,7 +570,24 @@
   (Function) oatoi,
   /* 292 - 295 */
   (Function) str_isdigit,
-  (Function) remove_crlf
+  (Function) remove_crlf,
+#ifdef USE_TCL_BYTE_ARRAYS
+ (Function) Tcl_EggSetVar,        /* 294 */
+ (Function) Tcl_EggSetVar2,       /* 295 */
+ (Function) Tcl_EggAppendResult,  /* 296 */
+ (Function) Tcl_EggAppendElement, /* 297 */
+ (Function) Tcl_EggEval,          /* 298 */
+ (Function) Tcl_EggGlobalEval,    /* 299 */
+ (Function) Tcl_EggNewStringObj   /* 300 */
+#else
+ (Function) 0,
+ (Function) 0,
+ (Function) 0,
+ (Function) 0,
+ (Function) 0,
+ (Function) 0,
+ (Function) 0
+#endif /* USE_TCL_BYTE_ARRAYS */
 };
 
 void init_modules(void)
--- eggdrop1.6.18/src/net.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/net.c.suzi_sp0007				2006-07-27 22:36:50.000000000 +0400
@@ -53,7 +53,7 @@
 #endif
 
 extern struct dcc_t *dcc;
-extern int backgrd, use_stderr, resolve_timeout, dcc_total;
+extern int backgrd, use_stderr, resolve_timeout, dcc_total, select_timeout;
 extern unsigned long otraffic_irc_today, otraffic_bn_today, otraffic_dcc_today,
                      otraffic_filesys_today, otraffic_trans_today,
                      otraffic_unknown_today;
@@ -597,8 +597,8 @@
     fds = FD_SETSIZE;           /* Fixes YET ANOTHER freebsd bug!!! */
 #endif
   /* timeout: 1 sec */
-  t.tv_sec = 1;
-  t.tv_usec = 0;
+  t.tv_sec = select_timeout / 1000;
+  t.tv_usec = (select_timeout % 1000) * 1000;
   FD_ZERO(&fd);
 
   for (i = 0; i < MAXSOCKS; i++) {
--- eggdrop1.6.18/src/tcl.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/tcl.c.suzi_sp0007				2006-07-29 16:46:37.000000000 +0400
@@ -59,7 +59,11 @@
            die_on_sigterm, max_logs, max_logsize, dcc_total, raw_log,
            identtimeout, dcc_sanitycheck, dupwait_timeout, egg_numver,
            share_unlinks, protect_telnet, sort_users, strict_host,
-           resolve_timeout, default_uflags, userfile_perm;
+           resolve_timeout, default_uflags, userfile_perm, select_timeout;
+
+#ifdef USE_TCL_EVENTS
+extern int max_tcl_events;
+#endif /* USE_TCL_EVENTS */
 
 extern struct dcc_t *dcc;
 extern tcl_timer_t *timer, *utimer;
@@ -277,17 +281,31 @@
       Tcl_Obj *obj;
       unsigned char *bytes;
       int len;
+      Tcl_DString ds;
+      int binary;
 
       obj = Tcl_GetVar2Ex(interp, name1, name2, 0);
       if (!obj)
         return NULL;
       len = 0;
-      bytes = Tcl_GetByteArrayFromObj(obj, &len);
-      if (!bytes)
-        return NULL;
+      binary = 0;
+      if (obj->typePtr != NULL)  
+        if (strcmp(obj->typePtr->name, "bytearray") == 0)
+          binary = 1; 
+      if (!binary) {
+        char *strptr = Tcl_GetStringFromObj(obj, &len);
+        bytes = (unsigned char *)Tcl_UtfToExternalDString(NULL, strptr, len, &ds);
+      }
+      else {
+        bytes = Tcl_GetByteArrayFromObj(obj, &len);
+        if (!bytes)
+          return NULL;
+      }
       s = malloc(len + 1);
       egg_memcpy(s, bytes, len);
       s[len] = 0;
+      if (!binary)
+        Tcl_DStringFree(&ds);
     }
 #else
     s = (char *) Tcl_GetVar2(interp, name1, name2, 0);
@@ -331,6 +349,8 @@
   void **callback_data;
   Function func;
   ClientData cd;
+  Tcl_DString ds;
+  int binary;
 
   objc += 5;
   strings = (char **) nmalloc(sizeof(char *) * objc);
@@ -339,11 +359,23 @@
   utftot += sizeof(char *) * objc;
   objc -= 5;
   for (i = 0; i < objc; i++) {
-    byteptr = (char *) Tcl_GetByteArrayFromObj(objv[i], &len);
+    binary = 0;
+    if (objv[i]->typePtr != NULL)  
+      if (strcmp(objv[i]->typePtr->name, "bytearray") == 0)
+        binary = 1;       
+    if (!binary) {
+      char *strptr = Tcl_GetStringFromObj(objv[i], &len);
+      byteptr = Tcl_UtfToExternalDString(NULL, strptr, len, &ds);
+    }
+    else {
+      byteptr = (char *)Tcl_GetByteArrayFromObj(objv[i], &len);
+    }
     strings[i] = (char *) nmalloc(len + 1);
     utftot += len + 1;
     strncpy(strings[i], byteptr, len);
     strings[i][len] = 0;
+    if (!binary)
+      Tcl_DStringFree(&ds);
   }
   callback_data = (void **) cdata;
   func = (Function) callback_data[0];
@@ -471,6 +503,7 @@
   {"telnet-banner",   bannerfile,     120,           STR_PROTECT},
   {"logfile-suffix",  logfile_suffix, 20,                      0},
   {"pidfile",         pid_file,       120,           STR_PROTECT},
+  {"sp_version",      "0007",         0,                       0},
   {NULL,              NULL,           0,                       0}
 };
 
@@ -522,6 +555,10 @@
   {"enable-simul",          &enable_simul,         0}, /* compat */
   {"debug-output",          &debug_output,         0}, /* compat */
   {"use-console-r",         &use_console_r,        0}, /* compat */
+#ifdef USE_TCL_EVENTS
+  {"max_tcl_events",        &max_tcl_events,       0},
+#endif  
+  {"select_timeout",        &select_timeout,       0},
   {NULL,                    NULL,                  0}
 };
 
@@ -559,9 +596,9 @@
 void init_tcl(int argc, char **argv)
 {
 #ifdef USE_TCL_ENCODING
-  const char *encoding;
+/*  const char *encoding;
   int i;
-  char *langEnv;
+  char *langEnv; */
 #endif /* USE_TCL_ENCODING */
 #ifdef USE_TCL_PACKAGE
   int j;
@@ -595,9 +632,13 @@
 
 /* Code based on Tcl's TclpSetInitialEncodings() */
 #ifdef USE_TCL_ENCODING
-  /* Determine the current encoding from the LC_* or LANG environment
+/* I don't know why this code included in eggdrop
+   because Tcl_Init() do the same things. And it do it better! */
+#if 0 
+ /* Determine the current encoding from the LC_* or LANG environment
    * variables.
    */
+  goto reset2;
   langEnv = getenv("LC_ALL");
   if (langEnv == NULL || langEnv[0] == '\0') {
     langEnv = getenv("LC_CTYPE");
@@ -665,6 +706,7 @@
   /* Keep the iso8859-1 encoding preloaded.  The IO package uses it for
    * gets on a binary channel. */
   Tcl_GetEncoding(NULL, "iso8859-1");
+#endif /* 0 */
 #endif /* USE_TCL_ENCODING */
 
 #ifdef USE_TCL_PACKAGE
--- eggdrop1.6.18/src/tclegg.h					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/tclegg.h.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -174,7 +174,7 @@
 void rem_tcl_coups(tcl_coups *);
 void add_tcl_ints(tcl_ints *);
 void rem_tcl_ints(tcl_ints *);
-
+#if 0
 /* From Tcl's tclUnixInit.c */
 /* The following table is used to map from Unix locale strings to
  * encoding files.
@@ -221,5 +221,5 @@
 
   {NULL,                  NULL}
 };
-
+#endif /* 0 */
 #endif /* _EGG_TCLEGG_H */
--- eggdrop1.6.18/src/tclhash.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/tclhash.c.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -1227,3 +1227,104 @@
     nfree(l);
   }
 }
+
+#ifdef USE_TCL_BYTE_ARRAYS
+#undef Tcl_SetVar2
+#undef Tcl_AppendResult
+#undef Tcl_AppendElement
+#undef Tcl_Eval
+#undef Tcl_GlobalEval
+#undef Tcl_NewStringObj
+
+void Tcl_EggAppendResult TCL_VARARGS_DEF(Tcl_Interp *, arg1)
+{
+  Tcl_Interp *interp;
+  va_list argList;
+  Tcl_DString ds;
+  char *param;
+  char *string;
+  interp = TCL_VARARGS_START(Tcl_Interp *,arg1,argList);
+  while (1) {
+    string = va_arg(argList, char *);
+
+    if (string == NULL) break;
+      param = (char *) Tcl_ExternalToUtfDString(NULL, string, -1, &ds);
+      Tcl_AppendResult(interp, param, NULL);
+      Tcl_DStringFree(&ds);
+  }
+  va_end(argList);
+}
+
+void Tcl_EggAppendElement(Tcl_Interp *interp, CONST char *string)
+{
+  Tcl_DString ds;
+  char *param;
+  param = (char *) Tcl_ExternalToUtfDString(NULL, string, -1, &ds);
+  Tcl_AppendElement(interp, param);
+  Tcl_DStringFree(&ds);
+}
+
+CONST char *Tcl_EggSetVar(Tcl_Interp *interp, CONST char *varName, 
+       CONST char *newValue, int flags)
+{
+  Tcl_DString ds;
+  char *ret;
+  ret = (char *) Tcl_SetVar2(interp, varName, (char *) NULL, 
+                  (char *) Tcl_ExternalToUtfDString(NULL, newValue, -1, &ds), flags);
+  Tcl_DStringFree(&ds);
+  return ret;
+}
+
+CONST char *Tcl_EggSetVar2(Tcl_Interp *interp, CONST char *part1, CONST char *part2, 
+              CONST char *newValue, int flags)
+{
+  Tcl_DString ds;
+  char *ret;
+  ret = (char *) Tcl_SetVar2(interp, part1, part2, 
+   (char *) Tcl_ExternalToUtfDString(NULL, newValue, -1, &ds), flags);
+  Tcl_DStringFree(&ds);
+  return ret;
+}
+
+int Tcl_EggEval(Tcl_Interp *interp, CONST char *script)
+{
+  Tcl_DString ds;
+  int ret;
+  ret = Tcl_Eval(interp, (char *) Tcl_ExternalToUtfDString(NULL, script, -1, &ds));
+  Tcl_DStringFree(&ds);
+  return ret;
+}
+
+int Tcl_EggGlobalEval(Tcl_Interp *interp, CONST char *script)
+{
+  Tcl_DString ds;
+  int ret;
+  ret = Tcl_GlobalEval(interp, (char *) Tcl_ExternalToUtfDString(NULL, script, -1, &ds));
+  Tcl_DStringFree(&ds);
+  return ret;
+}
+
+Tcl_Obj *Tcl_EggNewStringObj(CONST char *bytes, int length) 
+{
+  Tcl_DString ds;
+  Tcl_Obj *ret;
+  int len;
+  char *ptr;
+
+  ptr = Tcl_ExternalToUtfDString(NULL, bytes, length, &ds);
+  len = Tcl_DStringLength(&ds);
+
+  ret = Tcl_NewStringObj(ptr, len);
+
+  Tcl_DStringFree(&ds);
+  return ret;
+}
+
+#define Tcl_SetVar2 Tcl_EggSetVar2
+#define Tcl_AppendResult Tcl_EggAppendResult
+#define Tcl_AppendElement Tcl_EggAppendElement
+#define Tcl_Eval Tcl_EggEval
+#define Tcl_GlobalEval Tcl_EggGlobalEval
+#define Tcl_NewStringObj Tcl_EggNewStringObj
+
+#endif /* USE_TCL_BYTE_ARRAYS */
--- eggdrop1.6.18/src/tclhash.h					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/tclhash.h.suzi_sp0007			2006-07-27 22:40:57.000000000 +0400
@@ -25,6 +25,26 @@
 #ifndef _EGG_TCLHASH_H
 #define _EGG_TCLHASH_H
 
+#ifdef USE_TCL_BYTE_ARRAYS
+
+#define Tcl_SetVar          Tcl_EggSetVar
+#define Tcl_SetVar2         Tcl_EggSetVar2
+#define Tcl_AppendResult    Tcl_EggAppendResult
+#define Tcl_AppendElement   Tcl_EggAppendElement
+#define Tcl_Eval            Tcl_EggEval
+#define Tcl_GlobalEval      Tcl_EggGlobalEval
+#define Tcl_NewStringObj    Tcl_EggNewStringObj
+
+CONST char *Tcl_EggSetVar(Tcl_Interp *, CONST char *, CONST char *newValue, int);
+CONST char *Tcl_EggSetVar2(Tcl_Interp *, CONST char *, CONST char *, CONST char *, int);
+void Tcl_EggAppendResult TCL_VARARGS_DEF(Tcl_Interp *,arg1);
+void Tcl_EggAppendElement(Tcl_Interp *, CONST char *);
+int Tcl_EggEval(Tcl_Interp *interp, CONST char *script);
+int Tcl_EggGlobalEval(Tcl_Interp *interp, CONST char *script);
+Tcl_Obj * Tcl_EggNewStringObj(CONST char *bytes, int length);
+
+#endif /* USE_TCL_BYTE_ARRAYS */
+
 
 #define TC_DELETED   0x0001     /* This command/trigger was deleted. */
 
--- eggdrop1.6.18/src/tcluser.c					2006-03-28 06:35:50.000000000 +0400
+++ eggdrop1.6.18/src/tcluser.c.suzi_sp0007			2006-07-27 21:19:02.000000000 +0400
@@ -393,9 +393,11 @@
     x = 0;
   else {
     strncpyz(newhand, argv[2], sizeof newhand);
-    for (i = 0; i < strlen(newhand); i++)
-      if ((newhand[i] <= 32) || (newhand[i] >= 127) || (newhand[i] == '@'))
+
+ for (i = 0; i < strlen(newhand); i++)
+      if ((((unsigned char *)newhand)[i] <= 32) || (newhand[i] == '@'))
         newhand[i] = '?';
+
     if (strchr(BADHANDCHARS, newhand[0]) != NULL)
       x = 0;
     else if (strlen(newhand) < 1)


Index: eggdrop.spec
===================================================================
RCS file: /cvs/extras/rpms/eggdrop/EL-5/eggdrop.spec,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- eggdrop.spec	8 Dec 2007 16:41:51 -0000	1.10
+++ eggdrop.spec	10 Feb 2008 22:04:49 -0000	1.11
@@ -1,7 +1,7 @@
 Summary:	The world's most popular Open Source IRC bot
 Name:		eggdrop
 Version:	1.6.18
-Release:	12%{?dist}
+Release:	14%{?dist}
 License:	GPLv2+
 Group:		Applications/Communications
 URL:		http://www.eggheads.org/
@@ -9,6 +9,7 @@
 Patch0:		eggdrop-1.6.17-conf.patch
 Patch1:		eggdrop-1.6.17-langdir.patch
 Patch2:		http://nion.modprobe.de/01_CVE-2007-2807_servmsg.patch
+Patch3:		eggdrop-1.6.18-suzi_sp0007.patch
 BuildRequires:	tcl-devel >= 8.3, bind-devel, zlib-devel, gawk
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -23,6 +24,7 @@
 %patch0 -p1 -b .conf
 %patch1 -p1 -b .langdir
 %patch2 -p0 -b .servmsg
+%patch3 -p1 -b .suzi_sp0007
 
 %build
 %configure
@@ -47,6 +49,12 @@
 rm -rf doc/man1
 chmod -x doc/WEIRD-MESSAGES eggdrop.conf src/mod/transfer.mod/*.c
 
+# Convert everything to UTF-8
+iconv -f iso-8859-1 -t utf-8 -o doc/KNOWN-PROBLEMS.utf8 doc/KNOWN-PROBLEMS
+mv -f doc/KNOWN-PROBLEMS.utf8 doc/KNOWN-PROBLEMS
+iconv -f iso-8859-1 -t utf-8 -o doc/UPDATES1.6.utf8 doc/UPDATES1.6
+mv -f doc/UPDATES1.6.utf8 doc/UPDATES1.6
+
 # Fix paths of example eggdrop.conf
 perl -pi -e s":scripts/:%{_datadir}/%{name}/scripts/:" eggdrop.conf
 perl -pi -e s":help/:%{_datadir}/%{name}/help/:" eggdrop.conf
@@ -57,13 +65,19 @@
 
 %files
 %defattr(-,root,root)
-%doc COPYING FEATURES INSTALL NEWS README doc/* html eggdrop.conf
+%doc COPYING FEATURES INSTALL NEWS README UTF-8 doc/* html eggdrop.conf
 %{_bindir}/%{name}
 %{_libdir}/%{name}
 %{_datadir}/%{name}
 %{_mandir}/man?/*
 
 %changelog
+* Sun Feb 10 2008 Robert Scheck <robert at fedoraproject.org> 1.6.18-14
+- Added patch to provide better non-latin support (#429621)
+
+* Sat Jan 05 2008 Robert Scheck <robert at fedoraproject.org> 1.6.18-13
+- Rebuild for tcl 8.5
+
 * Sat Dec 08 2007 Robert Scheck <robert at fedoraproject.org> 1.6.18-12
 - Added a patch to fix some stack based overflows (CVE-2007-2807)
 




More information about the fedora-extras-commits mailing list