aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debian/bitlbee-common.init (renamed from debian/bitlbee.init)0
-rw-r--r--debian/bitlbee-common.postinst (renamed from debian/bitlbee.postinst)23
-rw-r--r--debian/bitlbee-common.postrm (renamed from debian/bitlbee.postrm)0
-rw-r--r--debian/bitlbee-common.prerm13
-rw-r--r--debian/bitlbee.prerm16
-rw-r--r--debian/changelog2
-rwxr-xr-xdebian/rules37
-rw-r--r--doc/user-guide/commands.xml11
-rw-r--r--doc/user-guide/misc.xml42
-rw-r--r--irc.c7
-rw-r--r--irc_channel.c1
-rw-r--r--irc_send.c2
-rw-r--r--lib/proxy.c118
-rw-r--r--protocols/bee.c1
-rw-r--r--protocols/bee.h2
-rw-r--r--protocols/bee_user.c9
-rw-r--r--protocols/nogaim.h3
-rw-r--r--protocols/oscar/oscar.c4
-rw-r--r--protocols/purple/purple.c50
-rw-r--r--protocols/yahoo/yahoo.c2
-rw-r--r--root_commands.c58
-rw-r--r--set.h9
22 files changed, 299 insertions, 111 deletions
diff --git a/debian/bitlbee.init b/debian/bitlbee-common.init
index be1dcd66..be1dcd66 100644
--- a/debian/bitlbee.init
+++ b/debian/bitlbee-common.init
diff --git a/debian/bitlbee.postinst b/debian/bitlbee-common.postinst
index db541f6c..c965e09c 100644
--- a/debian/bitlbee.postinst
+++ b/debian/bitlbee-common.postinst
@@ -63,11 +63,20 @@ if [ -e /usr/share/bitlbee/help.upgrading ]; then
fi
fi
-if [ -n "$2" -a "$BITLBEE_UPGRADE_DONT_RESTART" != "1" ]; then
- if which invoke-rc.d >/dev/null 2>&1; then
- invoke-rc.d bitlbee restart
+# The official way to check if we're upgrading is to check if $2 is
+# non-empty. However, previous versions of BitlBee didn't have a
+# bitlbee-common package so in that case the var will also be empty.
+# Instead, check if the port is in use (if netstat is available). This
+# works since the debconf code will pick a free port on new installs.
+if [ "$BITLBEE_UPGRADE_DONT_RESTART" != "1" ]; then
+ unset IS_UPGRADE
+ if type netstat > /dev/null 2> /dev/null; then
+ netstat -an | grep -q :$PORT\\b.*LISTEN && IS_UPGRADE=1
else
- /etc/init.d/bitlbee restart
+ [ -n "$2" ] && IS_UPGRADE=1
+ fi
+ if [ -n "$IS_UPGRADE" ]; then
+ invoke-rc.d bitlbee restart
fi
fi
@@ -94,9 +103,5 @@ else
fi
if [ -z "$2" ]; then
- if which invoke-rc.d >/dev/null 2>&1; then
- invoke-rc.d bitlbee start
- else
- /etc/init.d/bitlbee start
- fi
+ invoke-rc.d bitlbee start
fi
diff --git a/debian/bitlbee.postrm b/debian/bitlbee-common.postrm
index 5c3b4b2e..5c3b4b2e 100644
--- a/debian/bitlbee.postrm
+++ b/debian/bitlbee-common.postrm
diff --git a/debian/bitlbee-common.prerm b/debian/bitlbee-common.prerm
new file mode 100644
index 00000000..50a49bee
--- /dev/null
+++ b/debian/bitlbee-common.prerm
@@ -0,0 +1,13 @@
+#!/bin/sh -e
+
+if [ "$1" = "upgrade" ]; then
+ ## To prevent the help function from breaking in currently running
+ ## BitlBee processes. Have to do it like this because dpkg-reconfigure
+ ## looks a lot like an upgrade and we don't want to lose help.txt...
+ if [ -e /usr/share/bitlbee/help.txt ]; then
+ rm -f /usr/share/bitlbee/help.upgrading
+ mv /usr/share/bitlbee/help.txt /usr/share/bitlbee/help.upgrading
+ fi
+else
+ invoke-rc.d bitlbee stop || exit 0
+fi
diff --git a/debian/bitlbee.prerm b/debian/bitlbee.prerm
index 687c2cc1..c61db24b 100644
--- a/debian/bitlbee.prerm
+++ b/debian/bitlbee.prerm
@@ -1,17 +1,5 @@
#!/bin/sh -e
-if [ "$1" = "upgrade" ]; then
- ## To prevent the help function from breaking in currently running
- ## BitlBee processes. Have to do it like this because dpkg-reconfigure
- ## looks a lot like an upgrade and we don't want to lose help.txt...
- if [ -e /usr/share/bitlbee/help.txt ]; then
- rm -f /usr/share/bitlbee/help.upgrading
- mv /usr/share/bitlbee/help.txt /usr/share/bitlbee/help.upgrading
- fi
-else
- if which invoke-rc.d >/dev/null 2>&1; then
- invoke-rc.d bitlbee stop || exit 0
- else
- /etc/init.d/bitlbee stop || exit 0
- fi
+if [ "$1" != "upgrade" ]; then
+ invoke-rc.d bitlbee stop || exit 0
fi
diff --git a/debian/changelog b/debian/changelog
index 70f1ed47..8e3cabcb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,7 +5,7 @@ bitlbee (1.3-0) unstable; urgency=low
* Added a bitlbee-libpurple package, and split off docs and stuff into
bitlbee-common.
- -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 05 Jun 2010 15:16:38 +0100
+ -- Wilmer van der Gaast <wilmer@gaast.net> Wed, 18 Aug 2010 00:53:11 +0100
bitlbee (1.2.8-1) unstable; urgency=low
diff --git a/debian/rules b/debian/rules
index c6edfe2b..c5397085 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,6 +7,8 @@
# exercise is over now.
#
+# Include the bitlbee-libpurple variant by default
+BITLBEE_LIBPURPLE ?= 1
BITLBEE_CONFIGURE_FLAGS ?=
DEBUG ?= 0
@@ -15,6 +17,10 @@ ifndef BITLBEE_VERSION
BITLBEE_CONFIGURE_VERSION ?= BITLBEE_VERSION=\"$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')\"
endif
+ifneq ($(BITLBEE_LIBPURPLE),1)
+DH_OPTIONS += -Nbitlbee-libpurple
+endif
+
build: build-stamp
build-stamp:
dh_testdir
@@ -23,9 +29,11 @@ build-stamp:
ROOT=$$PWD; cd debian/build-native; $(BITLBEE_CONFIGURE_VERSION) $$ROOT/configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent $(BITLBEE_CONFIGURE_FLAGS)
$(MAKE) -C debian/build-native
+ifeq ($(BITLBEE_LIBPURPLE),1)
mkdir -p debian/build-libpurple
ROOT=$$PWD; cd debian/build-libpurple; $(BITLBEE_CONFIGURE_VERSION) $$ROOT/configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --purple=1 $(BITLBEE_CONFIGURE_FLAGS)
$(MAKE) -C debian/build-libpurple
+endif
$(MAKE) -C doc
@@ -36,7 +44,7 @@ clean:
dh_testroot
rm -f build-stamp
- rm -rf build-arch-stamp debian/build-*
+ rm -rf build-arch-stamp debian/build-* debian/bitlbee-libpurple.prerm
$(MAKE) distclean
dh_clean
@@ -47,12 +55,15 @@ install: build
dh_clean -k
dh_installdirs
- $(MAKE) -C debian/build-native install install-etc DESTDIR=`pwd`/debian/bitlbee
- $(MAKE) -C debian/build-libpurple install install-etc DESTDIR=`pwd`/debian/bitlbee-libpurple
+ $(MAKE) -C debian/build-native install DESTDIR=`pwd`/debian/bitlbee
+ $(MAKE) -C debian/build-native install-etc DESTDIR=`pwd`/debian/bitlbee-common
$(MAKE) -C debian/build-native install-dev DESTDIR=`pwd`/debian/bitlbee-dev
+ patch debian/bitlbee-common/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff
- patch debian/bitlbee/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff
- patch debian/bitlbee-libpurple/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff
+ifeq ($(BITLBEE_LIBPURPLE),1)
+ $(MAKE) -C debian/build-libpurple install DESTDIR=`pwd`/debian/bitlbee-libpurple
+ ln -sf debian/bitlbee.prerm debian/bitlbee-libpurple.prerm
+endif
mkdir -p debian/bitlbee-common/usr
mv debian/bitlbee/usr/share debian/bitlbee-common/usr
@@ -67,21 +78,15 @@ binary-common:
dh_installdocs #--link-doc=bitlbee-common
# TODO: Restore --link-doc up here and remove the hack below once
# Hardy and Lenny are deprecated.
- for p in bitlbee bitlbee-libpurple bitlbee-dev; do rm -rf debian/$$p/usr/share/doc/$$p; ln -s bitlbee-common debian/$$p/usr/share/doc/$$p; done
+ for p in bitlbee bitlbee-libpurple bitlbee-dev; do rm -r debian/$$p/usr/share/doc/$$p && ln -s bitlbee-common debian/$$p/usr/share/doc/$$p; done
dh_installdebconf
- dh_installinit
-ifeq ($(DH_OPTIONS),-a)
- cp -a debian/bitlbee/etc debian/bitlbee-libpurple
-endif
+ dh_installinit --init-script=bitlbee
dh_installman
dh_strip
dh_link
dh_compress
dh_fixperms
dh_installdeb
-ifeq ($(DH_OPTIONS),-a)
- cp -a debian/bitlbee/DEBIAN/post* debian/bitlbee/DEBIAN/pre* debian/bitlbee-libpurple/DEBIAN
-endif
dh_shlibdeps
ifdef BITLBEE_VERSION
dh_gencontrol -- -v1:$(BITLBEE_VERSION)-0 -Vbee:Version=1:$(BITLBEE_VERSION)-0
@@ -92,13 +97,13 @@ endif
dh_builddeb
binary-indep: build install
- $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
+ DH_OPTIONS=-i $(MAKE) -f debian/rules binary-common
binary-arch: build install
- $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
+ DH_OPTIONS=-a $(MAKE) -f debian/rules binary-common
binary-%: build install
- make -f debian/rules binary-common DH_OPTIONS=-p$*
+ DH_OPTIONS=-p$* $(MAKE) -f debian/rules binary-common
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary-common binary install
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index 8bbada95..989fc392 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -828,6 +828,17 @@
</bitlbee-setting>
+ <bitlbee-setting name="mobile_is_away" type="boolean" scope="global">
+ <default>false</default>
+
+ <description>
+ <para>
+ Most IM networks have a mobile version of their client. People who use these may not be paying that much attention to messages coming in. By enabling this setting, people using mobile clients will always be shown as away.
+ </para>
+ </description>
+
+ </bitlbee-setting>
+
<bitlbee-setting name="nick" type="string" scope="chat">
<description>
<para>
diff --git a/doc/user-guide/misc.xml b/doc/user-guide/misc.xml
index 7829a432..dc0ce5ed 100644
--- a/doc/user-guide/misc.xml
+++ b/doc/user-guide/misc.xml
@@ -233,4 +233,46 @@ everything in the handle up to the first @.
</sect1>
+<sect1 id="news1.3">
+<title>New stuff in BitlBee 1.3dev</title>
+
+<para>
+Most of the core of BitlBee was rewritten since the last release. This entry
+should sum up the majority of the changes.
+</para>
+
+<para>
+First of all, you can now have as many control channels as you want. Or you
+can have none, it's finally possible to leave &amp;bitlbee and still talk to
+all your contacts. Or you can have a &amp;work with all your work-related
+contacts, or a &amp;msn with all your MSN Messenger contacts. See <emphasis>help
+channels</emphasis> for more information about this.
+</para>
+
+<para>
+Also, you can change how nicknames are generated for your contacts. Like
+automatically adding a [fb] tag to the nicks of all your Facebook contacts.
+See <emphasis>help nick_format</emphasis>.
+</para>
+
+<para>
+When you're already connected to a BitlBee server and you connect from
+elsewhere, you can take over the old session.
+</para>
+
+<para>
+Instead of account numbers, accounts now also get tags. These are
+automatically generated but can be changed (<emphasis>help set
+tag</emphasis>). You can now use them instead of accounts numbers.
+(Example: <emphasis>acc gtalk on</emphasis>)
+</para>
+
+<para>
+Last of all: You can finally change your nickname and
+shorten root commands (try <emphasis>acc li</emphasis> instead
+of <emphasis>account list</emphasis>).
+</para>
+
+</sect1>
+
</chapter>
diff --git a/irc.c b/irc.c
index e4af555c..836d5f81 100644
--- a/irc.c
+++ b/irc.c
@@ -102,12 +102,15 @@ irc_t *irc_new( int fd )
s = set_add( &b->set, "allow_takeover", "true", set_eval_bool, irc );
s = set_add( &b->set, "away_devoice", "true", set_eval_bw_compat, irc );
+ s->flags |= SET_HIDDEN;
s = set_add( &b->set, "away_reply_timeout", "3600", set_eval_int, irc );
s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc );
s = set_add( &b->set, "default_target", "root", NULL, irc );
s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc );
s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc );
s = set_add( &b->set, "handle_unknown", "add_channel", NULL, irc );
+ s = set_add( &b->set, "last_version", NULL, NULL, irc );
+ s->flags |= SET_HIDDEN;
s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc );
s = set_add( &b->set, "nick_format", "%-@nick", NULL, irc );
s = set_add( &b->set, "offline_user_quits", "true", set_eval_bool, irc );
@@ -121,7 +124,9 @@ irc_t *irc_new( int fd )
s = set_add( &b->set, "private", "true", set_eval_bool, irc );
s = set_add( &b->set, "query_order", "lifo", NULL, irc );
s = set_add( &b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc );
+ s->flags |= SET_HIDDEN;
s = set_add( &b->set, "show_offline", "false", set_eval_bw_compat, irc );
+ s->flags |= SET_HIDDEN;
s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc );
s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc );
s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc );
@@ -914,7 +919,7 @@ static char *set_eval_bw_compat( set_t *set, char *value )
else if( strcmp( set->key, "show_offline" ) == 0 && bool2int( value ) )
val = "online@,away+,offline";
else
- return SET_INVALID;
+ val = "online+,away";
for( l = irc->channels; l; l = l->next )
{
diff --git a/irc_channel.c b/irc_channel.c
index 118fef74..80b1cb62 100644
--- a/irc_channel.c
+++ b/irc_channel.c
@@ -758,6 +758,7 @@ static gboolean control_channel_free( irc_channel_t *ic )
set_del( &ic->set, "fill_by" );
set_del( &ic->set, "group" );
set_del( &ic->set, "protocol" );
+ set_del( &ic->set, "show_users" );
g_free( icc );
ic->data = NULL;
diff --git a/irc_send.c b/irc_send.c
index cb387059..5f4dc350 100644
--- a/irc_send.c
+++ b/irc_send.c
@@ -326,7 +326,7 @@ void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char
void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg )
{
irc_write( iu->irc, ":%s!%s@%s %s %s :%s",
- iu->nick, iu->user, iu->host, type, dst, msg );
+ iu->nick, iu->user, iu->host, type, dst, msg && *msg ? msg : " " );
}
void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... )
diff --git a/lib/proxy.c b/lib/proxy.c
index 0b1866ea..e7d35351 100644
--- a/lib/proxy.c
+++ b/lib/proxy.c
@@ -48,6 +48,11 @@ int proxytype = PROXY_NONE;
char proxyuser[128] = "";
char proxypass[128] = "";
+/* Some systems don't know this one. It's not essential, so set it to 0 then. */
+#ifndef AI_NUMERICSERV
+#define AI_NUMERICSERV 0
+#endif
+
struct PHB {
b_event_handler func, proxy_func;
gpointer data, proxy_data;
@@ -55,8 +60,11 @@ struct PHB {
int port;
int fd;
gint inpa;
+ struct addrinfo *gai, *gai_cur;
};
+static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb);
+
static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
{
struct PHB *phb = data;
@@ -65,7 +73,19 @@ static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition
len = sizeof(error);
#ifndef _WIN32
- if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+ if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
+ if ((phb->gai_cur = phb->gai_cur->ai_next)) {
+ int new_fd;
+ b_event_remove(phb->inpa);
+ if ((new_fd = proxy_connect_none(NULL, 0, phb))) {
+ b_event_remove(phb->inpa);
+ closesocket(source);
+ dup2(new_fd, source);
+ phb->inpa = b_input_add(source, B_EV_IO_WRITE, gaim_io_connected, phb);
+ return FALSE;
+ }
+ }
+ freeaddrinfo(phb->gai);
closesocket(source);
b_event_remove(phb->inpa);
if( phb->proxy_func )
@@ -77,6 +97,7 @@ static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition
return FALSE;
}
#endif
+ freeaddrinfo(phb->gai);
sock_make_blocking(source);
b_event_remove(phb->inpa);
if( phb->proxy_func )
@@ -93,64 +114,61 @@ static int proxy_connect_none(const char *host, unsigned short port_, struct PHB
{
struct sockaddr_in me;
int fd = -1;
- int ret;
- char port[6];
- struct addrinfo hints;
- struct addrinfo* result;
-
- g_snprintf(port, sizeof(port), "%d", port_);
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
-
- if (!(ret = getaddrinfo(host, port, &hints, &result)))
+
+ if (phb->gai_cur == NULL)
{
- struct addrinfo* rp;
-
- for (rp = result; rp; rp = rp->ai_next)
- {
- if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) {
- event_debug( "socket failed: %d\n", errno);
- continue;
- }
+ int ret;
+ char port[6];
+ struct addrinfo hints;
+
+ g_snprintf(port, sizeof(port), "%d", port_);
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
+
+ if (!(ret = getaddrinfo(host, port, &hints, &phb->gai)))
+ phb->gai_cur = phb->gai;
+ else
+ event_debug("gai(): %s\n", gai_strerror(ret));
+ }
+
+ for (; phb->gai_cur; phb->gai_cur = phb->gai_cur->ai_next)
+ {
+ if ((fd = socket(phb->gai_cur->ai_family, phb->gai_cur->ai_socktype, phb->gai_cur->ai_protocol)) < 0) {
+ event_debug( "socket failed: %d\n", errno);
+ continue;
+ }
- sock_make_nonblocking(fd);
+ sock_make_nonblocking(fd);
- if (global.conf->iface_out)
- {
- me.sin_family = AF_INET;
- me.sin_port = 0;
- me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
+ if (global.conf->iface_out)
+ {
+ me.sin_family = AF_INET;
+ me.sin_port = 0;
+ me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
- if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0)
- event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out);
- }
+ if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0)
+ event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out);
+ }
- event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
+ event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
- if (connect(fd, rp->ai_addr, rp->ai_addrlen) < 0 && !sockerr_again()) {
- event_debug( "connect failed: %s\n", strerror(errno));
- closesocket(fd);
- fd = -1;
- continue;
- } else {
- phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
- phb->fd = fd;
-
- break;
- }
+ if (connect(fd, phb->gai_cur->ai_addr, phb->gai_cur->ai_addrlen) < 0 && !sockerr_again()) {
+ event_debug( "connect failed: %s\n", strerror(errno));
+ closesocket(fd);
+ fd = -1;
+ continue;
+ } else {
+ phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
+ phb->fd = fd;
+
+ break;
}
-
- freeaddrinfo(result);
- }
- else
- {
- event_debug("gai(): %s\n", gai_strerror(ret));
}
- if(fd < 0)
+ if(fd < 0 && host)
g_free(phb);
return fd;
diff --git a/protocols/bee.c b/protocols/bee.c
index c5eeee17..81cb7619 100644
--- a/protocols/bee.c
+++ b/protocols/bee.c
@@ -39,6 +39,7 @@ bee_t *bee_new()
s = set_add( &b->set, "auto_reconnect", "true", set_eval_bool, b );
s = set_add( &b->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, b );
s = set_add( &b->set, "debug", "false", set_eval_bool, b );
+ s = set_add( &b->set, "mobile_is_away", "false", set_eval_bool, b );
s = set_add( &b->set, "save_on_quit", "true", set_eval_bool, b );
s = set_add( &b->set, "status", NULL, set_eval_away_status, b );
s->flags |= SET_NULL_OK;
diff --git a/protocols/bee.h b/protocols/bee.h
index 6e3cf563..d7da3671 100644
--- a/protocols/bee.h
+++ b/protocols/bee.h
@@ -55,10 +55,12 @@ typedef struct bee
bee_t *bee_new();
void bee_free( bee_t *b );
+/* TODO(wilmer): Kill at least the OPT_ flags that have an equivalent here. */
typedef enum
{
BEE_USER_ONLINE = 1, /* Compatibility with old OPT_LOGGED_IN flag */
BEE_USER_AWAY = 4, /* Compatibility with old OPT_AWAY flag */
+ BEE_USER_MOBILE = 8, /* Compatibility with old OPT_MOBILE flag */
BEE_USER_LOCAL = 256, /* Locally-added contacts (not in real contact list) */
} bee_user_flags_t;
diff --git a/protocols/bee_user.c b/protocols/bee_user.c
index 86f87f86..71b15d29 100644
--- a/protocols/bee_user.c
+++ b/protocols/bee_user.c
@@ -194,6 +194,13 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,
else
bu->status = NULL;
+ if( bu->status == NULL && ( flags & OPT_MOBILE ) &&
+ set_getbool( &bee->set, "mobile_is_away" ) )
+ {
+ bu->flags |= BEE_USER_AWAY;
+ bu->status = g_strdup( "Mobile" );
+ }
+
if( bee->ui->user_status )
bee->ui->user_status( bee, bu, old );
@@ -267,7 +274,7 @@ void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, ui
imcb_log( ic, "Message from unknown handle %s:\n%s", handle, msg );
}
-void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags )
+void imcb_buddy_typing( struct im_connection *ic, const char *handle, uint32_t flags )
{
bee_user_t *bu;
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index 90254508..2069cf6b 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -62,6 +62,7 @@
#define OPT_LOGGED_IN 0x00000001
#define OPT_LOGGING_OUT 0x00000002
#define OPT_AWAY 0x00000004
+#define OPT_MOBILE 0x00000008
#define OPT_DOES_HTML 0x00000010
#define OPT_LOCALBUDDY 0x00000020 /* For nicks local to one groupchat */
#define OPT_TYPING 0x00000100 /* Some pieces of code make assumptions */
@@ -311,7 +312,7 @@ G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *h
G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname );
G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
-G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
+G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, const char *handle, uint32_t flags );
G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle );
G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c
index 3f5272cd..db6a28f4 100644
--- a/protocols/oscar/oscar.c
+++ b/protocols/oscar/oscar.c
@@ -898,6 +898,10 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
flags |= OPT_AWAY;
}
+ /* Maybe this should be done just for AIM contacts, not sure. */
+ if (info->flags & AIM_FLAG_WIRELESS)
+ flags |= OPT_MOBILE;
+
if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) {
if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) &&
(info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) {
diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c
index c7cfcfda..5522c0fc 100644
--- a/protocols/purple/purple.c
+++ b/protocols/purple/purple.c
@@ -426,23 +426,16 @@ static void purple_keepalive( struct im_connection *ic )
static int purple_send_typing( struct im_connection *ic, char *who, int flags )
{
PurpleTypingState state = PURPLE_NOT_TYPING;
- PurpleConversation *conv;
+ PurpleAccount *pa = ic->proto_data;
if( flags & OPT_TYPING )
state = PURPLE_TYPING;
else if( flags & OPT_THINKING )
state = PURPLE_TYPED;
- if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM,
- who, ic->proto_data ) ) == NULL )
- {
- purple_conv_im_set_typing_state( purple_conversation_get_im_data( conv ), state );
- return 1;
- }
- else
- {
- return 0;
- }
+ serv_send_typing( purple_account_get_connection( pa ), who, state );
+
+ return 1;
}
static void purple_chat_msg( struct groupchat *gc, char *message, int flags )
@@ -808,6 +801,32 @@ static void prplcb_conv_im( PurpleConversation *conv, const char *who, const cha
imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime );
}
+/* No, this is not a ui_op but a signal. */
+static void prplcb_buddy_typing( PurpleAccount *account, const char *who, gpointer null )
+{
+ PurpleConversation *conv;
+ PurpleConvIm *im;
+ int state;
+
+ if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, who, account ) ) == NULL )
+ return;
+
+ im = PURPLE_CONV_IM(conv);
+ switch( purple_conv_im_get_typing_state( im ) )
+ {
+ case PURPLE_TYPING:
+ state = OPT_TYPING;
+ break;
+ case PURPLE_TYPED:
+ state = OPT_THINKING;
+ break;
+ default:
+ state = 0;
+ }
+
+ imcb_buddy_typing( purple_ic_by_pa( account ), who, state );
+}
+
static PurpleConversationUiOps bee_conv_uiops =
{
prplcb_conv_new, /* create_conversation */
@@ -1138,6 +1157,15 @@ void purple_initmodule()
/* Meh? */
purple_prefs_load();
+ /* No, really. So far there were ui_ops for everything, but now suddenly
+ one needs to use signals for typing notification stuff. :-( */
+ purple_signal_connect( purple_conversations_get_handle(), "buddy-typing",
+ &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL );
+ purple_signal_connect( purple_conversations_get_handle(), "buddy-typed",
+ &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL );
+ purple_signal_connect( purple_conversations_get_handle(), "buddy-typing-stopped",
+ &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL );
+
memset( &funcs, 0, sizeof( funcs ) );
funcs.login = purple_login;
funcs.init = purple_init;
diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c
index 9f7a7896..7708ed63 100644
--- a/protocols/yahoo/yahoo.c
+++ b/protocols/yahoo/yahoo.c
@@ -588,6 +588,8 @@ void ext_yahoo_status_changed( int id, const char *who, int stat, const char *ms
if( away )
flags |= OPT_AWAY;
+ if( mobile )
+ flags |= OPT_MOBILE;
switch (stat)
{
diff --git a/root_commands.c b/root_commands.c
index 2cd1a617..280c93a2 100644
--- a/root_commands.c
+++ b/root_commands.c
@@ -99,6 +99,7 @@ static void cmd_help( irc_t *irc, char **cmd )
}
static void cmd_account( irc_t *irc, char **cmd );
+static void bitlbee_whatsnew( irc_t *irc );
static void cmd_identify( irc_t *irc, char **cmd )
{
@@ -155,6 +156,8 @@ static void cmd_identify( irc_t *irc, char **cmd )
irc->status |= USTATUS_IDENTIFIED;
irc_umode_set( irc, "+R", 1 );
+ bitlbee_whatsnew( irc );
+
/* The following code is a bit hairy now. With takeover
support, we shouldn't immediately auto_connect in case
we're going to offer taking over an existing session.
@@ -266,6 +269,13 @@ static void cmd_showset( irc_t *irc, set_t **head, char *key )
if( ( val = set_getstr( head, key ) ) )
irc_usermsg( irc, "%s = `%s'", key, val );
+ else if( !set_find( head, key ) )
+ {
+ irc_usermsg( irc, "Setting `%s' does not exist.", key );
+ if( *head == irc->b->set )
+ irc_usermsg( irc, "It might be an account or channel setting. "
+ "See \x02help account set\x02 and \x02help channel set\x02." );
+ }
else
irc_usermsg( irc, "%s is empty", key );
}
@@ -303,7 +313,8 @@ static int cmd_set_real( irc_t *irc, char **cmd, set_t **head, cmd_set_checkflag
else
st = set_setstr( head, set_name, value );
- if( set_getstr( head, set_name ) == NULL )
+ if( set_getstr( head, set_name ) == NULL &&
+ set_find( head, set_name ) )
{
/* This happens when changing the passwd, for example.
Showing these msgs instead gives slightly clearer
@@ -327,7 +338,8 @@ static int cmd_set_real( irc_t *irc, char **cmd, set_t **head, cmd_set_checkflag
set_t *s = *head;
while( s )
{
- cmd_showset( irc, &s, s->key );
+ if( !( s->flags & SET_HIDDEN ) )
+ cmd_showset( irc, &s, s->key );
s = s->next;
}
}
@@ -1007,7 +1019,8 @@ static void cmd_blist( irc_t *irc, char **cmd )
irc_usermsg( irc, format, "Nick", "Handle/Account", "Status" );
- if( strcmp( set_getstr( &irc->root->last_channel->set, "type" ), "control" ) != 0 )
+ if( irc->root->last_channel &&
+ strcmp( set_getstr( &irc->root->last_channel->set, "type" ), "control" ) != 0 )
irc->root->last_channel = NULL;
for( l = irc->users; l; l = l->next )
@@ -1270,6 +1283,45 @@ static void cmd_transfer( irc_t *irc, char **cmd )
}
}
+/* Maybe this should be a stand-alone command as well? */
+static void bitlbee_whatsnew( irc_t *irc )
+{
+ int last = set_getint( &irc->b->set, "last_version" );
+ GString *msg = g_string_new( "" );
+ char s[16];
+
+ if( last >= BITLBEE_VERSION_CODE )
+ return;
+
+ if( last < 0x010206 ) /* 1.2.6 */
+ {
+ g_string_append( msg,
+ "Twitter support. See \x02help account add twitter\x02.\n" );
+ }
+ if( last < 0x010300 ) /* 1.3dev */
+ {
+ g_string_append( msg,
+ "Support for multiple configurable control channels, "
+ "each with a subset of your contact list. See "
+ "\x02help channels\x02 for more information.\n"
+ "File transfer support for some protocols (more if "
+ "you use libpurple). Just /DCC SEND stuff. Incoming "
+ "files also become DCC transfers.\n"
+ "Many more things, briefly described in "
+ "\x02help news1.3\x02.\n" );
+ }
+
+ if( msg->len > 0 )
+ irc_usermsg( irc, "%s: This seems to be your first time using this "
+ "this version of BitlBee. Here's a list of new "
+ "features you may like to know about:\n\n%s\n",
+ irc->user->nick, msg->str );
+
+ g_string_free( msg, TRUE );
+ g_snprintf( s, sizeof( s ), "%d", BITLBEE_VERSION_CODE );
+ set_setstr( &irc->b->set, "last_version", s );
+}
+
/* IMPORTANT: Keep this list sorted! The short command logic needs that. */
const command_t commands[] = {
{ "account", 1, cmd_account, 0 },
diff --git a/set.h b/set.h
index 4bd1ce18..d5be7644 100644
--- a/set.h
+++ b/set.h
@@ -42,7 +42,11 @@ typedef char *(*set_eval) ( struct set *set, char *value );
extern char *SET_INVALID;
-#define SET_NULL_OK 0x0100
+typedef enum
+{
+ SET_NULL_OK = 0x0100,
+ SET_HIDDEN = 0x0200,
+} set_flags_t;
typedef struct set
{
@@ -59,8 +63,7 @@ typedef struct set
In fact, you should only read values using
set_getstr/int(). */
- int flags; /* See account.h, for example. set.c doesn't use
- this (yet?). */
+ set_flags_t flags; /* Mostly defined per user. */
/* Eval: Returns SET_INVALID if the value is incorrect, exactly
the passed value variable, or a corrected value. In case of