[cvslog] [CVS] Module eggdrop1.6: Change committed

cvs at eggheads.org cvs at eggheads.org
Mon Jan 4 07:15:21 CST 2010


CVSROOT    : /usr/local/cvsroot
Module     : eggdrop1.6
Commit time: 2010-01-04 13:15:21 UTC
Committer  : Rumen Stoyanov <pseudo at egg6.net>

Modified files:
     README doc/Changes1.6 src/botcmd.c src/cmds.c src/dcc.c
     src/eggdrop.h src/tcldcc.c src/tcluser.c
     src/mod/irc.mod/cmdsirc.c

Log message:

Modified various checks to allow non-latin characters in handles. Added missing checks to tcl_adduser() and tcl_chhand().

Added telnet autodetection to src/dcc.c. Made changes to stop interpreting telnet codes from bots. Reworked telnet handlers to properly understand and escape character 0xff in data.
Fixes Bugzilla Bug # 419 "droped chars when sharing"

Patch by: pseudo

---------------------- diff included ----------------------
Index: eggdrop1.6/README
diff -u eggdrop1.6/README:1.51 eggdrop1.6/README:1.52
--- eggdrop1.6/README:1.51	Sun Jan  3 08:48:39 2010
+++ eggdrop1.6/README	Mon Jan  4 07:15:10 2010
@@ -1,4 +1,4 @@
-$Id: README,v 1.51 2010/01/03 14:48:39 pseudo Exp $
+$Id: README,v 1.52 2010/01/04 13:15:10 pseudo Exp $
 
 Readme
 Last revised: June 5, 2002
@@ -478,7 +478,7 @@
     the Eggdrop source code and any related files are Copyright (C) by Eggheads
     Development Team. The source code will still be distributed according to
     the GNU General Public License as Robey Pointer did in the past.
-an
+
     Releases previous to 1.0m were made using a different licensing scheme.
     You may, at your option, use the GNU General Public License on those
     versions (instead of the license packaged with them) with my blessing.
Index: eggdrop1.6/doc/Changes1.6
diff -u eggdrop1.6/doc/Changes1.6:1.52 eggdrop1.6/doc/Changes1.6:1.53
--- eggdrop1.6/doc/Changes1.6:1.52	Sun Jan  3 08:48:39 2010
+++ eggdrop1.6/doc/Changes1.6	Mon Jan  4 07:15:11 2010
@@ -1,4 +1,4 @@
-$Id: Changes1.6,v 1.52 2010/01/03 14:48:39 pseudo Exp $
+$Id: Changes1.6,v 1.53 2010/01/04 13:15:11 pseudo Exp $
 
 Eggdrop Changes (since version 1.6.0)
 
@@ -6,6 +6,14 @@
 
 1.6.20 (CVS):
 
+  - Modified various checks to allow non-latin characters in handles. Added
+    missing checks to tcl_adduser() and tcl_chhand().
+  - Added telnet autodetection to src/dcc.c. Made changes to stop interpreting
+    telnet codes from bots. Reworked telnet handlers to properly understand
+    and escape character 0xff in data.
+    Fixes Bugzilla Bug # 419 "droped chars when sharing"
+    Patch by: pseudo
+
   - Various minor docfixes.
     Patch by: pseudo
 
Index: eggdrop1.6/src/botcmd.c
diff -u eggdrop1.6/src/botcmd.c:1.50 eggdrop1.6/src/botcmd.c:1.51
--- eggdrop1.6/src/botcmd.c:1.50	Sun Jan  3 07:27:31 2010
+++ eggdrop1.6/src/botcmd.c	Mon Jan  4 07:15:11 2010
@@ -3,7 +3,7 @@
  *   commands that comes across the botnet
  *   userfile transfer and update commands from sharebots
  *
- * $Id: botcmd.c,v 1.50 2010/01/03 13:27:31 pseudo Exp $
+ * $Id: botcmd.c,v 1.51 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -116,7 +116,8 @@
   for (p = s = from; *s; s++)
     if ((*s > 31) && (*s != 127))
       *p++ = *s;
-  *p = 0;
+  if (*p)
+    *p = 0;
   p = strchr(from, '@');
   if (p) {
     snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg);
@@ -211,7 +212,8 @@
   for (p = s = from; *s; s++)
     if ((*s > 31) && (*s != 127))
       *p++ = *s;
