aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2008-03-29 23:15:04 +0000
committerWilmer van der Gaast <wilmer@gaast.net>2008-03-29 23:15:04 +0000
commit18ff38fad0d6d47853fb43ec5a99b29ba031a8ca (patch)
tree3d22c1c9f364481aa0abff8b27c88352d7a1f429
parenta199d33ed818820ffba328f718799bbd77392f6a (diff)
Be more liberal with accepted line endings. ERC on Windows likes to use
"\r\r\n", for example, and until now BitlBee only chopped off the \r\n, leaving the first \r as part of the command, which means it couldn't log in to BitlBee at all. (Bad character in nickname.)
-rw-r--r--irc.c54
-rw-r--r--tests/check_irc.c4
2 files changed, 28 insertions, 30 deletions
diff --git a/irc.c b/irc.c
index fa0c03fe..99f0de9a 100644
--- a/irc.c
+++ b/irc.c
@@ -296,9 +296,8 @@ void irc_process( irc_t *irc )
{
char conv[IRC_MAX_LINE+1];
- /* [WvG] Because irc_tokenize splits at every newline, the lines[] list
- should end with an empty string. This is why this actually works.
- Took me a while to figure out, Maurits. :-P */
+ /* [WvG] If the last line isn't empty, it's an incomplete line and we
+ should wait for the rest to come in before processing it. */
if( lines[i+1] == NULL )
{
temp = g_strdup( lines[i] );
@@ -368,42 +367,41 @@ void irc_process( irc_t *irc )
contains an incomplete line at the end, ends with an empty string. */
char **irc_tokenize( char *buffer )
{
- int i, j;
+ int i, j, n = 3;
char **lines;
- /* Count the number of elements we're gonna need. */
- for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
- {
- if( buffer[i] == '\n' )
- if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
- j ++;
- }
-
- /* Allocate j+1 elements. */
- lines = g_new( char *, j + 1 );
-
- /* NULL terminate our list. */
- lines[j] = NULL;
+ /* Allocate n+1 elements. */
+ lines = g_new( char *, n + 1 );
lines[0] = buffer;
- /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
- * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
- */
- for( i = 0, j = 0; buffer[i] != '\0'; i ++)
+ /* Split the buffer in several strings, and accept any kind of line endings,
+ * knowing that ERC on Windows may send something interesting like \r\r\n,
+ * and surely there must be clients that think just \n is enough... */
+ for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
{
- if( buffer[i] == '\n' )
+ if( buffer[i] == '\r' || buffer[i] == '\n' )
{
- buffer[i] = '\0';
+ while( buffer[i] == '\r' || buffer[i] == '\n' )
+ buffer[i++] = '\0';
- if( i > 0 && buffer[i-1] == '\r' )
- buffer[i-1] = '\0';
- if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
- lines[++j] = buffer + i + 1;
+ lines[++j] = buffer + i;
+
+ if( j >= n )
+ {
+ n *= 2;
+ lines = g_renew( char *, lines, n + 1 );
+ }
+
+ if( buffer[i] == '\0' )
+ break;
}
}
- return( lines );
+ /* NULL terminate our list. */
+ lines[++j] = NULL;
+
+ return lines;
}
/* Split an IRC-style line into little parts/arguments. */
diff --git a/tests/check_irc.c b/tests/check_irc.c
index c1cf05a5..66fe0021 100644
--- a/tests/check_irc.c
+++ b/tests/check_irc.c
@@ -36,8 +36,8 @@ START_TEST(test_login)
irc = irc_new(g_io_channel_unix_get_fd(ch1));
- fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\n"
- "USER a a a a\r\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL);
+ fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\r\n"
+ "USER a a a a\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL);
fail_unless(g_io_channel_flush(ch2, NULL) == G_IO_STATUS_NORMAL);
g_main_iteration(FALSE);