aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.bzrignore2
-rw-r--r--Makefile14
-rw-r--r--account.c29
-rw-r--r--bitlbee.c4
-rw-r--r--bitlbee.h7
-rw-r--r--conf.c2
-rwxr-xr-xconfigure29
-rw-r--r--doc/bitlbee.82
-rw-r--r--doc/bitlbee.xinetd11
-rw-r--r--doc/example_plugin.c3
-rw-r--r--doc/user-guide/commands.xml16
-rw-r--r--help.c17
-rw-r--r--ipc.c5
-rw-r--r--ipc.h4
-rw-r--r--irc.c82
-rw-r--r--irc.h12
-rw-r--r--irc_commands.c12
-rw-r--r--log.h2
-rw-r--r--protocols/http_client.c52
-rw-r--r--protocols/http_client.h2
-rw-r--r--protocols/jabber/jabber.c46
-rw-r--r--protocols/jabber/xmlparse.c25
-rw-r--r--protocols/msn/msn.h5
-rw-r--r--protocols/msn/msn_util.c14
-rw-r--r--protocols/msn/ns.c51
-rw-r--r--protocols/msn/sb.c8
-rw-r--r--protocols/nogaim.c454
-rw-r--r--protocols/nogaim.h131
-rw-r--r--protocols/oscar/aim.h7
-rw-r--r--protocols/oscar/chat.c14
-rw-r--r--protocols/oscar/oscar.c33
-rw-r--r--protocols/oscar/oscar_util.c4
-rw-r--r--protocols/oscar/service.c5
-rw-r--r--protocols/ssl_nss.c12
-rw-r--r--protocols/ssl_openssl.c86
-rw-r--r--protocols/yahoo/yahoo.c10
-rw-r--r--query.c16
-rw-r--r--root_commands.c130
-rw-r--r--set.c6
-rw-r--r--user.c4
-rw-r--r--user.h1
-rw-r--r--util.c49
-rw-r--r--util.h50
-rw-r--r--utils/bitlbeed.c2
44 files changed, 885 insertions, 585 deletions
diff --git a/.bzrignore b/.bzrignore
index ad4f8534..a5c25a72 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -18,3 +18,5 @@ build-arch-stamp
tags
decode
encode
+bitlbee.pc
+.gdb_history
diff --git a/Makefile b/Makefile
index ae5bd5df..721e4101 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@
# Program variables
objects = account.o bitlbee.o crypting.o help.o ini.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o storage_text.o url.o user.o util.o
+headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h
subdirs = protocols
ifeq ($(ARCH),Windows)
@@ -25,7 +26,7 @@ CFLAGS += -Wall
all: $(OUTFILE)
$(MAKE) -C doc
-uninstall: uninstall-bin uninstall-doc
+uninstall: uninstall-bin uninstall-doc
@echo -e '\nmake uninstall does not remove files in '$(DESTDIR)$(ETCDIR)', you can use make uninstall-etc to do that.\n'
install: install-bin install-doc
@@ -62,6 +63,17 @@ install-bin:
uninstall-bin:
rm -f $(DESTDIR)$(BINDIR)/$(OUTFILE)
+install-dev:
+ mkdir -p $(DESTDIR)$(INCLUDEDIR)
+ install -m 0644 $(headers) $(DESTDIR)$(INCLUDEDIR)
+ mkdir -p $(DESTDIR)$(PCDIR)
+ install -m 0644 bitlbee.pc $(DESTDIR)$(PCDIR)
+
+uninstall-dev:
+ rm -f $(foreach hdr,$(headers),$(DESTDIR)$(INCLUDEDIR)/$(hdr))
+ -rmdir $(DESTDIR)$(INCLUDEDIR)
+ rm -f $(DESTDIR)$(PCDIR)/bitlbee.pc
+
install-etc:
mkdir -p $(DESTDIR)$(ETCDIR)
install -m 0644 motd.txt $(DESTDIR)$(ETCDIR)/motd.txt
diff --git a/account.c b/account.c
index ed6b98c0..168d18c0 100644
--- a/account.c
+++ b/account.c
@@ -52,8 +52,34 @@ account_t *account_add( irc_t *irc, struct prpl *prpl, char *user, char *pass )
account_t *account_get( irc_t *irc, char *id )
{
account_t *a, *ret = NULL;
+ char *handle, *s;
int nr;
+ /* This checks if the id string ends with (...) */
+ if( ( handle = strchr( id, '(' ) ) && ( s = strchr( handle, ')' ) ) && s[1] == 0 )
+ {
+ struct prpl *proto;
+
+ *s = *handle = 0;
+ handle ++;
+
+ if( ( proto = find_protocol( id ) ) )
+ {
+ for( a = irc->accounts; a; a = a->next )
+ if( a->prpl == proto &&
+ a->prpl->cmp_buddynames( handle, a->user ) == 0 )
+ ret = a;
+ }
+
+ /* Restore the string. */
+ handle --;
+ *handle = '(';
+ *s = ')';
+
+ if( ret )
+ return ret;
+ }
+
if( sscanf( id, "%d", &nr ) == 1 && nr < 1000 )
{
for( a = irc->accounts; a; a = a->next )
@@ -140,7 +166,8 @@ void account_on( irc_t *irc, account_t *a )
void account_off( irc_t *irc, account_t *a )
{
- account_offline( a->gc );
+ a->gc->wants_to_die = TRUE;
+ signoff( a->gc );
a->gc = NULL;
if( a->reconnect )
{
diff --git a/bitlbee.c b/bitlbee.c
index 752ed659..cca14916 100644
--- a/bitlbee.c
+++ b/bitlbee.c
@@ -110,8 +110,8 @@ int bitlbee_daemon_init()
/* Sometimes std* are already closed (for example when we're in a RESTARTed
BitlBee process. So let's only close TTY-fds. */
if( isatty( 0 ) ) close( 0 );
- if( isatty( 0 ) ) close( 1 );
- if( isatty( 0 ) ) close( 2 );
+ if( isatty( 1 ) ) close( 1 );
+ if( isatty( 2 ) ) close( 2 );
}
#endif
diff --git a/bitlbee.h b/bitlbee.h
index f2ea8280..07ac54bc 100644
--- a/bitlbee.h
+++ b/bitlbee.h
@@ -98,7 +98,7 @@ extern char *CONF_FILE;
#include "irc.h"
#include "storage.h"
#include "set.h"
-#include "protocols/nogaim.h"
+#include "nogaim.h"
#include "commands.h"
#include "account.h"
#include "conf.h"
@@ -107,6 +107,7 @@ extern char *CONF_FILE;
#include "help.h"
#include "query.h"
#include "sock.h"
+#include "util.h"
typedef struct global {
/* In forked mode, child processes store the fd of the IPC socket here. */
@@ -129,10 +130,6 @@ gboolean bitlbee_io_current_client_write( GIOChannel *source, GIOCondition condi
void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
void root_command( irc_t *irc, char *command[] );
void bitlbee_shutdown( gpointer data );
-double gettime( void );
-G_MODULE_EXPORT void http_encode( char *s );
-G_MODULE_EXPORT void http_decode( char *s );
-G_MODULE_EXPORT char *strip_newlines(char *source);
extern global_t global;
diff --git a/conf.c b/conf.c
index 0bd9cbc8..7538825d 100644
--- a/conf.c
+++ b/conf.c
@@ -94,7 +94,7 @@ conf_t *conf_load( int argc, char *argv[] )
}
conf->port = i;
}
- else if( opt == 'p' )
+ else if( opt == 'P' )
{
g_free( conf->pidfile );
conf->pidfile = g_strdup( optarg );
diff --git a/configure b/configure
index cc678e01..8a54c009 100755
--- a/configure
+++ b/configure
@@ -16,6 +16,8 @@ config='/var/lib/bitlbee/'
pidfile='/var/run/bitlbee.pid'
ipcsocket='/var/run/bitlbee'
plugindir='$prefix/lib/bitlbee'
+pcdir='$prefix/lib/pkgconfig'
+includedir='$prefix/include/bitlbee'
msn=1
jabber=1
@@ -79,6 +81,8 @@ config=`eval echo "$config/" | sed 's/\/\{1,\}/\//g'`
plugindir=`eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g'`
pidfile=`eval echo "$pidfile" | sed 's/\/\{1,\}/\//g'`
ipcsocket=`eval echo "$ipcsocket" | sed 's/\/\{1,\}/\//g'`
+includedir=`eval echo "$includedir" | sed 's/\/\{1,\}/\//g'`
+pcdir=`eval echo "$pcdir" | sed 's/\/\{1,\}/\//g'`
cat<<EOF>Makefile.settings
## BitlBee settings, generated by configure
@@ -90,6 +94,8 @@ DATADIR=$datadir
PLUGINDIR=$plugindir
CONFIG=$config
IPCSOCKET=$ipcsocket
+INCLUDEDIR=$includedir
+PCDIR=$pcdir
ARCH=$arch
CPU=$cpu
@@ -299,10 +305,16 @@ else
fi
echo
-if [ -z "$BITLBEE_VERSION" -a -d .bzr -a -x "`which bzr`" ]; then
+if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then
+ nick=`bzr nick`
+ if [ -n "$nick" -a "$nick" != "bitlbee" ]; then
+ nick="-$nick"
+ else
+ nick=""
+ fi
rev=`bzr revno`
echo 'Using bzr revision #'$rev' as version number'
- BITLBEE_VERSION=\"bzr-$rev\"
+ BITLBEE_VERSION=\"bzr$nick-$rev\"
fi
if [ -n "$BITLBEE_VERSION" ]; then
@@ -312,6 +324,19 @@ if [ -n "$BITLBEE_VERSION" ]; then
echo
fi
+cat <<EOF>bitlbee.pc
+prefix=$prefix
+includedir=$includedir
+
+Name: bitlbee
+Description: IRC to IM gateway
+Requires: glib-2.0
+Version: $BITLBEE_VERSION
+Libs:
+Cflags: -I\${includedir}
+
+EOF
+
protocols=''
protoobjs=''
diff --git a/doc/bitlbee.8 b/doc/bitlbee.8
index f1d4dbce..201e366e 100644
--- a/doc/bitlbee.8
+++ b/doc/bitlbee.8
@@ -115,7 +115,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple PLace, Suite 330, Boston, MA 02111-1307 USA
.SH AUTHORS
.PP
- Wilmer van der Gaast <lintux@lintux.cx>
+ Wilmer van der Gaast <wilmer@gaast.net>
.BR
Jelmer Vernooij <jelmer@vernstok.nl>
.BR
diff --git a/doc/bitlbee.xinetd b/doc/bitlbee.xinetd
index 5f05e26e..88d02013 100644
--- a/doc/bitlbee.xinetd
+++ b/doc/bitlbee.xinetd
@@ -13,7 +13,12 @@ service ircd
user = nobody
server = /usr/local/sbin/bitlbee
- ## xinetd is fucking retarded, what's the use of this port flag if
- ## it HAS to be the same as in /etc/services ?
- # port = 6667
+ ## You might want to limit access to localhost only:
+ # bind = 127.0.0.1
+
+ ## Thanks a lot to friedman@splode.com for telling us about the type
+ ## argument, so now this file can be used without having to edit
+ ## /etc/services too.
+ type = UNLISTED
+ port = 6667
}
diff --git a/doc/example_plugin.c b/doc/example_plugin.c
index 38d02260..a33907a8 100644
--- a/doc/example_plugin.c
+++ b/doc/example_plugin.c
@@ -2,10 +2,11 @@
* This is the most simple possible BitlBee plugin. To use, compile it as
* a shared library and place it in the plugin directory:
*
- * gcc -o example.so -shared example.c
+ * gcc -o example.so -shared example.c `pkg-config --cflags bitlbee`
* cp example.so /usr/local/lib/bitlbee
*/
#include <stdio.h>
+#include <bitlbee.h>
void init_plugin(void)
{
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index b04a6b0a..44a9882f 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -140,6 +140,7 @@
<bitlbee-command name="add">
<short-description>Add a buddy to your contact list</short-description>
<syntax>add &lt;connection&gt; &lt;handle&gt; [&lt;nick&gt;]</syntax>
+ <syntax>add -tmp &lt;connection&gt; &lt;handle&gt; [&lt;nick&gt;]</syntax>
<description>
<para>
@@ -149,6 +150,10 @@
<para>
If you want, you can also tell BitlBee what nick to give the new contact. Of course you can also use the <emphasis>rename</emphasis> command for that, but sometimes this might be more convenient.
</para>
+
+ <para>
+ Adding -tmp adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by <emphasis>set handle_unknown add</emphasis>). This allows you to talk to people who are not in your contact list.
+ </para>
</description>
<ircexample>
@@ -196,11 +201,16 @@
<short-description>Block someone</short-description>
<syntax>block &lt;nick&gt;</syntax>
<syntax>block &lt;connection&gt; &lt;handle&gt;</syntax>
+ <syntax>block &lt;connection&gt;</syntax>
<description>
<para>
Puts the specified user on your ignore list. Either specify the user's nick when you have him/her in your contact list or a connection number and a user handle.
</para>
+
+ <para>
+ When called with only a connection specification as an argument, the command displays the current block list for that connection.
+ </para>
</description>
</bitlbee-command>
@@ -213,6 +223,10 @@
<para>
Reverse of block. Unignores the specified user or user handle on specified connection.
</para>
+
+ <para>
+ When called with only a connection specification as an argument, the command displays the current allow list for that connection.
+ </para>
</description>
</bitlbee-command>
@@ -606,7 +620,7 @@
</para>
<para>
- To identify yourself in later sessions, you can use the <emphasis>identify</emphasis> command.
+ To identify yourself in later sessions, you can use the <emphasis>identify</emphasis> command. To change your password later, you can use the <emphasis>set password</emphasis> command.
</para>
</description>
diff --git a/help.c b/help.c
index 8959a70b..7c6d2dda 100644
--- a/help.c
+++ b/help.c
@@ -115,22 +115,21 @@ char *help_get( help_t **help, char *string )
if( g_strcasecmp( h->string, string ) == 0 ) break;
h = h->next;
}
- if( h )
+ if( h && h->length > 0 )
{
char *s = g_new( char, h->length + 1 );
if( fstat( h->fd, stat ) != 0 )
{
g_free( h );
- *help=NULL;
- return( NULL );
+ *help = NULL;
+ return NULL;
}
mtime = stat->st_mtime;
- if( mtime > h->mtime ) {
- return( NULL );
- return( g_strdup( "Help file changed during this session. Please restart to get help back." ) );
- }
+ if( mtime > h->mtime )
+ return NULL;
+
s[h->length] = 0;
if( h->fd >= 0 )
{
@@ -141,8 +140,8 @@ char *help_get( help_t **help, char *string )
{
strncpy( s, h->offset.mem_offset, h->length );
}
- return( s );
+ return s;
}
- return( NULL );
+ return NULL;
}
diff --git a/ipc.c b/ipc.c
index 1b813e7f..18d3284e 100644
--- a/ipc.c
+++ b/ipc.c
@@ -83,8 +83,6 @@ void ipc_master_cmd_rehash( irc_t *data, char **cmd )
void ipc_master_cmd_restart( irc_t *data, char **cmd )
{
- struct bitlbee_child *child = (void*) data;
-
if( global.conf->runmode != RUNMODE_FORKDAEMON )
{
/* Tell child that this is unsupported. */
@@ -508,7 +506,7 @@ int ipc_master_listen_socket()
return 0;
}
- if (bind(serversock, &un_addr, sizeof(un_addr)) == -1) {
+ if (bind(serversock, (struct sockaddr *)&un_addr, sizeof(un_addr)) == -1) {
log_message( LOGLVL_WARNING, "Unable to bind UNIX socket to %s: %s", IPCSOCKET, strerror(errno) );
return 0;
}
@@ -572,5 +570,6 @@ int ipc_master_load_state()
ipc_to_children_str( "HELLO\r\n" );
ipc_to_children_str( "OPERMSG :New BitlBee master process started (version " BITLBEE_VERSION ")\r\n" );
+ fclose( fp );
return 1;
}
diff --git a/ipc.h b/ipc.h
index 7ff74a15..db05d63c 100644
--- a/ipc.h
+++ b/ipc.h
@@ -46,9 +46,9 @@ void ipc_master_free_one( struct bitlbee_child *child );
void ipc_master_free_all();
void ipc_to_master( char **cmd );
-void ipc_to_master_str( char *format, ... );
+void ipc_to_master_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 );
void ipc_to_children( char **cmd );
-void ipc_to_children_str( char *format, ... );
+void ipc_to_children_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 );
/* We need this function in inetd mode, so let's just make it non-static. */
void ipc_master_cmd_rehash( irc_t *data, char **cmd );
diff --git a/irc.c b/irc.c
index 93cbc293..fb85de62 100644
--- a/irc.c
+++ b/irc.c
@@ -198,7 +198,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 );
@@ -231,9 +231,14 @@ void irc_free(irc_t * irc)
g_io_channel_unref( irc->io_channel );
irc_connection_list = g_slist_remove( irc_connection_list, irc );
- for (account = irc->accounts; account; account = account->next)
- if (account->gc)
+ for (account = irc->accounts; account; account = account->next) {
+ if (account->gc) {
+ account->gc->wants_to_die = TRUE;
signoff(account->gc);
+ } else if (account->reconnect) {
+ cancel_auto_reconnect(account);
+ }
+ }
g_free(irc->sendbuffer);
g_free(irc->readbuffer);
@@ -281,10 +286,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) {
@@ -342,7 +347,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 )
@@ -351,6 +356,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] );
@@ -358,7 +368,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;
@@ -384,6 +401,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;
@@ -424,6 +443,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;
@@ -483,6 +503,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;
@@ -535,7 +556,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 );
@@ -559,16 +580,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 );
@@ -799,7 +829,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 );
}
}
@@ -855,7 +885,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 );
}
@@ -880,7 +910,7 @@ void irc_kill( irc_t *irc, user_t *u )
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 );
}
@@ -980,7 +1010,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 );
@@ -990,8 +1020,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;
@@ -999,7 +1033,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 )
@@ -1012,7 +1046,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 );
}
@@ -1020,14 +1054,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 );
@@ -1043,7 +1077,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 );
}
}
diff --git a/irc.h b/irc.h
index 5c53273a..79faea0b 100644
--- a/irc.h
+++ b/irc.h
@@ -32,7 +32,7 @@
#define IRC_LOGIN_TIMEOUT 60
#define IRC_PING_STRING "PinglBee"
-#define UMODES "iasw"
+#define UMODES "abisw"
#define UMODES_PRIV "Ro"
#define CMODES "nt"
#define CMODE "t"
@@ -104,7 +104,7 @@ typedef struct irc
extern GSList *irc_connection_list;
irc_t *irc_new( int fd );
-void irc_abort( irc_t *irc, int immed, char *format, ... );
+void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
void irc_free( irc_t *irc );
void irc_exec( irc_t *irc, char **cmd );
@@ -113,10 +113,10 @@ char **irc_parse_line( char *line );
char *irc_build_line( char **cmd );
void irc_vawrite( irc_t *irc, char *format, va_list params );
-void irc_write( irc_t *irc, char *format, ... );
-void irc_write_all( int now, char *format, ... );
-void irc_reply( irc_t *irc, int code, char *format, ... );
-G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... );
+void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
+void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
+void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
+G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
char **irc_tokenize( char *buffer );
void irc_login( irc_t *irc );
diff --git a/irc_commands.c b/irc_commands.c
index f2c7a645..fe67a534 100644
--- a/irc_commands.c
+++ b/irc_commands.c
@@ -384,9 +384,9 @@ static void irc_cmd_watch( irc_t *irc, char **cmd )
g_hash_table_insert( irc->watches, nick, nick );
if( u && u->online )
- irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, time( NULL ), "is online" );
+ irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
else
- irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", time( NULL ), "is offline" );
+ irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
}
else if( cmd[i][0] == '-' )
{
@@ -447,7 +447,7 @@ static void irc_cmd_away( irc_t *irc, char **cmd )
struct gaim_connection *gc = a->gc;
if( gc && gc->flags & OPT_LOGGED_IN )
- proto_away( gc, u->away );
+ bim_set_away( gc, u->away );
}
}
@@ -510,6 +510,11 @@ static void irc_cmd_pong( irc_t *irc, char **cmd )
irc->pinging = 0;
}
+static void irc_cmd_version( irc_t *irc, char **cmd )
+{
+ irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
+}
+
static void irc_cmd_completions( irc_t *irc, char **cmd )
{
user_t *u = user_find( irc, irc->mynick );
@@ -567,6 +572,7 @@ static const command_t irc_commands[] = {
{ "ns", 1, irc_cmd_nickserv, IRC_CMD_LOGGED_IN },
{ "motd", 0, irc_cmd_motd, IRC_CMD_LOGGED_IN },
{ "pong", 0, irc_cmd_pong, IRC_CMD_LOGGED_IN },
+ { "version", 0, irc_cmd_version, IRC_CMD_LOGGED_IN },
{ "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
{ "die", 0, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
{ "wallops", 1, NULL, IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
diff --git a/log.h b/log.h
index 6679121d..f574ae07 100644
--- a/log.h
+++ b/log.h
@@ -53,7 +53,7 @@ typedef struct log_t {
void log_init(void);
void log_link(int level, int output);
-void log_message(int level, char *message, ...);
+void log_message(int level, char *message, ...) G_GNUC_PRINTF( 2, 3 );
void log_error(char *functionname);
#endif
diff --git a/protocols/http_client.c b/protocols/http_client.c
index 9417e200..5db31782 100644
--- a/protocols/http_client.c
+++ b/protocols/http_client.c
@@ -70,6 +70,37 @@ void *http_dorequest( char *host, int port, int ssl, char *request, http_input_f
return( req );
}
+void *http_dorequest_url( char *url_string, http_input_function func, gpointer data )
+{
+ url_t *url = g_new0( url_t, 1 );
+ char *request;
+ void *ret;
+
+ if( !url_set( url, url_string ) )
+ {
+ g_free( url );
+ return NULL;
+ }
+
+ if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS )
+ {
+ g_free( url );
+ return NULL;
+ }
+
+ request = g_strdup_printf( "GET %s HTTP/1.0\r\n"
+ "Host: %s\r\n"
+ "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n"
+ "\r\n", url->file, url->host );
+
+ ret = http_dorequest( url->host, url->port,
+ url->proto == PROTO_HTTPS, request, func, data );
+
+ g_free( url );
+ g_free( request );
+ return ret;
+}
+
/* This one is actually pretty simple... Might get more calls if we can't write
the whole request at once. */
static void http_connected( gpointer data, int source, GaimInputCondition cond )
@@ -221,21 +252,24 @@ got_reply:
end1 = end2 + 1;
evil_server = 1;
}
- else
+ else if( end1 )
{
end1 += 2;
}
-
- if( end1 )
+ else
{
- *end1 = 0;
-
- if( evil_server )
- req->reply_body = end1 + 1;
- else
- req->reply_body = end1 + 2;
+ goto cleanup;
}
+ *end1 = 0;
+
+ if( evil_server )
+ req->reply_body = end1 + 1;
+ else
+ req->reply_body = end1 + 2;
+
+ req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
+
if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
{
if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 )
diff --git a/protocols/http_client.h b/protocols/http_client.h
index 53c6fcd6..860cdd86 100644
--- a/protocols/http_client.h
+++ b/protocols/http_client.h
@@ -38,6 +38,7 @@ struct http_request
int status_code;
char *reply_headers;
char *reply_body;
+ int body_size;
int finished;
void *ssl;
@@ -52,3 +53,4 @@ struct http_request
};
void *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data );
+void *http_dorequest_url( char *url_string, http_input_function func, gpointer data );
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index ba652b8a..ac6481a1 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -1044,7 +1044,7 @@ static void jabber_accept_add(gpointer w, struct jabber_add_permit *jap)
* ask if we want him or her added.
*/
if(find_buddy(GJ_GC(jap->gjc), jap->user) == NULL) {
- show_got_added(GJ_GC(jap->gjc), NULL, jap->user, NULL, NULL);
+ show_got_added(GJ_GC(jap->gjc), jap->user, NULL);
}
g_free(jap->user);
g_free(jap);
@@ -1231,9 +1231,7 @@ static void jabber_handleroster(gjconn gjc, xmlnode querynode)
x = xmlnode_get_nextsibling(x);
}
- x = jutil_presnew(0, NULL, "Online");
- gjab_send(gjc, x);
- xmlnode_free(x);
+ account_online(GJ_GC(gjc));
}
static void jabber_handleauthresp(gjconn gjc, jpacket p)
@@ -1249,7 +1247,6 @@ static void jabber_handleauthresp(gjconn gjc, jpacket p)
gjab_auth(gjc);
} else {
gjab_reqroster(gjc);
- account_online(GJ_GC(gjc));
((struct jabber_data *)GJ_GC(gjc)->proto_data)->did_import = TRUE;
}
@@ -1551,7 +1548,9 @@ static gboolean jabber_free(gpointer data)
if(jd->gjc != NULL) {
gjab_delete(jd->gjc);
+ /* YAY for modules with their own memory pool managers!...
g_free(jd->gjc->sid);
+ And a less sarcastic yay for valgrind. :-) */
jd->gjc = NULL;
}
g_free(jd);
@@ -1887,24 +1886,11 @@ static void jabber_set_away(struct gaim_connection *gc, char *state, char *messa
xmlnode_free(x);
}
-static void jabber_set_idle(struct gaim_connection *gc, int idle) {
- struct jabber_data *jd = (struct jabber_data *)gc->proto_data;
- jd->idle = idle ? time(NULL) - idle : idle;
-}
-
static void jabber_keepalive(struct gaim_connection *gc) {
struct jabber_data *jd = (struct jabber_data *)gc->proto_data;
gjab_send_raw(jd->gjc, " \t ");
}
-static void jabber_buddy_free(struct buddy *b)
-{
- while (b->proto_data) {
- g_free(((GSList *)b->proto_data)->data);
- b->proto_data = g_slist_remove(b->proto_data, ((GSList *)b->proto_data)->data);
- }
-}
-
/*---------------------------------------*/
/* Jabber "set info" (vCard) support */
/*---------------------------------------*/
@@ -2340,29 +2326,12 @@ static void jabber_handlevcard(gjconn gjc, xmlnode querynode, char *from)
g_string_free(str, TRUE);
}
-
-static GList *jabber_actions()
-{
- GList *m = NULL;
-
- m = g_list_append(m, _("Set User Info"));
- /*
- m = g_list_append(m, _("Set Dir Info"));
- m = g_list_append(m, _("Change Password"));
- */
-
- return m;
-}
-
-
void jabber_init()
{
struct prpl *ret = g_new0(struct prpl, 1);
- /* the NULL's aren't required but they're nice to have */
ret->name = "jabber";
ret->away_states = jabber_away_states;
- ret->actions = jabber_actions;
ret->login = jabber_login;
ret->close = jabber_close;
ret->send_im = jabber_send_im;
@@ -2370,16 +2339,9 @@ void jabber_init()
ret->get_info = jabber_get_info;
ret->set_away = jabber_set_away;
ret->get_away = jabber_get_away_msg;
- ret->set_idle = jabber_set_idle;
ret->add_buddy = jabber_add_buddy;
ret->remove_buddy = jabber_remove_buddy;
- ret->add_permit = NULL;
- ret->add_deny = NULL;
- ret->rem_permit = NULL;
- ret->rem_deny = NULL;
- ret->set_permit_deny = NULL;
ret->keepalive = jabber_keepalive;
- ret->buddy_free = jabber_buddy_free;
ret->alias_buddy = jabber_roster_update;
ret->group_buddy = jabber_group_change;
ret->cmp_buddynames = g_strcasecmp;
diff --git a/protocols/jabber/xmlparse.c b/protocols/jabber/xmlparse.c
index 492da948..bbef7d59 100644
--- a/protocols/jabber/xmlparse.c
+++ b/protocols/jabber/xmlparse.c
@@ -1460,7 +1460,7 @@ initializeEncoding(XML_Parser parser)
#else
s = protocolEncodingName;
#endif
- if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+ if (ns ? XmlInitEncodingNS(&initEncoding, &encoding, s) : XmlInitEncoding(&initEncoding, &encoding, s))
return XML_ERROR_NONE;
return handleUnknownEncoding(parser, protocolEncodingName);
}
@@ -1474,8 +1474,7 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
const char *version;
int standalone = -1;
if (!(ns
- ? XmlParseXmlDeclNS
- : XmlParseXmlDecl)(isGeneralTextEntity,
+ ? XmlParseXmlDeclNS(isGeneralTextEntity,
encoding,
s,
next,
@@ -1483,7 +1482,16 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
&version,
&encodingName,
&newEncoding,
- &standalone))
+ &standalone)
+ : XmlParseXmlDecl(isGeneralTextEntity,
+ encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &encodingName,
+ &newEncoding,
+ &standalone)))
return XML_ERROR_SYNTAX;
if (!isGeneralTextEntity && standalone == 1)
dtd.standalone = 1;
@@ -1536,11 +1544,14 @@ handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
return XML_ERROR_NO_MEMORY;
}
enc = (ns
- ? XmlInitUnknownEncodingNS
- : XmlInitUnknownEncoding)(unknownEncodingMem,
+ ? XmlInitUnknownEncodingNS(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data)
+ : XmlInitUnknownEncoding(unknownEncodingMem,
info.map,
info.convert,
- info.data);
+ info.data));
if (enc) {
unknownEncodingData = info.data;
unknownEncodingRelease = info.release;
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h
index 9727c537..0cd174f2 100644
--- a/protocols/msn/msn.h
+++ b/protocols/msn/msn.h
@@ -65,8 +65,11 @@ struct msn_data
GSList *msgq;
GSList *switchboards;
- int buddycount;
const struct msn_away_state *away_state;
+
+ int buddycount;
+ int groupcount;
+ char **grouplist;
};
struct msn_switchboard
diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c
index e5f0b2c9..c3bd73cc 100644
--- a/protocols/msn/msn_util.c
+++ b/protocols/msn/msn_util.c
@@ -45,19 +45,8 @@ int msn_write( struct gaim_connection *gc, char *s, int len )
int msn_logged_in( struct gaim_connection *gc )
{
- struct msn_data *md = gc->proto_data;
- char buf[1024];
-
account_online( gc );
- /* account_online() sets an away state if there is any, so only
- execute this code if we're not away. */
- if( md->away_state == msn_away_state_list )
- {
- g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 );
- return( msn_write( gc, buf, strlen( buf ) ) );
- }
-
return( 0 );
}
@@ -141,6 +130,9 @@ static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla )
{
msn_buddy_list_add( bla->gc, "AL", bla->handle, bla->realname );
+ if( find_buddy( bla->gc, bla->handle ) == NULL )
+ show_got_added( bla->gc, bla->handle, NULL );
+
g_free( bla->handle );
g_free( bla->realname );
g_free( bla );
diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c
index 4ced58a0..90d525ef 100644
--- a/protocols/msn/ns.c
+++ b/protocols/msn/ns.c
@@ -256,6 +256,9 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
if( num_parts == 5 )
{
md->buddycount = atoi( cmd[3] );
+ md->groupcount = atoi( cmd[4] );
+ if( md->groupcount > 0 )
+ md->grouplist = g_new0( char *, md->groupcount );
if( !*cmd[3] || md->buddycount == 0 )
msn_logged_in( gc );
@@ -268,18 +271,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
msn_logged_in( gc );
}
}
- else if( strcmp( cmd[0], "GTC" ) == 0 )
- {
- }
- else if( strcmp( cmd[0], "BLP" ) == 0 )
- {
- }
- else if( strcmp( cmd[0], "PRP" ) == 0 )
- {
- }
- else if( strcmp( cmd[0], "LSG" ) == 0 )
- {
- }
else if( strcmp( cmd[0], "LST" ) == 0 )
{
int list;
@@ -296,7 +287,13 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
if( list & 1 ) /* FL */
{
- add_buddy( gc, NULL, cmd[1], cmd[2] );
+ char *group = NULL;
+ int num;
+
+ if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 )
+ group = md->grouplist[num];
+
+ add_buddy( gc, group, cmd[1], cmd[2] );
}
if( list & 2 ) /* AL */
{
@@ -326,11 +323,22 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
}
}
}
- else if( strcmp( cmd[0], "BPR" ) == 0 )
- {
- }
- else if( strcmp( cmd[0], "CHG" ) == 0 )
+ else if( strcmp( cmd[0], "LSG" ) == 0 )
{
+ int num;
+
+ if( num_parts != 4 )
+ {
+ hide_login_progress_error( gc, "Syntax error" );
+ signoff( gc );
+ return( 0 );
+ }
+
+ http_decode( cmd[2] );
+ num = atoi( cmd[1] );
+
+ if( num < md->groupcount )
+ md->grouplist[num] = g_strdup( cmd[2] );
}
else if( strcmp( cmd[0], "CHL" ) == 0 )
{
@@ -356,12 +364,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
return( msn_write( gc, buf, strlen( buf ) ) );
}
- else if( strcmp( cmd[0], "QRY" ) == 0 )
- {
- }
- else if( strcmp( cmd[0], "QNG" ) == 0 )
- {
- }
else if( strcmp( cmd[0], "ILN" ) == 0 )
{
const struct msn_away_state *st;
@@ -478,9 +480,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )
msn_buddy_ask( gc, cmd[4], cmd[5] );
}
}
- else if( strcmp( cmd[0], "REM" ) == 0 )
- {
- }
else if( strcmp( cmd[0], "OUT" ) == 0 )
{
if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 )
diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c
index deaceba1..234be1d6 100644
--- a/protocols/msn/sb.c
+++ b/protocols/msn/sb.c
@@ -201,9 +201,6 @@ void msn_sb_destroy( struct msn_switchboard *sb )
debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" );
- if( sb->key ) g_free( sb->key );
- if( sb->who ) g_free( sb->who );
-
if( sb->msgq )
{
struct msn_message *m;
@@ -221,9 +218,12 @@ void msn_sb_destroy( struct msn_switchboard *sb )
serv_got_crap( gc, "Warning: Closing down MSN switchboard connection with "
"unsent message to %s, you'll have to resend it.",
- m->who ? m->who : "(unknown)" );
+ sb->who ? sb->who : "(unknown)" );
}
+ if( sb->key ) g_free( sb->key );
+ if( sb->who ) g_free( sb->who );
+
if( sb->chat )
{
serv_got_chat_left( gc, sb->chat->id );
diff --git a/protocols/nogaim.c b/protocols/nogaim.c
index 29ae860a..04d48236 100644
--- a/protocols/nogaim.c
+++ b/protocols/nogaim.c
@@ -13,7 +13,7 @@
* from scratch for BitlBee and doesn't contain any code from Gaim anymore
* (except for the function names).
*
- * Copyright 2002-2004 Wilmer van der Gaast <lintux@lintux.cx>
+ * Copyright 2002-2006 Wilmer van der Gaast <wilmer@gaast.net> and others
*/
/*
@@ -36,19 +36,6 @@
#define BITLBEE_CORE
#include "nogaim.h"
#include <ctype.h>
-#include <iconv.h>
-
-static char *proto_away_alias[7][5] =
-{
- { "Away from computer", "Away", "Extended away", NULL },
- { "NA", "N/A", "Not available", NULL },
- { "Busy", "Do not disturb", "DND", "Occupied", NULL },
- { "Be right back", "BRB", NULL },
- { "On the phone", "Phone", "On phone", NULL },
- { "Out to lunch", "Lunch", "Food", NULL },
- { NULL }
-};
-static char *proto_away_alias_find( GList *gcm, char *away );
static int remove_chat_buddy_silent( struct conversation *b, char *handle );
@@ -157,83 +144,6 @@ void nogaim_init()
GSList *get_connections() { return connections; }
-int proto_away( struct gaim_connection *gc, char *away )
-{
- GList *m, *ms;
- char *s;
-
- if( !away ) away = "";
- ms = m = gc->prpl->away_states( gc );
-
- while( m )
- {
- if( *away )
- {
- if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 )
- break;
- }
- else
- {
- if( g_strcasecmp( m->data, "Available" ) == 0 )
- break;
- if( g_strcasecmp( m->data, "Online" ) == 0 )
- break;
- }
- m = m->next;
- }
-
- if( m )
- {
- gc->prpl->set_away( gc, m->data, *away ? away : NULL );
- }
- else
- {
- s = proto_away_alias_find( ms, away );
- if( s )
- {
- gc->prpl->set_away( gc, s, away );
- if( set_getint( gc->irc, "debug" ) )
- serv_got_crap( gc, "Setting away state to %s", s );
- }
- else
- gc->prpl->set_away( gc, GAIM_AWAY_CUSTOM, away );
- }
-
- g_list_free( ms );
-
- return( 1 );
-}
-
-static char *proto_away_alias_find( GList *gcm, char *away )
-{
- GList *m;
- int i, j;
-
- for( i = 0; *proto_away_alias[i]; i ++ )
- {
- for( j = 0; proto_away_alias[i][j]; j ++ )
- if( g_strncasecmp( away, proto_away_alias[i][j], strlen( proto_away_alias[i][j] ) ) == 0 )
- break;
-
- if( !proto_away_alias[i][j] ) /* If we reach the end, this row */
- continue; /* is not what we want. Next! */
-
- /* Now find an entry in this row which exists in gcm */
- for( j = 0; proto_away_alias[i][j]; j ++ )
- {
- m = gcm;
- while( m )
- {
- if( g_strcasecmp( proto_away_alias[i][j], m->data ) == 0 )
- return( proto_away_alias[i][j] );
- m = m->next;
- }
- }
- }
-
- return( NULL );
-}
-
/* multi.c */
struct gaim_connection *new_gaim_conn( struct aim_user *user )
@@ -304,36 +214,29 @@ void hide_login_progress_error( struct gaim_connection *gc, char *msg )
void serv_got_crap( struct gaim_connection *gc, char *format, ... )
{
va_list params;
- char text[1024], buf[1024], acc_id[33];
- char *msg;
+ char *text;
account_t *a;
va_start( params, format );
- g_vsnprintf( text, sizeof( text ), format, params );
+ text = g_strdup_vprintf( format, params );
va_end( params );
- if( g_strncasecmp( set_getstr( gc->irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( "UTF8", set_getstr( gc->irc, "charset" ), text, buf, 0, 1024 ) != -1 )
- msg = buf;
- else
- msg = text;
-
if( ( g_strcasecmp( set_getstr( gc->irc, "strip_html" ), "always" ) == 0 ) ||
( ( gc->flags & OPT_CONN_HTML ) && set_getint( gc->irc, "strip_html" ) ) )
- strip_html( msg );
+ strip_html( text );
/* Try to find a different connection on the same protocol. */
for( a = gc->irc->accounts; a; a = a->next )
if( a->prpl == gc->prpl && a->gc != gc )
break;
- /* If we found one, add the screenname to the acc_id. */
+ /* If we found one, include the screenname in the message. */
if( a )
- g_snprintf( acc_id, 32, "%s(%s)", gc->prpl->name, gc->username );
+ irc_usermsg( gc->irc, "%s(%s) - %s", gc->prpl->name, gc->username, text );
else
- g_snprintf( acc_id, 32, "%s", gc->prpl->name );
+ irc_usermsg( gc->irc, "%s - %s", gc->prpl->name, text );
- irc_usermsg( gc->irc, "%s - %s", acc_id, msg );
+ g_free( text );
}
static gboolean send_keepalive( gpointer d )
@@ -351,7 +254,7 @@ void account_online( struct gaim_connection *gc )
user_t *u;
/* MSN servers sometimes redirect you to a different server and do
- the whole login sequence again, so subsequent calls to this
+ the whole login sequence again, so these "late" calls to this
function should be handled correctly. (IOW, ignored) */
if( gc->flags & OPT_LOGGED_IN )
return;
@@ -363,18 +266,9 @@ void account_online( struct gaim_connection *gc )
gc->keepalive = g_timeout_add( 60000, send_keepalive, gc );
gc->flags |= OPT_LOGGED_IN;
- if( u && u->away ) proto_away( gc, u->away );
-
- if( !strcmp(gc->prpl->name, "icq") )
- {
- for( u = gc->irc->users; u; u = u->next )
- if( u->gc == gc )
- break;
-
- if( u == NULL )
- serv_got_crap( gc, "\x02""***\x02"" BitlBee now supports ICQ server-side contact lists. "
- "See \x02""help import_buddies\x02"" for more information." );
- }
+ /* Also necessary when we're not away, at least for some of the
+ protocols. */
+ bim_set_away( gc, u->away );
}
gboolean auto_reconnect( gpointer data )
@@ -393,12 +287,6 @@ void cancel_auto_reconnect( account_t *a )
a->reconnect = 0;
}
-void account_offline( struct gaim_connection *gc )
-{
- gc->wants_to_die = TRUE;
- signoff( gc );
-}
-
void signoff( struct gaim_connection *gc )
{
irc_t *irc = gc->irc;
@@ -469,16 +357,6 @@ void do_ask_dialog( struct gaim_connection *gc, char *msg, void *data, void *doi
/* list.c */
-int bud_list_cache_exists( struct gaim_connection *gc )
-{
- return( 0 );
-}
-
-void do_import( struct gaim_connection *gc, void *null )
-{
- return;
-}
-
void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *realname )
{
user_t *u;
@@ -514,7 +392,14 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea
}
else if( gc->user->proto_opt[0] && *gc->user->proto_opt[0] )
{
- u->host = g_strdup( gc->user->proto_opt[0] );
+ char *colon;
+
+ if( ( colon = strchr( gc->user->proto_opt[0], ':' ) ) )
+ u->host = g_strndup( gc->user->proto_opt[0],
+ colon - gc->user->proto_opt[0] );
+ else
+ u->host = g_strdup( gc->user->proto_opt[0] );
+
u->user = g_strdup( handle );
/* s/ /_/ ... important for AOL screennames */
@@ -530,6 +415,7 @@ void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *rea
u->gc = gc;
u->handle = g_strdup( handle );
+ if( group ) u->group = g_strdup( group );
u->send_handler = buddy_send_handler;
u->last_typing_notice = 0;
}
@@ -553,11 +439,6 @@ struct buddy *find_buddy( struct gaim_connection *gc, char *handle )
return( b );
}
-void do_export( struct gaim_connection *gc )
-{
- return;
-}
-
void signoff_blocked( struct gaim_connection *gc )
{
return; /* Make all blocked users look invisible (TODO?) */
@@ -567,22 +448,14 @@ void signoff_blocked( struct gaim_connection *gc )
void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname )
{
user_t *u = user_findhandle( gc, handle );
- char *name, buf[1024];
if( !u ) return;
- /* Convert all UTF-8 */
- if( g_strncasecmp( set_getstr( gc->irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( "UTF-8", set_getstr( gc->irc, "charset" ), realname, buf, 0, sizeof( buf ) ) != -1 )
- name = buf;
- else
- name = realname;
-
- if( g_strcasecmp( u->realname, name ) != 0 )
+ if( g_strcasecmp( u->realname, realname ) != 0 )
{
if( u->realname != u->nick ) g_free( u->realname );
- u->realname = g_strdup( name );
+ u->realname = g_strdup( realname );
if( ( gc->flags & OPT_LOGGED_IN ) && set_getint( gc->irc, "display_namechanges" ) )
serv_got_crap( gc, "User `%s' changed name to `%s'", u->nick, u->realname );
@@ -592,9 +465,40 @@ void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname
/* prpl.c */
-void show_got_added( struct gaim_connection *gc, char *id, char *handle, const char *realname, const char *msg )
+struct show_got_added_data
+{
+ struct gaim_connection *gc;
+ char *handle;
+};
+
+void show_got_added_no( gpointer w, struct show_got_added_data *data )
+{
+ g_free( data->handle );
+ g_free( data );
+}
+
+void show_got_added_yes( gpointer w, struct show_got_added_data *data )
{
- return;
+ data->gc->prpl->add_buddy( data->gc, data->handle );
+ add_buddy( data->gc, NULL, data->handle, data->handle );
+
+ return show_got_added_no( w, data );
+}
+
+void show_got_added( struct gaim_connection *gc, char *handle, const char *realname )
+{
+ struct show_got_added_data *data = g_new0( struct show_got_added_data, 1 );
+ char *s;
+
+ /* TODO: Make a setting for this! */
+ if( user_findhandle( gc, handle ) != NULL )
+ return;
+
+ s = g_strdup_printf( "The user %s is not in your buddy list yet. Do you want to add him/her now?", handle );
+
+ data->gc = gc;
+ data->handle = g_strdup( handle );
+ query_add( gc->irc, gc, s, show_got_added_yes, show_got_added_no, data );
}
@@ -624,7 +528,8 @@ void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, in
return;
}
- return;
+ /* Why did we have this here....
+ return; */
}
oa = u->away != NULL;
@@ -688,7 +593,6 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f
{
irc_t *irc = gc->irc;
user_t *u;
- char buf[8192];
u = user_findhandle( gc, handle );
@@ -730,10 +634,6 @@ void serv_got_im( struct gaim_connection *gc, char *handle, char *msg, guint32 f
( ( gc->flags & OPT_CONN_HTML ) && set_getint( gc->irc, "strip_html" ) ) )
strip_html( msg );
- if( g_strncasecmp( set_getstr( irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( "UTF-8", set_getstr( irc, "charset" ), msg, buf, 0, 8192 ) != -1 )
- msg = buf;
-
while( strlen( msg ) > 425 )
{
char tmp, *nl;
@@ -830,7 +730,6 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe
{
struct conversation *c;
user_t *u;
- char buf[8192];
/* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
if( g_strcasecmp( who, gc->user->username ) == 0 )
@@ -843,10 +742,6 @@ void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whispe
( ( gc->flags & OPT_CONN_HTML ) && set_getint( gc->irc, "strip_html" ) ) )
strip_html( msg );
- if( g_strncasecmp( set_getstr( gc->irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( "UTF-8", set_getstr( gc->irc, "charset" ), msg, buf, 0, 8192 ) != -1 )
- msg = buf;
-
if( c && u )
irc_privmsg( gc->irc, u, "PRIVMSG", c->channel, "", msg );
else
@@ -883,11 +778,6 @@ struct conversation *serv_got_joined_chat( struct gaim_connection *gc, int id, c
return( c );
}
-void serv_finish_login( struct gaim_connection *gc )
-{
- return;
-}
-
/* buddy_chat.c */
@@ -972,20 +862,6 @@ static int remove_chat_buddy_silent( struct conversation *b, char *handle )
}
-/* prefs.c */
-
-/* Necessary? */
-void build_block_list()
-{
- return;
-}
-
-void build_allow_list()
-{
- return;
-}
-
-
/* Misc. BitlBee stuff which shouldn't really be here */
struct conversation *conv_findchannel( char *channel )
@@ -1064,89 +940,179 @@ char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value )
return( set_eval_bool( irc, set, value ) );
}
-int serv_send_im( irc_t *irc, user_t *u, char *msg, int flags )
+
+
+
+/* The plan is to not allow straight calls to prpl functions anymore, but do
+ them all from some wrappers. We'll start to define some down here: */
+
+int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flags )
{
- char buf[8192];
+ char *buf = NULL;
+ int st;
- if( g_strncasecmp( set_getstr( irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( set_getstr( irc, "charset" ), "UTF-8", msg, buf, 0, 8192 ) != -1 )
- msg = buf;
-
- if( ( u->gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
+ if( ( gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
{
- char *html;
-
- html = escape_html( msg );
- strncpy( buf, html, 8192 );
- g_free( html );
-
+ buf = escape_html( msg );
msg = buf;
}
- return( ((struct gaim_connection *)u->gc)->prpl->send_im( u->gc, u->handle, msg, strlen( msg ), flags ) );
+ st = gc->prpl->send_im( gc, handle, msg, strlen( msg ), flags );
+ g_free( buf );
+
+ return st;
}
-int serv_send_chat( irc_t *irc, struct gaim_connection *gc, int id, char *msg )
+int bim_chat_msg( struct gaim_connection *gc, int id, char *msg )
{
- char buf[8192];
+ char *buf = NULL;
+ int st;
- if( g_strncasecmp( set_getstr( irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( set_getstr( irc, "charset" ), "UTF-8", msg, buf, 0, 8192 ) != -1 )
+ if( ( gc->flags & OPT_CONN_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
+ {
+ buf = escape_html( msg );
msg = buf;
-
- if( gc->flags & OPT_CONN_HTML) {
- char * html = escape_html(msg);
- strncpy(buf, html, 8192);
- g_free(html);
}
- return( gc->prpl->chat_send( gc, id, msg ) );
+ st = gc->prpl->chat_send( gc, id, msg );
+ g_free( buf );
+
+ return st;
}
-/* Convert from one charset to another.
-
- from_cs, to_cs: Source and destination charsets
- src, dst: Source and destination strings
- size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though.
- maxbuf: Maximum number of bytes to write to dst
-
- Returns the number of bytes written to maxbuf or -1 on an error.
-*/
-signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf )
+static char *bim_away_alias_find( GList *gcm, char *away );
+
+int bim_set_away( struct gaim_connection *gc, char *away )
{
- iconv_t cd;
- size_t res;
- size_t inbytesleft, outbytesleft;
- char *inbuf = src;
- char *outbuf = dst;
-
- cd = iconv_open( to_cs, from_cs );
- if( cd == (iconv_t) -1 )
- return( -1 );
-
- inbytesleft = size ? size : strlen( src );
- outbytesleft = maxbuf - 1;
- res = iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
- *outbuf = '\0';
- iconv_close( cd );
-
- if( res == (size_t) -1 )
- return( -1 );
+ GList *m, *ms;
+ char *s;
+
+ if( !away ) away = "";
+ ms = m = gc->prpl->away_states( gc );
+
+ while( m )
+ {
+ if( *away )
+ {
+ if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 )
+ break;
+ }
+ else
+ {
+ if( g_strcasecmp( m->data, "Available" ) == 0 )
+ break;
+ if( g_strcasecmp( m->data, "Online" ) == 0 )
+ break;
+ }
+ m = m->next;
+ }
+
+ if( m )
+ {
+ gc->prpl->set_away( gc, m->data, *away ? away : NULL );
+ }
else
- return( outbuf - dst );
+ {
+ s = bim_away_alias_find( ms, away );
+ if( s )
+ {
+ gc->prpl->set_away( gc, s, away );
+ if( set_getint( gc->irc, "debug" ) )
+ serv_got_crap( gc, "Setting away state to %s", s );
+ }
+ else
+ gc->prpl->set_away( gc, GAIM_AWAY_CUSTOM, away );
+ }
+
+ g_list_free( ms );
+
+ return( 1 );
}
-char *set_eval_charset( irc_t *irc, set_t *set, char *value )
+static char *bim_away_alias_list[8][5] =
{
- iconv_t cd;
+ { "Away from computer", "Away", "Extended away", NULL },
+ { "NA", "N/A", "Not available", NULL },
+ { "Busy", "Do not disturb", "DND", "Occupied", NULL },
+ { "Be right back", "BRB", NULL },
+ { "On the phone", "Phone", "On phone", NULL },
+ { "Out to lunch", "Lunch", "Food", NULL },
+ { "Invisible", "Hidden" },
+ { NULL }
+};
- if ( g_strncasecmp( value, "none", 4 ) == 0 )
- return( value );
+static char *bim_away_alias_find( GList *gcm, char *away )
+{
+ GList *m;
+ int i, j;
+
+ for( i = 0; *bim_away_alias_list[i]; i ++ )
+ {
+ for( j = 0; bim_away_alias_list[i][j]; j ++ )
+ if( g_strncasecmp( away, bim_away_alias_list[i][j], strlen( bim_away_alias_list[i][j] ) ) == 0 )
+ break;
+
+ if( !bim_away_alias_list[i][j] ) /* If we reach the end, this row */
+ continue; /* is not what we want. Next! */
+
+ /* Now find an entry in this row which exists in gcm */
+ for( j = 0; bim_away_alias_list[i][j]; j ++ )
+ {
+ m = gcm;
+ while( m )
+ {
+ if( g_strcasecmp( bim_away_alias_list[i][j], m->data ) == 0 )
+ return( bim_away_alias_list[i][j] );
+ m = m->next;
+ }
+ }
+ }
+
+ return( NULL );
+}
- cd = iconv_open( "UTF-8", value );
- if( cd == (iconv_t) -1 )
- return( NULL );
+void bim_add_allow( struct gaim_connection *gc, char *handle )
+{
+ if( g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) == NULL )
+ {
+ gc->permit = g_slist_prepend( gc->permit, g_strdup( handle ) );
+ }
+
+ gc->prpl->add_permit( gc, handle );
+}
+
+void bim_rem_allow( struct gaim_connection *gc, char *handle )
+{
+ GSList *l;
+
+ if( ( l = g_slist_find_custom( gc->permit, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) ) )
+ {
+ g_free( l->data );
+ gc->permit = g_slist_delete_link( gc->permit, l );
+ }
+
+ gc->prpl->rem_permit( gc, handle );
+}
- iconv_close( cd );
- return( value );
+void bim_add_block( struct gaim_connection *gc, char *handle )
+{
+ if( g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) == NULL )
+ {
+ gc->deny = g_slist_prepend( gc->deny, g_strdup( handle ) );
+ }
+
+ gc->prpl->add_deny( gc, handle );
+}
+
+void bim_rem_block( struct gaim_connection *gc, char *handle )
+{
+ GSList *l;
+
+ if( ( l = g_slist_find_custom( gc->deny, handle, (GCompareFunc) gc->prpl->cmp_buddynames ) ) )
+ {
+ g_free( l->data );
+ gc->deny = g_slist_delete_link( gc->deny, l );
+ }
+
+ gc->prpl->rem_deny( gc, handle );
}
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index afc39a80..3721361c 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -14,7 +14,7 @@
*
* Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
* (and possibly other members of the Gaim team)
- * Copyright 2002-2004 Wilmer van der Gaast <lintux@lintux.cx>
+ * Copyright 2002-2004 Wilmer van der Gaast <wilmer@gaast.net>
*/
/*
@@ -51,31 +51,24 @@
#define SELF_ALIAS_LEN 400
#define BUDDY_ALIAS_MAXLEN 388 /* because MSN names can be 387 characters */
-#define PERMIT_ALL 1
-#define PERMIT_NONE 2
-#define PERMIT_SOME 3
-#define DENY_SOME 4
-
#define WEBSITE "http://www.bitlee.org/"
#define IM_FLAG_AWAY 0x0020
#define OPT_CONN_HTML 0x00000001
#define OPT_LOGGED_IN 0x00010000
#define GAIM_AWAY_CUSTOM "Custom"
-#define GAIM_LOGO 0
-#define GAIM_ERROR 1
-#define GAIM_WARNING 2
-#define GAIM_INFO 3
-
/* ok. now the fun begins. first we create a connection structure */
-struct gaim_connection {
- /* we need to do either oscar or TOC */
- /* we make this as an int in case if we want to add more protocols later */
+struct gaim_connection
+{
struct prpl *prpl;
guint32 flags;
+ /* each connection then can have its own protocol-specific data */
+ void *proto_data;
+
/* all connections need an input watcher */
int inpa;
+ guint keepalive;
/* buddy list stuff. there is still a global groups for the buddy list, but
* we need to maintain our own set of buddies, and our own permit/deny lists */
@@ -83,33 +76,19 @@ struct gaim_connection {
GSList *deny;
int permdeny;
- /* all connections need a list of chats, even if they don't have chat */
- GSList *buddy_chats;
-
- /* each connection then can have its own protocol-specific data */
- void *proto_data;
-
struct aim_user *user;
char username[64];
char displayname[128];
char password[32];
- guint keepalive;
- /* stuff needed for per-connection idle times */
- guint idle_timer;
- time_t login_time;
- time_t lastsent;
- int is_idle;
char *away;
- int is_auto_away;
int evil;
gboolean wants_to_die; /* defaults to FALSE */
/* BitlBee */
irc_t *irc;
- int lstitems; /* added for msnP8 */
struct conversation *conversations;
};
@@ -182,66 +161,41 @@ struct prpl {
int options;
const char *name;
- /* for ICQ and Yahoo, who have off/on per-conversation options */
- /* char *checkbox; this should be per-connection */
-
- GList *(* away_states)(struct gaim_connection *gc);
- GList *(* actions)();
- void (* do_action)(struct gaim_connection *, char *);
- /* user_opts returns a GList* of g_malloc'd struct proto_user_opts */
- GList *(* user_opts)();
- GList *(* chat_info)(struct gaim_connection *);
-
- /* all the server-related functions */
-
- /* a lot of these (like get_dir) are protocol-dependent and should be removed. ones like
- * set_dir (which is also protocol-dependent) can stay though because there's a dialog
- * (i.e. the prpl says you can set your dir info, the ui shows a dialog and needs to call
- * set_dir in order to set it) */
-
void (* login) (struct aim_user *);
+ void (* keepalive) (struct gaim_connection *);
void (* close) (struct gaim_connection *);
+
int (* send_im) (struct gaim_connection *, char *who, char *message, int len, int away);
- int (* send_typing) (struct gaim_connection *, char *who, int typing);
- void (* set_info) (struct gaim_connection *, char *info);
- void (* get_info) (struct gaim_connection *, char *who);
void (* set_away) (struct gaim_connection *, char *state, char *message);
void (* get_away) (struct gaim_connection *, char *who);
- void (* set_idle) (struct gaim_connection *, int idletime);
+ int (* send_typing) (struct gaim_connection *, char *who, int typing);
+
void (* add_buddy) (struct gaim_connection *, char *name);
+ void (* group_buddy) (struct gaim_connection *, char *who, char *old_group, char *new_group);
void (* remove_buddy) (struct gaim_connection *, char *name, char *group);
void (* add_permit) (struct gaim_connection *, char *name);
void (* add_deny) (struct gaim_connection *, char *name);
void (* rem_permit) (struct gaim_connection *, char *name);
void (* rem_deny) (struct gaim_connection *, char *name);
void (* set_permit_deny)(struct gaim_connection *);
+
+ void (* set_info) (struct gaim_connection *, char *info);
+ void (* get_info) (struct gaim_connection *, char *who);
+ void (* alias_buddy) (struct gaim_connection *, char *who); /* save/store buddy's alias on server list/roster */
+
+ /* Group chat stuff. */
void (* join_chat) (struct gaim_connection *, GList *data);
void (* chat_invite) (struct gaim_connection *, int id, char *who, char *message);
void (* chat_leave) (struct gaim_connection *, int id);
- void (* chat_whisper) (struct gaim_connection *, int id, char *who, char *message);
int (* chat_send) (struct gaim_connection *, int id, char *message);
int (* chat_open) (struct gaim_connection *, char *who);
- void (* keepalive) (struct gaim_connection *);
-
- /* get "chat buddy" info and away message */
- void (* get_cb_info) (struct gaim_connection *, int, char *who);
- void (* get_cb_away) (struct gaim_connection *, int, char *who);
-
- /* save/store buddy's alias on server list/roster */
- void (* alias_buddy) (struct gaim_connection *, char *who);
-
- /* change a buddy's group on a server list/roster */
- void (* group_buddy) (struct gaim_connection *, char *who, char *old_group, char *new_group);
-
- /* file transfers */
- struct ft_send_req *(* req_send_file) (struct gaim_connection *, const char *file);
- void (* send_file_part) (struct gaim_connection *, struct ft*, void *data, size_t length);
- void (* accept_recv_file) (struct gaim_connection *, struct ft*, ft_recv_handler);
-
- void (* buddy_free) (struct buddy *);
-
+
+ /* DIE! */
char *(* get_status_string) (struct gaim_connection *gc, int stat);
-
+
+ GList *(* away_states)(struct gaim_connection *gc);
+
+ /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* */
int (* cmp_buddynames) (const char *who1, const char *who2);
};
@@ -258,14 +212,16 @@ G_MODULE_EXPORT struct prpl *find_protocol(const char *name);
G_MODULE_EXPORT void register_protocol(struct prpl *);
/* nogaim.c */
-int serv_send_im(irc_t *irc, user_t *u, char *msg, int flags);
-int serv_send_chat(irc_t *irc, struct gaim_connection *gc, int id, char *msg );
+int bim_set_away( struct gaim_connection *gc, char *away );
+int bim_buddy_msg( struct gaim_connection *gc, char *handle, char *msg, int flags );
+int bim_chat_msg( struct gaim_connection *gc, int id, char *msg );
-G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf );
-char *set_eval_charset( irc_t *irc, set_t *set, char *value );
+void bim_add_allow( struct gaim_connection *gc, char *handle );
+void bim_rem_allow( struct gaim_connection *gc, char *handle );
+void bim_add_block( struct gaim_connection *gc, char *handle );
+void bim_rem_block( struct gaim_connection *gc, char *handle );
void nogaim_init();
-int proto_away( struct gaim_connection *gc, char *away );
char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value );
gboolean auto_reconnect( gpointer data );
@@ -277,9 +233,8 @@ G_MODULE_EXPORT void destroy_gaim_conn( struct gaim_connection *gc );
G_MODULE_EXPORT void set_login_progress( struct gaim_connection *gc, int step, char *msg );
G_MODULE_EXPORT void hide_login_progress( struct gaim_connection *gc, char *msg );
G_MODULE_EXPORT void hide_login_progress_error( struct gaim_connection *gc, char *msg );
-G_MODULE_EXPORT void serv_got_crap( struct gaim_connection *gc, char *format, ... );
+G_MODULE_EXPORT void serv_got_crap( struct gaim_connection *gc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
G_MODULE_EXPORT void account_online( struct gaim_connection *gc );
-G_MODULE_EXPORT void account_offline( struct gaim_connection *gc );
G_MODULE_EXPORT void signoff( struct gaim_connection *gc );
/* dialogs.c */
@@ -287,11 +242,8 @@ G_MODULE_EXPORT void do_error_dialog( struct gaim_connection *gc, char *msg, cha
G_MODULE_EXPORT void do_ask_dialog( struct gaim_connection *gc, char *msg, void *data, void *doit, void *dont );
/* list.c */
-G_MODULE_EXPORT int bud_list_cache_exists( struct gaim_connection *gc );
-G_MODULE_EXPORT void do_import( struct gaim_connection *gc, void *null );
G_MODULE_EXPORT void add_buddy( struct gaim_connection *gc, char *group, char *handle, char *realname );
G_MODULE_EXPORT struct buddy *find_buddy( struct gaim_connection *gc, char *handle );
-G_MODULE_EXPORT void do_export( struct gaim_connection *gc );
G_MODULE_EXPORT void signoff_blocked( struct gaim_connection *gc );
G_MODULE_EXPORT void serv_buddy_rename( struct gaim_connection *gc, char *handle, char *realname );
@@ -301,7 +253,7 @@ G_MODULE_EXPORT void add_chat_buddy( struct conversation *b, char *handle );
G_MODULE_EXPORT void remove_chat_buddy( struct conversation *b, char *handle, char *reason );
/* prpl.c */
-G_MODULE_EXPORT void show_got_added( struct gaim_connection *gc, char *id, char *handle, const char *realname, const char *msg );
+G_MODULE_EXPORT void show_got_added( struct gaim_connection *gc, char *handle, const char *realname );
/* server.c */
G_MODULE_EXPORT void serv_got_update( struct gaim_connection *gc, char *handle, int loggedin, int evil, time_t signon, time_t idle, int type, guint caps );
@@ -312,23 +264,6 @@ G_MODULE_EXPORT struct conversation *serv_got_joined_chat( struct gaim_connectio
G_MODULE_EXPORT void serv_got_chat_in( struct gaim_connection *gc, int id, char *who, int whisper, char *msg, time_t mtime );
G_MODULE_EXPORT void serv_got_chat_left( struct gaim_connection *gc, int id );
-/* util.c */
-G_MODULE_EXPORT void strip_linefeed( gchar *text );
-G_MODULE_EXPORT char *add_cr( char *text );
-G_MODULE_EXPORT char *tobase64( const char *text );
-G_MODULE_EXPORT char *normalize( const char *s );
-G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec );
-G_MODULE_EXPORT void strip_html( char *msg );
-G_MODULE_EXPORT char *escape_html( const char *html );
-G_MODULE_EXPORT void info_string_append(GString *str, char *newline, char *name, char *value);
-G_MODULE_EXPORT char *ipv6_wrap( char *src );
-G_MODULE_EXPORT char *ipv6_unwrap( char *src );
-
-/* prefs.c */
-G_MODULE_EXPORT void build_block_list();
-G_MODULE_EXPORT void build_allow_list();
-
struct conversation *conv_findchannel( char *channel );
-
#endif
diff --git a/protocols/oscar/aim.h b/protocols/oscar/aim.h
index 24cd7730..93887103 100644
--- a/protocols/oscar/aim.h
+++ b/protocols/oscar/aim.h
@@ -727,8 +727,11 @@ struct aim_chat_exchangeinfo {
char *lang2;
};
-#define AIM_CHATFLAGS_NOREFLECT 0x0001
-#define AIM_CHATFLAGS_AWAY 0x0002
+#define AIM_CHATFLAGS_NOREFLECT 0x0001
+#define AIM_CHATFLAGS_AWAY 0x0002
+#define AIM_CHATFLAGS_UNICODE 0x0004
+#define AIM_CHATFLAGS_ISO_8859_1 0x0008
+
int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const char *msg, int msglen);
int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance);
int aim_chat_attachname(aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance);
diff --git a/protocols/oscar/chat.c b/protocols/oscar/chat.c
index 033c2577..8843b499 100644
--- a/protocols/oscar/chat.c
+++ b/protocols/oscar/chat.c
@@ -158,7 +158,19 @@ int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const
*/
if (flags & AIM_CHATFLAGS_AWAY)
aim_addtlvtochain_noval(&otl, 0x0007);
-
+
+ /* [WvG] This wasn't there originally, but we really should send
+ the right charset flags, as we also do with normal
+ messages. Hope this will work. :-) */
+ if (flags & AIM_CHATFLAGS_UNICODE)
+ aimbs_put16(&fr->data, 0x0002);
+ else if (flags & AIM_CHATFLAGS_ISO_8859_1)
+ aimbs_put16(&fr->data, 0x0003);
+ else
+ aimbs_put16(&fr->data, 0x0000);
+
+ aimbs_put16(&fr->data, 0x0000);
+
/*
* SubTLV: Type 1: Message
*/
diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c
index 4e552bce..5174f95c 100644
--- a/protocols/oscar/oscar.c
+++ b/protocols/oscar/oscar.c
@@ -1,6 +1,8 @@
/*
* gaim
*
+ * Some code copyright (C) 2002-2006, Jelmer Vernooij <jelmer@samba.org>
+ * and the BitlBee team.
* Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
* libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx>
*
@@ -355,7 +357,9 @@ static void oscar_login(struct aim_user *user) {
if (isdigit(*user->username)) {
odata->icq = TRUE;
- /* this is odd but it's necessary for a proper do_import and do_export */
+ /* This is odd but it's necessary for a proper do_import and do_export.
+ We don't do those anymore, but let's stick with it, just in case
+ it accidentally fixes something else too... */
gc->password[8] = 0;
} else {
gc->flags |= OPT_CONN_HTML;
@@ -380,7 +384,7 @@ static void oscar_login(struct aim_user *user) {
if (g_strcasecmp(user->proto_opt[USEROPT_AUTH], "login.icq.com") != 0 &&
g_strcasecmp(user->proto_opt[USEROPT_AUTH], "login.oscar.aol.com") != 0) {
- serv_got_crap(gc, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.");
+ serv_got_crap(gc, "Warning: Unknown OSCAR server: `%s'. Please review your configuration if the connection fails.",user->proto_opt[USEROPT_AUTH]);
}
g_snprintf(buf, sizeof(buf), _("Signon: %s"), gc->username);
@@ -1116,7 +1120,8 @@ static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) {
message = 0;
aim_ssi_auth_reply(od->sess, od->conn, uin, 1, "");
// aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message);
- show_got_added(data->gc, NULL, uin, NULL, NULL);
+ if(find_buddy(data->gc, uin) == NULL)
+ show_got_added(data->gc, uin, NULL);
g_free(uin);
g_free(data);
@@ -1147,7 +1152,7 @@ static void gaim_icq_authask(struct gaim_connection *gc, guint32 uin, char *msg)
if (strlen(msg) > 6)
reason = msg + 6;
- dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason:\n\n%s", uin, reason ? reason : "No reason given.");
+ dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason: %s", uin, reason ? reason : "No reason given.");
data->gc = gc;
data->uin = uin;
do_ask_dialog(gc, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny);
@@ -1736,11 +1741,6 @@ static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) {
odata->rights.maxpermits = (guint)maxpermits;
odata->rights.maxdenies = (guint)maxdenies;
-// serv_finish_login(gc);
-
- if (bud_list_cache_exists(gc))
- do_import(gc, NULL);
-
aim_clientready(sess, fr->conn);
aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV);
@@ -2059,7 +2059,6 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
char *name;
name = g_strdup(normalize(curitem->name));
gc->permit = g_slist_append(gc->permit, name);
- build_allow_list();
tmp++;
}
}
@@ -2073,7 +2072,6 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
char *name;
name = g_strdup(normalize(curitem->name));
gc->deny = g_slist_append(gc->deny, name);
- build_block_list();
tmp++;
}
}
@@ -2095,8 +2093,6 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
} /* End of switch on curitem->type */
} /* End of for loop */
- if (tmp)
- do_export(gc);
aim_ssi_enable(sess, fr->conn);
/* Request offline messages, now that the buddy list is complete. */
@@ -2281,7 +2277,7 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...)
struct tm tm;
tm.tm_mday = (int)info->birthday;
tm.tm_mon = (int)info->birthmonth-1;
- tm.tm_year = (int)info->birthyear-1900;
+ tm.tm_year = (int)info->birthyear%100;
strftime(date, sizeof(date), "%Y-%m-%d", &tm);
info_string_append(str, "\n", _("Birthday"), date);
}
@@ -2505,6 +2501,7 @@ int oscar_chat_send(struct gaim_connection * gc, int id, char *message)
struct chat_connection * ccon;
int ret;
guint8 len = strlen(message);
+ guint16 flags;
char *s;
if(!(ccon = find_oscar_chat(gc, id)))
@@ -2513,15 +2510,19 @@ int oscar_chat_send(struct gaim_connection * gc, int id, char *message)
for (s = message; *s; s++)
if (*s & 128)
break;
-
+
+ flags = AIM_CHATFLAGS_NOREFLECT;
+
/* Message contains high ASCII chars, time for some translation! */
if (*s) {
s = g_malloc(BUF_LONG);
/* Try if we can put it in an ISO8859-1 string first.
If we can't, fall back to UTF16. */
if ((ret = do_iconv("UTF-8", "ISO8859-1", message, s, len, BUF_LONG)) >= 0) {
+ flags |= AIM_CHATFLAGS_ISO_8859_1;
len = ret;
} else if ((ret = do_iconv("UTF-8", "UNICODEBIG", message, s, len, BUF_LONG)) >= 0) {
+ flags |= AIM_CHATFLAGS_UNICODE;
len = ret;
} else {
/* OOF, translation failed... Oh well.. */
@@ -2532,7 +2533,7 @@ int oscar_chat_send(struct gaim_connection * gc, int id, char *message)
s = message;
}
- ret = aim_chat_send_im(od->sess, ccon->conn, AIM_CHATFLAGS_NOREFLECT, s, len);
+ ret = aim_chat_send_im(od->sess, ccon->conn, flags, s, len);
if (s != message) {
g_free(s);
diff --git a/protocols/oscar/oscar_util.c b/protocols/oscar/oscar_util.c
index 1bb27559..0ce06bd9 100644
--- a/protocols/oscar/oscar_util.c
+++ b/protocols/oscar/oscar_util.c
@@ -108,7 +108,7 @@ static int aim_snlen(const char *sn)
return 0;
curPtr = sn;
- while ( (*curPtr) != (char) NULL) {
+ while ( (*curPtr) != (char) '\0') {
if ((*curPtr) != ' ')
i++;
curPtr++;
@@ -139,7 +139,7 @@ int aim_sncmp(const char *sn1, const char *sn2)
curPtr1 = sn1;
curPtr2 = sn2;
- while ( (*curPtr1 != (char) NULL) && (*curPtr2 != (char) NULL) ) {
+ while ( (*curPtr1 != (char) '\0') && (*curPtr2 != (char) '\0') ) {
if ( (*curPtr1 == ' ') || (*curPtr2 == ' ') ) {
if (*curPtr1 == ' ')
curPtr1++;
diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c
index 573e1983..4596974f 100644
--- a/protocols/oscar/service.c
+++ b/protocols/oscar/service.c
@@ -732,7 +732,7 @@ int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status)
guint32 data;
int tlvlen;
- data = AIM_ICQ_STATE_WEBAWARE | AIM_ICQ_STATE_HIDEIP | status; /* yay for error checking ;^) */
+ data = AIM_ICQ_STATE_HIDEIP | status; /* yay for error checking ;^) */
tlvlen = aim_addtlvtochain32(&tl, 0x0006, data);
@@ -880,13 +880,14 @@ int aim_sendmemblock(aim_session_t *sess, aim_conn_t *conn, guint32 offset, guin
aimbs_put32(&fr->data, 0xa46d3b39);
#endif
+/* len can't be 0 here anyway...
} else if ((offset == 0x00001000) && (len == 0x00000000)) {
aimbs_put32(&fr->data, 0xd41d8cd9);
aimbs_put32(&fr->data, 0x8f00b204);
aimbs_put32(&fr->data, 0xe9800998);
aimbs_put32(&fr->data, 0xecf8427e);
-
+*/
} else
do_error_dialog(sess->aux_data, "WARNING: unknown hash request", "Gaim");
diff --git a/protocols/ssl_nss.c b/protocols/ssl_nss.c
index dfd32622..00d32834 100644
--- a/protocols/ssl_nss.c
+++ b/protocols/ssl_nss.c
@@ -121,10 +121,10 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
if( source == -1 )
goto ssl_connected_failure;
-
-
-
+ /* Until we find out how to handle non-blocking I/O with NSS... */
+ sock_make_blocking( conn->fd );
+
conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source));
SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE);
SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
@@ -180,3 +180,9 @@ int ssl_getfd( void *conn )
{
return( ((struct scd*)conn)->fd );
}
+
+GaimInputCondition ssl_getdirection( void *conn )
+{
+ /* Just in case someone calls us, let's return the most likely case: */
+ return GAIM_INPUT_READ;
+}
diff --git a/protocols/ssl_openssl.c b/protocols/ssl_openssl.c
index e62f95b9..b79088cc 100644
--- a/protocols/ssl_openssl.c
+++ b/protocols/ssl_openssl.c
@@ -4,7 +4,7 @@
* Copyright 2002-2004 Wilmer van der Gaast and others *
\********************************************************************/
-/* SSL module - OpenTLS version */
+/* SSL module - OpenSSL version */
/*
This program is free software; you can redistribute it and/or modify
@@ -40,11 +40,13 @@ static gboolean initialized = FALSE;
struct scd
{
- SslInputFunction func;
+ ssl_input_function func;
gpointer data;
int fd;
gboolean established;
+ int inpa;
+ int lasterr; /* Necessary for SSL_get_error */
SSL *ssl;
SSL_CTX *ssl_ctx;
};
@@ -53,7 +55,7 @@ static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
-void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
+void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
SSL_METHOD *meth;
@@ -92,19 +94,45 @@ void *ssl_connect( char *host, int port, SslInputFunction func, gpointer data )
return( conn );
}
+static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond );
+
static void ssl_connected( gpointer data, gint source, GaimInputCondition cond )
{
struct scd *conn = data;
if( source == -1 )
- goto ssl_connected_failure;
+ return ssl_handshake( data, -1, cond );
+ /* Make it non-blocking at least during the handshake... */
+ sock_make_nonblocking( conn->fd );
SSL_set_fd( conn->ssl, conn->fd );
- if( SSL_connect( conn->ssl ) < 0 )
- goto ssl_connected_failure;
+ return ssl_handshake( data, source, cond );
+}
+
+static void ssl_handshake( gpointer data, gint source, GaimInputCondition cond )
+{
+ struct scd *conn = data;
+ int st;
+
+ if( conn->inpa != -1 )
+ {
+ gaim_input_remove( conn->inpa );
+ conn->inpa = -1;
+ }
+
+ if( ( st = SSL_connect( conn->ssl ) ) < 0 )
+ {
+ conn->lasterr = SSL_get_error( conn->ssl, st );
+ if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
+ goto ssl_connected_failure;
+
+ conn->inpa = gaim_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data );
+ return;
+ }
conn->established = TRUE;
+ sock_make_blocking( conn->fd ); /* For now... */
conn->func( conn->data, conn, cond );
return;
@@ -126,24 +154,57 @@ ssl_connected_failure:
int ssl_read( void *conn, char *buf, int len )
{
+ int st;
+
if( !((struct scd*)conn)->established )
- return( 0 );
+ {
+ ssl_errno = SSL_NOHANDSHAKE;
+ return -1;
+ }
+
+ st = SSL_read( ((struct scd*)conn)->ssl, buf, len );
- return( SSL_read( ((struct scd*)conn)->ssl, buf, len ) );
+ ssl_errno = SSL_OK;
+ if( st <= 0 )
+ {
+ ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
+ if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
+ ssl_errno = SSL_AGAIN;
+ }
+
+ return st;
}
int ssl_write( void *conn, const char *buf, int len )
{
+ int st;
+
if( !((struct scd*)conn)->established )
- return( 0 );
+ {
+ ssl_errno = SSL_NOHANDSHAKE;
+ return -1;
+ }
+
+ st = SSL_write( ((struct scd*)conn)->ssl, buf, len );
- return( SSL_write( ((struct scd*)conn)->ssl, buf, len ) );
+ ssl_errno = SSL_OK;
+ if( st <= 0 )
+ {
+ ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st );
+ if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE )
+ ssl_errno = SSL_AGAIN;
+ }
+
+ return st;
}
void ssl_disconnect( void *conn_ )
{
struct scd *conn = conn_;
+ if( conn->inpa != -1 )
+ gaim_input_remove( conn->inpa );
+
if( conn->established )
SSL_shutdown( conn->ssl );
@@ -158,3 +219,8 @@ int ssl_getfd( void *conn )
{
return( ((struct scd*)conn)->fd );
}
+
+GaimInputCondition ssl_getdirection( void *conn )
+{
+ return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );
+}
diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c
index 4f257d99..1c3c73d9 100644
--- a/protocols/yahoo/yahoo.c
+++ b/protocols/yahoo/yahoo.c
@@ -226,16 +226,11 @@ static void byahoo_set_away( struct gaim_connection *gc, char *state, char *msg
yd->current_status = YAHOO_STATUS_INVISIBLE;
else if( g_strcasecmp( state, GAIM_AWAY_CUSTOM ) == 0 )
{
- if (gc->is_idle)
- yd->current_status = YAHOO_STATUS_IDLE;
- else
- yd->current_status = YAHOO_STATUS_AVAILABLE;
+ yd->current_status = YAHOO_STATUS_AVAILABLE;
gc->away = NULL;
}
}
- else if( gc->is_idle )
- yd->current_status = YAHOO_STATUS_IDLE;
else
yd->current_status = YAHOO_STATUS_AVAILABLE;
@@ -614,7 +609,8 @@ void ext_yahoo_status_changed( int id, char *who, int stat, char *msg, int away
{
struct gaim_connection *gc = byahoo_get_gc_by_id( id );
- serv_got_update( gc, who, stat != YAHOO_STATUS_OFFLINE, 0, 0, 0,
+ serv_got_update( gc, who, stat != YAHOO_STATUS_OFFLINE, 0, 0,
+ ( stat == YAHOO_STATUS_IDLE ) ? away : 0,
( stat != YAHOO_STATUS_AVAILABLE ) | ( stat << 1 ), 0 );
}
diff --git a/query.c b/query.c
index 670dde36..39821f3a 100644
--- a/query.c
+++ b/query.c
@@ -39,6 +39,17 @@ query_t *query_add( irc_t *irc, struct gaim_connection *gc, char *question, void
q->no = no;
q->data = data;
+ if( strchr( irc->umode, 'b' ) != NULL )
+ {
+ char *s;
+
+ /* At least for the machine-parseable version, get rid of
+ newlines to make "parsing" easier. */
+ for( s = q->question; *s; s ++ )
+ if( *s == '\r' || *s == '\n' )
+ *s = ' ';
+ }
+
if( irc->queries )
{
query_t *l = irc->queries;
@@ -126,16 +137,15 @@ void query_answer( irc_t *irc, query_t *q, int ans )
q = query_default( irc );
disp = 1;
}
- //Using irc_usermsg instead of serv_got_crap because \x02A is a char too, so a SPACE is needed.
if( ans )
{
- q->yes( NULL, q->data );
serv_got_crap( q->gc, "Accepted: %s", q->question );
+ q->yes( NULL, q->data );
}
else
{
- q->no( NULL, q->data );
serv_got_crap( q->gc, "Rejected: %s", q->question );
+ q->no( NULL, q->data );
}
q->data = NULL;
diff --git a/root_commands.c b/root_commands.c
index f69442d3..0e12e9ab 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -56,6 +56,17 @@ void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
cmd[k++] = s;
s --;
}
+ else
+ {
+ break;
+ }
+ }
+ else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
+ {
+ char *cpy;
+
+ for( cpy = s; *cpy; cpy ++ )
+ cpy[0] = cpy[1];
}
else if( *s == q )
{
@@ -244,6 +255,9 @@ static void cmd_account( irc_t *irc, char **cmd )
{
int i = 0;
+ if( strchr( irc->umode, 'b' ) )
+ irc_usermsg( irc, "Account list:" );
+
for( a = irc->accounts; a; a = a->next )
{
char *con;
@@ -346,6 +360,13 @@ static void cmd_account( irc_t *irc, char **cmd )
static void cmd_add( irc_t *irc, char **cmd )
{
account_t *a;
+ int add_for_real = 1;
+
+ if( g_strcasecmp( cmd[1], "-tmp" ) == 0 )
+ {
+ add_for_real = 0;
+ cmd ++; /* So evil... :-D */
+ }
if( !( a = account_get( irc, cmd[1] ) ) )
{
@@ -375,7 +396,12 @@ static void cmd_add( irc_t *irc, char **cmd )
nick_set( irc, cmd[2], a->gc->prpl, cmd[3] );
}
}
- a->gc->prpl->add_buddy( a->gc, cmd[2] );
+
+ /* By making this optional, you can talk to people without having to
+ add them to your *real* (server-side) contact list. */
+ if( add_for_real )
+ a->gc->prpl->add_buddy( a->gc, cmd[2] );
+
add_buddy( a->gc, NULL, cmd[2], cmd[2] );
irc_usermsg( irc, "User `%s' added to your contact list as `%s'", cmd[2], user_findhandle( a->gc, cmd[2] )->nick );
@@ -483,7 +509,27 @@ static void cmd_block( irc_t *irc, char **cmd )
struct gaim_connection *gc;
account_t *a;
- if( !cmd[2] )
+ if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->gc )
+ {
+ char *format;
+ GSList *l;
+
+ if( strchr( irc->umode, 'b' ) != NULL )
+ format = "%s\t%s";
+ else
+ format = "%-32.32s %-16.16s";
+
+ irc_usermsg( irc, format, "Handle", "Nickname" );
+ for( l = a->gc->deny; l; l = l->next )
+ {
+ user_t *u = user_findhandle( a->gc, l->data );
+ irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
+ }
+ irc_usermsg( irc, "End of list." );
+
+ return;
+ }
+ else if( !cmd[2] )
{
user_t *u = user_find( irc, cmd[1] );
if( !u || !u->gc )
@@ -511,9 +557,9 @@ static void cmd_block( irc_t *irc, char **cmd )
}
else
{
- gc->prpl->rem_permit( gc, cmd[2] );
- gc->prpl->add_deny( gc, cmd[2] );
- irc_usermsg( irc, "Buddy `%s' moved from your permit- to your deny-list", cmd[2] );
+ bim_rem_allow( gc, cmd[2] );
+ bim_add_block( gc, cmd[2] );
+ irc_usermsg( irc, "Buddy `%s' moved from your allow- to your block-list", cmd[2] );
}
}
@@ -522,7 +568,27 @@ static void cmd_allow( irc_t *irc, char **cmd )
struct gaim_connection *gc;
account_t *a;
- if( !cmd[2] )
+ if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->gc )
+ {
+ char *format;
+ GSList *l;
+
+ if( strchr( irc->umode, 'b' ) != NULL )
+ format = "%s\t%s";
+ else
+ format = "%-32.32s %-16.16s";
+
+ irc_usermsg( irc, format, "Handle", "Nickname" );
+ for( l = a->gc->deny; l; l = l->next )
+ {
+ user_t *u = user_findhandle( a->gc, l->data );
+ irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
+ }
+ irc_usermsg( irc, "End of list." );
+
+ return;
+ }
+ else if( !cmd[2] )
{
user_t *u = user_find( irc, cmd[1] );
if( !u || !u->gc )
@@ -550,10 +616,10 @@ static void cmd_allow( irc_t *irc, char **cmd )
}
else
{
- gc->prpl->rem_deny( gc, cmd[2] );
- gc->prpl->add_permit( gc, cmd[2] );
+ bim_rem_block( gc, cmd[2] );
+ bim_add_allow( gc, cmd[2] );
- irc_usermsg( irc, "Buddy `%s' moved from your deny- to your permit-list", cmd[2] );
+ irc_usermsg( irc, "Buddy `%s' moved from your block- to your allow-list", cmd[2] );
}
}
@@ -634,7 +700,8 @@ static void cmd_blist( irc_t *irc, char **cmd )
{
int online = 0, away = 0, offline = 0;
user_t *u;
- char s[64];
+ char s[256];
+ char *format;
int n_online = 0, n_away = 0, n_offline = 0;
if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 )
@@ -648,26 +715,41 @@ static void cmd_blist( irc_t *irc, char **cmd )
else
online = away = 1;
- irc_usermsg( irc, "%-16.16s %-40.40s %s", "Nick", "User/Host/Network", "Status" );
+ if( strchr( irc->umode, 'b' ) != NULL )
+ format = "%s\t%s\t%s";
+ else
+ format = "%-16.16s %-40.40s %s";
+
+ irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" );
- if( online == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && !u->away )
+ for( u = irc->users; u; u = u->next ) if( u->gc && u->online && !u->away )
{
- g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name );
- irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Online" );
+ if( online == 1 )
+ {
+ g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name );
+ irc_usermsg( irc, format, u->nick, s, "Online" );
+ }
+
n_online ++;
}
- if( away == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && u->online && u->away )
+ for( u = irc->users; u; u = u->next ) if( u->gc && u->online && u->away )
{
- g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name );
- irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, u->away );
+ if( away == 1 )
+ {
+ g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name );
+ irc_usermsg( irc, format, u->nick, s, u->away );
+ }
n_away ++;
}
- if( offline == 1 ) for( u = irc->users; u; u = u->next ) if( u->gc && !u->online )
+ for( u = irc->users; u; u = u->next ) if( u->gc && !u->online )
{
- g_snprintf( s, 63, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name );
- irc_usermsg( irc, "%-16.16s %-40.40s %s", u->nick, s, "Offline" );
+ if( offline == 1 )
+ {
+ g_snprintf( s, sizeof( s ) - 1, "%s@%s (%s)", u->user, u->host, u->gc->user->prpl->name );
+ irc_usermsg( irc, format, u->nick, s, "Offline" );
+ }
n_offline ++;
}
@@ -696,15 +778,9 @@ static void cmd_nick( irc_t *irc, char **cmd )
}
else
{
- char utf8[1024];
-
irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );
- if( g_strncasecmp( set_getstr( irc, "charset" ), "none", 4 ) != 0 &&
- do_iconv( set_getstr( irc, "charset" ), "UTF-8", cmd[2], utf8, 0, 1024 ) != -1 )
- a->gc->prpl->set_info( a->gc, utf8 );
- else
- a->gc->prpl->set_info( a->gc, cmd[2] );
+ a->gc->prpl->set_info( a->gc, cmd[2] );
}
}
diff --git a/set.c b/set.c
index 4207df81..60912e10 100644
--- a/set.c
+++ b/set.c
@@ -149,7 +149,11 @@ void set_del( irc_t *irc, char *key )
}
if( s )
{
- t->next = s->next;
+ if( t )
+ t->next = s->next;
+ else
+ irc->set = s->next;
+
g_free( s->key );
if( s->value ) g_free( s->value );
if( s->def ) g_free( s->def );
diff --git a/user.c b/user.c
index b795c864..9c987fa5 100644
--- a/user.c
+++ b/user.c
@@ -167,8 +167,8 @@ void user_rename( irc_t *irc, char *oldnick, char *newnick )
if( u->nick == u->realname ) u->realname = NULL;
u->nick = g_strdup( newnick );
if( !u->user ) u->user = u->nick;
- if( !u->host ) u->user = u->host;
- if( !u->realname ) u->user = u->realname;
+ if( !u->host ) u->host = u->nick;
+ if( !u->realname ) u->realname = u->nick;
/* Remove the old reference to this user from the hash and create a
new one with the new nick. This is indeed a bit messy. */
diff --git a/user.h b/user.h
index da657a4d..b8896d92 100644
--- a/user.h
+++ b/user.h
@@ -36,6 +36,7 @@ typedef struct __USER
char online;
char *handle;
+ char *group;
struct gaim_connection *gc;
char *sendbuf;
diff --git a/util.c b/util.c
index db783fe0..43e1c19f 100644
--- a/util.c
+++ b/util.c
@@ -38,6 +38,7 @@
#include <ctype.h>
#include <glib.h>
#include <time.h>
+#include <iconv.h>
void strip_linefeed(gchar *text)
{
@@ -444,3 +445,51 @@ char *ipv6_unwrap( char *src )
return ( src + 7 );
}
#endif
+
+/* Convert from one charset to another.
+
+ from_cs, to_cs: Source and destination charsets
+ src, dst: Source and destination strings
+ size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though.
+ maxbuf: Maximum number of bytes to write to dst
+
+ Returns the number of bytes written to maxbuf or -1 on an error.
+*/
+signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf )
+{
+ iconv_t cd;
+ size_t res;
+ size_t inbytesleft, outbytesleft;
+ char *inbuf = src;
+ char *outbuf = dst;
+
+ cd = iconv_open( to_cs, from_cs );
+ if( cd == (iconv_t) -1 )
+ return( -1 );
+
+ inbytesleft = size ? size : strlen( src );
+ outbytesleft = maxbuf - 1;
+ res = iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
+ *outbuf = '\0';
+ iconv_close( cd );
+
+ if( res == (size_t) -1 )
+ return( -1 );
+ else
+ return( outbuf - dst );
+}
+
+char *set_eval_charset( irc_t *irc, set_t *set, char *value )
+{
+ iconv_t cd;
+
+ if ( g_strncasecmp( value, "none", 4 ) == 0 )
+ return( value );
+
+ cd = iconv_open( "UTF-8", value );
+ if( cd == (iconv_t) -1 )
+ return( NULL );
+
+ iconv_close( cd );
+ return( value );
+}
diff --git a/util.h b/util.h
new file mode 100644
index 00000000..8e13d9dd
--- /dev/null
+++ b/util.h
@@ -0,0 +1,50 @@
+ /********************************************************************\
+ * BitlBee -- An IRC to other IM-networks gateway *
+ * *
+ * Copyright 2002-2004 Wilmer van der Gaast and others *
+ \********************************************************************/
+
+/* Misc. functions */
+
+/*
+ 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 2 of the License, 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 with
+ the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+ if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+G_MODULE_EXPORT void strip_linefeed( gchar *text );
+G_MODULE_EXPORT char *add_cr( char *text );
+G_MODULE_EXPORT char *strip_newlines(char *source);
+G_MODULE_EXPORT char *tobase64( const char *text );
+G_MODULE_EXPORT char *normalize( const char *s );
+G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value );
+
+G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec );
+double gettime( void );
+
+G_MODULE_EXPORT void strip_html( char *msg );
+G_MODULE_EXPORT char *escape_html( const char *html );
+G_MODULE_EXPORT void http_decode( char *s );
+G_MODULE_EXPORT void http_encode( char *s );
+
+G_MODULE_EXPORT char *ipv6_wrap( char *src );
+G_MODULE_EXPORT char *ipv6_unwrap( char *src );
+
+G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf );
+char *set_eval_charset( irc_t *irc, set_t *set, char *value );
+
+#endif
diff --git a/utils/bitlbeed.c b/utils/bitlbeed.c
index b8db348e..82bd0879 100644
--- a/utils/bitlbeed.c
+++ b/utils/bitlbeed.c
@@ -5,7 +5,7 @@
* A tiny daemon to allow you to run The Bee as a non-root user *
* (without access to /etc/inetd.conf or whatever) *
* *
-* Copyright 2002-2004 Wilmer van der Gaast <lintux@debian.org> *
+* Copyright 2002-2004 Wilmer van der Gaast <wilmer@gaast.net> *
* *
* Licensed under the GNU General Public License *
* *