-  *p = 0;
+  if (*p)
+    *p = 0;
   chanout_but(-1, chan, "* %s %s\n", from, par);
   botnet_send_act(idx, from, NULL, chan, par);
   check_tcl_act(from, chan, par);
Index: eggdrop1.6/src/cmds.c
diff -u eggdrop1.6/src/cmds.c:1.123 eggdrop1.6/src/cmds.c:1.124
--- eggdrop1.6/src/cmds.c:1.123	Sun Jan  3 07:27:31 2010
+++ eggdrop1.6/src/cmds.c	Mon Jan  4 07:15:11 2010
@@ -3,7 +3,7 @@
  *   commands from a user via dcc
  *   (split in 2, this portion contains no-irc commands)
  *
- * $Id: cmds.c,v 1.123 2010/01/03 13:27:31 pseudo Exp $
+ * $Id: cmds.c,v 1.124 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -834,7 +834,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 "
@@ -878,7 +878,7 @@
     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,
Index: eggdrop1.6/src/dcc.c
diff -u eggdrop1.6/src/dcc.c:1.90 eggdrop1.6/src/dcc.c:1.91
--- eggdrop1.6/src/dcc.c:1.90	Sun Jan  3 07:27:31 2010
+++ eggdrop1.6/src/dcc.c	Mon Jan  4 07:15:11 2010
@@ -4,7 +4,7 @@
  *   disconnect on a dcc socket
  *   ...and that's it!  (but it's a LOT)
  *
- * $Id: dcc.c,v 1.90 2010/01/03 13:27:31 pseudo Exp $
+ * $Id: dcc.c,v 1.91 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -69,6 +69,22 @@
 static void dcc_telnet_pass(int, int);
 
 
+/* Escape telnet IAC and prepend CR to LF */
+static char *escape_telnet(char *s)
+{
+  static char buf[1024];
+  char *p;
+
+  for (p = buf; *s && (p < (buf + sizeof(buf) - 2)); *p++ = *s++)
+    if ((unsigned char) *s == TLN_IAC)
+      *p++ = *s;
+    else if (*s == '\n')
+      *p++ = '\r';
+  *p = 0;
+
+  return buf;
+}
+
 static void strip_telnet(int sock, char *buf, int *len)
 {
   unsigned char *p = (unsigned char *) buf, *o = (unsigned char *) buf;
@@ -86,27 +102,28 @@
         mark = 3;
         if (!*(p + 1))
           mark = 2;             /* bogus */
-      }
-      if (*p == TLN_WILL) {
+      } else if (*p == TLN_WILL) {
         /* WILL X -> response: DONT X */
         /* except WILL ECHO which we just smile and ignore */
         if (*(p + 1) != TLN_ECHO) {
           write(sock, TLN_IAC_C TLN_DONT_C, 2);
           write(sock, p + 1, 1);
         }
-      }
-      if (*p == TLN_DO) {
+      } else if (*p == TLN_DO) {
         /* DO X -> response: WONT X */
         /* except DO ECHO which we just smile and ignore */
         if (*(p + 1) != TLN_ECHO) {
           write(sock, TLN_IAC_C TLN_WONT_C, 2);
           write(sock, p + 1, 1);
         }
-      }
-      if (*p == TLN_AYT) {
-        /* "are you there?" */
-        /* response is: "hell yes!" */
+      } else if (*p == TLN_AYT) {
+        /* "Are You There?" */
+        /* response is: "Hell, yes!" */
         write(sock, "\r\nHell, yes!\r\n", 14);
+      } else if (*p == TLN_IAC) {
+        /* IAC character in data, escaped with another IAC */
+        *o++ = *p++;
+        mark = 1;
       }
       /* Anything else can probably be ignored */
       p += mark - 1;
@@ -317,7 +334,6 @@
   struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
   char *code;
 
-  strip_telnet(dcc[idx].sock, buf, &x);
   code = newsplit(&buf);
   if (!egg_strcasecmp(code, "*hello!"))
     greet_new_bot(idx);
@@ -404,7 +420,6 @@
   char *msg;
   int f;
 
