aboutsummaryrefslogtreecommitdiffstats
path: root/irc.c
diff options
context:
space:
mode:
Diffstat (limited to 'irc.c')
-rw-r--r--irc.c113
1 files changed, 81 insertions, 32 deletions
diff --git a/irc.c b/irc.c
index 096f9d99..3d3baca6 100644
--- a/irc.c
+++ b/irc.c
@@ -54,13 +54,9 @@ irc_t *irc_new( int fd )
irc->fd = fd;
irc->io_channel = g_io_channel_unix_new( fd );
-#ifdef GLIB2
g_io_channel_set_encoding (irc->io_channel, NULL, NULL);
g_io_channel_set_buffered (irc->io_channel, FALSE);
g_io_channel_set_flags( irc->io_channel, G_IO_FLAG_NONBLOCK, NULL );
-#else
- fcntl( irc->fd, F_SETFL, O_NONBLOCK);
-#endif
irc->r_watch_source_id = g_io_add_watch( irc->io_channel, G_IO_IN | G_IO_ERR | G_IO_HUP, bitlbee_io_current_client_read, irc );
irc->status = USTATUS_OFFLINE;
@@ -198,7 +194,7 @@ void irc_abort( irc_t *irc, int immed, char *format, ... )
}
}
-static gboolean irc_free_userhash( gpointer key, gpointer value, gpointer data )
+static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
{
g_free( key );
@@ -232,10 +228,12 @@ void irc_free(irc_t * irc)
irc_connection_list = g_slist_remove( irc_connection_list, irc );
for (account = irc->accounts; account; account = account->next) {
- if (account->gc)
- account_offline(account->gc);
- else if (account->reconnect)
- g_source_remove(account->reconnect);
+ if (account->gc) {
+ account->gc->wants_to_die = TRUE;
+ signoff(account->gc);
+ } else if (account->reconnect) {
+ cancel_auto_reconnect(account);
+ }
}
g_free(irc->sendbuffer);
@@ -284,10 +282,10 @@ void irc_free(irc_t * irc)
}
}
- g_hash_table_foreach_remove(irc->userhash, irc_free_userhash, NULL);
+ g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL);
g_hash_table_destroy(irc->userhash);
- g_hash_table_foreach_remove(irc->watches, irc_free_userhash, NULL);
+ g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);
g_hash_table_destroy(irc->watches);
if (irc->nicks != NULL) {
@@ -345,7 +343,7 @@ void irc_setpass (irc_t *irc, const char *pass)
void irc_process( irc_t *irc )
{
- char **lines, *temp, **cmd;
+ char **lines, *temp, **cmd, *cs;
int i;
if( irc->readbuffer != NULL )
@@ -354,6 +352,11 @@ void irc_process( irc_t *irc )
for( i = 0; *lines[i] != '\0'; i ++ )
{
+ 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 */
if( lines[i+1] == NULL )
{
temp = g_strdup( lines[i] );
@@ -361,7 +364,14 @@ void irc_process( irc_t *irc )
irc->readbuffer = temp;
i ++;
break;
- }
+ }
+
+ if( ( cs = set_getstr( irc, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
+ {
+ conv[IRC_MAX_LINE] = 0;
+ if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) != -1 )
+ lines[i] = conv;
+ }
if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
continue;
@@ -387,6 +397,8 @@ void irc_process( irc_t *irc )
}
}
+/* Splits a long string into separate lines. The array is NULL-terminated and, unless the string
+ contains an incomplete line at the end, ends with an empty string. */
char **irc_tokenize( char *buffer )
{
int i, j;
@@ -427,6 +439,7 @@ char **irc_tokenize( char *buffer )
return( lines );
}
+/* Split an IRC-style line into little parts/arguments. */
char **irc_parse_line( char *line )
{
int i, j;
@@ -486,6 +499,7 @@ char **irc_parse_line( char *line )
return cmd;
}
+/* Converts such an array back into a command string. Mainly used for the IPC code right now. */
char *irc_build_line( char **cmd )
{
int i, len;
@@ -538,7 +552,7 @@ int irc_usermsg( irc_t *irc, char *format, ... )
user_t *u;
u = user_find( irc, irc->mynick );
- if( u ) is_private = u->is_private;
+ is_private = u->is_private;
va_start( params, format );
g_vsnprintf( text, sizeof( text ), format, params );
@@ -562,16 +576,25 @@ void irc_write( irc_t *irc, char *format, ... )
void irc_vawrite( irc_t *irc, char *format, va_list params )
{
int size;
- char line[IRC_MAX_LINE];
-
+ char line[IRC_MAX_LINE+1], *cs;
+
if( irc->quit )
return;
-
- g_vsnprintf( line, IRC_MAX_LINE - 3, format, params );
-
+
+ line[IRC_MAX_LINE] = 0;
+ g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
+
strip_newlines( line );
+ if( ( cs = set_getstr( irc, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
+ {
+ char conv[IRC_MAX_LINE+1];
+
+ conv[IRC_MAX_LINE] = 0;
+ if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 )
+ strcpy( line, conv );
+ }
strcat( line, "\r\n" );
-
+
if( irc->sendbuffer != NULL ) {
size = strlen( irc->sendbuffer ) + strlen( line );
irc->sendbuffer = g_renew ( char, irc->sendbuffer, size + 1 );
@@ -802,7 +825,7 @@ void irc_topic( irc_t *irc, char *channel )
if( c )
irc_reply( irc, 332, "%s :BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", channel, c->title );
else
- irc_reply( irc, 331, "%s :No topic for this channel" );
+ irc_reply( irc, 331, "%s :No topic for this channel", channel );
}
}
@@ -858,7 +881,7 @@ void irc_join( irc_t *irc, user_t *u, char *channel )
nick_lc( nick );
if( g_hash_table_lookup( irc->watches, nick ) )
{
- irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "logged online" );
+ irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" );
}
g_free( nick );
}
@@ -875,15 +898,37 @@ void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker )
void irc_kill( irc_t *irc, user_t *u )
{
- char *nick;
+ char *nick, *s;
+ char reason[64];
- irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, "Leaving..." );
+ if( u->gc && u->gc->flags & OPT_LOGGING_OUT )
+ {
+ if( u->gc->user->proto_opt[0][0] )
+ g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
+ u->gc->user->proto_opt[0] );
+ else if( ( s = strchr( u->gc->username, '@' ) ) )
+ g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
+ s + 1 );
+ else
+ g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost,
+ u->gc->prpl->name, irc->myhost );
+
+ /* proto_opt might contain garbage after the : */
+ if( ( s = strchr( reason, ':' ) ) )
+ *s = 0;
+ }
+ else
+ {
+ strcpy( reason, "Leaving..." );
+ }
+
+ irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason );
nick = g_strdup( u->nick );
nick_lc( nick );
if( g_hash_table_lookup( irc->watches, nick ) )
{
- irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "logged offline" );
+ irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" );
}
g_free( nick );
}
@@ -983,7 +1028,7 @@ int irc_send( irc_t *irc, char *nick, char *s, int flags )
}
else if( c && c->gc && c->gc->prpl )
{
- return( serv_send_chat( irc, c->gc, c->id, s ) );
+ return( bim_chat_msg( c->gc, c->id, s ) );
}
return( 0 );
@@ -993,8 +1038,12 @@ gboolean buddy_send_handler_delayed( gpointer data )
{
user_t *u = data;
+ /* Shouldn't happen, but just to be sure. */
+ if( u->sendbuf_len < 2 )
+ return FALSE;
+
u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */
- serv_send_im( u->gc->irc, u, u->sendbuf, u->sendbuf_flags );
+ bim_buddy_msg( u->gc, u->handle, u->sendbuf, u->sendbuf_flags );
g_free( u->sendbuf );
u->sendbuf = NULL;
@@ -1002,7 +1051,7 @@ gboolean buddy_send_handler_delayed( gpointer data )
u->sendbuf_timer = 0;
u->sendbuf_flags = 0;
- return( FALSE );
+ return FALSE;
}
void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
@@ -1015,7 +1064,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
if( u->sendbuf_len > 0 && u->sendbuf_flags != flags)
{
- //Flush the buffer
+ /* Flush the buffer */
g_source_remove( u->sendbuf_timer );
buddy_send_handler_delayed( u );
}
@@ -1023,14 +1072,14 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
if( u->sendbuf_len == 0 )
{
u->sendbuf_len = strlen( msg ) + 2;
- u->sendbuf = g_new (char, u->sendbuf_len );
+ u->sendbuf = g_new( char, u->sendbuf_len );
u->sendbuf[0] = 0;
u->sendbuf_flags = flags;
}
else
{
u->sendbuf_len += strlen( msg ) + 1;
- u->sendbuf = g_renew ( char, u->sendbuf, u->sendbuf_len );
+ u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len );
}
strcat( u->sendbuf, msg );
@@ -1046,7 +1095,7 @@ void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
}
else
{
- serv_send_im( irc, u, msg, flags );
+ bim_buddy_msg( u->gc, u->handle, msg, flags );
}
}