-  strip_telnet(dcc[idx].sock, code, &i);
   if (raw_log) {
     if (code[0] == 's')
       putlog(LOG_BOTSHARE, "*", "{%s} %s", dcc[idx].nick, code + 2);
@@ -540,7 +555,8 @@
 {
   if (!atr)
     return;
-  strip_telnet(dcc[idx].sock, buf, &atr);
+  if (dcc[idx].status & STAT_TELNET)
+    strip_telnet(dcc[idx].sock, buf, &atr);
   atr = dcc[idx].user ? dcc[idx].user->flags : 0;
 
   /* Check for MD5 digest from remote _bot_. <cybah> */
@@ -587,7 +603,7 @@
       dcc[idx].u.chat->channel = -2;
       /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
       if (dcc[idx].status & STAT_TELNET)
-        dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
+        tputs(dcc[idx].sock, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n", 4);
       dcc_chatter(idx);
     }
   } else {
@@ -600,7 +616,7 @@
     if (dcc[idx].u.chat->away) {        /* su from a dumb user */
       /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
       if (dcc[idx].status & STAT_TELNET)
-        dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
+        tputs(dcc[idx].sock, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n", 4);
       dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
       strcpy(dcc[idx].nick, dcc[idx].u.chat->away);
       nfree(dcc[idx].u.chat->away);
@@ -772,7 +788,7 @@
     }
     c->buffer = 0;
     dcc[idx].status &= ~STAT_PAGE;
-    do_boot(idx, botnetnick, "too many pages - senq full");
+    do_boot(idx, botnetnick, "too many pages - sendq full");
     return;
   }
   if ((c->line_count < c->max_line) && (c->buffer == NULL)) {
@@ -798,6 +814,7 @@
   }
 }
 
+
 static void out_dcc_general(int idx, char *buf, void *x)
 {
   register struct chat_info *p = (struct chat_info *) x;
@@ -805,7 +822,7 @@
 
   strip_mirc_codes(p->strip_flags, buf);
   if (dcc[idx].status & STAT_TELNET)
-    y = add_cr(buf);
+    y = escape_telnet(buf);
   if (dcc[idx].status & STAT_PAGE)
     append_line(idx, y);
   else
@@ -867,7 +884,8 @@
   int nathan = 0, doron = 0, fixed = 0;
   char *v, *d, filtbuf[2048];
 
-  strip_telnet(dcc[idx].sock, buf, &i);
+  if (dcc[idx].status & STAT_TELNET)
+    strip_telnet(dcc[idx].sock, buf, &i);
   if (buf[0] && (buf[0] != '.') &&
       detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx))
     return;
@@ -1320,12 +1338,33 @@
     }
 }
 
+/* This is not a universal telnet detector. You need to send WILL STATUS to the
+ * other side and pass the reply to this function. A telnet client will respond
+ * to this with either DO or DONT STATUS.
+ */
+static int detect_telnet(unsigned char *buf)
+{
+  if (!buf || !buf[0] || !buf[1])
+    return 0;
+  while (buf[2]) {
+    if (buf[0] == TLN_IAC && (buf[1] == TLN_DO || buf[1] == TLN_DONT) &&
+        buf[2] == TLN_STATUS)
+      return 1;
+    buf++;
+  }
+  return 0;
+}
+
 static void dcc_telnet_id(int idx, char *buf, int atr)
 {
   int ok = 0;
   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
 
-  strip_telnet(dcc[idx].sock, buf, &atr);
+  if (detect_telnet((unsigned char *) buf)) {
+    dcc[idx].status |= STAT_TELNET;
+    strip_telnet(dcc[idx].sock, buf, &atr);
+  } else
+    dcc[idx].status &= ~STAT_TELNET;
   buf[HANDLEN] = 0;
   /* Toss out bad nicknames */
   if (dcc[idx].nick[0] != '@' && !wild_match(dcc[idx].nick, buf)) {
@@ -1484,7 +1523,13 @@
      */
 
     /* Turn off remote telnet echo (send IAC WILL ECHO). */
-    dprintf(idx, "\n%s" TLN_IAC_C TLN_WILL_C TLN_ECHO_C "\n", DCC_ENTERPASS);
+    if (dcc[idx].status & STAT_TELNET) {
+      char buf[1030];
+      snprintf(buf, sizeof buf, "\n%s%s\r\n", escape_telnet(DCC_ENTERPASS),
+               TLN_IAC_C TLN_WILL_C TLN_ECHO_C);
+      tputs(dcc[idx].sock, buf, strlen(buf));
+    } else
+      dprintf(idx, "\n%s\n", DCC_ENTERPASS);
   }
 }
 
@@ -1530,7 +1575,8 @@
   char work[1024], *p, *q, *r;
 
   buf[HANDLEN] = 0;
-  strip_telnet(dcc[idx].sock, buf, &x);
+  if (dcc[idx].status & STAT_TELNET)
+    strip_telnet(dcc[idx].sock, buf, &x);
   dcc[idx].timeval = now;
   for (x = 0; x < strlen(buf); x++)
     if ((buf[x] <= 32) || (buf[x] >= 127))
@@ -1538,7 +1584,7 @@
   if (!ok) {
     dprintf(idx, "\nYou can't use weird symbols in your nick.\n");
     dprintf(idx, "Try another one please:\n");
-  } else if (strchr("-,+*=:!.@#;$", buf[0]) != NULL) {
+  } else if (strchr(BADHANDCHARS, buf[0]) != NULL) {
     dprintf(idx, "\nYou can't start your nick with the character '%c'\n",
             buf[0]);
     dprintf(idx, "Try another one please:\n");
@@ -1595,7 +1641,8 @@
   char *newpass;
   int ok;
 
-  strip_telnet(dcc[idx].sock, buf, &x);
+  if (dcc[idx].status & STAT_TELNET)
+    strip_telnet(dcc[idx].sock, buf, &x);
   buf[16] = 0;
   ok = 1;
   if (strlen(buf) < 4) {
@@ -1729,7 +1776,8 @@
 {
   long oldsock;
 
-  strip_telnet(dcc[idx].sock, buf, &len);
+  if (dcc[idx].status & STAT_TELNET)
+    strip_telnet(dcc[idx].sock, buf, &len);
   if (!len)
     return;
 
@@ -2053,6 +2101,11 @@
   dcc[i].u.chat = get_data_ptr(sizeof(struct chat_info));
   egg_bzero(dcc[i].u.chat, sizeof(struct chat_info));
 
+  /* Note: we don't really care about telnet status here. We use the
+   * STATUS option as a hopefully harmless way to detect if the other
+   * side is a telnet client or not. */
+  dprintf(i, TLN_IAC_C TLN_WILL_C TLN_STATUS_C "\n");
+
   /* Copy acceptable-nick/host mask */
   dcc[i].status = STAT_TELNET | STAT_ECHO;
   if (!strcmp(dcc[idx].nick, "(bots)"))
Index: eggdrop1.6/src/eggdrop.h
diff -u eggdrop1.6/src/eggdrop.h:1.71 eggdrop1.6/src/eggdrop.h:1.72
--- eggdrop1.6/src/eggdrop.h:1.71	Sun Jan  3 07:27:32 2010
+++ eggdrop1.6/src/eggdrop.h	Mon Jan  4 07:15:11 2010
@@ -4,7 +4,7 @@
  *
  *   IF YOU ALTER THIS FILE, YOU NEED TO RECOMPILE THE BOT.
  *
- * $Id: eggdrop.h,v 1.71 2010/01/03 13:27:32 pseudo Exp $
+ * $Id: eggdrop.h,v 1.72 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -681,6 +681,8 @@
 
 /* Telnet codes.  See "TELNET Protocol Specification" (RFC 854) and
  * "TELNET Echo Option" (RFC 875) for details. */
+
+/* Telnet commands */
 #define TLN_AYT         246     /* Are You There        */
 #define TLN_WILL        251     /* Will                 */
 #define TLN_WILL_C      "\373"
@@ -693,7 +695,10 @@
 #define TLN_IAC         255     /* Interpret As Command */
 #define TLN_IAC_C       "\377"
 
-#define TLN_ECHO        1       /* Echo                 */
+/* Telnet options */
+#define TLN_ECHO        1       /* Echo (RFC 875)        */
 #define TLN_ECHO_C      "\001"
+#define TLN_STATUS      5       /* STATUS (RFC 859)      */
+#define TLN_STATUS_C    "\005"
 
 #endif /* _EGG_EGGDROP_H */
Index: eggdrop1.6/src/mod/irc.mod/cmdsirc.c
diff -u eggdrop1.6/src/mod/irc.mod/cmdsirc.c:1.64 eggdrop1.6/src/mod/irc.mod/cmdsirc.c:1.65
--- eggdrop1.6/src/mod/irc.mod/cmdsirc.c:1.64	Sun Jan  3 07:27:54 2010
+++ eggdrop1.6/src/mod/irc.mod/cmdsirc.c	Mon Jan  4 07:15:11 2010
@@ -2,7 +2,7 @@
  * chancmds.c -- part of irc.mod
  *   handles commands directly relating to channel interaction
  *
- * $Id: cmdsirc.c,v 1.64 2010/01/03 13:27:54 pseudo Exp $
+ * $Id: cmdsirc.c,v 1.65 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -1001,12 +1001,12 @@
     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");
       return;
-    } else if (strchr("-,+*=:!.@#;$", par[0]) != NULL) {
+    } else if (strchr(BADHANDCHARS, par[0]) != NULL) {
       dprintf(idx, "You can't start a nick with '%c'.\n", par[0]);
       return;
     }
Index: eggdrop1.6/src/tcldcc.c
diff -u eggdrop1.6/src/tcldcc.c:1.66 eggdrop1.6/src/tcldcc.c:1.67
--- eggdrop1.6/src/tcldcc.c:1.66	Sun Jan  3 07:27:32 2010
+++ eggdrop1.6/src/tcldcc.c	Mon Jan  4 07:15:11 2010
@@ -2,7 +2,7 @@
  * tcldcc.c -- handles:
  *   Tcl stubs for the dcc commands
  *
- * $Id: tcldcc.c,v 1.66 2010/01/03 13:27:32 pseudo Exp $
+ * $Id: tcldcc.c,v 1.67 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -59,17 +59,16 @@
 
 static int tcl_putdcc STDVAR
 {
-  int i, j;
+  int j;
 
   BADARGS(3, 3, " idx text");
 
-  i = atoi(argv[1]);
-  j = findidx(i);
+  j = findidx(atoi(argv[1]));
   if (j < 0) {
     Tcl_AppendResult(irp, "invalid idx", NULL);
     return TCL_ERROR;
   }
-  dumplots(-i, "", argv[2]);
+  dumplots(j, "", argv[2]);
 
   return TCL_OK;
 }
Index: eggdrop1.6/src/tcluser.c
diff -u eggdrop1.6/src/tcluser.c:1.48 eggdrop1.6/src/tcluser.c:1.49
--- eggdrop1.6/src/tcluser.c:1.48	Sun Jan  3 07:27:32 2010
+++ eggdrop1.6/src/tcluser.c	Mon Jan  4 07:15:11 2010
@@ -2,7 +2,7 @@
  * tcluser.c -- handles:
  *   Tcl stubs for the user-record-oriented commands
  *
- * $Id: tcluser.c,v 1.48 2010/01/03 13:27:32 pseudo Exp $
+ * $Id: tcluser.c,v 1.49 2010/01/04 13:15:11 pseudo Exp $
  */
 /*
  * Copyright (C) 1997 Robey Pointer
@@ -272,11 +272,18 @@
 
 static int tcl_adduser STDVAR
 {
+  unsigned char *p;
+
   BADARGS(2, 3, " handle ?hostmask?");
 
   if (strlen(argv[1]) > HANDLEN)
     argv[1][HANDLEN] = 0;
-  if ((argv[1][0] == '*') || get_user_by_handle(userlist, argv[1]))
+  for (p = (unsigned char *) argv[1]; *p; p++)
+    if (*p <= 32 || *p == '@')
+      *p = '?';
+
+  if ((argv[1][0] == '*') || strchr(BADHANDCHARS, argv[1][0]) ||
+      get_user_by_handle(userlist, argv[1]))
     Tcl_AppendResult(irp, "0", NULL);
   else {
     userlist = adduser(userlist, argv[1], argv[2], "-", default_flags);
@@ -294,9 +301,12 @@
 
   if (strlen(argv[1]) > HANDLEN)
     argv[1][HANDLEN] = 0;
-  if (get_user_by_handle(userlist, argv[1]))
-    Tcl_AppendResult(irp, "0", NULL);
-  else if (argv[1][0] == '*')
+  for (p = argv[1]; *p; p++)
+    if ((unsigned char) *p <= 32 || *p == '@')
+      *p = '?';
+  
+  if ((argv[1][0] == '*') || strchr(BADHANDCHARS, argv[1][0]) ||
+      get_user_by_handle(userlist, argv[1]))
     Tcl_AppendResult(irp, "0", NULL);
   else {
     userlist = adduser(userlist, argv[1], "none", "-", USER_BOT);
@@ -409,7 +419,7 @@
   else {
     strncpyz(newhand, argv[2], sizeof newhand);
     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)
       x = 0;
----------------------- End of diff -----------------------


More information about the Changes mailing list