Changes in / [8b8def58:38ff846]


Ignore:
Files:
15 added
35 deleted
70 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r8b8def58 r38ff846  
    1010
    1111# Program variables
    12 objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS)
    13 headers = account.h bitlbee.h commands.h conf.h config.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/ftutil.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/ft.h protocols/nogaim.h
     12objects = account.o bitlbee.o chat.o crypting.o help.o ipc.o irc.o irc_commands.o nick.o query.o root_commands.o set.o storage.o $(STORAGE_OBJS) user.o
     13headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h user.h lib/events.h lib/http_client.h lib/ini.h lib/md5.h lib/misc.h lib/proxy.h lib/sha1.h lib/ssl_client.h lib/url.h protocols/nogaim.h
    1414subdirs = lib protocols
    1515
     
    8282install-dev:
    8383        mkdir -p $(DESTDIR)$(INCLUDEDIR)
    84         install -m 0644 config.h $(DESTDIR)$(INCLUDEDIR)
    85         for i in $(headers); do install -m 0644 $(SRCDIR)$$i $(DESTDIR)$(INCLUDEDIR); done
     84        install -m 0644 $(headers) $(DESTDIR)$(INCLUDEDIR)
    8685        mkdir -p $(DESTDIR)$(PCDIR)
    8786        install -m 0644 bitlbee.pc $(DESTDIR)$(PCDIR)
     
    9493install-etc:
    9594        mkdir -p $(DESTDIR)$(ETCDIR)
    96         install -m 0644 $(SRCDIR)motd.txt $(DESTDIR)$(ETCDIR)/motd.txt
    97         install -m 0644 $(SRCDIR)bitlbee.conf $(DESTDIR)$(ETCDIR)/bitlbee.conf
     95        install -m 0644 motd.txt $(DESTDIR)$(ETCDIR)/motd.txt
     96        install -m 0644 bitlbee.conf $(DESTDIR)$(ETCDIR)/bitlbee.conf
    9897
    9998uninstall-etc:
     
    111110        @$(MAKE) -C $@ $(MAKECMDGOALS)
    112111
    113 $(objects): %.o: $(SRCDIR)%.c
     112$(objects): %.o: %.c
    114113        @echo '*' Compiling $<
    115114        @$(CC) -c $(CFLAGS) $< -o $@
  • bitlbee.c

    r8b8def58 r38ff846  
    121121        }
    122122       
    123         global.listen_watch_source_id = b_input_add( global.listen_socket, B_EV_IO_READ, bitlbee_io_new_client, NULL );
     123        global.listen_watch_source_id = b_input_add( global.listen_socket, GAIM_INPUT_READ, bitlbee_io_new_client, NULL );
    124124       
    125125#ifndef _WIN32
     
    321321                        child->pid = client_pid;
    322322                        child->ipc_fd = fds[0];
    323                         child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
     323                        child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    324324                        child_list = g_slist_append( child_list, child );
    325325                       
     
    349349                        /* We can store the IPC fd there now. */
    350350                        global.listen_socket = fds[1];
    351                         global.listen_watch_source_id = b_input_add( fds[1], B_EV_IO_READ, ipc_child_read, irc );
     351                        global.listen_watch_source_id = b_input_add( fds[1], GAIM_INPUT_READ, ipc_child_read, irc );
    352352                       
    353353                        close( fds[0] );
  • bitlbee.h

    r8b8def58 r38ff846  
    4343
    4444#if HAVE_CONFIG_H
    45 #include <config.h>
     45#include "config.h"
    4646#endif
    4747
     
    126126#define CONF_FILE_DEF ETCDIR "bitlbee.conf"
    127127
    128 #include "bee.h"
    129128#include "irc.h"
    130129#include "storage.h"
     
    161160gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond );
    162161
    163 void root_command_string( irc_t *irc, char *command );
     162void root_command_string( irc_t *irc, user_t *u, char *command, int flags );
    164163void root_command( irc_t *irc, char *command[] );
    165164gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond );
  • conf.c

    r8b8def58 r38ff846  
    6363        conf->ping_timeout = 300;
    6464        conf->user = NULL;
    65         conf->ft_max_size = SIZE_MAX;
    66         conf->ft_max_kbps = G_MAXUINT;
    67         conf->ft_listen = NULL;
    6865        conf->protocols = NULL;
    6966        proxytype = 0;
     
    318315                                conf->user = g_strdup( ini->value );
    319316                        }
    320                         else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 )
    321                         {
    322                                 size_t ft_max_size;
    323                                 if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 )
    324                                 {
    325                                         fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
    326                                         return 0;
    327                                 }
    328                                 conf->ft_max_size = ft_max_size;
    329                         }
    330                         else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 )
    331                         {
    332                                 if( sscanf( ini->value, "%d", &i ) != 1 )
    333                                 {
    334                                         fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value );
    335                                         return 0;
    336                                 }
    337                                 conf->ft_max_kbps = i;
    338                         }
    339                         else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 )
    340                         {
    341                                 g_free( conf->ft_listen );
    342                                 conf->ft_listen = g_strdup( ini->value );
    343                         }
    344317                        else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
    345318                        {
     
    376349                if( g_strcasecmp( ini->section, "defaults" ) == 0 )
    377350                {
    378                         set_t *s = set_find( &irc->b->set, ini->key );
     351                        set_t *s = set_find( &irc->set, ini->key );
    379352                       
    380353                        if( s )
  • conf.h

    r8b8def58 r38ff846  
    5050        int ping_timeout;
    5151        char *user;
    52         size_t ft_max_size;
    53         int ft_max_kbps;
    54         char *ft_listen;
    5552        char **protocols;
    5653} conf_t;
  • configure

    r8b8def58 r38ff846  
    2727yahoo=1
    2828twitter=1
    29 twitter=1
    30 purple=0
    3129
    3230debug=0
     
    6967--oscar=0/1     Disable/enable Oscar part (ICQ, AIM)    $oscar
    7068--yahoo=0/1     Disable/enable Yahoo part               $yahoo
    71 --twitter=0/1   Disable/enable Twitter part             $twitter
    72 
    73 --purple=0/1    Disable/enable libpurple support        $purple
     69--twitter=0/1 Disable/enable Twitter part               $twitter
    7470
    7571--debug=0/1     Disable/enable debugging                $debug
     
    125121EOF
    126122
    127 srcdir="$(dirname $0)"
    128 if [ "$srcdir" != "." ]; then
    129         echo
    130         echo "configure script run from a different directory. Will create some symlinks..."
    131         if [ ! -e Makefile -o -L Makefile ]; then
    132                 COPYDIRS="doc lib protocols tests utils"
    133                 mkdir -p $(cd "$srcdir"; find $COPYDIRS -type d)
    134                 find . -name Makefile -type l -print0 | xargs -0 rm 2> /dev/null
    135                 dst="$PWD"
    136                 cd "$srcdir"
    137                 for i in $(find . -name Makefile -type f); do
    138                         ln -s "$PWD${i#.}" "$dst/$i";
    139                 done
    140                 cd "$dst"
    141                 rm -rf .bzr
    142         fi
    143        
    144         echo "SRCDIR=$srcdir/" >> Makefile.settings
    145         CFLAGS="$CFLAGS -I${dst}"
    146 else
    147         srcdir=$PWD
    148 fi
    149 
    150123cat<<EOF>config.h
    151124/* BitlBee settings, generated by configure
     
    185158
    186159echo CFLAGS=$CFLAGS >> Makefile.settings
    187 echo CFLAGS+=-I${srcdir} -I${srcdir}/lib -I${srcdir}/protocols -I. >> Makefile.settings
     160echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings
    188161
    189162echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings
     
    425398fi
    426399
    427 STORAGES="xml"
     400STORAGES="text xml"
    428401
    429402if [ "$ldap" = "auto" ]; then
     
    535508protoobjs=''
    536509
    537 if [ "$purple" = 0 ]; then
    538         echo '#undef WITH_PURPLE' >> config.h
    539 else
    540         if ! $PKG_CONFIG purple; then
    541                 echo
    542                 echo 'Cannot find libpurple development libraries, aborting. (Install libpurple-dev?)'
    543                 exit 1
    544         fi
    545         echo '#define WITH_PURPLE' >> config.h
    546         cat<<EOF>>Makefile.settings
    547 EFLAGS += $($PKG_CONFIG purple --libs)
    548 PURPLE_CFLAGS += $($PKG_CONFIG purple --cflags)
    549 EOF
    550         protocols=$protocols'purple '
    551         protoobjs=$protoobjs'purple_mod.o '
    552 
    553         # Having both libpurple and native IM modules in one binary may
    554         # do strange things. Let's not do that.
    555         msn=0
    556         jabber=0
    557         oscar=0
    558         yahoo=0
    559         twitter=0
    560        
    561         if [ "$events" = "libevent" ]; then
    562                 echo
    563                 echo 'Warning: Some libpurple modules (including msn-pecan) do their event handling'
    564                 echo 'outside libpurple, talking to GLib directly. At least for now the combination'
    565                 echo 'libpurple + libevent is *not* recommended!'
    566         fi
    567 fi
    568 
    569510if [ "$msn" = 0 ]; then
    570511        echo '#undef WITH_MSN' >> config.h
  • debian/bitlbee.init

    • Property mode changed from 100644 to 100755
  • debian/changelog

    r8b8def58 r38ff846  
    1 bitlbee (1.3-0) unstable; urgency=low
    2 
    3   * Setting some bogus version number, fix that later.
    4   * Now using debhelper to improve maintainability.
    5   * Added a bitlbee-libpurple package, and split off docs and stuff into
    6     bitlbee-common.
    7 
    8  -- Wilmer van der Gaast <wilmer@gaast.net>  Sat, 05 Jun 2010 15:16:38 +0100
    9 
    101bitlbee (1.2.7-1) unstable; urgency=high
    112
  • debian/control

    r8b8def58 r38ff846  
    44Maintainer: Wilmer van der Gaast <wilmer@gaast.net>
    55Uploaders: Jelmer Vernooij <jelmer@samba.org>
    6 Standards-Version: 3.8.4
    7 Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), po-debconf, libpurple-dev, debhelper (>= 6)
     6Standards-Version: 3.8.0
     7Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf
    88Homepage: http://www.bitlbee.org/
    99Vcs-Bzr: http://code.bitlbee.org/bitlbee/
     
    1212Package: bitlbee
    1313Architecture: any
    14 Depends: ${shlibs:Depends}, adduser, debianutils (>= 1.16), bitlbee-common (= ${bee:Version})
    15 Conflicts: bitlbee-libpurple
    16 Replaces: bitlbee-libpurple
    17 Description: An IRC to other chat networks gateway (default version)
     14Depends: ${shlibs:Depends}, adduser, net-tools, ${debconf-depends}, debianutils (>= 1.16)
     15Description: An IRC to other chat networks gateway
    1816 This program can be used as an IRC server which forwards everything you
    1917 say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and
    2018 Twitter.
    2119
    22 Package: bitlbee-libpurple
    23 Architecture: any
    24 Depends: ${shlibs:Depends}, adduser, debianutils (>= 1.16), bitlbee-common (= ${bee:Version})
    25 Conflicts: bitlbee
    26 Replaces: bitlbee
    27 Description: An IRC to other chat networks gateway (using libpurple)
    28  This program can be used as an IRC server which forwards everything you
    29  say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and
    30  Twitter.
    31  .
    32  This package contains a version of BitlBee that uses the libpurple instant
    33  messaging library instead of built-in code, which adds support for more IM
    34  protocols (all protocols supported by Pidgin/Finch) and features (like file
    35  transfers), at the price of being less lightweight.
    36  .
    37  This variant may not be very suitable for BitlBee instances used by many
    38  (tens or hundreds) of clients.
    39 
    40 Package: bitlbee-common
    41 Architecture: all
    42 Depends: ${misc:Depends}, net-tools
    43 Replaces: bitlbee
    44 Description: An IRC to other chat networks gateway (common files/docs)
    45  This program can be used as an IRC server which forwards everything you
    46  say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and
    47  Twitter.
    48  .
    49  This package contains common files (mostly documentation) for bitlbee and
    50  bitlbee-libpurple.
    51 
    5220Package: bitlbee-dev
    5321Architecture: all
    54 Depends: ${misc:Depends}, bitlbee (>= ${bee:Version}), bitlbee (<< ${bee:Version}.1~)
    55 Description: An IRC to other chat networks gateway (dev files)
     22Depends: bitlbee (>= ${source:Version}), bitlbee (<< ${source:Version}.1~)
     23Description: An IRC to other chat networks gateway
    5624 This program can be used as an IRC server which forwards everything you
    5725 say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and
  • debian/patches/bitlbee.conf.diff

    r8b8def58 r38ff846  
    1 --- bitlbee.conf        2009-06-01 00:20:24.000000000 +0100
    2 +++ bitlbee.conf        2009-06-07 21:16:19.000000000 +0100
     1--- debian/bitlbee/etc/bitlbee/bitlbee.conf     2009-06-01 00:20:24.000000000 +0100
     2+++ debian/bitlbee/etc/bitlbee/bitlbee.conf     2009-06-07 21:16:19.000000000 +0100
    33@@ -23,13 +23,18 @@
    44 ## If BitlBee is started by root as a daemon, it can drop root privileges,
  • debian/po/POTFILES.in

    r8b8def58 r38ff846  
    1 [type: gettext/rfc822deb] bitlbee-common.templates
     1[type: gettext/rfc822deb] templates
  • debian/rules

    r8b8def58 r38ff846  
    11#!/usr/bin/make -f
    2 #
    3 # Finally switching to debhelper.
    4 #
    5 # Not using debhelper was an exercise suggested to me by my AM (Gergely
    6 # Nagy). It was educating at the time but I finally decided that the
    7 # exercise is over now.
    8 #
    92
    10 BITLBEE_CONFIGURE_FLAGS ?=
    113DEBUG ?= 0
    124
    13 ifndef BITLBEE_VERSION
     5ifdef BITLBEE_VERSION
     6BITLBEE_FORCE_VERSION=1
     7else
    148# Want to use the full package version number instead of just the release.
    15 BITLBEE_CONFIGURE_VERSION ?= BITLBEE_VERSION=\"$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')\"
     9BITLBEE_VERSION ?= "$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')"
     10export BITLBEE_VERSION
    1611endif
    1712
    18 build: build-stamp
    19 build-stamp:
    20         dh_testdir
    21 
    22         mkdir -p debian/build-native
    23         ROOT=$$PWD; cd debian/build-native; $(BITLBEE_CONFIGURE_VERSION) $$ROOT/configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent $(BITLBEE_CONFIGURE_FLAGS)
    24         $(MAKE) -C debian/build-native
    25 
    26         mkdir -p debian/build-libpurple
    27         ROOT=$$PWD; cd debian/build-libpurple; $(BITLBEE_CONFIGURE_VERSION) $$ROOT/configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --purple=1 $(BITLBEE_CONFIGURE_FLAGS)
    28         $(MAKE) -C debian/build-libpurple
    29 
    30         $(MAKE) -C doc
    31 
    32         touch build-stamp
     13build-arch: build-arch-stamp
     14build-arch-stamp:
     15        [ -d debian ]
     16        ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent
     17        $(MAKE)
     18#       $(MAKE) -C doc/ all
     19        touch build-arch-stamp
    3320
    3421clean:
    35         dh_testdir
    36         dh_testroot
    37         rm -f build-stamp
     22        [ "`whoami`" = "root" -a -d debian ]
     23        rm -rf build-arch-stamp debian/bitlbee debian/*.substvars debian/files debian/bitlbee-dev
     24        $(MAKE) distclean
     25#       -$(MAKE) -C doc/ clean
     26                               
    3827
    39         rm -rf build-arch-stamp debian/build-*
    40         $(MAKE) distclean
     28install-arch: build-arch
     29        [ "`whoami`" = "root" -a -d debian ]
     30        mkdir -p debian/bitlbee/DEBIAN/
     31        $(MAKE) install install-etc DESTDIR=`pwd`/debian/bitlbee
    4132
    42         dh_clean
     33        mkdir -p debian/bitlbee/usr/share/doc/bitlbee/
     34        cp doc/user-guide/user-guide.txt debian/bitlbee/usr/share/doc/bitlbee/
     35        cp doc/user-guide/user-guide.html debian/bitlbee/usr/share/doc/bitlbee/
    4336
    44 install: build
    45         dh_testdir
    46         dh_testroot
    47         dh_clean -k
    48         dh_installdirs
     37install-indep: install-arch
     38        [ "`whoami`" = "root" -a -d debian ]
     39        mkdir -p debian/bitlbee-dev/DEBIAN/
     40        $(MAKE) install-dev DESTDIR=`pwd`/debian/bitlbee-dev
    4941
    50         $(MAKE) -C debian/build-native install install-etc DESTDIR=`pwd`/debian/bitlbee
    51         $(MAKE) -C debian/build-libpurple install install-etc DESTDIR=`pwd`/debian/bitlbee-libpurple
    52         $(MAKE) -C debian/build-native install-dev DESTDIR=`pwd`/debian/bitlbee-dev
     42        mkdir -p debian/bitlbee-dev/usr/share/doc/bitlbee-dev/
    5343
    54         patch debian/bitlbee/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff
    55         patch debian/bitlbee-libpurple/etc/bitlbee/bitlbee.conf debian/patches/bitlbee.conf.diff
     44binary-arch: build-arch install-arch
     45        [ "`whoami`" = "root" -a -d debian ]
    5646
    57         mkdir -p debian/bitlbee-common/usr
    58         mv debian/bitlbee/usr/share debian/bitlbee-common/usr
    59         rm -rf debian/bitlbee-libpurple/usr/share
     47        chmod 755 debian/post* debian/pre* debian/config debian/bitlbee.init
    6048
    61 binary-common:
    62         dh_testdir
    63         dh_testroot
     49        mkdir -p debian/bitlbee/usr/share/doc/bitlbee/examples/ debian/bitlbee/etc/init.d/
     50        -cp doc/RELEASE-SPEECH* debian/bitlbee/usr/share/doc/bitlbee/ && gzip -9 debian/bitlbee/usr/share/doc/bitlbee/RELEASE-SPEECH*
     51        cp doc/CREDITS doc/AUTHORS doc/README doc/FAQ debian/README.Debian debian/bitlbee/usr/share/doc/bitlbee/
     52        cp debian/changelog debian/bitlbee/usr/share/doc/bitlbee/changelog.Debian
     53        cp debian/copyright debian/bitlbee/usr/share/doc/bitlbee/copyright
     54        cp doc/CHANGES debian/bitlbee/usr/share/doc/bitlbee/changelog
     55        cp utils/* debian/bitlbee/usr/share/doc/bitlbee/examples/
     56        cp debian/bitlbee.init debian/bitlbee/etc/init.d/bitlbee
     57        patch -p0 < debian/patches/bitlbee.conf.diff
     58        cd debian/bitlbee/usr/share/; \
     59                gzip -9 doc/bitlbee/changelog.Debian doc/bitlbee/changelog doc/bitlbee/user-guide.txt \
     60                        doc/bitlbee/examples/* man/man8/bitlbee.8 man/man5/bitlbee.conf.5
     61       
     62        chown -R root:root debian/bitlbee/
     63        find debian/bitlbee/usr/share/ -type d -exec chmod 755 {} \;
     64        find debian/bitlbee/usr/share/ -type f -exec chmod 644 {} \;
     65       
     66        cp debian/prerm debian/bitlbee/DEBIAN/
     67        cp debian/postinst debian/bitlbee/DEBIAN/
     68        cp debian/postrm debian/bitlbee/DEBIAN/
     69        cp debian/config debian/bitlbee/DEBIAN/
    6470
    65         dh_installchangelogs doc/CHANGES
    66         dh_installexamples
    67         dh_installdocs #--link-doc=bitlbee-common
    68         # TODO: Restore --link-doc up here and remove the hack below once
    69         # Hardy and Lenny are deprecated.
    70         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
    71         dh_installdebconf
    72         dh_installinit
    73 ifeq ($(DH_OPTIONS),-a)
    74         cp -a debian/bitlbee/etc debian/bitlbee-libpurple
     71        po2debconf debian/templates > debian/bitlbee/DEBIAN/templates
     72        cp debian/conffiles debian/bitlbee/DEBIAN/
     73       
     74        if [ "$(DEBUG)" = "0" ]; then strip -R .comment -R .note debian/bitlbee/usr/sbin/bitlbee; fi
     75
     76        cd debian/bitlbee; \
     77                find usr -type f -exec md5sum {} \; > DEBIAN/md5sums
     78        dpkg-shlibdeps -Tdebian/bitlbee.substvars -dDepends debian/bitlbee/usr/sbin/bitlbee
     79ifdef BITLBEE_FORCE_VERSION
     80        dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v1:$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0'
     81else
     82        dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0'
    7583endif
    76         dh_installman
    77         dh_strip
    78         dh_link
    79         dh_compress
    80         dh_fixperms
    81         dh_installdeb
    82 ifeq ($(DH_OPTIONS),-a)
    83         cp -a debian/bitlbee/DEBIAN/post* debian/bitlbee/DEBIAN/pre* debian/bitlbee-libpurple/DEBIAN
     84
     85        dpkg --build debian/bitlbee ..
     86
     87binary-indep: install-indep
     88        [ "`whoami`" = "root" -a -d debian ]
     89
     90        chown -R root.root debian/bitlbee-dev/
     91        find debian/bitlbee-dev/usr/share/ -type d -exec chmod 755 {} \;
     92        find debian/bitlbee-dev/usr/share/ -type f -exec chmod 644 {} \;
     93
     94        cp debian/changelog debian/bitlbee-dev/usr/share/doc/bitlbee-dev/changelog.Debian
     95        gzip -9 debian/bitlbee-dev/usr/share/doc/bitlbee-dev/changelog.Debian
     96        cp debian/copyright debian/bitlbee-dev/usr/share/doc/bitlbee-dev/copyright
     97
     98        cd debian/bitlbee-dev; \
     99                find usr -type f -exec md5sum {} \; > DEBIAN/md5sums
     100
     101ifdef BITLBEE_FORCE_VERSION
     102        dpkg-gencontrol -ldebian/changelog -isp -pbitlbee-dev -Pdebian/bitlbee-dev -v1:$(BITLBEE_VERSION)-0
     103else
     104        dpkg-gencontrol -ldebian/changelog -isp -pbitlbee-dev -Pdebian/bitlbee-dev
    84105endif
    85         dh_shlibdeps
    86 ifdef BITLBEE_VERSION
    87         dh_gencontrol -- -v1:$(BITLBEE_VERSION)-0  -Vbee:Version=1:$(BITLBEE_VERSION)-0
    88 else
    89         dh_gencontrol -- -Vbee:Version=$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}' | sed -e 's/+[^+]*$$//')
    90 endif
    91         dh_md5sums
    92         dh_builddeb
    93106
    94 binary-indep: build install
    95         $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common
     107        dpkg --build debian/bitlbee-dev ..
    96108
    97 binary-arch: build install
    98         $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
     109binary: binary-arch binary-indep
     110build: build-arch
     111install: install-arch install-indep
    99112
    100 binary-%: build install
    101         make -f debian/rules binary-common DH_OPTIONS=-p$*
    102 
    103 binary: binary-indep binary-arch
    104 .PHONY: build clean binary-indep binary-arch binary-common binary install
     113.PHONY: build-arch build clean binary-arch binary install-arch install binary-indep install-indep
  • doc/Makefile

    r8b8def58 r38ff846  
    11-include ../Makefile.settings
    2 ifdef SRCDIR
    3 SRCDIR := $(SRCDIR)doc/
    4 endif
    52
    63all:
     
    107install:
    118        mkdir -p $(DESTDIR)$(MANDIR)/man8/ $(DESTDIR)$(MANDIR)/man5/
    12         install -m 0644 $(SRCDIR)bitlbee.8 $(DESTDIR)$(MANDIR)/man8/
    13         install -m 0644 $(SRCDIR)bitlbee.conf.5 $(DESTDIR)$(MANDIR)/man5/
     9        install -m 0644 bitlbee.8 $(DESTDIR)$(MANDIR)/man8/
     10        install -m 0644 bitlbee.conf.5 $(DESTDIR)$(MANDIR)/man5/
    1411        $(MAKE) -C user-guide $@
    1512
  • doc/user-guide/Makefile

    r8b8def58 r38ff846  
    11-include ../../Makefile.settings
    2 ifdef SRCDIR
    3 SRCDIR := $(SRCDIR)doc/user-guide/
    4 endif
    5 
    62EXTRAPARANEWLINE = 1
    73# EXTRAPARANEWLINE = 0
     
    4238        chmod 0755 $(DESTDIR)$(DATADIR)
    4339        rm -f $(DESTDIR)$(DATADIR)/help.txt # Prevent help function from breaking in running sessions
    44         install -m 0644 $(SRCDIR)help.txt $(DESTDIR)$(DATADIR)/help.txt
     40        install -m 0644 help.txt $(DESTDIR)$(DATADIR)/help.txt
    4541
    4642uninstall:
  • doc/user-guide/commands.xml

    r8b8def58 r38ff846  
    484484        </bitlbee-setting>
    485485
    486         <bitlbee-setting name="away_reply_timeout" type="integer" scope="global">
    487                 <default>3600</default>
    488 
    489                 <description>
    490                         <para>
    491                                 Most IRC servers send a user's away message every time s/he gets a private message, to inform the sender that they may not get a response immediately. With this setting set to 0, BitlBee will also behave like this.
    492                         </para>
    493 
    494                         <para>
    495                                 Since not all IRC clients do an excellent job at suppressing these messages, this setting lets BitlBee do it instead. BitlBee will wait this many seconds (or until the away state/message changes) before re-informing you that the person's away.
     486        <bitlbee-setting name="buddy_sendbuffer" type="boolean" scope="global">
     487                <default>false</default>
     488
     489                <description>
     490                        <para>
     491                                By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data.
     492                        </para>
     493
     494                        <para>
     495                                Using the <emphasis>buddy_sendbuffer_delay</emphasis> setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent.
     496                        </para>
     497
     498                        <para>
     499                                Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases.
     500                        </para>
     501                </description>
     502        </bitlbee-setting>
     503
     504        <bitlbee-setting name="buddy_sendbuffer_delay" type="integer" scope="global">
     505                <default>200</default>
     506
     507                <description>
     508
     509                        <para>
     510                                Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds.
     511                        </para>
     512
     513                        <para>
     514                                See also the <emphasis>buddy_sendbuffer</emphasis> setting.
    496515                        </para>
    497516                </description>
     
    574593
    575594        <bitlbee-setting name="handle_unknown" type="string" scope="global">
    576                 <default>add_channel</default>
     595                <default>root</default>
    577596                <possible-values>root, add, add_private, add_channel, ignore</possible-values>
    578597
     
    752771                </description>
    753772        </bitlbee-setting>
    754 
    755         <bitlbee-setting name="paste_buffer" type="boolean" scope="global">
    756                 <default>false</default>
    757 
    758                 <description>
    759                         <para>
    760                                 By default, when you send a message to someone, BitlBee forwards this message to the user immediately. When you paste a large number of lines, the lines will be sent in separate messages, which might not be very nice to read. If you enable this setting, BitlBee will buffer your messages and wait for more data.
    761                         </para>
    762 
    763                         <para>
    764                                 Using the <emphasis>paste_buffer_delay</emphasis> setting you can specify the number of seconds BitlBee should wait for more data before the complete message is sent.
    765                         </para>
    766 
    767                         <para>
    768                                 Please note that if you remove a buddy from your list (or if the connection to that user drops) and there's still data in the buffer, this data will be lost. BitlBee will not try to send the message to the user in those cases.
    769                         </para>
    770                 </description>
    771         </bitlbee-setting>
    772 
    773         <bitlbee-setting name="paste_buffer_delay" type="integer" scope="global">
    774                 <default>200</default>
    775 
    776                 <description>
    777 
    778                         <para>
    779                                 Tell BitlBee after how many (mili)seconds a buffered message should be sent. Values greater than 5 will be interpreted as miliseconds, 5 and lower as seconds.
    780                         </para>
    781 
    782                         <para>
    783                                 See also the <emphasis>paste_buffer</emphasis> setting.
    784                         </para>
    785                 </description>
    786         </bitlbee-setting>
    787773       
    788774        <bitlbee-setting name="port" type="integer" scope="account">
     
    11421128
    11431129        <bitlbee-command name="identify">
    1144                 <syntax>identify [-noload|-force] &lt;password&gt;</syntax>
     1130                <syntax>identify &lt;password&gt;</syntax>
    11451131                <short-description>Identify yourself with your password</short-description>
    11461132
     
    11521138                        <para>
    11531139                                Once you're registered, you can change your password using <emphasis>set password &lt;password&gt;</emphasis>.
    1154                         </para>
    1155 
    1156                         <para>
    1157                                 The <emphasis>-noload</emphasis> and <emphasis>-force</emphasis> flags can be used to identify when you're logged into some IM accounts already. <emphasis>-force</emphasis> will let you identify yourself and load all saved accounts (and keep the accounts you're logged into already).
    1158                         </para>
    1159                        
    1160                         <para>
    1161                                 <emphasis>-noload</emphasis> will log you in but not load any accounts and settings saved under your current nickname. These will be overwritten once you save your settings (i.e. when you disconnect).
    11621140                        </para>
    11631141                </description>
     
    12041182
    12051183        </bitlbee-command>
    1206        
    1207         <bitlbee-command name="transfers">
    1208                 <short-description>Monitor, cancel, or reject file transfers</short-description>
    1209                 <syntax>transfers [&lt;cancel&gt; id | &lt;reject&gt;]</syntax>
    1210                
    1211                 <description>
    1212                         <para>
    1213                                 Without parameters the currently pending file transfers and their status will be listed. Available actions are <emphasis>cancel</emphasis> and <emphasis>reject</emphasis>. See <emphasis>help transfers &lt;action&gt;</emphasis> for more information.
    1214                         </para>
    1215 
    1216                         <ircexample>
    1217                                 <ircline nick="ulim">transfers</ircline>
    1218                         </ircexample>
    1219                 </description>
    1220                
    1221                 <bitlbee-command name="cancel">
    1222                         <short-description>Cancels the file transfer with the given id</short-description>
    1223                         <syntax>transfers &lt;cancel&gt; id</syntax>
    1224 
    1225                         <description>
    1226                                 <para>Cancels the file transfer with the given id</para>
    1227                         </description>
    1228 
    1229                         <ircexample>
    1230                                 <ircline nick="ulim">transfers cancel 1</ircline>
    1231                                 <ircline nick="root">Canceling file transfer for test</ircline>
    1232                         </ircexample>
    1233                 </bitlbee-command>
    1234 
    1235                 <bitlbee-command name="reject">
    1236                         <short-description>Rejects all incoming transfers</short-description>
    1237                         <syntax>transfers &lt;reject&gt;</syntax>
    1238 
    1239                         <description>
    1240                                 <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is neccessary. Or is it?</para>
    1241                         </description>
    1242 
    1243                         <ircexample>
    1244                                 <ircline nick="ulim">transfers reject</ircline>
    1245                         </ircexample>
    1246                 </bitlbee-command>
    1247         </bitlbee-command>
    1248        
    12491184</chapter>
  • doc/user-guide/help.xml

    r8b8def58 r38ff846  
    1414  <varlistentry><term>quickstart</term><listitem><para>A short introduction into BitlBee</para></listitem></varlistentry>
    1515  <varlistentry><term>commands</term><listitem><para>All available commands and settings</para></listitem></varlistentry>
    16   <varlistentry><term>channels</term><listitem><para>About creating and customizing channels</para></listitem></varlistentry>
    1716  <varlistentry><term>away</term><listitem><para>About setting away states</para></listitem></varlistentry>
    1817  <varlistentry><term>smileys</term><listitem><para>A summary of some non-standard smileys you might find and fail to understand</para></listitem></varlistentry>
  • doc/user-guide/misc.xml

    r8b8def58 r38ff846  
    117117</sect1>
    118118
    119 <sect1 id="nick_changes">
    120 <title>Changing your nickname</title>
    121 
    122 <para>
    123 BitlBee now allows you to change your nickname. So far this was not possible because it made managing saved accounts more complicated.
    124 </para>
    125 
    126 <para>
    127 The restriction no longer exists now though. When you change your nick (just using the <emphasis>/nick</emphasis> command), your logged-in status will be reset, which means any changes made to your settings/accounts will not be saved.
    128 </para>
    129 
    130 <para>
    131 To restore your logged-in status, you need to either use the <emphasis>register</emphasis> command to create an account under the new nickname, or use <emphasis>identify -noload</emphasis> to re-identify yourself under the new nickname. The <emphasis>-noload</emphasis> flag tells the command to verify your password and log you in, but not load any new settings. See <emphasis>help identify</emphasis> for more information.
    132 </para>
    133 
    134 </sect1>
    135 
    136 <sect1 id="channels">
    137 <title>Dealing with channels</title>
    138 
    139 <para>
    140 You can have as many channels in BitlBee as you want. You maintain your channel list using the <emphasis>channel</emphasis> command. You can create new channels by just joining them, like on regular IRC networks.
    141 </para>
    142 
    143 <para>
    144 You can create two kinds of channels. Control channels, and groupchat channels. By default, BitlBee will set up new channels as control channels if their name starts with an &amp;, and as chat channels if it starts with a #.
    145 </para>
    146 
    147 <para>
    148 Control channels are where you see your contacts. By default, you will have one control channel called &amp;bitlbee, containing all your contacts. But you can create more, if you want, and divide your contact list accross several channels.
    149 </para>
    150 
    151 <para>
    152 For example, you can have one channel with all contacts from your MSN Messenger account in it. Or all contacts from the group called "Work".
    153 </para>
    154 
    155 <para>
    156 Type <emphasis>help channels2</emphasis> to read more.
    157 </para>
    158 
    159 </sect1>
    160 
    161 <sect1 id="channels2">
    162 <title>Creating a channel</title>
    163 
    164 <para>
    165 When you create a new channel, BitlBee will try to guess from its name which contacts to fill it with. For example, if the channel name (excluding the &amp;) matches the name of a group in which you have one or more contacts, the channel will contain all those contacts.
    166 </para>
    167 
    168 <para>
    169 Any valid account ID (so a number, protocol name or part of screenname, as long as it's unique) can also be used as a channel name. So if you just join &amp;msn, it will contain all your MSN contacts (as long as you have only one MSN account set up). And if you have a Facebook account set up, you can see its contacts by just joining &amp;facebook.
    170 </para>
    171 
    172 <para>
    173 To start a simple group chat, you simply join a channel which a name starting with #, and invite people into it. All people you invite have to be on the same IM network and contact list.
    174 </para>
    175 
    176 <para>
    177 If you want to configure your own channels, you can use the <emphasis>channel set</emphasis>.
    178 </para>
    179 
    180 </sect1>
    181 
    182119</chapter>
  • help.c

    r8b8def58 r38ff846  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2009 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    169169        return NULL;
    170170}
    171 
    172 int help_add_mem( help_t **help, const char *title, const char *content )
    173 {
    174         help_t *h, *l = NULL;
    175        
    176         for( h = *help; h; h = h->next )
    177         {
    178                 if( g_strcasecmp( h->title, title ) == 0 )
    179                         return 0;
    180                
    181                 l = h;
    182         }
    183        
    184         if( l )
    185                 h = l->next = g_new0( struct help, 1 );
    186         else
    187                 *help = h = g_new0( struct help, 1 );
    188         h->fd = -1;
    189         h->title = g_strdup( title );
    190         h->length = strlen( content );
    191         h->offset.mem_offset = g_strdup( content );
    192        
    193         return 1;
    194 }
  • help.h

    r8b8def58 r38ff846  
    4646void help_free( help_t **help );
    4747char *help_get( help_t **help, char *title );
    48 int help_add_mem( help_t **help, const char *title, const char *content_ );
    4948
    5049#endif
  • ipc.c

    r8b8def58 r38ff846  
    138138       
    139139        if( strchr( irc->umode, 'w' ) )
    140                 irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] );
     140                irc_write( irc, ":%s WALLOPS :%s", irc->myhost, cmd[1] );
    141141}
    142142
     
    147147       
    148148        if( strchr( irc->umode, 's' ) )
    149                 irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] );
     149                irc_write( irc, ":%s NOTICE %s :%s", irc->myhost, irc->nick, cmd[1] );
    150150}
    151151
     
    156156       
    157157        if( strchr( irc->umode, 'o' ) )
    158                 irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] );
     158                irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->myhost, irc->nick, cmd[1] );
    159159}
    160160
     
    176176                return;
    177177       
    178         if( nick_cmp( cmd[1], irc->user->nick ) != 0 )
     178        if( nick_cmp( cmd[1], irc->nick ) != 0 )
    179179                return;         /* It's not for us. */
    180180       
    181         irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] );
     181        irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );
    182182        irc_abort( irc, 0, "Killed by operator: %s", cmd[2] );
    183183}
     
    188188                ipc_to_master_str( "HELLO\r\n" );
    189189        else
    190                 ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
     190                ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    191191}
    192192
     
    514514        }
    515515               
    516         child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
     516        child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    517517       
    518518        child_list = g_slist_append( child_list, child );
     
    552552        }
    553553       
    554         b_input_add( serversock, B_EV_IO_READ, new_ipc_client, NULL );
     554        b_input_add( serversock, GAIM_INPUT_READ, new_ipc_client, NULL );
    555555       
    556556        return 1;
     
    597597                        return 0;
    598598                }
    599                 child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
     599                child->ipc_inpa = b_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
    600600               
    601601                child_list = g_slist_append( child_list, child );
  • irc.c

    r8b8def58 r38ff846  
    55  \********************************************************************/
    66
    7 /* The IRC-based UI (for now the only one)                              */
     7/* The big hairy IRCd part of the project                               */
    88
    99/*
     
    2424*/
    2525
     26#define BITLBEE_CORE
    2627#include "bitlbee.h"
     28#include "sock.h"
     29#include "crypting.h"
    2730#include "ipc.h"
    28 #include "dcc.h"
    29 
    30 GSList *irc_connection_list;
    31 
    32 static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond );
    33 static char *set_eval_charset( set_t *set, char *value );
    34 static char *set_eval_password( set_t *set, char *value );
     31
     32static gboolean irc_userping( gpointer _irc, int fd, b_input_condition cond );
     33
     34GSList *irc_connection_list = NULL;
     35
     36static char *set_eval_password( set_t *set, char *value )
     37{
     38        irc_t *irc = set->data;
     39       
     40        if( irc->status & USTATUS_IDENTIFIED && value )
     41        {
     42                irc_setpass( irc, value );
     43                return NULL;
     44        }
     45        else
     46        {
     47                return SET_INVALID;
     48        }
     49}
     50
     51static char *set_eval_charset( set_t *set, char *value )
     52{
     53        irc_t *irc = set->data;
     54        char *test;
     55        gsize test_bytes = 0;
     56        GIConv ic, oc;
     57
     58        if( g_strcasecmp( value, "none" ) == 0 )
     59                value = g_strdup( "utf-8" );
     60
     61        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     62        {
     63                return NULL;
     64        }
     65       
     66        /* Do a test iconv to see if the user picked an IRC-compatible
     67           charset (for example utf-16 goes *horribly* wrong). */
     68        if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL ||
     69            test_bytes > 1 )
     70        {
     71                g_free( test );
     72                g_iconv_close( oc );
     73                irc_usermsg( irc, "Unsupported character set: The IRC protocol "
     74                                  "only supports 8-bit character sets." );
     75                return NULL;
     76        }
     77        g_free( test );
     78       
     79        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
     80        {
     81                g_iconv_close( oc );
     82                return NULL;
     83        }
     84       
     85        if( irc->iconv != (GIConv) -1 )
     86                g_iconv_close( irc->iconv );
     87        if( irc->oconv != (GIConv) -1 )
     88                g_iconv_close( irc->oconv );
     89       
     90        irc->iconv = ic;
     91        irc->oconv = oc;
     92
     93        return value;
     94}
     95
     96static char *set_eval_away_status( set_t *set, char *value )
     97{
     98        irc_t *irc = set->data;
     99        account_t *a;
     100       
     101        g_free( set->value );
     102        set->value = g_strdup( value );
     103       
     104        for( a = irc->accounts; a; a = a->next )
     105        {
     106                struct im_connection *ic = a->ic;
     107               
     108                if( ic && ic->flags & OPT_LOGGED_IN )
     109                        imc_away_send_update( ic );
     110        }
     111       
     112        return value;
     113}
    35114
    36115irc_t *irc_new( int fd )
     
    39118        struct sockaddr_storage sock;
    40119        socklen_t socklen = sizeof( sock );
    41         char *host = NULL, *myhost = NULL;
    42         irc_user_t *iu;
    43120        set_t *s;
    44         bee_t *b;
    45121       
    46122        irc = g_new0( irc_t, 1 );
     
    49125        sock_make_nonblocking( irc->fd );
    50126       
    51         irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc );
     127        irc->r_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_READ, bitlbee_io_current_client_read, irc );
    52128       
    53129        irc->status = USTATUS_OFFLINE;
    54130        irc->last_pong = gettime();
    55131       
    56         irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal );
     132        irc->userhash = g_hash_table_new( g_str_hash, g_str_equal );
    57133        irc->watches = g_hash_table_new( g_str_hash, g_str_equal );
     134       
     135        strcpy( irc->umode, UMODE );
     136        irc->mynick = g_strdup( ROOT_NICK );
     137        irc->channel = g_strdup( ROOT_CHAN );
    58138       
    59139        irc->iconv = (GIConv) -1;
     
    62142        if( global.conf->hostname )
    63143        {
    64                 myhost = g_strdup( global.conf->hostname );
     144                irc->myhost = g_strdup( global.conf->hostname );
    65145        }
    66146        else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 )
     
    71151                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    72152                {
    73                         myhost = g_strdup( ipv6_unwrap( buf ) );
     153                        irc->myhost = g_strdup( ipv6_unwrap( buf ) );
    74154                }
    75155        }
     
    82162                                 NI_MAXHOST, NULL, 0, 0 ) == 0 )
    83163                {
    84                         host = g_strdup( ipv6_unwrap( buf ) );
    85                 }
    86         }
    87        
    88         if( host == NULL )
    89                 host = g_strdup( "localhost.localdomain" );
    90         if( myhost == NULL )
    91                 myhost = g_strdup( "localhost.localdomain" );
     164                        irc->host = g_strdup( ipv6_unwrap( buf ) );
     165                }
     166        }
     167       
     168        if( irc->host == NULL )
     169                irc->host = g_strdup( "localhost.localdomain" );
     170        if( irc->myhost == NULL )
     171                irc->myhost = g_strdup( "localhost.localdomain" );
    92172       
    93173        if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 )
    94174                irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc );
     175       
     176        irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );
    95177
    96178        irc_connection_list = g_slist_append( irc_connection_list, irc );
    97179       
    98         b = irc->b = bee_new();
    99         b->ui_data = irc;
    100         b->ui = &irc_ui_funcs;
    101        
    102         s = set_add( &b->set, "away_devoice", "true", set_eval_away_devoice, irc );
    103         s = set_add( &b->set, "away_reply_timeout", "3600", set_eval_int, irc );
    104         s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc );
    105         s = set_add( &b->set, "default_target", "root", NULL, irc );
    106         s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc );
    107         s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc );
    108         s = set_add( &b->set, "handle_unknown", "add_channel", NULL, irc );
    109         s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc );
    110         s = set_add( &b->set, "ops", "both", set_eval_irc_channel_ops, irc );
    111         s = set_add( &b->set, "paste_buffer", "false", set_eval_bool, irc );
    112         s->old_key = g_strdup( "buddy_sendbuffer" );
    113         s = set_add( &b->set, "paste_buffer_delay", "200", set_eval_int, irc );
    114         s->old_key = g_strdup( "buddy_sendbuffer_delay" );
    115         s = set_add( &b->set, "password", NULL, set_eval_password, irc );
     180        s = set_add( &irc->set, "away", NULL,  set_eval_away_status, irc );
    116181        s->flags |= SET_NULL_OK;
    117         s = set_add( &b->set, "private", "true", set_eval_bool, irc );
    118         s = set_add( &b->set, "query_order", "lifo", NULL, irc );
    119         s = set_add( &b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc );
    120         s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc );
    121         s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc );
    122         s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc );
    123         s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc );
    124 
    125         irc->root = iu = irc_user_new( irc, ROOT_NICK );
    126         iu->host = g_strdup( myhost );
    127         iu->fullname = g_strdup( ROOT_FN );
    128         iu->f = &irc_user_root_funcs;
    129        
    130         iu = irc_user_new( irc, NS_NICK );
    131         iu->host = g_strdup( myhost );
    132         iu->fullname = g_strdup( ROOT_FN );
    133         iu->f = &irc_user_root_funcs;
    134        
    135         irc->user = g_new0( irc_user_t, 1 );
    136         irc->user->host = g_strdup( host );
     182        s = set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
     183        s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
     184        s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc );
     185        s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
     186        s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
     187        s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
     188        s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
     189        s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc );
     190        s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
     191        s = set_add( &irc->set, "default_target", "root", NULL, irc );
     192        s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
     193        s = set_add( &irc->set, "display_timestamps", "true", set_eval_bool, irc );
     194        s = set_add( &irc->set, "handle_unknown", "root", NULL, irc );
     195        s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
     196        s = set_add( &irc->set, "ops", "both", set_eval_ops, irc );
     197        s = set_add( &irc->set, "password", NULL, set_eval_password, irc );
     198        s->flags |= SET_NULL_OK;
     199        s = set_add( &irc->set, "private", "true", set_eval_bool, irc );
     200        s = set_add( &irc->set, "query_order", "lifo", NULL, irc );
     201        s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
     202        s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
     203        s = set_add( &irc->set, "show_offline", "false", set_eval_bool, irc );
     204        s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
     205        s = set_add( &irc->set, "status", NULL,  set_eval_away_status, irc );
     206        s->flags |= SET_NULL_OK;
     207        s = set_add( &irc->set, "strip_html", "true", NULL, irc );
     208        s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc );
     209        s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
     210        s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
    137211       
    138212        conf_loaddefaults( irc );
    139213       
    140214        /* Evaluator sets the iconv/oconv structures. */
    141         set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) );
    142        
    143         irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" );
    144        
    145         g_free( myhost );
    146         g_free( host );
    147        
    148         nogaim_init();
    149        
    150         return irc;
     215        set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
     216       
     217        return( irc );
    151218}
    152219
     
    169236               
    170237                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    171                                    irc->user->nick ? irc->user->nick : "(NONE)", irc->user->host, reason );
     238                                   irc->nick ? irc->nick : "(NONE)", irc->host, reason );
    172239               
    173240                g_free( reason );
     
    179246               
    180247                ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n",
    181                                    irc->user->nick ? irc->user->nick : "(NONE)", irc->user->host, "No reason given" );
     248                                   irc->nick ? irc->nick : "(NONE)", irc->host, "No reason given" );
    182249        }
    183250       
     
    200267}
    201268
    202 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data );
    203 
     269static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
     270{
     271        g_free( key );
     272       
     273        return( TRUE );
     274}
     275
     276/* Because we have no garbage collection, this is quite annoying */
    204277void irc_free( irc_t * irc )
    205278{
     279        user_t *user, *usertmp;
     280       
    206281        log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd );
    207282       
    208         if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) )
     283        if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->set, "save_on_quit" ) )
    209284                if( storage_save( irc, NULL, TRUE ) != STORAGE_OK )
    210                         log_message( LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick );
     285                        irc_usermsg( irc, "Error while saving settings!" );
    211286       
    212287        irc_connection_list = g_slist_remove( irc_connection_list, irc );
     288       
     289        while( irc->accounts )
     290        {
     291                if( irc->accounts->ic )
     292                        imc_logout( irc->accounts->ic, FALSE );
     293                else if( irc->accounts->reconnect )
     294                        cancel_auto_reconnect( irc->accounts );
     295               
     296                if( irc->accounts->ic == NULL )
     297                        account_del( irc, irc->accounts );
     298                else
     299                        /* Nasty hack, but account_del() doesn't work in this
     300                           case and we don't want infinite loops, do we? ;-) */
     301                        irc->accounts = irc->accounts->next;
     302        }
    213303       
    214304        while( irc->queries != NULL )
    215305                query_del( irc, irc->queries );
    216306       
    217         /* This is a little bit messy: bee_free() frees all b->users which
    218            calls us back to free the corresponding irc->users. So do this
    219            before we clear the remaining ones ourselves. */
    220         bee_free( irc->b );
    221        
    222         while( irc->users )
    223                 irc_user_free( irc, (irc_user_t *) irc->users->data );
    224        
    225         while( irc->channels )
    226                 irc_channel_free( irc->channels->data );
     307        while( irc->set )
     308                set_del( &irc->set, irc->set->key );
     309       
     310        if (irc->users != NULL)
     311        {
     312                user = irc->users;
     313                while( user != NULL )
     314                {
     315                        g_free( user->nick );
     316                        g_free( user->away );
     317                        g_free( user->handle );
     318                        if( user->user != user->nick ) g_free( user->user );
     319                        if( user->host != user->nick ) g_free( user->host );
     320                        if( user->realname != user->nick ) g_free( user->realname );
     321                        b_event_remove( user->sendbuf_timer );
     322                                       
     323                        usertmp = user;
     324                        user = user->next;
     325                        g_free( usertmp );
     326                }
     327        }
    227328       
    228329        if( irc->ping_source_id > 0 )
     
    236337        irc->fd = -1;
    237338       
    238         g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL );
    239         g_hash_table_destroy( irc->nick_user_hash );
     339        g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
     340        g_hash_table_destroy( irc->userhash );
    240341       
    241342        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     
    249350        g_free( irc->sendbuffer );
    250351        g_free( irc->readbuffer );
     352       
     353        g_free( irc->nick );
     354        g_free( irc->user );
     355        g_free( irc->host );
     356        g_free( irc->realname );
    251357        g_free( irc->password );
    252         g_free( irc->last_root_cmd );
     358       
     359        g_free( irc->myhost );
     360        g_free( irc->mynick );
     361       
     362        g_free( irc->channel );
     363       
     364        g_free( irc->last_target );
    253365       
    254366        g_free( irc );
     
    262374}
    263375
    264 static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data )
    265 {
    266         g_free( key );
    267        
    268         return( TRUE );
    269 }
    270 
    271376/* USE WITH CAUTION!
    272377   Sets pass without checking */
    273 void irc_setpass (irc_t *irc, const char *pass)
     378void irc_setpass (irc_t *irc, const char *pass) 
    274379{
    275380        g_free (irc->password);
     
    282387}
    283388
    284 static char *set_eval_password( set_t *set, char *value )
    285 {
    286         irc_t *irc = set->data;
    287        
    288         if( irc->status & USTATUS_IDENTIFIED && value )
    289         {
    290                 irc_setpass( irc, value );
    291                 return NULL;
    292         }
    293         else
    294         {
    295                 return SET_INVALID;
    296         }
    297 }
    298 
    299 static char **irc_splitlines( char *buffer );
    300 
    301389void irc_process( irc_t *irc )
    302390{
     
    306394        if( irc->readbuffer != NULL )
    307395        {
    308                 lines = irc_splitlines( irc->readbuffer );
     396                lines = irc_tokenize( irc->readbuffer );
    309397               
    310398                for( i = 0; *lines[i] != '\0'; i ++ )
     
    343431                                                                  "`help set charset' for more information. Your "
    344432                                                                  "message was ignored.",
    345                                                                   set_getstr( &irc->b->set, "charset" ) );
     433                                                                  set_getstr( &irc->set, "charset" ) );
    346434                                               
    347435                                                g_free( conv );
     
    350438                                        else
    351439                                        {
    352                                                 irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host,
     440                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
    353441                                                           "Warning: invalid characters received at login time." );
    354442                                               
     
    388476}
    389477
    390 /* Splits a long string into separate lines. The array is NULL-terminated
    391    and, unless the string contains an incomplete line at the end, ends with
    392    an empty string. Could use g_strsplit() but this one does it in-place.
    393    (So yes, it's destructive.) */
    394 static char **irc_splitlines( char *buffer )
     478/* Splits a long string into separate lines. The array is NULL-terminated and, unless the string
     479   contains an incomplete line at the end, ends with an empty string. */
     480char **irc_tokenize( char *buffer )
    395481{
    396482        int i, j, n = 3;
     
    523609}
    524610
     611void irc_reply( irc_t *irc, int code, char *format, ... )
     612{
     613        char text[IRC_MAX_LINE];
     614        va_list params;
     615       
     616        va_start( params, format );
     617        g_vsnprintf( text, IRC_MAX_LINE, format, params );
     618        va_end( params );
     619        irc_write( irc, ":%s %03d %s %s", irc->myhost, code, irc->nick?irc->nick:"*", text );
     620       
     621        return;
     622}
     623
     624int irc_usermsg( irc_t *irc, char *format, ... )
     625{
     626        char text[1024];
     627        va_list params;
     628        char is_private = 0;
     629        user_t *u;
     630       
     631        u = user_find( irc, irc->mynick );
     632        is_private = u->is_private;
     633       
     634        va_start( params, format );
     635        g_vsnprintf( text, sizeof( text ), format, params );
     636        va_end( params );
     637       
     638        return( irc_msgfrom( irc, u->nick, text ) );
     639}
     640
    525641void irc_write( irc_t *irc, char *format, ... )
    526642{
     
    533649        return;
    534650}
    535 
    536 void irc_write_all( int now, char *format, ... )
    537 {
    538         va_list params;
    539         GSList *temp;   
    540        
    541         va_start( params, format );
    542        
    543         temp = irc_connection_list;
    544         while( temp != NULL )
    545         {
    546                 irc_t *irc = temp->data;
    547                
    548                 if( now )
    549                 {
    550                         g_free( irc->sendbuffer );
    551                         irc->sendbuffer = g_strdup( "\r\n" );
    552                 }
    553                 irc_vawrite( temp->data, format, params );
    554                 if( now )
    555                 {
    556                         bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE );
    557                 }
    558                 temp = temp->next;
    559         }
    560        
    561         va_end( params );
    562         return;
    563 }
    564651
    565652void irc_vawrite( irc_t *irc, char *format, va_list params )
     
    609696                   in the event queue. */
    610697                /* Really can't be done as long as the code doesn't do error checking very well:
    611                 if( bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ) ) */
     698                if( bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE ) ) */
    612699               
    613700                /* So just always do it via the event handler. */
    614                 irc->w_watch_source_id = b_input_add( irc->fd, B_EV_IO_WRITE, bitlbee_io_current_client_write, irc );
     701                irc->w_watch_source_id = b_input_add( irc->fd, GAIM_INPUT_WRITE, bitlbee_io_current_client_write, irc );
    615702        }
    616703       
     
    618705}
    619706
     707void irc_write_all( int now, char *format, ... )
     708{
     709        va_list params;
     710        GSList *temp;   
     711       
     712        va_start( params, format );
     713       
     714        temp = irc_connection_list;
     715        while( temp != NULL )
     716        {
     717                irc_t *irc = temp->data;
     718               
     719                if( now )
     720                {
     721                        g_free( irc->sendbuffer );
     722                        irc->sendbuffer = g_strdup( "\r\n" );
     723                }
     724                irc_vawrite( temp->data, format, params );
     725                if( now )
     726                {
     727                        bitlbee_io_current_client_write( irc, irc->fd, GAIM_INPUT_WRITE );
     728                }
     729                temp = temp->next;
     730        }
     731       
     732        va_end( params );
     733        return;
     734}
     735
     736void irc_names( irc_t *irc, char *channel )
     737{
     738        user_t *u;
     739        char namelist[385] = "";
     740        struct groupchat *c = NULL;
     741        char *ops = set_getstr( &irc->set, "ops" );
     742       
     743        /* RFCs say there is no error reply allowed on NAMES, so when the
     744           channel is invalid, just give an empty reply. */
     745       
     746        if( g_strcasecmp( channel, irc->channel ) == 0 )
     747        {
     748                for( u = irc->users; u; u = u->next ) if( u->online )
     749                {
     750                        if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
     751                        {
     752                                irc_reply( irc, 353, "= %s :%s", channel, namelist );
     753                                *namelist = 0;
     754                        }
     755                       
     756                        if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) )
     757                                strcat( namelist, "+" );
     758                        else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ||
     759                                 ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) )
     760                                strcat( namelist, "@" );
     761                       
     762                        strcat( namelist, u->nick );
     763                        strcat( namelist, " " );
     764                }
     765        }
     766        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
     767        {
     768                GList *l;
     769               
     770                /* root and the user aren't in the channel userlist but should
     771                   show up in /NAMES, so list them first: */
     772                sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick,
     773                                                 strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick );
     774               
     775                for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )
     776                {
     777                        if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 )
     778                        {
     779                                irc_reply( irc, 353, "= %s :%s", channel, namelist );
     780                                *namelist = 0;
     781                        }
     782                       
     783                        strcat( namelist, u->nick );
     784                        strcat( namelist, " " );
     785                }
     786        }
     787       
     788        if( *namelist )
     789                irc_reply( irc, 353, "= %s :%s", channel, namelist );
     790       
     791        irc_reply( irc, 366, "%s :End of /NAMES list", channel );
     792}
     793
    620794int irc_check_login( irc_t *irc )
    621795{
    622         if( irc->user->user && irc->user->nick )
     796        if( irc->user && irc->nick )
    623797        {
    624798                if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) )
    625799                {
    626                         irc_send_num( irc, 464, ":This server is password-protected." );
     800                        irc_reply( irc, 464, ":This server is password-protected." );
    627801                        return 0;
    628802                }
    629803                else
    630804                {
    631                         irc_channel_t *ic;
    632                         irc_user_t *iu = irc->user;
    633                        
    634                         irc->user = irc_user_new( irc, iu->nick );
    635                         irc->user->user = iu->user;
    636                         irc->user->host = iu->host;
    637                         irc->user->fullname = iu->fullname;
    638                         irc->user->f = &irc_user_self_funcs;
    639                         g_free( iu->nick );
    640                         g_free( iu );
    641                        
    642                         if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
    643                                 ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
    644                        
    645                         irc->status |= USTATUS_LOGGED_IN;
    646                        
    647                         irc_send_login( irc );
    648                        
    649                         irc->umode[0] = '\0';
    650                         irc_umode_set( irc, "+" UMODE, TRUE );
    651                        
    652                         ic = irc->default_channel = irc_channel_new( irc, ROOT_CHAN );
    653                         irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root );
    654                         irc_channel_add_user( ic, irc->user );
    655                        
    656                         irc->last_root_cmd = g_strdup( ROOT_CHAN );
    657                        
    658                         irc_send_msg( irc->root, "PRIVMSG", ROOT_CHAN,
    659                                       "Welcome to the BitlBee gateway!\n\n"
    660                                       "If you've never used BitlBee before, please do read the help "
    661                                       "information using the \x02help\x02 command. Lots of FAQs are "
    662                                       "answered there.\n"
    663                                       "If you already have an account on this server, just use the "
    664                                       "\x02identify\x02 command to identify yourself.", NULL );
    665                        
    666                         /* This is for bug #209 (use PASS to identify to NickServ). */
    667                         if( irc->password != NULL )
    668                         {
    669                                 char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
    670                                
    671                                 irc_setpass( irc, NULL );
    672                                 root_command( irc, send_cmd );
    673                                 g_free( send_cmd[1] );
    674                         }
    675                        
     805                        irc_login( irc );
    676806                        return 1;
    677807                }
     
    684814}
    685815
    686 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv )
     816void irc_login( irc_t *irc )
     817{
     818        user_t *u;
     819       
     820        irc_reply( irc,   1, ":Welcome to the BitlBee gateway, %s", irc->nick );
     821        irc_reply( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->myhost );
     822        irc_reply( irc,   3, ":%s", IRCD_INFO );
     823        irc_reply( irc,   4, "%s %s %s %s", irc->myhost, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
     824        irc_reply( irc,   5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee "
     825                             "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server",
     826                             CTYPES, CMODES, MAX_NICK_LENGTH - 1 );
     827        irc_motd( irc );
     828        irc->umode[0] = '\0';
     829        irc_umode_set( irc, "+" UMODE, 1 );
     830
     831        u = user_add( irc, irc->mynick );
     832        u->host = g_strdup( irc->myhost );
     833        u->realname = g_strdup( ROOT_FN );
     834        u->online = 1;
     835        u->send_handler = root_command_string;
     836        u->is_private = 0; /* [SH] The channel is root's personal playground. */
     837        irc_spawn( irc, u );
     838       
     839        u = user_add( irc, NS_NICK );
     840        u->host = g_strdup( irc->myhost );
     841        u->realname = g_strdup( ROOT_FN );
     842        u->online = 0;
     843        u->send_handler = root_command_string;
     844        u->is_private = 1; /* [SH] NickServ is not in the channel, so should always /query. */
     845       
     846        u = user_add( irc, irc->nick );
     847        u->user = g_strdup( irc->user );
     848        u->host = g_strdup( irc->host );
     849        u->realname = g_strdup( irc->realname );
     850        u->online = 1;
     851        irc_spawn( irc, u );
     852       
     853        irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
     854                          "If you've never used BitlBee before, please do read the help "
     855                          "information using the \x02help\x02 command. Lots of FAQs are "
     856                          "answered there.\n"
     857                          "If you already have an account on this server, just use the "
     858                          "\x02identify\x02 command to identify yourself." );
     859       
     860        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     861                ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
     862       
     863        irc->status |= USTATUS_LOGGED_IN;
     864       
     865        /* This is for bug #209 (use PASS to identify to NickServ). */
     866        if( irc->password != NULL )
     867        {
     868                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
     869               
     870                irc_setpass( irc, NULL );
     871                root_command( irc, send_cmd );
     872                g_free( send_cmd[1] );
     873        }
     874}
     875
     876void irc_motd( irc_t *irc )
     877{
     878        int fd;
     879       
     880        fd = open( global.conf->motdfile, O_RDONLY );
     881        if( fd == -1 )
     882        {
     883                irc_reply( irc, 422, ":We don't need MOTDs." );
     884        }
     885        else
     886        {
     887                char linebuf[80];       /* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */
     888                char *add, max;
     889                int len;
     890               
     891                linebuf[79] = len = 0;
     892                max = sizeof( linebuf ) - 1;
     893               
     894                irc_reply( irc, 375, ":- %s Message Of The Day - ", irc->myhost );
     895                while( read( fd, linebuf + len, 1 ) == 1 )
     896                {
     897                        if( linebuf[len] == '\n' || len == max )
     898                        {
     899                                linebuf[len] = 0;
     900                                irc_reply( irc, 372, ":- %s", linebuf );
     901                                len = 0;
     902                        }
     903                        else if( linebuf[len] == '%' )
     904                        {
     905                                read( fd, linebuf + len, 1 );
     906                                if( linebuf[len] == 'h' )
     907                                        add = irc->myhost;
     908                                else if( linebuf[len] == 'v' )
     909                                        add = BITLBEE_VERSION;
     910                                else if( linebuf[len] == 'n' )
     911                                        add = irc->nick;
     912                                else
     913                                        add = "%";
     914                               
     915                                strncpy( linebuf + len, add, max - len );
     916                                while( linebuf[++len] );
     917                        }
     918                        else if( len < max )
     919                        {
     920                                len ++;
     921                        }
     922                }
     923                irc_reply( irc, 376, ":End of MOTD" );
     924                close( fd );
     925        }
     926}
     927
     928void irc_topic( irc_t *irc, char *channel )
     929{
     930        struct groupchat *c = irc_chat_by_channel( irc, channel );
     931       
     932        if( c && c->topic )
     933                irc_reply( irc, 332, "%s :%s", channel, c->topic );
     934        else if( g_strcasecmp( channel, irc->channel ) == 0 )
     935                irc_reply( irc, 332, "%s :%s", channel, CONTROL_TOPIC );
     936        else
     937                irc_reply( irc, 331, "%s :No topic for this channel", channel );
     938}
     939
     940void irc_umode_set( irc_t *irc, char *s, int allow_priv )
    687941{
    688942        /* allow_priv: Set to 0 if s contains user input, 1 if you want
    689943           to set a "privileged" mode (+o, +R, etc). */
    690         char m[128], st = 1;
    691         const char *t;
     944        char m[256], st = 1, *t;
    692945        int i;
    693946        char changes[512], *p, st2 = 2;
     
    697950       
    698951        for( t = irc->umode; *t; t ++ )
    699                 if( *t < sizeof( m ) )
    700                         m[(int)*t] = 1;
    701        
     952                m[(int)*t] = 1;
     953
    702954        p = changes;
    703955        for( t = s; *t; t ++ )
     
    705957                if( *t == '+' || *t == '-' )
    706958                        st = *t == '+';
    707                 else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) ||
    708                          ( st == 1 && strchr( UMODES, *t ) ) ||
    709                          ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) )
     959                else if( st == 0 || ( strchr( UMODES, *t ) || ( allow_priv && strchr( UMODES_PRIV, *t ) ) ) )
    710960                {
    711961                        if( m[(int)*t] != st)
     
    724974        memset( irc->umode, 0, sizeof( irc->umode ) );
    725975       
    726         for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
     976        for( i = 0; i < 256 && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ )
    727977                if( m[i] )
    728978                        irc->umode[strlen(irc->umode)] = i;
    729979       
    730980        if( badflag )
    731                 irc_send_num( irc, 501, ":Unknown MODE flag" );
     981                irc_reply( irc, 501, ":Unknown MODE flag" );
     982        /* Deliberately no !user@host on the prefix here */
    732983        if( *changes )
    733                 irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick,
    734                            irc->user->user, irc->user->host, irc->user->nick,
    735                            changes );
     984                irc_write( irc, ":%s MODE %s %s", irc->nick, irc->nick, changes );
     985}
     986
     987void irc_spawn( irc_t *irc, user_t *u )
     988{
     989        irc_join( irc, u, irc->channel );
     990}
     991
     992void irc_join( irc_t *irc, user_t *u, char *channel )
     993{
     994        char *nick;
     995       
     996        if( ( g_strcasecmp( channel, irc->channel ) != 0 ) || user_find( irc, irc->nick ) )
     997                irc_write( irc, ":%s!%s@%s JOIN :%s", u->nick, u->user, u->host, channel );
     998       
     999        if( nick_cmp( u->nick, irc->nick ) == 0 )
     1000        {
     1001                irc_write( irc, ":%s MODE %s +%s", irc->myhost, channel, CMODE );
     1002                irc_names( irc, channel );
     1003                irc_topic( irc, channel );
     1004        }
     1005       
     1006        nick = g_strdup( u->nick );
     1007        nick_lc( nick );
     1008        if( g_hash_table_lookup( irc->watches, nick ) )
     1009        {
     1010                irc_reply( irc, 600, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged online" );
     1011        }
     1012        g_free( nick );
     1013}
     1014
     1015void irc_part( irc_t *irc, user_t *u, char *channel )
     1016{
     1017        irc_write( irc, ":%s!%s@%s PART %s :%s", u->nick, u->user, u->host, channel, "" );
     1018}
     1019
     1020void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker )
     1021{
     1022        irc_write( irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, kicker->host, channel, u->nick, "" );
     1023}
     1024
     1025void irc_kill( irc_t *irc, user_t *u )
     1026{
     1027        char *nick, *s;
     1028        char reason[128];
     1029       
     1030        if( u->ic && u->ic->flags & OPT_LOGGING_OUT && set_getbool( &irc->set, "simulate_netsplit" ) )
     1031        {
     1032                if( u->ic->acc->server )
     1033                        g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
     1034                                    u->ic->acc->server );
     1035                else if( ( s = strchr( u->ic->acc->user, '@' ) ) )
     1036                        g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
     1037                                    s + 1 );
     1038                else
     1039                        g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost,
     1040                                    u->ic->acc->prpl->name, irc->myhost );
     1041               
     1042                /* proto_opt might contain garbage after the : */
     1043                if( ( s = strchr( reason, ':' ) ) )
     1044                        *s = 0;
     1045        }
     1046        else
     1047        {
     1048                strcpy( reason, "Leaving..." );
     1049        }
     1050       
     1051        irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason );
     1052       
     1053        nick = g_strdup( u->nick );
     1054        nick_lc( nick );
     1055        if( g_hash_table_lookup( irc->watches, nick ) )
     1056        {
     1057                irc_reply( irc, 601, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "logged offline" );
     1058        }
     1059        g_free( nick );
     1060}
     1061
     1062int irc_send( irc_t *irc, char *nick, char *s, int flags )
     1063{
     1064        struct groupchat *c = NULL;
     1065        user_t *u = NULL;
     1066       
     1067        if( strchr( CTYPES, *nick ) )
     1068        {
     1069                if( !( c = irc_chat_by_channel( irc, nick ) ) )
     1070                {
     1071                        irc_reply( irc, 403, "%s :Channel does not exist", nick );
     1072                        return( 0 );
     1073                }
     1074        }
     1075        else
     1076        {
     1077                u = user_find( irc, nick );
     1078               
     1079                if( !u )
     1080                {
     1081                        if( irc->is_private )
     1082                                irc_reply( irc, 401, "%s :Nick does not exist", nick );
     1083                        else
     1084                                irc_usermsg( irc, "Nick `%s' does not exist!", nick );
     1085                        return( 0 );
     1086                }
     1087        }
     1088       
     1089        if( *s == 1 && s[strlen(s)-1] == 1 )
     1090        {
     1091                if( g_strncasecmp( s + 1, "ACTION", 6 ) == 0 )
     1092                {
     1093                        if( s[7] == ' ' ) s ++;
     1094                        s += 3;
     1095                        *(s++) = '/';
     1096                        *(s++) = 'm';
     1097                        *(s++) = 'e';
     1098                        *(s++) = ' ';
     1099                        s -= 4;
     1100                        s[strlen(s)-1] = 0;
     1101                }
     1102                else if( g_strncasecmp( s + 1, "VERSION", 7 ) == 0 )
     1103                {
     1104                        u = user_find( irc, irc->mynick );
     1105                        irc_privmsg( irc, u, "NOTICE", irc->nick, "", "\001VERSION BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\001" );
     1106                        return( 1 );
     1107                }
     1108                else if( g_strncasecmp( s + 1, "PING", 4 ) == 0 )
     1109                {
     1110                        u = user_find( irc, irc->mynick );
     1111                        irc_privmsg( irc, u, "NOTICE", irc->nick, "", s );
     1112                        return( 1 );
     1113                }
     1114                else if( g_strncasecmp( s + 1, "TYPING", 6 ) == 0 )
     1115                {
     1116                        if( u && u->ic && u->ic->acc->prpl->send_typing && strlen( s ) >= 10 )
     1117                        {
     1118                                time_t current_typing_notice = time( NULL );
     1119                               
     1120                                if( current_typing_notice - u->last_typing_notice >= 5 )
     1121                                {
     1122                                        u->ic->acc->prpl->send_typing( u->ic, u->handle, ( s[8] - '0' ) << 8 );
     1123                                        u->last_typing_notice = current_typing_notice;
     1124                                }
     1125                        }
     1126                        return( 1 );
     1127                }
     1128                else
     1129                {
     1130                        irc_usermsg( irc, "Non-ACTION CTCP's aren't supported" );
     1131                        return( 0 );
     1132                }
     1133        }
     1134       
     1135        if( u )
     1136        {
     1137                /* For the next message, we probably do have to send new notices... */
     1138                u->last_typing_notice = 0;
     1139                u->is_private = irc->is_private;
     1140               
     1141                if( u->is_private )
     1142                {
     1143                        if( !u->online )
     1144                                irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
     1145                        else if( u->away )
     1146                                irc_reply( irc, 301, "%s :%s", u->nick, u->away );
     1147                }
     1148               
     1149                if( u->send_handler )
     1150                {
     1151                        u->send_handler( irc, u, s, flags );
     1152                        return 1;
     1153                }
     1154        }
     1155        else if( c && c->ic && c->ic->acc && c->ic->acc->prpl )
     1156        {
     1157                return( imc_chat_msg( c, s, 0 ) );
     1158        }
     1159       
     1160        return( 0 );
     1161}
     1162
     1163static gboolean buddy_send_handler_delayed( gpointer data, gint fd, b_input_condition cond )
     1164{
     1165        user_t *u = data;
     1166       
     1167        /* Shouldn't happen, but just to be sure. */
     1168        if( u->sendbuf_len < 2 )
     1169                return FALSE;
     1170       
     1171        u->sendbuf[u->sendbuf_len-2] = 0; /* Cut off the last newline */
     1172        imc_buddy_msg( u->ic, u->handle, u->sendbuf, u->sendbuf_flags );
     1173       
     1174        g_free( u->sendbuf );
     1175        u->sendbuf = NULL;
     1176        u->sendbuf_len = 0;
     1177        u->sendbuf_timer = 0;
     1178        u->sendbuf_flags = 0;
     1179       
     1180        return FALSE;
     1181}
     1182
     1183void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags )
     1184{
     1185        if( !u || !u->ic ) return;
     1186       
     1187        if( set_getbool( &irc->set, "buddy_sendbuffer" ) && set_getint( &irc->set, "buddy_sendbuffer_delay" ) > 0 )
     1188        {
     1189                int delay;
     1190               
     1191                if( u->sendbuf_len > 0 && u->sendbuf_flags != flags)
     1192                {
     1193                        /* Flush the buffer */
     1194                        b_event_remove( u->sendbuf_timer );
     1195                        buddy_send_handler_delayed( u, -1, 0 );
     1196                }
     1197
     1198                if( u->sendbuf_len == 0 )
     1199                {
     1200                        u->sendbuf_len = strlen( msg ) + 2;
     1201                        u->sendbuf = g_new( char, u->sendbuf_len );
     1202                        u->sendbuf[0] = 0;
     1203                        u->sendbuf_flags = flags;
     1204                }
     1205                else
     1206                {
     1207                        u->sendbuf_len += strlen( msg ) + 1;
     1208                        u->sendbuf = g_renew( char, u->sendbuf, u->sendbuf_len );
     1209                }
     1210               
     1211                strcat( u->sendbuf, msg );
     1212                strcat( u->sendbuf, "\n" );
     1213               
     1214                delay = set_getint( &irc->set, "buddy_sendbuffer_delay" );
     1215                if( delay <= 5 )
     1216                        delay *= 1000;
     1217               
     1218                if( u->sendbuf_timer > 0 )
     1219                        b_event_remove( u->sendbuf_timer );
     1220                u->sendbuf_timer = b_timeout_add( delay, buddy_send_handler_delayed, u );
     1221        }
     1222        else
     1223        {
     1224                imc_buddy_msg( u->ic, u->handle, msg, flags );
     1225        }
     1226}
     1227
     1228int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg )
     1229{
     1230        char last = 0;
     1231        char *s = msg, *line = msg;
     1232       
     1233        /* The almighty linesplitter .. woohoo!! */
     1234        while( !last )
     1235        {
     1236                if( *s == '\r' && *(s+1) == '\n' )
     1237                        *(s++) = 0;
     1238                if( *s == '\n' )
     1239                {
     1240                        last = s[1] == 0;
     1241                        *s = 0;
     1242                }
     1243                else
     1244                {
     1245                        last = s[0] == 0;
     1246                }
     1247                if( *s == 0 )
     1248                {
     1249                        if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && g_strcasecmp( type, "PRIVMSG" ) == 0 )
     1250                        {
     1251                                irc_write( irc, ":%s!%s@%s %s %s :\001ACTION %s\001", u->nick, u->user, u->host,
     1252                                           type, to, line + 4 );
     1253                        }
     1254                        else
     1255                        {
     1256                                irc_write( irc, ":%s!%s@%s %s %s :%s%s", u->nick, u->user, u->host,
     1257                                           type, to, prefix ? prefix : "", line );
     1258                        }
     1259                        line = s + 1;
     1260                }
     1261                s ++;
     1262        }
     1263       
     1264        return( 1 );
     1265}
     1266
     1267int irc_msgfrom( irc_t *irc, char *nick, char *msg )
     1268{
     1269        user_t *u = user_find( irc, nick );
     1270        static char *prefix = NULL;
     1271       
     1272        if( !u ) return( 0 );
     1273        if( prefix && *prefix ) g_free( prefix );
     1274       
     1275        if( !u->is_private && nick_cmp( u->nick, irc->mynick ) != 0 )
     1276        {
     1277                int len = strlen( irc->nick) + 3;
     1278                prefix = g_new (char, len );
     1279                g_snprintf( prefix, len, "%s%s", irc->nick, set_getstr( &irc->set, "to_char" ) );
     1280                prefix[len-1] = 0;
     1281        }
     1282        else
     1283        {
     1284                prefix = "";
     1285        }
     1286       
     1287        return( irc_privmsg( irc, u, "PRIVMSG", u->is_private ? irc->nick : irc->channel, prefix, msg ) );
     1288}
     1289
     1290int irc_noticefrom( irc_t *irc, char *nick, char *msg )
     1291{
     1292        user_t *u = user_find( irc, nick );
     1293       
     1294        if( u )
     1295                return( irc_privmsg( irc, u, "NOTICE", irc->nick, "", msg ) );
     1296        else
     1297                return( 0 );
    7361298}
    7371299
     
    7721334}
    7731335
    774 static char *set_eval_charset( set_t *set, char *value )
    775 {
    776         irc_t *irc = (irc_t*) set->data;
    777         char *test;
    778         gsize test_bytes = 0;
    779         GIConv ic, oc;
    780 
    781         if( g_strcasecmp( value, "none" ) == 0 )
    782                 value = g_strdup( "utf-8" );
    783 
    784         if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
    785         {
    786                 return NULL;
    787         }
    788        
    789         /* Do a test iconv to see if the user picked an IRC-compatible
    790            charset (for example utf-16 goes *horribly* wrong). */
    791         if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL ||
    792             test_bytes > 1 )
    793         {
    794                 g_free( test );
    795                 g_iconv_close( oc );
    796                 irc_usermsg( irc, "Unsupported character set: The IRC protocol "
    797                                   "only supports 8-bit character sets." );
    798                 return NULL;
    799         }
    800         g_free( test );
    801        
    802         if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
    803         {
    804                 g_iconv_close( oc );
    805                 return NULL;
    806         }
    807        
    808         if( irc->iconv != (GIConv) -1 )
    809                 g_iconv_close( irc->iconv );
    810         if( irc->oconv != (GIConv) -1 )
    811                 g_iconv_close( irc->oconv );
    812        
    813         irc->iconv = ic;
    814         irc->oconv = oc;
    815 
    816         return value;
    817 }
    818 
    819 char *set_eval_away_devoice( set_t *set, char *value )
    820 {
    821         irc_t *irc = set->data;
    822        
    823         if( !is_bool( value ) )
    824                 return SET_INVALID;
    825        
    826         /* The usual problem: The setting isn't actually changed at this
    827            point and we need it to be, so do it by hand. */
    828         g_free( set->value );
    829         set->value = g_strdup( value );
    830        
    831         bee_irc_channel_update( irc, NULL, NULL );
    832        
    833         return value;
    834 }
     1336struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel )
     1337{
     1338        struct groupchat *c;
     1339        account_t *a;
     1340       
     1341        /* This finds the connection which has a conversation which belongs to this channel */
     1342        for( a = irc->accounts; a; a = a->next )
     1343        {
     1344                if( a->ic == NULL )
     1345                        continue;
     1346               
     1347                c = a->ic->groupchats;
     1348                while( c )
     1349                {
     1350                        if( c->channel && g_strcasecmp( c->channel, channel ) == 0 )
     1351                                return c;
     1352                       
     1353                        c = c->next;
     1354                }
     1355        }
     1356       
     1357        return NULL;
     1358}
  • irc.h

    r8b8def58 r38ff846  
    55  \********************************************************************/
    66
    7 /* The IRC-based UI (for now the only one)                              */
     7/* The big hairy IRCd part of the project                               */
    88
    99/*
     
    3333#define IRC_PING_STRING "PinglBee"
    3434
    35 #define UMODES "abisw"     /* Allowed umodes (although they mostly do nothing) */
    36 #define UMODES_PRIV "Ro"   /* Allowed, but not by user directly */
    37 #define UMODES_KEEP "R"    /* Don't allow unsetting using /MODE */
    38 #define CMODES "nt"        /* Allowed modes */
    39 #define CMODE "t"          /* Default mode */
    40 #define UMODE "s"          /* Default mode */
    41 
    42 #define CTYPES "&#"        /* Valid channel name prefixes */
     35#define UMODES "abisw"
     36#define UMODES_PRIV "Ro"
     37#define CMODES "nt"
     38#define CMODE "t"
     39#define UMODE "s"
     40#define CTYPES "&#"
    4341
    4442typedef enum
     
    5048        USTATUS_SHUTDOWN = 8
    5149} irc_status_t;
    52 
    53 struct irc_user;
    5450
    5551typedef struct irc
     
    6359        GIConv iconv, oconv;
    6460
    65         struct irc_user *root;
    66         struct irc_user *user;
    67        
    68         char *last_root_cmd;
     61        int sentbytes;
     62        time_t oldtime;
    6963
     64        char *nick;
     65        char *user;
     66        char *host;
     67        char *realname;
    7068        char *password; /* HACK: Used to save the user's password, but before
    7169                           logging in, this may contain a password we should
     
    7472        char umode[8];
    7573       
     74        char *myhost;
     75        char *mynick;
     76
     77        char *channel;
     78        int c_id;
     79
     80        char is_private;                /* Not too nice... */
     81        char *last_target;
     82       
    7683        struct query *queries;
    77         GSList *file_transfers;
     84        struct account *accounts;
     85        struct chat *chatrooms;
    7886       
    79         GSList *users, *channels;
    80         struct irc_channel *default_channel;
    81         GHashTable *nick_user_hash;
     87        struct __USER *users;
     88        GHashTable *userhash;
    8289        GHashTable *watches;
     90        struct __NICK *nicks;
     91        struct set *set;
    8392
    8493        gint r_watch_source_id;
    8594        gint w_watch_source_id;
    8695        gint ping_source_id;
    87        
    88         struct bee *b;
    8996} irc_t;
    9097
    91 typedef enum
    92 {
    93         IRC_USER_PRIVATE = 1,
    94         IRC_USER_AWAY = 2,
    95 } irc_user_flags_t;
     98#include "user.h"
    9699
    97 typedef struct irc_user
    98 {
    99         irc_t *irc;
    100        
    101         char *nick;
    102         char *user;
    103         char *host;
    104         char *fullname;
    105        
    106         /* Nickname in lowercase for case sensitive searches */
    107         char *key;
    108        
    109         irc_user_flags_t flags;
    110        
    111         GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */
    112         guint pastebuf_timer;
    113         time_t away_reply_timeout; /* Only send a 301 if this time passed. */
    114        
    115         struct bee_user *bu;
    116        
    117         const struct irc_user_funcs *f;
    118 } irc_user_t;
    119 
    120 struct irc_user_funcs
    121 {
    122         gboolean (*privmsg)( irc_user_t *iu, const char *msg );
    123         gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp );
    124 };
    125 
    126 extern const struct irc_user_funcs irc_user_root_funcs;
    127 extern const struct irc_user_funcs irc_user_self_funcs;
    128 
    129 typedef enum
    130 {
    131         IRC_CHANNEL_JOINED = 1,
    132        
    133         /* Hack: Set this flag right before jumping into IM when we expect
    134            a call to imcb_chat_new(). */
    135         IRC_CHANNEL_CHAT_PICKME = 0x10000,
    136 } irc_channel_flags_t;
    137 
    138 typedef struct irc_channel
    139 {
    140         irc_t *irc;
    141         char *name;
    142         char mode[8];
    143         int flags;
    144        
    145         char *topic;
    146         char *topic_who;
    147         time_t topic_time;
    148        
    149         GSList *users; /* struct irc_channel_user */
    150         struct set *set;
    151        
    152         GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */
    153         guint pastebuf_timer;
    154        
    155         const struct irc_channel_funcs *f;
    156         void *data;
    157 } irc_channel_t;
    158 
    159 struct irc_channel_funcs
    160 {
    161         gboolean (*privmsg)( irc_channel_t *ic, const char *msg );
    162         gboolean (*join)( irc_channel_t *ic );
    163         gboolean (*part)( irc_channel_t *ic, const char *msg );
    164         gboolean (*topic)( irc_channel_t *ic, const char *new );
    165         gboolean (*invite)( irc_channel_t *ic, irc_user_t *iu );
    166        
    167         gboolean (*_init)( irc_channel_t *ic );
    168         gboolean (*_free)( irc_channel_t *ic );
    169 };
    170 
    171 typedef enum
    172 {
    173         IRC_CHANNEL_USER_OP = 1,
    174         IRC_CHANNEL_USER_HALFOP = 2,
    175         IRC_CHANNEL_USER_VOICE = 4,
    176 } irc_channel_user_flags_t;
    177 
    178 typedef struct irc_channel_user
    179 {
    180         irc_user_t *iu;
    181         int flags;
    182 } irc_channel_user_t;
    183 
    184 typedef enum
    185 {
    186         IRC_CC_TYPE_DEFAULT,
    187         IRC_CC_TYPE_REST,
    188         IRC_CC_TYPE_GROUP,
    189         IRC_CC_TYPE_ACCOUNT,
    190 } irc_control_channel_type_t;
    191 
    192 struct irc_control_channel
    193 {
    194         irc_control_channel_type_t type;
    195         struct bee_group *group;
    196         struct account *account;
    197 };
    198 
    199 extern const struct bee_ui_funcs irc_ui_funcs;
    200 
    201 /* irc.c */
    202100extern GSList *irc_connection_list;
    203101
     
    205103void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    206104void irc_free( irc_t *irc );
    207 void irc_setpass (irc_t *irc, const char *pass);
    208105
     106void irc_exec( irc_t *irc, char **cmd );
    209107void irc_process( irc_t *irc );
    210108char **irc_parse_line( char *line );
    211109char *irc_build_line( char **cmd );
    212110
     111void irc_vawrite( irc_t *irc, char *format, va_list params );
    213112void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    214113void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
    215 void irc_vawrite( irc_t *irc, char *format, va_list params );
     114void irc_reply( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
     115G_MODULE_EXPORT int irc_usermsg( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
     116char **irc_tokenize( char *buffer );
    216117
     118void irc_login( irc_t *irc );
    217119int irc_check_login( irc_t *irc );
     120void irc_motd( irc_t *irc );
     121void irc_names( irc_t *irc, char *channel );
     122void irc_topic( irc_t *irc, char *channel );
     123void irc_umode_set( irc_t *irc, char *s, int allow_priv );
     124void irc_who( irc_t *irc, char *channel );
     125void irc_spawn( irc_t *irc, user_t *u );
     126void irc_join( irc_t *irc, user_t *u, char *channel );
     127void irc_part( irc_t *irc, user_t *u, char *channel );
     128void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker );
     129void irc_kill( irc_t *irc, user_t *u );
     130void irc_invite( irc_t *irc, char *nick, char *channel );
     131void irc_whois( irc_t *irc, char *nick );
     132void irc_setpass( irc_t *irc, const char *pass ); /* USE WITH CAUTION! */
    218133
    219 void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv );
     134int irc_send( irc_t *irc, char *nick, char *s, int flags );
     135int irc_privmsg( irc_t *irc, user_t *u, char *type, char *to, char *prefix, char *msg );
     136int irc_msgfrom( irc_t *irc, char *nick, char *msg );
     137int irc_noticefrom( irc_t *irc, char *nick, char *msg );
    220138
    221 /* irc_channel.c */
    222 irc_channel_t *irc_channel_new( irc_t *irc, const char *name );
    223 irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name );
    224 irc_channel_t *irc_channel_get( irc_t *irc, char *id );
    225 int irc_channel_free( irc_channel_t *ic );
    226 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu );
    227 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu, gboolean silent, const char *msg );
    228 irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu );
    229 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who );
    230 void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags );
    231 void irc_channel_printf( irc_channel_t *ic, char *format, ... );
    232 gboolean irc_channel_name_ok( const char *name );
    233 int irc_channel_name_cmp( const char *a_, const char *b_ );
    234 void irc_channel_update_ops( irc_channel_t *ic, char *value );
    235 char *set_eval_irc_channel_ops( struct set *set, char *value );
    236 
    237 /* irc_commands.c */
    238 void irc_exec( irc_t *irc, char **cmd );
    239 
    240 /* irc_send.c */
    241 void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 );
    242 void irc_send_login( irc_t *irc );
    243 void irc_send_motd( irc_t *irc );
    244 void irc_usermsg( irc_t *irc, char *format, ... );
    245 void irc_send_join( irc_channel_t *ic, irc_user_t *iu );
    246 void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason );
    247 void irc_send_quit( irc_user_t *iu, const char *reason );
    248 void irc_send_names( irc_channel_t *ic );
    249 void irc_send_topic( irc_channel_t *ic, gboolean topic_change );
    250 void irc_send_whois( irc_user_t *iu );
    251 void irc_send_who( irc_t *irc, GSList *l, const char *channel );
    252 void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix );
    253 void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg );
    254 void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 );
    255 void irc_send_nick( irc_user_t *iu, const char *new );
    256 void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu,
    257                                       irc_channel_user_flags_t old, irc_channel_user_flags_t new );
    258 
    259 /* irc_user.c */
    260 irc_user_t *irc_user_new( irc_t *irc, const char *nick );
    261 int irc_user_free( irc_t *irc, irc_user_t *iu );
    262 irc_user_t *irc_user_by_name( irc_t *irc, const char *nick );
    263 int irc_user_set_nick( irc_user_t *iu, const char *new );
    264 gint irc_user_cmp( gconstpointer a_, gconstpointer b_ );
    265 const char *irc_user_get_away( irc_user_t *iu );
    266 
    267 /* irc_util.c */
    268 char *set_eval_timezone( struct set *set, char *value );
    269 char *irc_format_timestamp( irc_t *irc, time_t msg_ts );
    270 
    271 /* irc_im.c */
    272 void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu );
     139void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
     140struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );
    273141
    274142#endif
  • irc_commands.c

    r8b8def58 r38ff846  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2006 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    5353        else if( global.conf->auth_pass )
    5454        {
    55                 irc_send_num( irc, 464, ":Incorrect password" );
     55                irc_reply( irc, 464, ":Incorrect password" );
    5656        }
    5757        else
     
    6565static void irc_cmd_user( irc_t *irc, char **cmd )
    6666{
    67         irc->user->user = g_strdup( cmd[1] );
    68         irc->user->fullname = g_strdup( cmd[4] );
     67        irc->user = g_strdup( cmd[1] );
     68        irc->realname = g_strdup( cmd[4] );
    6969       
    7070        irc_check_login( irc );
     
    7373static void irc_cmd_nick( irc_t *irc, char **cmd )
    7474{
    75         if( irc_user_by_name( irc, cmd[1] ) )
    76         {
    77                 irc_send_num( irc, 433, ":This nick is already in use" );
     75        if( irc->status & USTATUS_IDENTIFIED && irc->nick )
     76        {
     77                irc_reply( irc, 438, "%s %s :You can only change your nick if you're not "
     78                           "logged in (i.e. pre-identify)", irc->nick, cmd[1] );
     79        }
     80        /* This is not clean, but for now it'll have to be like this... */
     81        else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) || ( user_find( irc, cmd[1] ) != NULL ) )
     82        {
     83                irc_reply( irc, 433, "%s :This nick is already in use", cmd[1] );
    7884        }
    7985        else if( !nick_ok( cmd[1] ) )
    8086        {
    8187                /* [SH] Invalid characters. */
    82                 irc_send_num( irc, 432, ":This nick contains invalid characters" );
    83         }
    84         else if( irc->user->nick )
    85         {
    86                 if( irc->status & USTATUS_IDENTIFIED )
    87                 {
    88                         irc_setpass( irc, NULL );
    89                         irc->status &= ~USTATUS_IDENTIFIED;
    90                         irc_umode_set( irc, "-R", 1 );
    91                         irc_usermsg( irc, "Changing nicks resets your identify status. "
    92                                      "Re-identify or register a new account if you want "
    93                                      "your configuration to be saved. See \x02help "
    94                                      "nick_changes\x02." );
    95                 }
    96                
    97                 irc_user_set_nick( irc->user, cmd[1] );
    98         }
    99         else
    100         {
    101                 irc->user->nick = g_strdup( cmd[1] );
     88                irc_reply( irc, 432, "%s :This nick contains invalid characters", cmd[1] );
     89        }
     90        else if(irc->nick)
     91        {
     92                if( user_find( irc, irc->nick ) )
     93                        user_rename(irc, irc->nick, cmd[1]);
     94
     95                irc_write( irc, ":%s!%s@%s NICK %s", irc->nick, irc->user, irc->host, cmd[1] );
     96                g_free(irc->nick);
     97                irc->nick = g_strdup( cmd[1] );
     98        }
     99        else
     100        {
     101                irc->nick = g_strdup( cmd[1] );
    102102               
    103103                irc_check_login( irc );
     
    115115static void irc_cmd_ping( irc_t *irc, char **cmd )
    116116{
    117         irc_write( irc, ":%s PONG %s :%s", irc->root->host,
    118                    irc->root->host, cmd[1]?cmd[1]:irc->root->host );
    119 }
    120 
    121 static void irc_cmd_pong( irc_t *irc, char **cmd )
    122 {
    123         /* We could check the value we get back from the user, but in
    124            fact we don't care, we're just happy s/he's still alive. */
    125         irc->last_pong = gettime();
    126         irc->pinging = 0;
    127 }
    128 
    129 static void irc_cmd_join( irc_t *irc, char **cmd )
    130 {
    131         irc_channel_t *ic;
    132        
    133         if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
    134                 ic = irc_channel_new( irc, cmd[1] );
    135        
    136         if( ic == NULL )
    137         {
    138                 irc_send_num( irc, 479, "%s :Invalid channel name", cmd[1] );
    139                 return;
    140         }
    141        
    142         if( ic->flags & IRC_CHANNEL_JOINED )
    143                 return; /* Dude, you're already there...
    144                            RFC doesn't have any reply for that though? */
    145        
    146         if( ic->f->join && !ic->f->join( ic ) )
    147                 /* The story is: FALSE either means the handler showed an error
    148                    message, or is doing some work before the join should be
    149                    confirmed. (In the latter case, the caller should take care
    150                    of that confirmation.)
    151                    TRUE means all's good, let the user join the channel right away. */
    152                 return;
    153        
    154         irc_channel_add_user( ic, irc->user );
    155 }
    156 
    157 static void irc_cmd_names( irc_t *irc, char **cmd )
    158 {
    159         irc_channel_t *ic;
    160        
    161         if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
    162                 irc_send_names( ic );
    163         /* With no args, we should show /names of all chans. Make the code
    164            below work well if necessary.
    165         else
    166         {
    167                 GSList *l;
    168                
    169                 for( l = irc->channels; l; l = l->next )
    170                         irc_send_names( l->data );
    171         }
    172         */
    173 }
    174 
    175 static void irc_cmd_part( irc_t *irc, char **cmd )
    176 {
    177         irc_channel_t *ic;
    178        
    179         if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
    180         {
    181                 irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
    182         }
    183         else if( irc_channel_del_user( ic, irc->user, FALSE, cmd[2] ) )
    184         {
    185                 if( ic->f->part )
    186                         ic->f->part( ic, NULL );
    187         }
    188         else
    189         {
    190                 irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] );
    191         }
    192 }
    193 
    194 static void irc_cmd_whois( irc_t *irc, char **cmd )
    195 {
    196         char *nick = cmd[1];
    197         irc_user_t *iu = irc_user_by_name( irc, nick );
    198        
    199         if( iu )
    200                 irc_send_whois( iu );
    201         else
    202                 irc_send_num( irc, 401, "%s :Nick does not exist", nick );
    203 }
    204 
    205 static void irc_cmd_whowas( irc_t *irc, char **cmd )
    206 {
    207         /* For some reason irssi tries a whowas when whois fails. We can
    208            ignore this, but then the user never gets a "user not found"
    209            message from irssi which is a bit annoying. So just respond
    210            with not-found and irssi users will get better error messages */
    211        
    212         irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] );
    213         irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] );
    214 }
    215 
    216 static void irc_cmd_motd( irc_t *irc, char **cmd )
    217 {
    218         irc_send_motd( irc );
    219 }
    220 
    221 static void irc_cmd_mode( irc_t *irc, char **cmd )
    222 {
    223         if( irc_channel_name_ok( cmd[1] ) )
    224         {
    225                 irc_channel_t *ic;
    226                
    227                 if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL )
    228                         irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
    229                 else if( cmd[2] )
    230                 {
    231                         if( *cmd[2] == '+' || *cmd[2] == '-' )
    232                                 irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] );
    233                         else if( *cmd[2] == 'b' )
    234                                 irc_send_num( irc, 368, "%s :No bans possible", cmd[1] );
    235                 }
    236                 else
    237                         irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode );
    238         }
    239         else
    240         {
    241                 if( nick_cmp( cmd[1], irc->user->nick ) == 0 )
    242                 {
    243                         if( cmd[2] )
    244                                 irc_umode_set( irc, cmd[2], 0 );
    245                         else
    246                                 irc_send_num( irc, 221, "+%s", irc->umode );
    247                 }
    248                 else
    249                         irc_send_num( irc, 502, ":Don't touch their modes" );
    250         }
    251 }
    252 
    253 static void irc_cmd_who( irc_t *irc, char **cmd )
    254 {
    255         char *channel = cmd[1];
    256         irc_channel_t *ic;
    257        
    258         if( !channel || *channel == '0' || *channel == '*' || !*channel )
    259                 irc_send_who( irc, irc->users, "**" );
    260         else if( ( ic = irc_channel_by_name( irc, channel ) ) )
    261                 irc_send_who( irc, ic->users, channel );
    262         else
    263                 irc_send_num( irc, 403, "%s :No such channel", channel );
    264 }
    265 
    266 static void irc_cmd_privmsg( irc_t *irc, char **cmd )
    267 {
    268         irc_channel_t *ic;
    269         irc_user_t *iu;
    270        
    271         if( !cmd[2] )
    272         {
    273                 irc_send_num( irc, 412, ":No text to send" );
    274                 return;
    275         }
    276        
    277         /* Don't treat CTCP actions as real CTCPs, just convert them right now. */
    278         if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 )
    279         {
    280                 cmd[2] += 4;
    281                 strcpy( cmd[2], "/me" );
    282                 if( cmd[2][strlen(cmd[2])-1] == '\001' )
    283                         cmd[2][strlen(cmd[2])-1] = '\0';
    284         }
    285        
    286         if( irc_channel_name_ok( cmd[1] ) &&
    287             ( ic = irc_channel_by_name( irc, cmd[1] ) ) )
    288         {
    289                 if( ic->f->privmsg )
    290                         ic->f->privmsg( ic, cmd[2] );
    291         }
    292         else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) )
    293         {
    294                 if( cmd[2][0] == '\001' )
    295                 {
    296                         char **ctcp;
    297                        
    298                         if( iu->f->ctcp == NULL )
    299                                 return;
    300                         if( cmd[2][strlen(cmd[2])-1] == '\001' )
    301                                 cmd[2][strlen(cmd[2])-1] = '\0';
    302                        
    303                         ctcp = split_command_parts( cmd[2] + 1 );
    304                         iu->f->ctcp( iu, ctcp );
    305                 }
    306                 else if( iu->f->privmsg )
    307                 {
    308                         iu->flags |= IRC_USER_PRIVATE;
    309                         iu->f->privmsg( iu, cmd[2] );
    310                 }
    311         }
    312         else
    313         {
    314                 irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] );
    315         }
    316 }
    317 
    318 static void irc_cmd_nickserv( irc_t *irc, char **cmd )
    319 {
    320         /* [SH] This aliases the NickServ command to PRIVMSG root */
    321         /* [TV] This aliases the NS command to PRIVMSG root as well */
    322         root_command( irc, cmd + 1 );
    323 }
    324 
    325 
     117        irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
     118}
    326119
    327120static void irc_cmd_oper( irc_t *irc, char **cmd )
     
    333126        {
    334127                irc_umode_set( irc, "+o", 1 );
    335                 irc_send_num( irc, 381, ":Password accepted" );
    336         }
    337         else
    338         {
    339                 irc_send_num( irc, 432, ":Incorrect password" );
     128                irc_reply( irc, 381, ":Password accepted" );
     129        }
     130        else
     131        {
     132                irc_reply( irc, 432, ":Incorrect password" );
     133        }
     134}
     135
     136static void irc_cmd_mode( irc_t *irc, char **cmd )
     137{
     138        if( strchr( CTYPES, *cmd[1] ) )
     139        {
     140                if( cmd[2] )
     141                {
     142                        if( *cmd[2] == '+' || *cmd[2] == '-' )
     143                                irc_reply( irc, 477, "%s :Can't change channel modes", cmd[1] );
     144                        else if( *cmd[2] == 'b' )
     145                                irc_reply( irc, 368, "%s :No bans possible", cmd[1] );
     146                }
     147                else
     148                        irc_reply( irc, 324, "%s +%s", cmd[1], CMODE );
     149        }
     150        else
     151        {
     152                if( nick_cmp( cmd[1], irc->nick ) == 0 )
     153                {
     154                        if( cmd[2] )
     155                                irc_umode_set( irc, cmd[2], 0 );
     156                        else
     157                                irc_reply( irc, 221, "+%s", irc->umode );
     158                }
     159                else
     160                        irc_reply( irc, 502, ":Don't touch their modes" );
     161        }
     162}
     163
     164static void irc_cmd_names( irc_t *irc, char **cmd )
     165{
     166        irc_names( irc, cmd[1]?cmd[1]:irc->channel );
     167}
     168
     169static void irc_cmd_part( irc_t *irc, char **cmd )
     170{
     171        struct groupchat *c;
     172       
     173        if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     174        {
     175                user_t *u = user_find( irc, irc->nick );
     176               
     177                /* Not allowed to leave control channel */
     178                irc_part( irc, u, irc->channel );
     179                irc_join( irc, u, irc->channel );
     180        }
     181        else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) )
     182        {
     183                user_t *u = user_find( irc, irc->nick );
     184               
     185                irc_part( irc, u, c->channel );
     186               
     187                if( c->ic )
     188                {
     189                        c->joined = 0;
     190                        c->ic->acc->prpl->chat_leave( c );
     191                }
     192        }
     193        else
     194        {
     195                irc_reply( irc, 403, "%s :No such channel", cmd[1] );
     196        }
     197}
     198
     199static void irc_cmd_join( irc_t *irc, char **cmd )
     200{
     201        if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     202                ; /* Dude, you're already there...
     203                     RFC doesn't have any reply for that though? */
     204        else if( cmd[1] )
     205        {
     206                struct chat *c;
     207               
     208                if( strchr( CTYPES, cmd[1][0] ) == NULL || cmd[1][1] == 0 )
     209                        irc_reply( irc, 479, "%s :Invalid channel name", cmd[1] );
     210                else if( ( c = chat_bychannel( irc, cmd[1] ) ) && c->acc && c->acc->ic )
     211                        chat_join( irc, c, cmd[2] );
     212                else
     213                        irc_reply( irc, 403, "%s :No such channel", cmd[1] );
    340214        }
    341215}
     
    343217static void irc_cmd_invite( irc_t *irc, char **cmd )
    344218{
    345         irc_channel_t *ic;
    346         irc_user_t *iu;
    347        
    348         if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL )
    349         {
    350                 irc_send_num( irc, 401, "%s :No such nick", cmd[1] );
    351                 return;
    352         }
    353         else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL )
    354         {
    355                 irc_send_num( irc, 403, "%s :No such channel", cmd[2] );
    356                 return;
    357         }
    358        
    359         if( !ic->f->invite )
    360                 irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] );
    361         else if( ic->f->invite( ic, iu ) )
    362                 irc_send_num( irc, 341, "%s %s", iu->nick, ic->name );
     219        char *nick = cmd[1], *channel = cmd[2];
     220        struct groupchat *c = irc_chat_by_channel( irc, channel );
     221        user_t *u = user_find( irc, nick );
     222       
     223        if( u && c && ( u->ic == c->ic ) )
     224                if( c->ic && c->ic->acc->prpl->chat_invite )
     225                {
     226                        c->ic->acc->prpl->chat_invite( c, u->handle, NULL );
     227                        irc_reply( irc, 341, "%s %s", nick, channel );
     228                        return;
     229                }
     230       
     231        irc_reply( irc, 482, "%s :Invite impossible; User/Channel non-existent or incompatible", channel );
     232}
     233
     234static void irc_cmd_privmsg( irc_t *irc, char **cmd )
     235{
     236        if ( !cmd[2] )
     237        {
     238                irc_reply( irc, 412, ":No text to send" );
     239        }
     240        else if ( irc->nick && g_strcasecmp( cmd[1], irc->nick ) == 0 )
     241        {
     242                irc_write( irc, ":%s!%s@%s %s %s :%s", irc->nick, irc->user, irc->host, cmd[0], cmd[1], cmd[2] );
     243        }
     244        else
     245        {
     246                if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     247                {
     248                        unsigned int i;
     249                        char *t = set_getstr( &irc->set, "default_target" );
     250                       
     251                        if( g_strcasecmp( t, "last" ) == 0 && irc->last_target )
     252                                cmd[1] = irc->last_target;
     253                        else if( g_strcasecmp( t, "root" ) == 0 )
     254                                cmd[1] = irc->mynick;
     255                       
     256                        for( i = 0; i < strlen( cmd[2] ); i ++ )
     257                        {
     258                                if( cmd[2][i] == ' ' ) break;
     259                                if( cmd[2][i] == ':' || cmd[2][i] == ',' )
     260                                {
     261                                        cmd[1] = cmd[2];
     262                                        cmd[2] += i;
     263                                        *cmd[2] = 0;
     264                                        while( *(++cmd[2]) == ' ' );
     265                                        break;
     266                                }
     267                        }
     268                       
     269                        irc->is_private = 0;
     270                       
     271                        if( cmd[1] != irc->last_target )
     272                        {
     273                                g_free( irc->last_target );
     274                                irc->last_target = g_strdup( cmd[1] );
     275                        }
     276                }
     277                else
     278                {
     279                        irc->is_private = 1;
     280                }
     281                irc_send( irc, cmd[1], cmd[2], ( g_strcasecmp( cmd[0], "NOTICE" ) == 0 ) ? OPT_AWAY : 0 );
     282        }
     283}
     284
     285static void irc_cmd_who( irc_t *irc, char **cmd )
     286{
     287        char *channel = cmd[1];
     288        user_t *u = irc->users;
     289        struct groupchat *c;
     290        GList *l;
     291       
     292        if( !channel || *channel == '0' || *channel == '*' || !*channel )
     293                while( u )
     294                {
     295                        irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", u->online ? irc->channel : "*", u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
     296                        u = u->next;
     297                }
     298        else if( g_strcasecmp( channel, irc->channel ) == 0 )
     299                while( u )
     300                {
     301                        if( u->online )
     302                                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
     303                        u = u->next;
     304                }
     305        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
     306                for( l = c->in_room; l; l = l->next )
     307                {
     308                        if( ( u = user_findhandle( c->ic, l->data ) ) )
     309                                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->away ? 'G' : 'H', u->realname );
     310                }
     311        else if( ( u = user_find( irc, channel ) ) )
     312                irc_reply( irc, 352, "%s %s %s %s %s %c :0 %s", channel, u->user, u->host, irc->myhost, u->nick, u->online ? ( u->away ? 'G' : 'H' ) : 'G', u->realname );
     313       
     314        irc_reply( irc, 315, "%s :End of /WHO list", channel?channel:"**" );
    363315}
    364316
    365317static void irc_cmd_userhost( irc_t *irc, char **cmd )
    366318{
     319        user_t *u;
    367320        int i;
    368321       
     
    374327       
    375328        for( i = 1; cmd[i]; i ++ )
    376         {
    377                 irc_user_t *iu = irc_user_by_name( irc, cmd[i] );
    378                
    379                 if( iu )
    380                         irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick,
    381                                       irc_user_get_away( iu ) ? '-' : '+',
    382                                       iu->user, iu->host );
    383         }
     329                if( ( u = user_find( irc, cmd[i] ) ) )
     330                {
     331                        if( u->online && u->away )
     332                                irc_reply( irc, 302, ":%s=-%s@%s", u->nick, u->user, u->host );
     333                        else
     334                                irc_reply( irc, 302, ":%s=+%s@%s", u->nick, u->user, u->host );
     335                }
    384336}
    385337
    386338static void irc_cmd_ison( irc_t *irc, char **cmd )
    387339{
     340        user_t *u;
    388341        char buff[IRC_MAX_LINE];
    389342        int lenleft, i;
     
    401354                while( *this )
    402355                {
    403                         irc_user_t *iu;
    404                        
    405356                        if( ( next = strchr( this, ' ' ) ) )
    406357                                *next = 0;
    407358                       
    408                         if( ( iu = irc_user_by_name( irc, this ) ) &&
    409                             iu->bu && iu->bu->flags & BEE_USER_ONLINE )
    410                         {
    411                                 lenleft -= strlen( iu->nick ) + 1;
     359                        if( ( u = user_find( irc, this ) ) && u->online )
     360                        {
     361                                lenleft -= strlen( u->nick ) + 1;
    412362                               
    413363                                if( lenleft < 0 )
    414364                                        break;
    415365                               
    416                                 strcat( buff, iu->nick );
     366                                strcat( buff, u->nick );
    417367                                strcat( buff, " " );
    418368                        }
     
    437387                buff[strlen(buff)-1] = '\0';
    438388       
    439         irc_send_num( irc, 303, ":%s", buff );
     389        irc_reply( irc, 303, ":%s", buff );
    440390}
    441391
     
    450400        {
    451401                char *nick;
    452                 irc_user_t *iu;
     402                user_t *u;
    453403               
    454404                if( !cmd[i][0] || !cmd[i][1] )
     
    458408                nick_lc( nick );
    459409               
    460                 iu = irc_user_by_name( irc, nick );
     410                u = user_find( irc, nick );
    461411               
    462412                if( cmd[i][0] == '+' )
     
    465415                                g_hash_table_insert( irc->watches, nick, nick );
    466416                       
    467                         if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE )
    468                                 irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user,
    469                                               iu->host, (int) time( NULL ), "is online" );
     417                        if( u && u->online )
     418                                irc_reply( irc, 604, "%s %s %s %d :%s", u->nick, u->user, u->host, (int) time( NULL ), "is online" );
    470419                        else
    471                                 irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*",
    472                                               (int) time( NULL ), "is offline" );
     420                                irc_reply( irc, 605, "%s %s %s %d :%s", nick, "*", "*", (int) time( NULL ), "is offline" );
    473421                }
    474422                else if( cmd[i][0] == '-' )
     
    481429                                g_free( okey );
    482430                               
    483                                 irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
     431                                irc_reply( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" );
    484432                        }
    485433                }
     
    489437static void irc_cmd_topic( irc_t *irc, char **cmd )
    490438{
    491         irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] );
    492         const char *new = cmd[2];
    493        
    494         if( ic == NULL )
    495         {
    496                 irc_send_num( irc, 403, "%s :No such channel", cmd[1] );
    497         }
    498         else if( new )
    499         {
    500                 if( ic->f->topic == NULL )
    501                         irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name );
    502                 else if( ic->f->topic( ic, new ) )
    503                         irc_send_topic( ic, TRUE );
    504         }
    505         else
    506         {
    507                 irc_send_topic( ic, FALSE );
     439        char *channel = cmd[1];
     440        char *topic = cmd[2];
     441       
     442        if( topic )
     443        {
     444                /* Send the topic */
     445                struct groupchat *c = irc_chat_by_channel( irc, channel );
     446                if( c && c->ic && c->ic->acc->prpl->chat_topic )
     447                        c->ic->acc->prpl->chat_topic( c, topic );
     448        }
     449        else
     450        {
     451                /* Get the topic */
     452                irc_topic( irc, channel );
    508453        }
    509454}
     
    511456static void irc_cmd_away( irc_t *irc, char **cmd )
    512457{
    513         if( cmd[1] && *cmd[1] )
    514         {
    515                 char away[strlen(cmd[1])+1];
     458        user_t *u = user_find( irc, irc->nick );
     459        char *away = cmd[1];
     460       
     461        if( !u ) return;
     462       
     463        if( away && *away )
     464        {
    516465                int i, j;
    517466               
    518467                /* Copy away string, but skip control chars. Mainly because
    519468                   Jabber really doesn't like them. */
    520                 for( i = j = 0; cmd[1][i]; i ++ )
    521                         if( ( away[j] = cmd[1][i] ) >= ' ' )
     469                u->away = g_malloc( strlen( away ) + 1 );
     470                for( i = j = 0; away[i]; i ++ )
     471                        if( ( u->away[j] = away[i] ) >= ' ' )
    522472                                j ++;
    523                 away[j] = '\0';
    524                
    525                 irc_send_num( irc, 306, ":You're now away: %s", away );
    526                 set_setstr( &irc->b->set, "away", away );
    527         }
    528         else
    529         {
    530                 irc_send_num( irc, 305, ":Welcome back" );
    531                 set_setstr( &irc->b->set, "away", NULL );
    532         }
     473                u->away[j] = 0;
     474               
     475                irc_reply( irc, 306, ":You're now away: %s", u->away );
     476                /* irc_umode_set( irc, irc->myhost, "+a" ); */
     477        }
     478        else
     479        {
     480                if( u->away ) g_free( u->away );
     481                u->away = NULL;
     482                /* irc_umode_set( irc, irc->myhost, "-a" ); */
     483                irc_reply( irc, 305, ":Welcome back" );
     484        }
     485       
     486        set_setstr( &irc->set, "away", u->away );
     487}
     488
     489static void irc_cmd_whois( irc_t *irc, char **cmd )
     490{
     491        char *nick = cmd[1];
     492        user_t *u = user_find( irc, nick );
     493       
     494        if( u )
     495        {
     496                irc_reply( irc, 311, "%s %s %s * :%s", u->nick, u->user, u->host, u->realname );
     497               
     498                if( u->ic )
     499                        irc_reply( irc, 312, "%s %s.%s :%s network", u->nick, u->ic->acc->user,
     500                                   u->ic->acc->server && *u->ic->acc->server ? u->ic->acc->server : "",
     501                                   u->ic->acc->prpl->name );
     502                else
     503                        irc_reply( irc, 312, "%s %s :%s", u->nick, irc->myhost, IRCD_INFO );
     504               
     505                if( !u->online )
     506                        irc_reply( irc, 301, "%s :%s", u->nick, "User is offline" );
     507                else if( u->away )
     508                        irc_reply( irc, 301, "%s :%s", u->nick, u->away );
     509                if( u->status_msg )
     510                        irc_reply( irc, 320, "%s :%s", u->nick, u->status_msg );
     511               
     512                irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
     513        }
     514        else
     515        {
     516                irc_reply( irc, 401, "%s :Nick does not exist", nick );
     517        }
     518}
     519
     520static void irc_cmd_whowas( irc_t *irc, char **cmd )
     521{
     522        /* For some reason irssi tries a whowas when whois fails. We can
     523           ignore this, but then the user never gets a "user not found"
     524           message from irssi which is a bit annoying. So just respond
     525           with not-found and irssi users will get better error messages */
     526       
     527        irc_reply( irc, 406, "%s :Nick does not exist", cmd[1] );
     528        irc_reply( irc, 369, "%s :End of WHOWAS", cmd[1] );
     529}
     530
     531static void irc_cmd_nickserv( irc_t *irc, char **cmd )
     532{
     533        /* [SH] This aliases the NickServ command to PRIVMSG root */
     534        /* [TV] This aliases the NS command to PRIVMSG root as well */
     535        root_command( irc, cmd + 1 );
     536}
     537
     538static void irc_cmd_motd( irc_t *irc, char **cmd )
     539{
     540        irc_motd( irc );
     541}
     542
     543static void irc_cmd_pong( irc_t *irc, char **cmd )
     544{
     545        /* We could check the value we get back from the user, but in
     546           fact we don't care, we're just happy he's still alive. */
     547        irc->last_pong = gettime();
     548        irc->pinging = 0;
    533549}
    534550
    535551static void irc_cmd_version( irc_t *irc, char **cmd )
    536552{
    537         irc_send_num( irc, 351, "bitlbee-%s. %s :%s/%s ",
    538                       BITLBEE_VERSION, irc->root->host, ARCH, CPU );
     553        irc_reply( irc, 351, "bitlbee-%s. %s :%s/%s ", BITLBEE_VERSION, irc->myhost, ARCH, CPU );
    539554}
    540555
    541556static void irc_cmd_completions( irc_t *irc, char **cmd )
    542557{
     558        user_t *u = user_find( irc, irc->mynick );
    543559        help_t *h;
    544560        set_t *s;
    545561        int i;
    546562       
    547         irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" );
     563        irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "OK" );
    548564       
    549565        for( i = 0; commands[i].command; i ++ )
    550                 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", commands[i].command );
     566                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", commands[i].command );
    551567       
    552568        for( h = global.help; h; h = h->next )
    553                 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title );
    554        
    555         for( s = irc->b->set; s; s = s->next )
    556                 irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key );
    557        
    558         irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" );
     569                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS help ", h->title );
     570       
     571        for( s = irc->set; s; s = s->next )
     572                irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS set ", s->key );
     573       
     574        irc_privmsg( irc, u, "NOTICE", irc->nick, "COMPLETIONS ", "END" );
    559575}
    560576
     
    566582                ipc_to_master( cmd );
    567583       
    568         irc_send_num( irc, 382, "%s :Rehashing", global.conf_file );
     584        irc_reply( irc, 382, "%s :Rehashing", global.conf_file );
    569585}
    570586
     
    575591        { "quit",        0, irc_cmd_quit,        0 },
    576592        { "ping",        0, irc_cmd_ping,        0 },
    577         { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
     593        { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
     594        { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
     595        { "names",       0, irc_cmd_names,       IRC_CMD_LOGGED_IN },
     596        { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
    578597        { "join",        1, irc_cmd_join,        IRC_CMD_LOGGED_IN },
    579         { "names",       1, irc_cmd_names,       IRC_CMD_LOGGED_IN },
    580         { "part",        1, irc_cmd_part,        IRC_CMD_LOGGED_IN },
    581         { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
    582         { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
    583         { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
    584         { "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
     598        { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
     599        { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
     600        { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    585601        { "who",         0, irc_cmd_who,         IRC_CMD_LOGGED_IN },
    586         { "privmsg",     1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    587         { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
    588         { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
    589         { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
    590         { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
    591         { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
    592602        { "userhost",    1, irc_cmd_userhost,    IRC_CMD_LOGGED_IN },
    593603        { "ison",        1, irc_cmd_ison,        IRC_CMD_LOGGED_IN },
    594604        { "watch",       1, irc_cmd_watch,       IRC_CMD_LOGGED_IN },
    595         { "invite",      2, irc_cmd_invite,      IRC_CMD_LOGGED_IN },
    596 #if 0
    597         { "notice",      1, irc_cmd_privmsg,     IRC_CMD_LOGGED_IN },
    598 #endif
    599605        { "topic",       1, irc_cmd_topic,       IRC_CMD_LOGGED_IN },
    600         { "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
     606        { "away",        0, irc_cmd_away,        IRC_CMD_LOGGED_IN },
     607        { "whois",       1, irc_cmd_whois,       IRC_CMD_LOGGED_IN },
     608        { "whowas",      1, irc_cmd_whowas,      IRC_CMD_LOGGED_IN },
     609        { "nickserv",    1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
     610        { "ns",          1, irc_cmd_nickserv,    IRC_CMD_LOGGED_IN },
     611        { "motd",        0, irc_cmd_motd,        IRC_CMD_LOGGED_IN },
     612        { "pong",        0, irc_cmd_pong,        IRC_CMD_LOGGED_IN },
     613        { "version",     0, irc_cmd_version,     IRC_CMD_LOGGED_IN },
     614        { "completions", 0, irc_cmd_completions, IRC_CMD_LOGGED_IN },
    601615        { "die",         0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
    602616        { "deaf",        0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
     
    624638                        if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN )
    625639                        {
    626                                 irc_send_num( irc, 462, ":Only allowed before logging in" );
     640                                irc_reply( irc, 462, ":Only allowed before logging in" );
    627641                        }
    628642                        else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) )
    629643                        {
    630                                 irc_send_num( irc, 451, ":Register first" );
     644                                irc_reply( irc, 451, ":Register first" );
    631645                        }
    632646                        else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) )
    633647                        {
    634                                 irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" );
     648                                irc_reply( irc, 481, ":Permission denied - You're not an IRC operator" );
    635649                        }
    636650                        else if( n_arg < irc_commands[i].required_parameters )
    637651                        {
    638                                 irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] );
     652                                irc_reply( irc, 461, "%s :Need more parameters", cmd[0] );
    639653                        }
    640654                        else if( irc_commands[i].flags & IRC_CMD_TO_MASTER )
     
    653667       
    654668        if( irc->status >= USTATUS_LOGGED_IN )
    655                 irc_send_num( irc, 421, "%s :Unknown command", cmd[0] );
    656 }
     669                irc_reply( irc, 421, "%s :Unknown command", cmd[0] );
     670}
  • lib/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)lib/
    12 endif
    1310
    1411# [SH] Program variables
    15 objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
     12objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
    1613
    1714CFLAGS += -Wall
     
    4037$(objects): ../Makefile.settings Makefile
    4138
    42 $(objects): %.o: $(SRCDIR)%.c
     39$(objects): %.o: %.c
    4340        @echo '*' Compiling $<
    4441        @$(CC) -c $(CFLAGS) $< -o $@
  • lib/events.h

    r8b8def58 r38ff846  
    4848   the given callback function. */
    4949typedef enum {
    50         B_EV_IO_READ = 1 << 0,
    51         B_EV_IO_WRITE = 1 << 1,
    52         B_EV_FLAG_FORCE_ONCE = 1 << 16,
    53         B_EV_FLAG_FORCE_REPEAT = 1 << 17,
     50        GAIM_INPUT_READ = 1 << 1,
     51        GAIM_INPUT_WRITE = 1 << 2
    5452} b_input_condition;
    5553typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond);
  • lib/events_glib.c

    r8b8def58 r38ff846  
    4949        b_event_handler function;
    5050        gpointer data;
    51         guint flags;
    5251} GaimIOClosure;
    5352
     
    7776
    7877        if (condition & GAIM_READ_COND)
    79                 gaim_cond |= B_EV_IO_READ;
     78                gaim_cond |= GAIM_INPUT_READ;
    8079        if (condition & GAIM_WRITE_COND)
    81                 gaim_cond |= B_EV_IO_WRITE;
     80                gaim_cond |= GAIM_INPUT_WRITE;
    8281       
    8382        event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data );
     
    8887                event_debug( "Returned FALSE, cancelling.\n" );
    8988       
    90         if (closure->flags & B_EV_FLAG_FORCE_ONCE)
    91                 return FALSE;
    92         else if (closure->flags & B_EV_FLAG_FORCE_REPEAT)
    93                 return TRUE;
    94         else
    95                 return st;
     89        return st;
    9690}
    9791
     
    111105        closure->function = function;
    112106        closure->data = data;
    113         closure->flags = condition;
    114107       
    115         if (condition & B_EV_IO_READ)
     108        if (condition & GAIM_INPUT_READ)
    116109                cond |= GAIM_READ_COND;
    117         if (condition & B_EV_IO_WRITE)
     110        if (condition & GAIM_INPUT_WRITE)
    118111                cond |= GAIM_WRITE_COND;
    119112       
  • lib/events_libevent.c

    r8b8def58 r38ff846  
    6060        b_event_handler function;
    6161        void *data;
    62         guint flags;
    6362};
    6463
     
    127126        {
    128127                if( event & EV_READ )
    129                         cond |= B_EV_IO_READ;
     128                        cond |= GAIM_INPUT_READ;
    130129                if( event & EV_WRITE )
    131                         cond |= B_EV_IO_WRITE;
     130                        cond |= GAIM_INPUT_WRITE;
    132131        }
    133132       
     
    151150                return;
    152151        }
    153         else if( !st && !( b_ev->flags & B_EV_FLAG_FORCE_REPEAT ) )
     152        else if( !st )
    154153        {
    155154                event_debug( "Handler returned FALSE: " );
     
    175174        event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data );
    176175       
    177         if( ( condition & B_EV_IO_READ  && ( b_ev = g_hash_table_lookup( read_hash,  &fd ) ) ) ||
    178             ( condition & B_EV_IO_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
     176        if( ( condition & GAIM_INPUT_READ  && ( b_ev = g_hash_table_lookup( read_hash,  &fd ) ) ) ||
     177            ( condition & GAIM_INPUT_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) )
    179178        {
    180179                /* We'll stick with this libevent entry, but give it a new BitlBee id. */
     
    199198               
    200199                out_cond = EV_PERSIST;
    201                 if( condition & B_EV_IO_READ )
     200                if( condition & GAIM_INPUT_READ )
    202201                        out_cond |= EV_READ;
    203                 if( condition & B_EV_IO_WRITE )
     202                if( condition & GAIM_INPUT_WRITE )
    204203                        out_cond |= EV_WRITE;
    205204               
     
    213212        }
    214213       
    215         b_ev->flags = condition;
    216214        g_hash_table_insert( id_hash, &b_ev->id, b_ev );
    217215        return b_ev->id;
  • lib/http_client.c

    r8b8def58 r38ff846  
    149149        if( req->bytes_written < req->request_length )
    150150                req->inpa = b_input_add( source,
    151                                          req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE,
     151                                         req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_WRITE,
    152152                                         http_connected, req );
    153153        else
    154                 req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req );
     154                req->inpa = b_input_add( source, GAIM_INPUT_READ, http_incoming_data, req );
    155155       
    156156        return FALSE;
     
    234234        /* There will be more! */
    235235        req->inpa = b_input_add( req->fd,
    236                                  req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ,
     236                                 req->ssl ? ssl_getdirection( req->ssl ) : GAIM_INPUT_READ,
    237237                                 http_incoming_data, req );
    238238       
  • lib/misc.c

    r8b8def58 r38ff846  
    647647        return ret;
    648648}
    649 
    650 char **split_command_parts( char *command )
    651 {
    652         static char *cmd[IRC_MAX_ARGS+1];
    653         char *s, q = 0;
    654         int k;
    655        
    656         memset( cmd, 0, sizeof( cmd ) );
    657         cmd[0] = command;
    658         k = 1;
    659         for( s = command; *s && k < IRC_MAX_ARGS; s ++ )
    660                 if( *s == ' ' && !q )
    661                 {
    662                         *s = 0;
    663                         while( *++s == ' ' );
    664                         if( *s == '"' || *s == '\'' )
    665                         {
    666                                 q = *s;
    667                                 s ++;
    668                         }
    669                         if( *s )
    670                         {
    671                                 cmd[k++] = s;
    672                                 s --;
    673                         }
    674                         else
    675                         {
    676                                 break;
    677                         }
    678                 }
    679                 else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
    680                 {
    681                         char *cpy;
    682                        
    683                         for( cpy = s; *cpy; cpy ++ )
    684                                 cpy[0] = cpy[1];
    685                 }
    686                 else if( *s == q )
    687                 {
    688                         q = *s = 0;
    689                 }
    690        
    691         /* Full zero-padding for easier argc checking. */
    692         while( k <= IRC_MAX_ARGS )
    693                 cmd[k++] = NULL;
    694        
    695         return cmd;
    696 }
  • lib/misc.h

    r8b8def58 r38ff846  
    6969G_MODULE_EXPORT int md5_verify_password( char *password, char *hash );
    7070
    71 G_MODULE_EXPORT char **split_command_parts( char *command );
    72 
    7371#endif
  • lib/proxy.c

    r8b8def58 r38ff846  
    9191                b_event_remove(phb->inpa);
    9292                if( phb->proxy_func )
    93                         phb->proxy_func(phb->proxy_data, -1, B_EV_IO_READ);
     93                        phb->proxy_func(phb->proxy_data, -1, GAIM_INPUT_READ);
    9494                else {
    95                         phb->func(phb->data, -1, B_EV_IO_READ);
     95                        phb->func(phb->data, -1, GAIM_INPUT_READ);
    9696                        g_free(phb);
    9797                }
     
    102102        b_event_remove(phb->inpa);
    103103        if( phb->proxy_func )
    104                 phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
     104                phb->proxy_func(phb->proxy_data, source, GAIM_INPUT_READ);
    105105        else {
    106                 phb->func(phb->data, source, B_EV_IO_READ);
     106                phb->func(phb->data, source, GAIM_INPUT_READ);
    107107                g_free(phb);
    108108        }
     
    147147                return -1;
    148148        } else {
    149                 phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
     149                phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
    150150                phb->fd = fd;
    151151               
     
    179179        if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) ||
    180180            (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
    181                 phb->func(phb->data, source, B_EV_IO_READ);
     181                phb->func(phb->data, source, GAIM_INPUT_READ);
    182182                g_free(phb->host);
    183183                g_free(phb);
     
    186186
    187187        close(source);
    188         phb->func(phb->data, -1, B_EV_IO_READ);
     188        phb->func(phb->data, -1, GAIM_INPUT_READ);
    189189        g_free(phb->host);
    190190        g_free(phb);
     
    204204        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    205205                close(source);
    206                 phb->func(phb->data, -1, B_EV_IO_READ);
     206                phb->func(phb->data, -1, GAIM_INPUT_READ);
    207207                g_free(phb->host);
    208208                g_free(phb);
     
    215215        if (send(source, cmd, strlen(cmd), 0) < 0) {
    216216                close(source);
    217                 phb->func(phb->data, -1, B_EV_IO_READ);
     217                phb->func(phb->data, -1, GAIM_INPUT_READ);
    218218                g_free(phb->host);
    219219                g_free(phb);
     
    230230                if (send(source, cmd, strlen(cmd), 0) < 0) {
    231231                        close(source);
    232                         phb->func(phb->data, -1, B_EV_IO_READ);
     232                        phb->func(phb->data, -1, GAIM_INPUT_READ);
    233233                        g_free(phb->host);
    234234                        g_free(phb);
     
    240240        if (send(source, cmd, strlen(cmd), 0) < 0) {
    241241                close(source);
    242                 phb->func(phb->data, -1, B_EV_IO_READ);
    243                 g_free(phb->host);
    244                 g_free(phb);
    245                 return FALSE;
    246         }
    247 
    248         phb->inpa = b_input_add(source, B_EV_IO_READ, http_canread, phb);
     242                phb->func(phb->data, -1, GAIM_INPUT_READ);
     243                g_free(phb->host);
     244                g_free(phb);
     245                return FALSE;
     246        }
     247
     248        phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb);
    249249       
    250250        return FALSE;
     
    273273        memset(packet, 0, sizeof(packet));
    274274        if (read(source, packet, 9) >= 4 && packet[1] == 90) {
    275                 phb->func(phb->data, source, B_EV_IO_READ);
     275                phb->func(phb->data, source, GAIM_INPUT_READ);
    276276                g_free(phb->host);
    277277                g_free(phb);
     
    280280
    281281        close(source);
    282         phb->func(phb->data, -1, B_EV_IO_READ);
     282        phb->func(phb->data, -1, GAIM_INPUT_READ);
    283283        g_free(phb->host);
    284284        g_free(phb);
     
    299299        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    300300                close(source);
    301                 phb->func(phb->data, -1, B_EV_IO_READ);
     301                phb->func(phb->data, -1, GAIM_INPUT_READ);
    302302                g_free(phb->host);
    303303                g_free(phb);
     
    309309        if (!(hp = gethostbyname(phb->host))) {
    310310                close(source);
    311                 phb->func(phb->data, -1, B_EV_IO_READ);
     311                phb->func(phb->data, -1, GAIM_INPUT_READ);
    312312                g_free(phb->host);
    313313                g_free(phb);
     
    326326        if (write(source, packet, 9) != 9) {
    327327                close(source);
    328                 phb->func(phb->data, -1, B_EV_IO_READ);
    329                 g_free(phb->host);
    330                 g_free(phb);
    331                 return FALSE;
    332         }
    333 
    334         phb->inpa = b_input_add(source, B_EV_IO_READ, s4_canread, phb);
     328                phb->func(phb->data, -1, GAIM_INPUT_READ);
     329                g_free(phb->host);
     330                g_free(phb);
     331                return FALSE;
     332        }
     333
     334        phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
    335335       
    336336        return FALSE;
     
    359359        if (read(source, buf, 10) < 10) {
    360360                close(source);
    361                 phb->func(phb->data, -1, B_EV_IO_READ);
     361                phb->func(phb->data, -1, GAIM_INPUT_READ);
    362362                g_free(phb->host);
    363363                g_free(phb);
     
    366366        if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
    367367                close(source);
    368                 phb->func(phb->data, -1, B_EV_IO_READ);
    369                 g_free(phb->host);
    370                 g_free(phb);
    371                 return FALSE;
    372         }
    373 
    374         phb->func(phb->data, source, B_EV_IO_READ);
     368                phb->func(phb->data, -1, GAIM_INPUT_READ);
     369                g_free(phb->host);
     370                g_free(phb);
     371                return FALSE;
     372        }
     373
     374        phb->func(phb->data, source, GAIM_INPUT_READ);
    375375        g_free(phb->host);
    376376        g_free(phb);
     
    396396        if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
    397397                close(source);
    398                 phb->func(phb->data, -1, B_EV_IO_READ);
     398                phb->func(phb->data, -1, GAIM_INPUT_READ);
    399399                g_free(phb->host);
    400400                g_free(phb);
     
    402402        }
    403403
    404         phb->inpa = b_input_add(source, B_EV_IO_READ, s5_canread_again, phb);
     404        phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
    405405}
    406406
     
    414414        if (read(source, buf, 2) < 2) {
    415415                close(source);
    416                 phb->func(phb->data, -1, B_EV_IO_READ);
     416                phb->func(phb->data, -1, GAIM_INPUT_READ);
    417417                g_free(phb->host);
    418418                g_free(phb);
     
    422422        if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
    423423                close(source);
    424                 phb->func(phb->data, -1, B_EV_IO_READ);
     424                phb->func(phb->data, -1, GAIM_INPUT_READ);
    425425                g_free(phb->host);
    426426                g_free(phb);
     
    442442        if (read(source, buf, 2) < 2) {
    443443                close(source);
    444                 phb->func(phb->data, -1, B_EV_IO_READ);
     444                phb->func(phb->data, -1, GAIM_INPUT_READ);
    445445                g_free(phb->host);
    446446                g_free(phb);
     
    450450        if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
    451451                close(source);
    452                 phb->func(phb->data, -1, B_EV_IO_READ);
     452                phb->func(phb->data, -1, GAIM_INPUT_READ);
    453453                g_free(phb->host);
    454454                g_free(phb);
     
    465465                if (write(source, buf, 3 + i + j) < 3 + i + j) {
    466466                        close(source);
    467                         phb->func(phb->data, -1, B_EV_IO_READ);
     467                        phb->func(phb->data, -1, GAIM_INPUT_READ);
    468468                        g_free(phb->host);
    469469                        g_free(phb);
     
    471471                }
    472472
    473                 phb->inpa = b_input_add(source, B_EV_IO_READ, s5_readauth, phb);
     473                phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_readauth, phb);
    474474        } else {
    475475                s5_sendconnect(phb, source);
     
    491491        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    492492                close(source);
    493                 phb->func(phb->data, -1, B_EV_IO_READ);
     493                phb->func(phb->data, -1, GAIM_INPUT_READ);
    494494                g_free(phb->host);
    495495                g_free(phb);
     
    513513        if (write(source, buf, i) < i) {
    514514                close(source);
    515                 phb->func(phb->data, -1, B_EV_IO_READ);
    516                 g_free(phb->host);
    517                 g_free(phb);
    518                 return FALSE;
    519         }
    520 
    521         phb->inpa = b_input_add(source, B_EV_IO_READ, s5_canread, phb);
     515                phb->func(phb->data, -1, GAIM_INPUT_READ);
     516                g_free(phb->host);
     517                g_free(phb);
     518                return FALSE;
     519        }
     520
     521        phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
    522522       
    523523        return FALSE;
  • lib/ssl_bogus.c

    r8b8def58 r38ff846  
    5959b_input_condition ssl_getdirection( void *conn )
    6060{
    61         return B_EV_IO_READ;
     61        return GAIM_INPUT_READ;
    6262}
    6363
  • lib/ssl_client.h

    r8b8def58 r38ff846  
    7171G_MODULE_EXPORT int ssl_getfd( void *conn );
    7272
    73 /* This function returns B_EV_IO_READ/WRITE. With SSL connections it's
     73/* This function returns GAIM_INPUT_READ/WRITE. With SSL connections it's
    7474   possible that something has to be read while actually were trying to
    7575   write something (think about key exchange/refresh/etc). So when an
  • lib/ssl_gnutls.c

    r8b8def58 r38ff846  
    106106        struct scd *conn = data;
    107107       
    108         return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
     108        return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE );
    109109}
    110110
     
    244244{
    245245        return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ?
    246                 B_EV_IO_WRITE : B_EV_IO_READ );
    247 }
     246                GAIM_INPUT_WRITE : GAIM_INPUT_READ );
     247}
  • lib/ssl_nss.c

    r8b8def58 r38ff846  
    193193{
    194194        /* Just in case someone calls us, let's return the most likely case: */
    195         return B_EV_IO_READ;
     195        return GAIM_INPUT_READ;
    196196}
  • lib/ssl_openssl.c

    r8b8def58 r38ff846  
    102102        struct scd *conn = data;
    103103       
    104         return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
     104        return ssl_connected( conn, conn->fd, GAIM_INPUT_WRITE );
    105105}
    106106
     
    270270b_input_condition ssl_getdirection( void *conn )
    271271{
    272         return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ );
    273 }
     272        return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? GAIM_INPUT_WRITE : GAIM_INPUT_READ );
     273}
  • lib/ssl_sspi.c

    r8b8def58 r38ff846  
    275275GaimInputCondition ssl_getdirection( void *conn )
    276276{
    277         return B_EV_IO_WRITE; /* FIXME: or B_EV_IO_READ */
    278 }
     277        return GAIM_INPUT_WRITE; /* FIXME: or GAIM_INPUT_READ */
     278}
  • nick.c

    r8b8def58 r38ff846  
    7878               
    7979                nick_strip( nick );
    80                 if( set_getbool( &acc->bee->set, "lcnicks" ) )
     80                if( set_getbool( &acc->irc->set, "lcnicks" ) )
    8181                        nick_lc( nick );
    8282        }
     
    9292void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] )
    9393{
    94         irc_t *irc = (irc_t*) acc->bee->ui_data;
    9594        int inf_protection = 256;
    9695       
    9796        /* Now, find out if the nick is already in use at the moment, and make
    9897           subtle changes to make it unique. */
    99         while( !nick_ok( nick ) || irc_user_by_name( irc, nick ) )
     98        while( !nick_ok( nick ) || user_find( acc->irc, nick ) )
    10099        {
    101100                if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) )
     
    113112                        int i;
    114113                       
    115                         irc_usermsg( irc, "Warning: Almost had an infinite loop in nick_get()! "
    116                                           "This used to be a fatal BitlBee bug, but we tried to fix it. "
    117                                           "This message should *never* appear anymore. "
    118                                           "If it does, please *do* send us a bug report! "
    119                                           "Please send all the following lines in your report:" );
    120                        
    121                         irc_usermsg( irc, "Trying to get a sane nick for handle %s", handle );
     114                        irc_usermsg( acc->irc, "Warning: Almost had an infinite loop in nick_get()! "
     115                                               "This used to be a fatal BitlBee bug, but we tried to fix it. "
     116                                               "This message should *never* appear anymore. "
     117                                               "If it does, please *do* send us a bug report! "
     118                                               "Please send all the following lines in your report:" );
     119                       
     120                        irc_usermsg( acc->irc, "Trying to get a sane nick for handle %s", handle );
    122121                        for( i = 0; i < MAX_NICK_LENGTH; i ++ )
    123                                 irc_usermsg( irc, "Char %d: %c/%d", i, nick[i], nick[i] );
    124                        
    125                         irc_usermsg( irc, "FAILED. Returning an insane nick now. Things might break. "
    126                                           "Good luck, and please don't forget to paste the lines up here "
    127                                           "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
     122                                irc_usermsg( acc->irc, "Char %d: %c/%d", i, nick[i], nick[i] );
     123                       
     124                        irc_usermsg( acc->irc, "FAILED. Returning an insane nick now. Things might break. "
     125                                               "Good luck, and please don't forget to paste the lines up here "
     126                                               "in #bitlbee on OFTC or in a mail to wilmer@gaast.net" );
    128127                       
    129128                        g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() );
  • protocols/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)protocols/
    12 endif
    1310
    1411# [SH] Program variables
    15 objects = account.o bee.o bee_chat.o bee_ft.o bee_user.o nogaim.o
    16 
     12objects = nogaim.o
    1713
    1814# [SH] The next two lines should contain the directory name (in $(subdirs))
     
    5349$(objects): ../Makefile.settings Makefile
    5450
    55 $(objects): %.o: $(SRCDIR)%.c
     51$(objects): %.o: %.c
    5652        @echo '*' Compiling $<
    5753        @$(CC) -c $(CFLAGS) $< -o $@
  • protocols/jabber/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)protocols/jabber/
    12 endif
    1310
    1411# [SH] Program variables
    15 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o
    1613
    1714CFLAGS += -Wall
     
    3633$(objects): ../../Makefile.settings Makefile
    3734
    38 $(objects): %.o: $(SRCDIR)%.c
     35$(objects): %.o: %.c
    3936        @echo '*' Compiling $<
    4037        @$(CC) -c $(CFLAGS) $< -o $@
  • protocols/jabber/conference.c

    r8b8def58 r38ff846  
    9292{
    9393        char *normalized = jabber_normalize( name );
    94         GSList *l;
    9594        struct groupchat *ret;
    9695        struct jabber_chat *jc;
    9796       
    98         for( l = ic->groupchats; l; l = l->next )
    99         {
    100                 ret = l->data;
     97        for( ret = ic->groupchats; ret; ret = ret->next )
     98        {
    10199                jc = ret->data;
    102100                if( strcmp( normalized, jc->name ) == 0 )
     
    105103        g_free( normalized );
    106104       
    107         return l ? ret : NULL;
     105        return ret;
    108106}
    109107
  • protocols/jabber/io.c

    r8b8def58 r38ff846  
    6464                   most cases it probably won't be necessary.) */
    6565                if( ( ret = jabber_write_queue( ic ) ) && jd->tx_len > 0 )
    66                         jd->w_inpa = b_input_add( jd->fd, B_EV_IO_WRITE, jabber_write_callback, ic );
     66                        jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, ic );
    6767        }
    6868        else
     
    504504       
    505505        if( jd->r_inpa <= 0 )
    506                 jd->r_inpa = b_input_add( jd->fd, B_EV_IO_READ, jabber_read_callback, ic );
     506                jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );
    507507       
    508508        greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
  • protocols/jabber/iq.c

    r8b8def58 r38ff846  
    9191                        pack = 0;
    9292                }
    93                 else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 )
    94                 {
    95                         const char *features[] = { XMLNS_DISCO_INFO,
     93                else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
     94                {
     95                        const char *features[] = { XMLNS_DISCOVER,
    9696                                                   XMLNS_VERSION,
    9797                                                   XMLNS_TIME,
     
    9999                                                   XMLNS_MUC,
    100100                                                   XMLNS_PING,
    101                                                    XMLNS_SI,
    102                                                    XMLNS_BYTESTREAMS,
    103                                                    XMLNS_FILETRANSFER,
    104101                                                   NULL };
    105102                        const char **f;
     
    121118                {
    122119                        xt_free_node( reply );
    123                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
     120                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
    124121                        pack = 0;
    125122                }
     
    127124        else if( strcmp( type, "set" ) == 0 )
    128125        {
    129                 if( ( c = xt_find_node( node->children, "si" ) ) &&
    130                     ( s = xt_find_attr( c, "xmlns" ) ) &&
    131                     ( strcmp( s, XMLNS_SI ) == 0 ) )
    132                 {
    133                         return jabber_si_handle_request( ic, node, c );
    134                 }
    135                 else if( !( c = xt_find_node( node->children, "query" ) ) ||
    136                          !( s = xt_find_attr( c, "xmlns" ) ) )
     126                if( !( c = xt_find_node( node->children, "query" ) ) ||
     127                    !( s = xt_find_attr( c, "xmlns" ) ) )
    137128                {
    138129                        return XT_HANDLED;
    139130                }
    140                 else if( strcmp( s, XMLNS_ROSTER ) == 0 )
    141                 {
     131               
    142132                /* This is a roster push. XMPP servers send this when someone
    143133                   was added to (or removed from) the buddy list. AFAIK they're
    144134                   sent even if we added this buddy in our own session. */
     135                if( strcmp( s, XMLNS_ROSTER ) == 0 )
     136                {
    145137                        int bare_len = strlen( ic->acc->user );
    146138                       
     
    159151                               
    160152                                xt_free_node( reply );
    161                                 reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL );
     153                                reply = jabber_make_error_packet( node, "not-allowed", "cancel" );
    162154                                pack = 0;
    163155                        }
    164156                }
    165                 else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 )
    166                 {
    167                         /* Bytestream Request (stage 2 of file transfer) */
    168                         return jabber_bs_recv_request( ic, node, c );
    169                 }
    170157                else
    171158                {
    172159                        xt_free_node( reply );
    173                         reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL );
     160                        reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel" );
    174161                        pack = 0;
    175162                }
     
    382369        while( ( c = xt_find_node( c, "item" ) ) )
    383370        {
    384                 struct xt_node *group = xt_find_node( c->children, "group" );
     371                struct xt_node *group = xt_find_node( node->children, "group" );
    385372                char *jid = xt_find_attr( c, "jid" );
    386373                char *name = xt_find_attr( c, "name" );
     
    391378                        if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
    392379                        {
    393                                 imcb_add_buddy( ic, jid, ( group && group->text_len ) ?
    394                                                            group->text : NULL );
     380                                if( initial || imcb_find_buddy( ic, jid ) == NULL )
     381                                        imcb_add_buddy( ic, jid, ( group && group->text_len ) ?
     382                                                                   group->text : NULL );
    395383                               
    396384                                if( name )
     
    555543static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
    556544
    557 int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group )
     545int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name )
    558546{
    559547        struct xt_node *node;
     
    565553        if( name )
    566554                xt_add_attr( node, "name", name );
    567         if( group )
    568                 xt_add_child( node, xt_new_node( "group", group, NULL ) );
    569555       
    570556        /* And pack it into a roster-add packet */
     
    590576            strcmp( s, "result" ) == 0 )
    591577        {
    592                 if( bee_user_by_handle( ic->bee, ic, jid ) == NULL )
     578                if( imcb_find_buddy( ic, jid ) == NULL )
    593579                        imcb_add_buddy( ic, jid, NULL );
    594580        }
     
    622608        return st;
    623609}
    624 
    625 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
    626 
    627 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid )
    628 {
    629         struct xt_node *node, *query;
    630         struct jabber_buddy *bud;
    631        
    632         if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL )
    633         {
    634                 /* Who cares about the unknown... */
    635                 imcb_log( ic, "Couldn't find buddy: %s", bare_jid);
    636                 return XT_HANDLED;
    637         }
    638        
    639         if( bud->features ) /* been here already */
    640                 return XT_HANDLED;
    641        
    642         node = xt_new_node( "query", NULL, NULL );
    643         xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO );
    644        
    645         if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) )
    646         {
    647                 imcb_log( ic, "WARNING: Couldn't generate feature query" );
    648                 xt_free_node( node );
    649                 return XT_HANDLED;
    650         }
    651 
    652         jabber_cache_add( ic, query, jabber_iq_parse_features );
    653 
    654         return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
    655 }
    656 
    657 xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
    658 {
    659         struct xt_node *c;
    660         struct jabber_buddy *bud;
    661         char *feature, *xmlns, *from;
    662 
    663         if( !( from = xt_find_attr( node, "from" ) ) ||
    664             !( c = xt_find_node( node->children, "query" ) ) ||
    665             !( xmlns = xt_find_attr( c, "xmlns" ) ) ||
    666             !( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) )
    667         {
    668                 imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
    669                 return XT_HANDLED;
    670         }
    671         if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL )
    672         {
    673                 /* Who cares about the unknown... */
    674                 imcb_log( ic, "Couldn't find buddy: %s", from );
    675                 return XT_HANDLED;
    676         }
    677        
    678         c = c->children;
    679         while( ( c = xt_find_node( c, "feature" ) ) )
    680         {
    681                 feature = xt_find_attr( c, "var" );
    682                 if( feature )
    683                         bud->features = g_slist_append( bud->features, g_strdup( feature ) );
    684                 c = c->next;
    685         }
    686 
    687         return XT_HANDLED;
    688 }
    689 
    690 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
    691 
    692 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns )
    693 {
    694         struct xt_node *node, *query;
    695         struct jabber_data *jd = ic->proto_data;
    696        
    697         node = xt_new_node( "query", NULL, NULL );
    698         xt_add_attr( node, "xmlns", xmlns );
    699        
    700         if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) )
    701         {
    702                 imcb_log( ic, "WARNING: Couldn't generate server query" );
    703                 xt_free_node( node );
    704         }
    705 
    706         jd->have_streamhosts--;
    707         jabber_cache_add( ic, query, jabber_iq_parse_server_features );
    708 
    709         return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT;
    710 }
    711 
    712 /*
    713  * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info
    714  */
    715 xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
    716 {
    717         struct xt_node *c;
    718         struct jabber_data *jd = ic->proto_data;
    719         char *xmlns, *from;
    720 
    721         if( !( c = xt_find_node( node->children, "query" ) ) ||
    722             !( from = xt_find_attr( node, "from" ) ) ||
    723             !( xmlns = xt_find_attr( c, "xmlns" ) ) )
    724         {
    725                 imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" );
    726                 return XT_HANDLED;
    727         }
    728 
    729         jd->have_streamhosts++;
    730 
    731         if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 )
    732         {
    733                 char *itemjid;
    734 
    735                 /* answer from server */
    736        
    737                 c = c->children;
    738                 while( ( c = xt_find_node( c, "item" ) ) )
    739                 {
    740                         itemjid = xt_find_attr( c, "jid" );
    741                        
    742                         if( itemjid )
    743                                 jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO );
    744 
    745                         c = c->next;
    746                 }
    747         }
    748         else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 )
    749         {
    750                 char *category, *type;
    751 
    752                 /* answer from potential proxy */
    753 
    754                 c = c->children;
    755                 while( ( c = xt_find_node( c, "identity" ) ) )
    756                 {
    757                         category = xt_find_attr( c, "category" );
    758                         type = xt_find_attr( c, "type" );
    759 
    760                         if( type && ( strcmp( type, "bytestreams" ) == 0 ) &&
    761                             category && ( strcmp( category, "proxy" ) == 0 ) )
    762                                 jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS );
    763 
    764                         c = c->next;
    765                 }
    766         }
    767         else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 )
    768         {
    769                 char *host, *jid, *port_s;
    770                 int port;
    771 
    772                 /* answer from proxy */
    773 
    774                 if( ( c = xt_find_node( c->children, "streamhost" ) ) &&
    775                     ( host = xt_find_attr( c, "host" ) ) &&
    776                     ( port_s = xt_find_attr( c, "port" ) ) &&
    777                     ( sscanf( port_s, "%d", &port ) == 1 ) &&
    778                     ( jid = xt_find_attr( c, "jid" ) ) )
    779                 {
    780                         jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 );
    781                        
    782                         sh->jid = g_strdup( jid );
    783                         sh->host = g_strdup( host );
    784                         g_snprintf( sh->port, sizeof( sh->port ), "%u", port );
    785 
    786                         imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port );
    787                         jd->streamhosts = g_slist_append( jd->streamhosts, sh );
    788                 }
    789         }
    790 
    791         if( jd->have_streamhosts == 0 )
    792                 jd->have_streamhosts++;
    793 
    794         return XT_HANDLED;
    795 }
  • protocols/jabber/jabber.c

    r8b8def58 r38ff846  
    6565       
    6666        s = set_add( &acc->set, "priority", "0", set_eval_priority, acc );
    67 
    68         s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc );
    6967       
    7068        s = set_add( &acc->set, "resource", "BitlBee", NULL, acc );
     
    268266        struct jabber_data *jd = ic->proto_data;
    269267       
    270         while( jd->filetransfers )
    271                 imcb_file_canceled( ic, ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" );
    272 
    273         while( jd->streamhosts )
    274         {
    275                 jabber_streamhost_t *sh = jd->streamhosts->data;
    276                 jd->streamhosts = g_slist_remove( jd->streamhosts, sh );
    277                 g_free( sh->jid );
    278                 g_free( sh->host );
    279                 g_free( sh );
    280         }
    281 
    282268        if( jd->fd >= 0 )
    283269                jabber_end_stream( ic );
    284270       
    285271        while( ic->groupchats )
    286                 jabber_chat_free( ic->groupchats->data );
     272                jabber_chat_free( ic->groupchats );
    287273       
    288274        if( jd->r_inpa >= 0 )
     
    415401        }
    416402       
    417         if( jabber_add_to_roster( ic, who, NULL, group ) )
     403        if( jabber_add_to_roster( ic, who, NULL ) )
    418404                presence_send_request( ic, who, "subscribe" );
    419405}
     
    563549        ret->send_typing = jabber_send_typing;
    564550        ret->handle_cmp = g_strcasecmp;
    565         ret->transfer_request = jabber_si_transfer_request;
    566551
    567552        register_protocol( ret );
  • protocols/jabber/jabber.h

    r8b8def58 r38ff846  
    6161} jabber_buddy_flags_t;
    6262
    63 /* Stores a streamhost's (a.k.a. proxy) data */
    64 typedef struct
    65 {
    66         char *jid;
    67         char *host;
    68         char port[6];
    69 } jabber_streamhost_t;
    70 
    7163typedef enum
    7264{
     
    9991        GHashTable *node_cache;
    10092        GHashTable *buddies;
    101 
    102         GSList *filetransfers;
    103         GSList *streamhosts;
    104         int have_streamhosts;
    10593};
    10694
     
    139127        struct jabber_away_state *away_state;
    140128        char *away_message;
    141         GSList *features;
    142129       
    143130        time_t last_msg;
     
    153140        char *my_full_jid; /* Separate copy because of case sensitivity. */
    154141        struct jabber_buddy *me;
    155 };
    156 
    157 struct jabber_transfer
    158 {
    159         /* bitlbee's handle for this transfer */
    160         file_transfer_t *ft;
    161 
    162         /* the stream's private handle */
    163         gpointer streamhandle;
    164 
    165         /* timeout for discover queries */
    166         gint disco_timeout;
    167         gint disco_timeout_fired;
    168 
    169         struct im_connection *ic;
    170 
    171         struct jabber_buddy *bud;
    172 
    173         int watch_in;
    174         int watch_out;
    175 
    176         char *ini_jid;
    177         char *tgt_jid;
    178         char *iq_id;
    179         char *sid;
    180         int accepted;
    181 
    182         size_t bytesread, byteswritten;
    183         int fd;
    184         struct sockaddr_storage saddr;
    185142};
    186143
     
    210167
    211168/* Some supported extensions/legacy stuff */
    212 #define XMLNS_AUTH         "jabber:iq:auth"                                      /* XEP-0078 */
    213 #define XMLNS_VERSION      "jabber:iq:version"                                   /* XEP-0092 */
    214 #define XMLNS_TIME         "jabber:iq:time"                                      /* XEP-0090 */
    215 #define XMLNS_PING         "urn:xmpp:ping"                                       /* XEP-0199 */
    216 #define XMLNS_VCARD        "vcard-temp"                                          /* XEP-0054 */
    217 #define XMLNS_DELAY        "jabber:x:delay"                                      /* XEP-0091 */
    218 #define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
    219 #define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
    220 #define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
    221 #define XMLNS_DISCO_ITEMS  "http://jabber.org/protocol/disco#items"              /* XEP-0030 */
    222 #define XMLNS_MUC          "http://jabber.org/protocol/muc"                      /* XEP-0045 */
    223 #define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"                 /* XEP-0045 */
    224 #define XMLNS_CAPS         "http://jabber.org/protocol/caps"                     /* XEP-0115 */
    225 #define XMLNS_FEATURE      "http://jabber.org/protocol/feature-neg"              /* XEP-0020 */
    226 #define XMLNS_SI           "http://jabber.org/protocol/si"                       /* XEP-0095 */
    227 #define XMLNS_FILETRANSFER "http://jabber.org/protocol/si/profile/file-transfer" /* XEP-0096 */
    228 #define XMLNS_BYTESTREAMS  "http://jabber.org/protocol/bytestreams"              /* XEP-0065 */
    229 #define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
     169#define XMLNS_AUTH         "jabber:iq:auth"                     /* XEP-0078 */
     170#define XMLNS_VERSION      "jabber:iq:version"                  /* XEP-0092 */
     171#define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
     172#define XMLNS_PING         "urn:xmpp:ping"                      /* XEP-0199 */
     173#define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
     174#define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
     175#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
     176#define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
     177#define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
     178#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
     179#define XMLNS_CAPS         "http://jabber.org/protocol/caps"    /* XEP-0115 */
    230180
    231181/* iq.c */
     
    235185int jabber_get_roster( struct im_connection *ic );
    236186int jabber_get_vcard( struct im_connection *ic, char *bare_jid );
    237 int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group );
     187int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name );
    238188int jabber_remove_from_roster( struct im_connection *ic, char *handle );
    239 xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid );
    240 xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns );
    241 
    242 /* si.c */
    243 int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode );
    244 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
    245 void jabber_si_free_transfer( file_transfer_t *ft);
    246 
    247 /* s5bytestream.c */
    248 int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode);
    249 gboolean jabber_bs_send_start( struct jabber_transfer *tf );
    250 gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len );
    251189
    252190/* message.c */
     
    262200char *set_eval_tls( set_t *set, char *value );
    263201struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children );
    264 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code );
     202struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type );
    265203void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func );
    266204struct xt_node *jabber_cache_get( struct im_connection *ic, char *id );
  • protocols/jabber/jabber_util.c

    r8b8def58 r38ff846  
    9999}
    100100
    101 struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code )
     101struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type )
    102102{
    103103        struct xt_node *node, *c;
     
    111111        c = xt_new_node( "error", NULL, c );
    112112        xt_add_attr( c, "type", err_type );
    113        
    114         /* Add the error code, if present */
    115         if (err_code)
    116                 xt_add_attr( c, "code", err_code );
    117113       
    118114        /* To make the actual error packet, we copy the original packet and
     
    279275        presence_send_request( bla->ic, bla->handle, "subscribed" );
    280276       
    281         imcb_ask_add( bla->ic, bla->handle, NULL );
     277        if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
     278                imcb_ask_add( bla->ic, bla->handle, NULL );
    282279       
    283280        g_free( bla->handle );
     
    461458               
    462459                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
    463                     ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) )
     460                    ( bare_exists || imcb_find_buddy( ic, jid ) ) )
    464461                {
    465462                        *s = '/';
     
    482479                if( bud == NULL )
    483480                        /* No match. Create it now? */
    484                         return ( ( flags & GET_BUDDY_CREAT ) &&
    485                                  bee_user_by_handle( ic->bee, ic, jid_ ) ) ?
     481                        return ( ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid_ ) ) ?
    486482                                   jabber_buddy_add( ic, jid_ ) : NULL;
    487483                else if( bud->resource && ( flags & GET_BUDDY_EXACT ) )
  • protocols/jabber/presence.c

    r8b8def58 r38ff846  
    205205        struct jabber_data *jd = ic->proto_data;
    206206        struct xt_node *node, *cap;
    207         GSList *l;
     207        struct groupchat *c;
    208208        int st;
    209209       
     
    229229        /* Have to send this update to all groupchats too, the server won't
    230230           do this automatically. */
    231         for( l = ic->groupchats; l && st; l = l->next )
    232         {
    233                 struct groupchat *c = l->data;
     231        for( c = ic->groupchats; c && st; c = c->next )
     232        {
    234233                struct jabber_chat *jc = c->data;
    235234               
  • protocols/msn/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)protocols/msn/
    12 endif
    1310
    1411# [SH] Program variables
     
    3633$(objects): ../../Makefile.settings Makefile
    3734
    38 $(objects): %.o: $(SRCDIR)%.c
     35$(objects): %.o: %.c
    3936        @echo '*' Compiling $<
    4037        @$(CC) -c $(CFLAGS) $< -o $@
  • protocols/msn/msn.c

    r8b8def58 r38ff846  
    7979        if( md )
    8080        {
    81                 /** Disabling MSN ft support for now.
    82                 while( md->filetransfers ) {
    83                         imcb_file_canceled( md->filetransfers->data, "Closing connection" );
    84                 }
    85                 */
    86                
    8781                if( md->fd >= 0 )
    8882                        closesocket( md->fd );
     
    10498                g_free( md->grouplist );
    10599               
    106                 while( md->grpq )
    107                 {
    108                         struct msn_groupadd *ga = md->grpq->data;
    109                         g_free( ga->group );
    110                         g_free( ga->who );
    111                         g_free( ga );
    112                         md->grpq = g_slist_remove( md->grpq, ga );
    113                 }
    114                
    115100                g_free( md );
    116101        }
     
    131116        struct msn_switchboard *sb;
    132117       
    133 #ifdef DEBUG
    134         if( strcmp( who, "raw" ) == 0 )
    135         {
    136                 msn_write( ic, message, strlen( message ) );
    137                 msn_write( ic, "\r\n", 2 );
    138         }
    139         else
    140 #endif
    141118        if( ( sb = msn_sb_by_handle( ic, who ) ) )
    142119        {
     
    199176static void msn_add_buddy( struct im_connection *ic, char *who, char *group )
    200177{
    201         msn_buddy_list_add( ic, "FL", who, who, group );
     178        msn_buddy_list_add( ic, "FL", who, who );
    202179}
    203180
     
    240217{
    241218        struct msn_switchboard *sb;
    242         struct groupchat *c = imcb_chat_new( ic, who );
    243219       
    244220        if( ( sb = msn_sb_by_handle( ic, who ) ) )
     
    258234                msn_sb_write_msg( ic, m );
    259235
    260                 return c;
    261         }
     236                return NULL;
     237        }
     238       
     239        return NULL;
    262240}
    263241
     
    269247static void msn_add_permit( struct im_connection *ic, char *who )
    270248{
    271         msn_buddy_list_add( ic, "AL", who, who, NULL );
     249        msn_buddy_list_add( ic, "AL", who, who );
    272250}
    273251
     
    281259        struct msn_switchboard *sb;
    282260       
    283         msn_buddy_list_add( ic, "BL", who, who, NULL );
     261        msn_buddy_list_add( ic, "BL", who, who );
    284262       
    285263        /* If there's still a conversation with this person, close it. */
     
    350328        ret->send_typing = msn_send_typing;
    351329        ret->handle_cmp = g_strcasecmp;
    352         //ret->transfer_request = msn_ftp_transfer_request;
    353330
    354331        register_protocol(ret);
  • protocols/msn/msn.h

    r8b8def58 r38ff846  
    7070        int trId;
    7171       
    72         GSList *msgq, *grpq;
     72        GSList *msgq;
    7373        GSList *switchboards;
    7474        int sb_failures;
    7575        time_t first_sb_failure;
    76         GSList *filetransfers;
    7776       
    7877        const struct msn_away_state *away_state;
     
    121120};
    122121
    123 struct msn_groupadd
    124 {
    125         char *who;
    126         char *group;
    127 };
    128 
    129122struct msn_handler_data
    130123{
     
    166159int msn_write( struct im_connection *ic, char *s, int len );
    167160int msn_logged_in( struct im_connection *ic );
    168 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group );
     161int msn_buddy_list_add( struct im_connection *ic, char *list, char *who, char *realname );
    169162int msn_buddy_list_remove( struct im_connection *ic, char *list, char *who );
    170163void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname );
     
    196189void msn_sb_stop_keepalives( struct msn_switchboard *sb );
    197190
    198 /* invitation.c */
    199 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who );
    200 
    201191#endif //_MSN_H
  • protocols/msn/msn_util.c

    r8b8def58 r38ff846  
    5151}
    5252
    53 int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group )
     53int msn_buddy_list_add( struct im_connection *ic, char *list, char *who, char *realname_ )
    5454{
    5555        struct msn_data *md = ic->proto_data;
    56         char buf[1024], *realname, groupid[8];
    57        
    58         *groupid = '\0';
    59         if( group )
    60         {
    61                 int i;
    62                 for( i = 0; i < md->groupcount; i ++ )
    63                         if( g_strcasecmp( md->grouplist[i], group ) == 0 )
    64                         {
    65                                 g_snprintf( groupid, sizeof( groupid ), " %d", i );
    66                                 break;
    67                         }
    68                
    69                 if( *groupid == '\0' )
    70                 {
    71                         /* Have to create this group, it doesn't exist yet. */
    72                         struct msn_groupadd *ga;
    73                         GSList *l;
    74                        
    75                         for( l = md->grpq; l; l = l->next )
    76                         {
    77                                 ga = l->data;
    78                                 if( g_strcasecmp( ga->group, group ) == 0 )
    79                                         break;
    80                         }
    81                        
    82                         ga = g_new0( struct msn_groupadd, 1 );
    83                         ga->who = g_strdup( who );
    84                         ga->group = g_strdup( group );
    85                         md->grpq = g_slist_prepend( md->grpq, ga );
    86                        
    87                         if( l == NULL )
    88                         {
    89                                 char *groupname = msn_http_encode( group );
    90                                 g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 );
    91                                 g_free( groupname );
    92                                 return msn_write( ic, buf, strlen( buf ) );
    93                         }
    94                         else
    95                         {
    96                                 /* This can happen if the user's doing lots of adds to a
    97                                    new group at once; we're still waiting for the server
    98                                    to confirm group creation. */
    99                                 return 1;
    100                         }
    101                 }
    102         }
     56        char buf[1024], *realname;
    10357       
    10458        realname = msn_http_encode( realname_ );
    105         g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid );
     59       
     60        g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s\r\n", ++md->trId, list, who, realname );
     61        if( msn_write( ic, buf, strlen( buf ) ) )
     62        {
     63                g_free( realname );
     64               
     65                return( 1 );
     66        }
     67       
    10668        g_free( realname );
    10769       
    108         return msn_write( ic, buf, strlen( buf ) );
     70        return( 0 );
    10971}
    11072
     
    13294        struct msn_buddy_ask_data *bla = data;
    13395       
    134         msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname, NULL );
    135        
    136         imcb_ask_add( bla->ic, bla->handle, NULL );
     96        msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname );
     97       
     98        if( imcb_find_buddy( bla->ic, bla->handle ) == NULL )
     99                imcb_ask_add( bla->ic, bla->handle, NULL );
    137100       
    138101        g_free( bla->handle );
     
    145108        struct msn_buddy_ask_data *bla = data;
    146109       
    147         msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname, NULL );
     110        msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname );
    148111       
    149112        g_free( bla->handle );
  • protocols/msn/ns.c

    r8b8def58 r38ff846  
    7676        if( msn_write( ic, s, strlen( s ) ) )
    7777        {
    78                 ic->inpa = b_input_add( md->fd, B_EV_IO_READ, msn_ns_callback, ic );
     78                ic->inpa = b_input_add( md->fd, GAIM_INPUT_READ, msn_ns_callback, ic );
    7979                imcb_log( ic, "Connected to server, waiting for reply" );
    8080        }
     
    533533                else if( num_parts >= 6 && strcmp( cmd[2], "FL" ) == 0 )
    534534                {
    535                         const char *group = NULL;
    536                         int num;
    537                        
    538                         if( cmd[6] != NULL && sscanf( cmd[6], "%d", &num ) == 1 && num < md->groupcount )
    539                                 group = md->grouplist[num];
    540                        
    541535                        http_decode( cmd[5] );
    542                         imcb_add_buddy( ic, cmd[4], group );
     536                        imcb_add_buddy( ic, cmd[4], NULL );
    543537                        imcb_rename_buddy( ic, cmd[4], cmd[5] );
    544538                }
     
    610604                        imc_logout( ic, TRUE );
    611605                        return( 0 );
    612                 }
    613         }
    614         else if( strcmp( cmd[0], "ADG" ) == 0 )
    615         {
    616                 char *group = g_strdup( cmd[3] );
    617                 int groupnum, i;
    618                 GSList *l, *next;
    619                
    620                 http_decode( group );
    621                 if( sscanf( cmd[4], "%d", &groupnum ) == 1 )
    622                 {
    623                         if( groupnum >= md->groupcount )
    624                         {
    625                                 md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 );
    626                                 for( i = md->groupcount; i <= groupnum; i ++ )
    627                                         md->grouplist[i] = NULL;
    628                                 md->groupcount = groupnum + 1;
    629                         }
    630                         g_free( md->grouplist[groupnum] );
    631                         md->grouplist[groupnum] = group;
    632                 }
    633                 else
    634                 {
    635                         /* Shouldn't happen, but if it does, give up on the group. */
    636                         g_free( group );
    637                         imcb_error( ic, "Syntax error" );
    638                         imc_logout( ic, TRUE );
    639                         return 0;
    640                 }
    641                
    642                 for( l = md->grpq; l; l = next )
    643                 {
    644                         struct msn_groupadd *ga = l->data;
    645                         next = l->next;
    646                         if( g_strcasecmp( ga->group, group ) == 0 )
    647                         {
    648                                 if( !msn_buddy_list_add( ic, "FL", ga->who, ga->who, group ) )
    649                                         return 0;
    650                                
    651                                 g_free( ga->group );
    652                                 g_free( ga->who );
    653                                 g_free( ga );
    654                                 md->grpq = g_slist_remove( md->grpq, ga );
    655                         }
    656606                }
    657607        }
  • protocols/msn/sb.c

    r8b8def58 r38ff846  
    2929#include "passport.h"
    3030#include "md5.h"
    31 #include "invitation.h"
    3231
    3332static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond );
     
    178177                {
    179178                        buf = g_strdup( SB_KEEPALIVE_HEADERS );
    180                         i = strlen( buf );
    181                 }
    182                 else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 )
    183                 {
    184                         buf = g_strdup( text );
    185179                        i = strlen( buf );
    186180                }
     
    233227{
    234228        struct im_connection *ic = sb->ic;
    235         struct groupchat *c = NULL;
    236229        char buf[1024];
    237230       
    238231        /* Create the groupchat structure. */
    239232        g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session );
    240         if( sb->who )
    241                 c = bee_chat_by_title( ic->bee, ic, sb->who );
    242         if( c && !msn_sb_by_chat( c ) )
    243                 sb->chat = c;
    244         else
    245                 sb->chat = imcb_chat_new( ic, buf );
     233        sb->chat = imcb_chat_new( ic, buf );
    246234       
    247235        /* Populate the channel. */
     
    327315       
    328316        if( msn_sb_write( sb, buf, strlen( buf ) ) )
    329                 sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb );
     317                sb->inp = b_input_add( sb->fd, GAIM_INPUT_READ, msn_sb_callback, sb );
    330318        else
    331319                debug( "Error %d while connecting to switchboard server", 2 );
     
    704692                        }
    705693                }
    706 #if 0
    707                 // Disable MSN ft support for now.
    708694                else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 )
    709695                {
    710                         char *command = msn_findheader( body, "Invitation-Command:", blen );
    711                         char *cookie = msn_findheader( body, "Invitation-Cookie:", blen );
    712                         unsigned int icookie;
     696                        char *itype = msn_findheader( body, "Application-GUID:", blen );
     697                        char buf[1024];
    713698                       
    714699                        g_free( ct );
    715700                       
    716                         /* Every invite should have both a Command and Cookie header */
    717                         if( !command || !cookie ) {
    718                                 g_free( command );
    719                                 g_free( cookie );
    720                                 imcb_log( ic, "Warning: No command or cookie from %s", sb->who );
    721                                 return 1;
    722                         }
    723                        
    724                         icookie = strtoul( cookie, NULL, 10 );
    725                         g_free( cookie );
    726                        
    727                         if( g_strncasecmp( command, "INVITE", 6 ) == 0 ) {
    728                                 msn_invitation_invite( sb, cmd[1], icookie, body, blen );
    729                         } else if( g_strncasecmp( command, "ACCEPT", 6 ) == 0 ) {
    730                                 msn_invitation_accept( sb, cmd[1], icookie, body, blen );
    731                         } else if( g_strncasecmp( command, "CANCEL", 6 ) == 0 ) {
    732                                 msn_invitation_cancel( sb, cmd[1], icookie, body, blen );
    733                         } else {
    734                                 imcb_log( ic, "Warning: Received invalid invitation with "
    735                                                 "command %s from %s", command, sb->who );
    736                         }
    737                        
    738                         g_free( command );
    739                 }
    740 #endif
    741                 else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 )
    742                 {
    743                         imcb_error( sb->ic, "Cannot receive file from %s: BitlBee does not "
    744                                         "support msnmsgrp2p yet.", sb->who );
    745                         g_free( ct );
     701                        *buf = 0;
     702                       
     703                        if( !itype )
     704                                return( 1 );
     705                       
     706                        /* File transfer. */
     707                        if( strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) == 0 )
     708                        {
     709                                char *name = msn_findheader( body, "Application-File:", blen );
     710                                char *size = msn_findheader( body, "Application-FileSize:", blen );
     711                               
     712                                if( name && size )
     713                                {
     714                                        g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Filetransfer: `%s', %s bytes >>\n"
     715                                                    "Filetransfers are not supported by BitlBee for now...", name, size );
     716                                }
     717                                else
     718                                {
     719                                        strcpy( buf, "<< \x02""BitlBee\x02"" - Corrupted MSN filetransfer invitation message >>" );
     720                                }
     721                               
     722                                if( name ) g_free( name );
     723                                if( size ) g_free( size );
     724                        }
     725                        else
     726                        {
     727                                char *iname = msn_findheader( body, "Application-Name:", blen );
     728                               
     729                                g_snprintf( buf, sizeof( buf ), "<< \x02""BitlBee\x02"" - Unknown MSN invitation - %s (%s) >>",
     730                                                                itype, iname ? iname : "no name" );
     731                               
     732                                if( iname ) g_free( iname );
     733                        }
     734                       
     735                        g_free( itype );
     736                       
     737                        if( !*buf )
     738                                return( 1 );
     739                       
     740                        if( sb->who )
     741                        {
     742                                imcb_buddy_msg( ic, cmd[1], buf, 0, 0 );
     743                        }
     744                        else if( sb->chat )
     745                        {
     746                                imcb_chat_msg( sb->chat, cmd[1], buf, 0, 0 );
     747                        }
     748                        else
     749                        {
     750                                /* PANIC! */
     751                        }
    746752                }
    747753                else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 )
     
    774780void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial )
    775781{
    776         bee_user_t *bu;
     782        struct buddy *b;
    777783       
    778784        if( sb && sb->who && sb->keepalive == 0 &&
    779             ( bu = bee_user_by_handle( sb->ic->bee, sb->ic, sb->who ) ) &&
    780             !( bu->flags & BEE_USER_ONLINE ) &&
     785            ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present &&
    781786            set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) )
    782787        {
  • protocols/nogaim.c

    r8b8def58 r38ff846  
    3838#include "chat.h"
    3939
     40static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
     41static char *format_timestamp( irc_t *irc, time_t msg_ts );
     42
    4043GSList *connections;
    4144
     
    8992}
    9093#endif
     94
     95/* nogaim.c */
    9196
    9297GList *protocols = NULL;
     
    112117{
    113118        GList *gl;
    114        
    115         for( gl = protocols; gl; gl = gl->next )
     119        for (gl = protocols; gl; gl = gl->next)
    116120        {
    117121                struct prpl *proto = gl->data;
    118                
    119                 if( g_strcasecmp( proto->name, name ) == 0 )
     122                if(!g_strcasecmp(proto->name, name))
    120123                        return proto;
    121124        }
    122        
    123125        return NULL;
    124126}
    125127
     128/* nogaim.c */
    126129void nogaim_init()
    127130{
     
    131134        extern void jabber_initmodule();
    132135        extern void twitter_initmodule();
    133         extern void purple_initmodule();
    134136
    135137#ifdef WITH_MSN
     
    153155#endif
    154156
    155 #ifdef WITH_PURPLE
    156         purple_initmodule();
    157 #endif
    158 
    159157#ifdef WITH_PLUGINS
    160158        load_plugins();
     
    164162GSList *get_connections() { return connections; }
    165163
     164/* multi.c */
     165
    166166struct im_connection *imcb_new( account_t *acc )
    167167{
     
    170170        ic = g_new0( struct im_connection, 1 );
    171171       
    172         ic->bee = acc->bee;
     172        ic->irc = acc->irc;
    173173        ic->acc = acc;
    174174        acc->ic = ic;
     
    184184       
    185185        /* Destroy the pointer to this connection from the account list */
    186         for( a = ic->bee->accounts; a; a = a->next )
     186        for( a = ic->irc->accounts; a; a = a->next )
    187187                if( a->ic == ic )
    188188                {
     
    205205        va_end( params );
    206206
    207         if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) ||
    208             ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) )
     207        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     208            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
    209209                strip_html( text );
    210210       
    211211        /* Try to find a different connection on the same protocol. */
    212         for( a = ic->bee->accounts; a; a = a->next )
     212        for( a = ic->irc->accounts; a; a = a->next )
    213213                if( a->prpl == ic->acc->prpl && a->ic != ic )
    214214                        break;
     
    216216        /* If we found one, include the screenname in the message. */
    217217        if( a )
    218                 /* FIXME(wilmer): ui_log callback or so */
    219                 irc_usermsg( ic->bee->ui_data, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
     218                irc_usermsg( ic->irc, "%s(%s) - %s", ic->acc->prpl->name, ic->acc->user, text );
    220219        else
    221                 irc_usermsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text );
     220                irc_usermsg( ic->irc, "%s - %s", ic->acc->prpl->name, text );
    222221       
    223222        g_free( text );
     
    270269void imcb_connected( struct im_connection *ic )
    271270{
     271        irc_t *irc = ic->irc;
     272        struct chat *c;
     273        user_t *u;
     274       
    272275        /* MSN servers sometimes redirect you to a different server and do
    273276           the whole login sequence again, so these "late" calls to this
     
    276279                return;
    277280       
     281        u = user_find( ic->irc, ic->irc->nick );
     282       
    278283        imcb_log( ic, "Logged in" );
    279284       
     
    288293        ic->acc->auto_reconnect_delay = 0;
    289294       
    290         /*
    291295        for( c = irc->chatrooms; c; c = c->next )
    292296        {
     
    297301                        chat_join( irc, c, NULL );
    298302        }
    299         */
    300303}
    301304
     
    305308       
    306309        a->reconnect = 0;
    307         account_on( a->bee, a );
     310        account_on( a->irc, a );
    308311       
    309312        return( FALSE );        /* Only have to run the timeout once */
     
    318321void imc_logout( struct im_connection *ic, int allow_reconnect )
    319322{
    320         bee_t *bee = ic->bee;
     323        irc_t *irc = ic->irc;
     324        user_t *t, *u;
    321325        account_t *a;
    322         GSList *l;
    323326        int delay;
    324327       
     
    340343        ic->away = NULL;
    341344       
    342         for( l = bee->users; l; )
    343         {
    344                 bee_user_t *bu = l->data;
    345                 GSList *next = l->next;
    346                
    347                 if( bu->ic == ic )
    348                         bee_user_free( bee, bu );
    349                
    350                 l = next;
    351         }
    352        
    353         query_del_by_conn( (irc_t*) ic->bee->ui_data, ic );
    354        
    355         for( a = bee->accounts; a; a = a->next )
     345        u = irc->users;
     346        while( u )
     347        {
     348                if( u->ic == ic )
     349                {
     350                        t = u->next;
     351                        user_del( irc, u->nick );
     352                        u = t;
     353                }
     354                else
     355                        u = u->next;
     356        }
     357       
     358        query_del_by_conn( ic->irc, ic );
     359       
     360        for( a = irc->accounts; a; a = a->next )
    356361                if( a->ic == ic )
    357362                        break;
     
    361366                /* Uhm... This is very sick. */
    362367        }
    363         else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) &&
     368        else if( allow_reconnect && set_getbool( &irc->set, "auto_reconnect" ) &&
    364369                 set_getbool( &a->set, "auto_reconnect" ) &&
    365370                 ( delay = account_reconnect_delay( a ) ) > 0 )
     
    372377}
    373378
     379
     380/* dialogs.c */
     381
    374382void imcb_ask( struct im_connection *ic, char *msg, void *data,
    375383               query_callback doit, query_callback dont )
    376384{
    377         query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, data );
    378 }
     385        query_add( ic->irc, ic, msg, doit, dont, data );
     386}
     387
     388
     389/* list.c */
    379390
    380391void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
    381392{
    382         bee_user_t *bu;
    383         bee_t *bee = ic->bee;
    384        
    385         if( !( bu = bee_user_by_handle( bee, ic, handle ) ) )
    386                 bu = bee_user_new( bee, ic, handle, 0 );
    387        
    388         bu->group = bee_group_by_name( bee, group, TRUE );
    389        
    390         if( bee->ui->user_group )
    391                 bee->ui->user_group( bee, bu );
    392 }
    393 
    394 void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *fullname )
    395 {
    396         bee_t *bee = ic->bee;
    397         bee_user_t *bu = bee_user_by_handle( bee, ic, handle );
    398        
    399         if( !bu || !fullname ) return;
    400        
    401         if( !bu->fullname || strcmp( bu->fullname, fullname ) != 0 )
    402         {
    403                 g_free( bu->fullname );
    404                 bu->fullname = g_strdup( fullname );
    405                
    406                 if( bee->ui->user_fullname )
    407                         bee->ui->user_fullname( bee, bu );
     393        user_t *u;
     394        char nick[MAX_NICK_LENGTH+1], *s;
     395        irc_t *irc = ic->irc;
     396       
     397        if( user_findhandle( ic, handle ) )
     398        {
     399                if( set_getbool( &irc->set, "debug" ) )
     400                        imcb_log( ic, "User already exists, ignoring add request: %s", handle );
     401               
     402                return;
     403               
     404                /* Buddy seems to exist already. Let's ignore this request then...
     405                   Eventually subsequent calls to this function *should* be possible
     406                   when a buddy is in multiple groups. But for now BitlBee doesn't
     407                   even support groups so let's silently ignore this for now. */
     408        }
     409       
     410        memset( nick, 0, MAX_NICK_LENGTH + 1 );
     411        strcpy( nick, nick_get( ic->acc, handle ) );
     412       
     413        u = user_add( ic->irc, nick );
     414       
     415//      if( !realname || !*realname ) realname = nick;
     416//      u->realname = g_strdup( realname );
     417       
     418        if( ( s = strchr( handle, '@' ) ) )
     419        {
     420                u->host = g_strdup( s + 1 );
     421                u->user = g_strndup( handle, s - handle );
     422        }
     423        else if( ic->acc->server )
     424        {
     425                u->host = g_strdup( ic->acc->server );
     426                u->user = g_strdup( handle );
     427               
     428                /* s/ /_/ ... important for AOL screennames */
     429                for( s = u->user; *s; s ++ )
     430                        if( *s == ' ' )
     431                                *s = '_';
     432        }
     433        else
     434        {
     435                u->host = g_strdup( ic->acc->prpl->name );
     436                u->user = g_strdup( handle );
     437        }
     438       
     439        u->ic = ic;
     440        u->handle = g_strdup( handle );
     441        if( group ) u->group = g_strdup( group );
     442        u->send_handler = buddy_send_handler;
     443        u->last_typing_notice = 0;
     444}
     445
     446struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle )
     447{
     448        static struct buddy b[1];
     449        user_t *u;
     450       
     451        u = user_findhandle( ic, handle );
     452       
     453        if( !u )
     454                return( NULL );
     455       
     456        memset( b, 0, sizeof( b ) );
     457        strncpy( b->name, handle, 80 );
     458        strncpy( b->show, u->realname, BUDDY_ALIAS_MAXLEN );
     459        b->present = u->online;
     460        b->ic = u->ic;
     461       
     462        return( b );
     463}
     464
     465void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )
     466{
     467        user_t *u = user_findhandle( ic, handle );
     468        char *set;
     469       
     470        if( !u || !realname ) return;
     471       
     472        if( g_strcasecmp( u->realname, realname ) != 0 )
     473        {
     474                if( u->realname != u->nick ) g_free( u->realname );
     475               
     476                u->realname = g_strdup( realname );
     477               
     478                if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) )
     479                        imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
     480        }
     481       
     482        set = set_getstr( &ic->acc->set, "nick_source" );
     483        if( strcmp( set, "handle" ) != 0 )
     484        {
     485                char *name = g_strdup( realname );
     486               
     487                if( strcmp( set, "first_name" ) == 0 )
     488                {
     489                        int i;
     490                        for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {}
     491                        name[i] = '\0';
     492                }
     493               
     494                imcb_buddy_nick_hint( ic, handle, name );
     495               
     496                g_free( name );
    408497        }
    409498}
     
    411500void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
    412501{
    413         bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) );
     502        user_t *u;
     503       
     504        if( ( u = user_findhandle( ic, handle ) ) )
     505                user_del( ic->irc, u->nick );
    414506}
    415507
     
    418510void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
    419511{
    420         bee_t *bee = ic->bee;
    421         bee_user_t *bu = bee_user_by_handle( bee, ic, handle );
    422        
    423         if( !bu || !nick ) return;
    424        
    425         if( bee->ui->user_nick_hint )
    426                 bee->ui->user_nick_hint( bee, bu, nick );
     512        user_t *u = user_findhandle( ic, handle );
     513        char newnick[MAX_NICK_LENGTH+1], *orig_nick;
     514       
     515        if( u && !u->online && !nick_saved( ic->acc, handle ) )
     516        {
     517                /* Only do this if the person isn't online yet (which should
     518                   be the case if we just added it) and if the user hasn't
     519                   assigned a nickname to this buddy already. */
     520               
     521                strncpy( newnick, nick, MAX_NICK_LENGTH );
     522                newnick[MAX_NICK_LENGTH] = 0;
     523               
     524                /* Some processing to make sure this string is a valid IRC nickname. */
     525                nick_strip( newnick );
     526                if( set_getbool( &ic->irc->set, "lcnicks" ) )
     527                        nick_lc( newnick );
     528               
     529                if( strcmp( u->nick, newnick ) != 0 )
     530                {
     531                        /* Only do this if newnick is different from the current one.
     532                           If rejoining a channel, maybe we got this nick already
     533                           (and dedupe would only add an underscore. */
     534                        nick_dedupe( ic->acc, handle, newnick );
     535                       
     536                        /* u->nick will be freed halfway the process, so it can't be
     537                           passed as an argument. */
     538                        orig_nick = g_strdup( u->nick );
     539                        user_rename( ic->irc, orig_nick, newnick );
     540                        g_free( orig_nick );
     541                }
     542        }
    427543}
    428544
     
    469585        data->ic = ic;
    470586        data->handle = g_strdup( handle );
    471         query_add( (irc_t *) ic->bee->ui_data, ic, s,
    472                    imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
     587        query_add( ic->irc, ic, s, imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, data );
    473588}
    474589
     
    495610       
    496611        /* TODO: Make a setting for this! */
    497         if( bee_user_by_handle( ic->bee, ic, handle ) != NULL )
     612        if( user_findhandle( ic, handle ) != NULL )
    498613                return;
    499614       
     
    502617        data->ic = ic;
    503618        data->handle = g_strdup( handle );
    504         query_add( (irc_t *) ic->bee->ui_data, ic, s,
    505                    imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
    506 }
    507 
    508 struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle )
    509 {
    510         return bee_user_by_handle( ic->bee, ic, handle );
     619        query_add( ic->irc, ic, s, imcb_ask_add_cb_yes, imcb_ask_add_cb_no, data );
     620}
     621
     622
     623/* server.c */                   
     624
     625void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message )
     626{
     627        user_t *u;
     628        int oa, oo;
     629       
     630        u = user_findhandle( ic, (char*) handle );
     631       
     632        if( !u )
     633        {
     634                if( g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "add" ) == 0 )
     635                {
     636                        imcb_add_buddy( ic, (char*) handle, NULL );
     637                        u = user_findhandle( ic, (char*) handle );
     638                }
     639                else
     640                {
     641                        if( set_getbool( &ic->irc->set, "debug" ) || g_strcasecmp( set_getstr( &ic->irc->set, "handle_unknown" ), "ignore" ) != 0 )
     642                        {
     643                                imcb_log( ic, "imcb_buddy_status() for unknown handle %s:", handle );
     644                                imcb_log( ic, "flags = %d, state = %s, message = %s", flags,
     645                                          state ? state : "NULL", message ? message : "NULL" );
     646                        }
     647                       
     648                        return;
     649                }
     650        }
     651       
     652        oa = u->away != NULL;
     653        oo = u->online;
     654       
     655        g_free( u->away );
     656        g_free( u->status_msg );
     657        u->away = u->status_msg = NULL;
     658       
     659        if( set_getbool( &ic->irc->set, "show_offline" ) && !u->online )
     660        {
     661                /* always set users as online */
     662                irc_spawn( ic->irc, u );
     663                u->online = 1;
     664                if( !( flags & OPT_LOGGED_IN ) )
     665                {
     666                        /* set away message if user isn't really online */
     667                        u->away = g_strdup( "User is offline" );
     668                }
     669        }
     670        else if( ( flags & OPT_LOGGED_IN ) && !u->online )
     671        {
     672                irc_spawn( ic->irc, u );
     673                u->online = 1;
     674        }
     675        else if( !( flags & OPT_LOGGED_IN ) && u->online )
     676        {
     677                struct groupchat *c;
     678               
     679                if( set_getbool( &ic->irc->set, "show_offline" ) )
     680                {
     681                        /* keep offline users in channel and set away message to "offline" */
     682                        u->away = g_strdup( "User is offline" );
     683
     684                        /* Keep showing him/her in the control channel but not in groupchats. */
     685                        for( c = ic->groupchats; c; c = c->next )
     686                        {
     687                                if( remove_chat_buddy_silent( c, handle ) && c->joined )
     688                                        irc_part( c->ic->irc, u, c->channel );
     689                        }
     690                }
     691                else
     692                {
     693                        /* kill offline users */
     694                        irc_kill( ic->irc, u );
     695                        u->online = 0;
     696
     697                        /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
     698                        for( c = ic->groupchats; c; c = c->next )
     699                                remove_chat_buddy_silent( c, handle );
     700                }
     701        }
     702
     703        if( flags & OPT_AWAY )
     704        {
     705                if( state && message )
     706                {
     707                        u->away = g_strdup_printf( "%s (%s)", state, message );
     708                }
     709                else if( state )
     710                {
     711                        u->away = g_strdup( state );
     712                }
     713                else if( message )
     714                {
     715                        u->away = g_strdup( message );
     716                }
     717                else
     718                {
     719                        u->away = g_strdup( "Away" );
     720                }
     721        }
     722        else
     723        {
     724                u->status_msg = g_strdup( message );
     725        }
     726       
     727        /* early if-clause for show_offline even if there is some redundant code here because this isn't LISP but C ;) */
     728        if( set_getbool( &ic->irc->set, "show_offline" ) && set_getbool( &ic->irc->set, "away_devoice" ) )
     729        {
     730                char *from;
     731               
     732                if( set_getbool( &ic->irc->set, "simulate_netsplit" ) )
     733                {
     734                        from = g_strdup( ic->irc->myhost );
     735                }
     736                else
     737                {
     738                        from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,
     739                                                            ic->irc->myhost );
     740                }
     741
     742                /* if we use show_offline, we op online users, voice away users, and devoice/deop offline users */
     743                if( flags & OPT_LOGGED_IN )
     744                {
     745                        /* user is "online" (either really online or away) */
     746                        irc_write( ic->irc, ":%s MODE %s %cv%co %s %s", from, ic->irc->channel,
     747                                                                  u->away?'+':'-', u->away?'-':'+', u->nick, u->nick );
     748                }
     749                else
     750                {
     751                        /* user is offline */
     752                        irc_write( ic->irc, ":%s MODE %s -vo %s %s", from, ic->irc->channel, u->nick, u->nick );
     753                }
     754        }
     755        else
     756        {
     757                /* LISPy... */
     758                if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&         /* Don't do a thing when user doesn't want it */
     759                    ( u->online ) &&                                            /* Don't touch offline people */
     760                    ( ( ( u->online != oo ) && !u->away ) ||                    /* Voice joining people */
     761                      ( ( u->online == oo ) && ( oa == !u->away ) ) ) )         /* (De)voice people changing state */
     762                {
     763                        char *from;
     764
     765                        if( set_getbool( &ic->irc->set, "simulate_netsplit" ) )
     766                        {
     767                                from = g_strdup( ic->irc->myhost );
     768                        }
     769                        else
     770                        {
     771                                from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,
     772                                                                    ic->irc->myhost );
     773                        }
     774                        irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel,
     775                                                                  u->away?'-':'+', u->nick );
     776                        g_free( from );
     777                }
     778        }
     779}
     780
     781void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )
     782{
     783        irc_t *irc = ic->irc;
     784        char *wrapped, *ts = NULL;
     785        user_t *u;
     786       
     787        u = user_findhandle( ic, handle );
     788       
     789        if( !u )
     790        {
     791                char *h = set_getstr( &irc->set, "handle_unknown" );
     792               
     793                if( g_strcasecmp( h, "ignore" ) == 0 )
     794                {
     795                        if( set_getbool( &irc->set, "debug" ) )
     796                                imcb_log( ic, "Ignoring message from unknown handle %s", handle );
     797                       
     798                        return;
     799                }
     800                else if( g_strncasecmp( h, "add", 3 ) == 0 )
     801                {
     802                        int private = set_getbool( &irc->set, "private" );
     803                       
     804                        if( h[3] )
     805                        {
     806                                if( g_strcasecmp( h + 3, "_private" ) == 0 )
     807                                        private = 1;
     808                                else if( g_strcasecmp( h + 3, "_channel" ) == 0 )
     809                                        private = 0;
     810                        }
     811                       
     812                        imcb_add_buddy( ic, handle, NULL );
     813                        u = user_findhandle( ic, handle );
     814                        u->is_private = private;
     815                }
     816                else
     817                {
     818                        imcb_log( ic, "Message from unknown handle %s:", handle );
     819                        u = user_find( irc, irc->mynick );
     820                }
     821        }
     822       
     823        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     824            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     825                strip_html( msg );
     826       
     827        if( set_getbool( &ic->irc->set, "display_timestamps" ) &&
     828            ( ts = format_timestamp( irc, sent_at ) ) )
     829        {
     830                char *new = g_strconcat( ts, msg, NULL );
     831                g_free( ts );
     832                ts = msg = new;
     833        }
     834       
     835        wrapped = word_wrap( msg, 425 );
     836        irc_msgfrom( irc, u->nick, wrapped );
     837        g_free( wrapped );
     838        g_free( ts );
     839}
     840
     841void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags )
     842{
     843        user_t *u;
     844       
     845        if( !set_getbool( &ic->irc->set, "typing_notice" ) )
     846                return;
     847       
     848        if( ( u = user_findhandle( ic, handle ) ) )
     849        {
     850                char buf[256];
     851               
     852                g_snprintf( buf, 256, "\1TYPING %d\1", ( flags >> 8 ) & 3 );
     853                irc_privmsg( ic->irc, u, "PRIVMSG", ic->irc->nick, NULL, buf );
     854        }
     855}
     856
     857struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle )
     858{
     859        struct groupchat *c;
     860       
     861        /* This one just creates the conversation structure, user won't see anything yet */
     862       
     863        if( ic->groupchats )
     864        {
     865                for( c = ic->groupchats; c->next; c = c->next );
     866                c = c->next = g_new0( struct groupchat, 1 );
     867        }
     868        else
     869                ic->groupchats = c = g_new0( struct groupchat, 1 );
     870       
     871        c->ic = ic;
     872        c->title = g_strdup( handle );
     873        c->channel = g_strdup_printf( "&chat_%03d", ic->irc->c_id++ );
     874        c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title );
     875       
     876        if( set_getbool( &ic->irc->set, "debug" ) )
     877                imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle );
     878       
     879        return c;
     880}
     881
     882void imcb_chat_name_hint( struct groupchat *c, const char *name )
     883{
     884        if( !c->joined )
     885        {
     886                struct im_connection *ic = c->ic;
     887                char stripped[MAX_NICK_LENGTH+1], *full_name;
     888               
     889                strncpy( stripped, name, MAX_NICK_LENGTH );
     890                stripped[MAX_NICK_LENGTH] = '\0';
     891                nick_strip( stripped );
     892                if( set_getbool( &ic->irc->set, "lcnicks" ) )
     893                        nick_lc( stripped );
     894               
     895                full_name = g_strdup_printf( "&%s", stripped );
     896               
     897                if( stripped[0] &&
     898                    nick_cmp( stripped, ic->irc->channel + 1 ) != 0 &&
     899                    irc_chat_by_channel( ic->irc, full_name ) == NULL )
     900                {
     901                        g_free( c->channel );
     902                        c->channel = full_name;
     903                }
     904                else
     905                {
     906                        g_free( full_name );
     907                }
     908        }
     909}
     910
     911void imcb_chat_free( struct groupchat *c )
     912{
     913        struct im_connection *ic = c->ic;
     914        struct groupchat *l;
     915        GList *ir;
     916       
     917        if( set_getbool( &ic->irc->set, "debug" ) )
     918                imcb_log( ic, "You were removed from conversation %p", c );
     919       
     920        if( c )
     921        {
     922                if( c->joined )
     923                {
     924                        user_t *u, *r;
     925                       
     926                        r = user_find( ic->irc, ic->irc->mynick );
     927                        irc_privmsg( ic->irc, r, "PRIVMSG", c->channel, "", "Cleaning up channel, bye!" );
     928                       
     929                        u = user_find( ic->irc, ic->irc->nick );
     930                        irc_kick( ic->irc, u, c->channel, r );
     931                        /* irc_part( ic->irc, u, c->channel ); */
     932                }
     933               
     934                /* Find the previous chat in the linked list. */
     935                for( l = ic->groupchats; l && l->next != c; l = l->next );
     936               
     937                if( l )
     938                        l->next = c->next;
     939                else
     940                        ic->groupchats = c->next;
     941               
     942                for( ir = c->in_room; ir; ir = ir->next )
     943                        g_free( ir->data );
     944                g_list_free( c->in_room );
     945                g_free( c->channel );
     946                g_free( c->title );
     947                g_free( c->topic );
     948                g_free( c );
     949        }
     950}
     951
     952void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
     953{
     954        struct im_connection *ic = c->ic;
     955        char *wrapped;
     956        user_t *u;
     957       
     958        /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
     959        if( g_strcasecmp( who, ic->acc->user ) == 0 )
     960                return;
     961       
     962        u = user_findhandle( ic, who );
     963       
     964        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     965            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     966                strip_html( msg );
     967       
     968        wrapped = word_wrap( msg, 425 );
     969        if( c && u )
     970        {
     971                char *ts = NULL;
     972                if( set_getbool( &ic->irc->set, "display_timestamps" ) )
     973                        ts = format_timestamp( ic->irc, sent_at );
     974                irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped );
     975                g_free( ts );
     976        }
     977        else
     978        {
     979                imcb_log( ic, "Message from/to conversation %s@%p (unknown conv/user): %s", who, c, wrapped );
     980        }
     981        g_free( wrapped );
     982}
     983
     984void imcb_chat_log( struct groupchat *c, char *format, ... )
     985{
     986        irc_t *irc = c->ic->irc;
     987        va_list params;
     988        char *text;
     989        user_t *u;
     990       
     991        va_start( params, format );
     992        text = g_strdup_vprintf( format, params );
     993        va_end( params );
     994       
     995        u = user_find( irc, irc->mynick );
     996       
     997        irc_privmsg( irc, u, "PRIVMSG", c->channel, "System message: ", text );
     998       
     999        g_free( text );
     1000}
     1001
     1002void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at )
     1003{
     1004        struct im_connection *ic = c->ic;
     1005        user_t *u = NULL;
     1006       
     1007        if( who == NULL)
     1008                u = user_find( ic->irc, ic->irc->mynick );
     1009        else if( g_strcasecmp( who, ic->acc->user ) == 0 )
     1010                u = user_find( ic->irc, ic->irc->nick );
     1011        else
     1012                u = user_findhandle( ic, who );
     1013       
     1014        if( ( g_strcasecmp( set_getstr( &ic->irc->set, "strip_html" ), "always" ) == 0 ) ||
     1015            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
     1016                strip_html( topic );
     1017       
     1018        g_free( c->topic );
     1019        c->topic = g_strdup( topic );
     1020       
     1021        if( c->joined && u )
     1022                irc_write( ic->irc, ":%s!%s@%s TOPIC %s :%s", u->nick, u->user, u->host, c->channel, topic );
     1023}
     1024
     1025
     1026/* buddy_chat.c */
     1027
     1028void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
     1029{
     1030        user_t *u = user_findhandle( b->ic, handle );
     1031        int me = 0;
     1032       
     1033        if( set_getbool( &b->ic->irc->set, "debug" ) )
     1034                imcb_log( b->ic, "User %s added to conversation %p", handle, b );
     1035       
     1036        /* It might be yourself! */
     1037        if( b->ic->acc->prpl->handle_cmp( handle, b->ic->acc->user ) == 0 )
     1038        {
     1039                u = user_find( b->ic->irc, b->ic->irc->nick );
     1040                if( !b->joined )
     1041                        irc_join( b->ic->irc, u, b->channel );
     1042                b->joined = me = 1;
     1043        }
     1044       
     1045        /* Most protocols allow people to join, even when they're not in
     1046           your contact list. Try to handle that here */
     1047        if( !u )
     1048        {
     1049                imcb_add_buddy( b->ic, handle, NULL );
     1050                u = user_findhandle( b->ic, handle );
     1051        }
     1052       
     1053        /* Add the handle to the room userlist, if it's not 'me' */
     1054        if( !me )
     1055        {
     1056                if( b->joined )
     1057                        irc_join( b->ic->irc, u, b->channel );
     1058                b->in_room = g_list_append( b->in_room, g_strdup( handle ) );
     1059        }
     1060}
     1061
     1062/* This function is one BIG hack... :-( EREWRITE */
     1063void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
     1064{
     1065        user_t *u;
     1066        int me = 0;
     1067       
     1068        if( set_getbool( &b->ic->irc->set, "debug" ) )
     1069                imcb_log( b->ic, "User %s removed from conversation %p (%s)", handle, b, reason ? reason : "" );
     1070       
     1071        /* It might be yourself! */
     1072        if( g_strcasecmp( handle, b->ic->acc->user ) == 0 )
     1073        {
     1074                if( b->joined == 0 )
     1075                        return;
     1076               
     1077                u = user_find( b->ic->irc, b->ic->irc->nick );
     1078                b->joined = 0;
     1079                me = 1;
     1080        }
     1081        else
     1082        {
     1083                u = user_findhandle( b->ic, handle );
     1084        }
     1085       
     1086        if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) )
     1087                irc_part( b->ic->irc, u, b->channel );
     1088}
     1089
     1090static int remove_chat_buddy_silent( struct groupchat *b, const char *handle )
     1091{
     1092        GList *i;
     1093       
     1094        /* Find the handle in the room userlist and shoot it */
     1095        i = b->in_room;
     1096        while( i )
     1097        {
     1098                if( g_strcasecmp( handle, i->data ) == 0 )
     1099                {
     1100                        g_free( i->data );
     1101                        b->in_room = g_list_remove( b->in_room, i->data );
     1102                        return( 1 );
     1103                }
     1104               
     1105                i = i->next;
     1106        }
     1107       
     1108        return( 0 );
     1109}
     1110
     1111
     1112/* Misc. BitlBee stuff which shouldn't really be here */
     1113
     1114char *set_eval_away_devoice( set_t *set, char *value )
     1115{
     1116        irc_t *irc = set->data;
     1117        int st;
     1118       
     1119        if( !is_bool( value ) )
     1120                return SET_INVALID;
     1121       
     1122        st = bool2int( value );
     1123       
     1124        /* Horror.... */
     1125       
     1126        if( st != set_getbool( &irc->set, "away_devoice" ) )
     1127        {
     1128                char list[80] = "";
     1129                user_t *u = irc->users;
     1130                int i = 0, count = 0;
     1131                char pm;
     1132                char v[80];
     1133               
     1134                if( st )
     1135                        pm = '+';
     1136                else
     1137                        pm = '-';
     1138               
     1139                while( u )
     1140                {
     1141                        if( u->ic && u->online && !u->away )
     1142                        {
     1143                                if( ( strlen( list ) + strlen( u->nick ) ) >= 79 )
     1144                                {
     1145                                        for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0;
     1146                                        irc_write( irc, ":%s MODE %s %c%s%s",
     1147                                                   irc->myhost,
     1148                                                   irc->channel, pm, v, list );
     1149                                       
     1150                                        *list = 0;
     1151                                        count = 0;
     1152                                }
     1153                               
     1154                                sprintf( list + strlen( list ), " %s", u->nick );
     1155                                count ++;
     1156                        }
     1157                        u = u->next;
     1158                }
     1159               
     1160                /* $v = 'v' x $i */
     1161                for( i = 0; i < count; v[i++] = 'v' ); v[i] = 0;
     1162                irc_write( irc, ":%s MODE %s %c%s%s", irc->myhost,
     1163                                                            irc->channel, pm, v, list );
     1164        }
     1165       
     1166        return value;
     1167}
     1168
     1169char *set_eval_timezone( set_t *set, char *value )
     1170{
     1171        char *s;
     1172       
     1173        if( strcmp( value, "local" ) == 0 ||
     1174            strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 )
     1175                return value;
     1176       
     1177        /* Otherwise: +/- at the beginning optional, then one or more numbers,
     1178           possibly followed by a colon and more numbers. Don't bother bound-
     1179           checking them since users are free to shoot themselves in the foot. */
     1180        s = value;
     1181        if( *s == '+' || *s == '-' )
     1182                s ++;
     1183       
     1184        /* \d+ */
     1185        if( !isdigit( *s ) )
     1186                return SET_INVALID;
     1187        while( *s && isdigit( *s ) ) s ++;
     1188       
     1189        /* EOS? */
     1190        if( *s == '\0' )
     1191                return value;
     1192       
     1193        /* Otherwise, colon */
     1194        if( *s != ':' )
     1195                return SET_INVALID;
     1196        s ++;
     1197       
     1198        /* \d+ */
     1199        if( !isdigit( *s ) )
     1200                return SET_INVALID;
     1201        while( *s && isdigit( *s ) ) s ++;
     1202       
     1203        /* EOS */
     1204        return *s == '\0' ? value : SET_INVALID;
     1205}
     1206
     1207static char *format_timestamp( irc_t *irc, time_t msg_ts )
     1208{
     1209        time_t now_ts = time( NULL );
     1210        struct tm now, msg;
     1211        char *set;
     1212       
     1213        /* If the timestamp is <= 0 or less than a minute ago, discard it as
     1214           it doesn't seem to add to much useful info and/or might be noise. */
     1215        if( msg_ts <= 0 || msg_ts > now_ts - 60 )
     1216                return NULL;
     1217       
     1218        set = set_getstr( &irc->set, "timezone" );
     1219        if( strcmp( set, "local" ) == 0 )
     1220        {
     1221                localtime_r( &now_ts, &now );
     1222                localtime_r( &msg_ts, &msg );
     1223        }
     1224        else
     1225        {
     1226                int hr, min = 0, sign = 60;
     1227               
     1228                if( set[0] == '-' )
     1229                {
     1230                        sign *= -1;
     1231                        set ++;
     1232                }
     1233                else if( set[0] == '+' )
     1234                {
     1235                        set ++;
     1236                }
     1237               
     1238                if( sscanf( set, "%d:%d", &hr, &min ) >= 1 )
     1239                {
     1240                        msg_ts += sign * ( hr * 60 + min );
     1241                        now_ts += sign * ( hr * 60 + min );
     1242                }
     1243               
     1244                gmtime_r( &now_ts, &now );
     1245                gmtime_r( &msg_ts, &msg );
     1246        }
     1247       
     1248        if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday )
     1249                return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
     1250                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1251        else
     1252                return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
     1253                                        "%02d:%02d:%02d\x02]\x02 ",
     1254                                        msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday,
     1255                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
    5111256}
    5121257
    5131258/* The plan is to not allow straight calls to prpl functions anymore, but do
    5141259   them all from some wrappers. We'll start to define some down here: */
     1260
     1261int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags )
     1262{
     1263        char *buf = NULL;
     1264        int st;
     1265       
     1266        if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) )
     1267        {
     1268                buf = escape_html( msg );
     1269                msg = buf;
     1270        }
     1271       
     1272        st = ic->acc->prpl->buddy_msg( ic, handle, msg, flags );
     1273        g_free( buf );
     1274       
     1275        return st;
     1276}
    5151277
    5161278int imc_chat_msg( struct groupchat *c, char *msg, int flags )
     
    5411303       
    5421304        away = set_getstr( &ic->acc->set, "away" ) ?
    543              : set_getstr( &ic->bee->set, "away" );
     1305             : set_getstr( &ic->irc->set, "away" );
    5441306        if( away && *away )
    5451307        {
     
    5521314                away = NULL;
    5531315                msg = set_getstr( &ic->acc->set, "status" ) ?
    554                     : set_getstr( &ic->bee->set, "status" );
     1316                    : set_getstr( &ic->irc->set, "status" );
    5551317        }
    5561318       
  • protocols/nogaim.h

    r8b8def58 r38ff846  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2010 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    4545#include "proxy.h"
    4646#include "query.h"
    47 #include "md5.h"
    48 #include "ft.h"
    4947
    5048#define BUDDY_ALIAS_MAXLEN 388   /* because MSN names can be 387 characters */
     
    8785       
    8886        /* BitlBee */
    89         bee_t *bee;
    90        
    91         GSList *groupchats;
     87        irc_t *irc;
     88       
     89        struct groupchat *groupchats;
    9290};
    9391
     
    10098         * already, for example to avoid adding somebody two times. */
    10199        GList *in_room;
    102         //GList *ignored;
    103        
    104         //struct groupchat *next;
     100        GList *ignored;
     101       
     102        struct groupchat *next;
     103        char *channel;
    105104        /* The title variable contains the ID you gave when you created the
    106105         * chat using imcb_chat_new(). */
     
    113112         * structure for your protocol's needs. */
    114113        void *data;
    115         void *ui_data;
    116114};
    117115
     
    134132         * - The user sees this name ie. when imcb_log() is used. */
    135133        const char *name;
    136         void *data;
    137134
    138135        /* Added this one to be able to add per-account settings, don't think
     
    231228        void (* auth_allow)     (struct im_connection *, const char *who);
    232229        void (* auth_deny)      (struct im_connection *, const char *who);
    233 
    234         /* Incoming transfer request */
    235         void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle );
    236230};
    237231
     
    287281G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
    288282
     283/* Buddy activity */
     284/* To manipulate the status of a handle.
     285 * - flags can be |='d with OPT_* constants. You will need at least:
     286 *   OPT_LOGGED_IN and OPT_AWAY.
     287 * - 'state' and 'message' can be NULL */
     288G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message );
     289/* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
     290/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
     291G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );
    289292G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
    290 G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle );
    291293G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
    292294
     
    314316/* Actions, or whatever. */
    315317int imc_away_send_update( struct im_connection *ic );
     318int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );
    316319int imc_chat_msg( struct groupchat *c, char *msg, int flags );
    317320
  • protocols/oscar/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)protocols/oscar/
    12 CFLAGS += -I$(SRCDIR)
    13 endif
    1410
    1511# [SH] Program variables
     
    3733$(objects): ../../Makefile.settings Makefile
    3834
    39 $(objects): %.o: $(SRCDIR)%.c
     35$(objects): %.o: %.c
    4036        @echo '*' Compiling $<
    4137        @$(CC) -c $(CFLAGS) $< -o $@
  • protocols/oscar/oscar.c

    r8b8def58 r38ff846  
    254254
    255255        u = t = g_strdup(s);
     256
     257        strcpy(t, s);
    256258        g_strdown(t);
    257259
     
    288290        odata = (struct oscar_data *)ic->proto_data;
    289291
    290         if (condition & B_EV_IO_READ) {
     292        if (condition & GAIM_INPUT_READ) {
    291293                if (aim_get_command(odata->sess, conn) >= 0) {
    292294                        aim_rxdispatch(odata->sess);
     
    360362
    361363        aim_conn_completeconnect(sess, conn);
    362         ic->inpa = b_input_add(conn->fd, B_EV_IO_READ,
     364        ic->inpa = b_input_add(conn->fd, GAIM_INPUT_READ,
    363365                        oscar_callback, conn);
    364366       
     
    491493
    492494        aim_conn_completeconnect(sess, bosconn);
    493         ic->inpa = b_input_add(bosconn->fd, B_EV_IO_READ,
     495        ic->inpa = b_input_add(bosconn->fd, GAIM_INPUT_READ,
    494496                        oscar_callback, bosconn);
    495497        imcb_log(ic, _("Connection established, cookie sent"));
     
    650652        struct im_connection *ic = sess->aux_data;
    651653        struct chat_connection *chatcon;
    652         struct groupchat *c = NULL;
    653654        static int id = 1;
    654655
     
    663664        chatcon = find_oscar_chat_by_conn(ic, fr->conn);
    664665        chatcon->id = id;
    665        
    666         c = bee_chat_by_title(ic->bee, ic, chatcon->show);
    667         if (c && !c->data)
    668                 chatcon->cnv = c;
    669         else
    670                 chatcon->cnv = imcb_chat_new(ic, chatcon->show);
     666        chatcon->cnv = imcb_chat_new(ic, chatcon->show);
    671667        chatcon->cnv->data = chatcon;
    672668
     
    707703
    708704        aim_conn_completeconnect(sess, tstconn);
    709         odata->cnpa = b_input_add(tstconn->fd, B_EV_IO_READ,
     705        odata->cnpa = b_input_add(tstconn->fd, GAIM_INPUT_READ,
    710706                                        oscar_callback, tstconn);
    711707       
     
    735731
    736732        aim_conn_completeconnect(sess, tstconn);
    737         odata->paspa = b_input_add(tstconn->fd, B_EV_IO_READ,
     733        odata->paspa = b_input_add(tstconn->fd, GAIM_INPUT_READ,
    738734                                oscar_callback, tstconn);
    739735       
     
    771767        aim_conn_completeconnect(sess, ccon->conn);
    772768        ccon->inpa = b_input_add(tstconn->fd,
    773                         B_EV_IO_READ,
     769                        GAIM_INPUT_READ,
    774770                        oscar_callback, tstconn);
    775771        odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon);
     
    938934        tmp = normalize(info->sn);
    939935        imcb_buddy_status(ic, tmp, flags, state_string, NULL);
    940         imcb_buddy_times(ic, tmp, signon, time_idle);
     936        /* imcb_buddy_times(ic, tmp, signon, time_idle); */
    941937
    942938
     
    10641060        aim_ssi_auth_reply(od->sess, od->conn, uin, 1, "");
    10651061        // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message);
    1066         imcb_ask_add(data->ic, uin, NULL);
     1062        if(imcb_find_buddy(data->ic, uin) == NULL)
     1063                imcb_ask_add(data->ic, uin, NULL);
    10671064       
    10681065        g_free(uin);
     
    18251822        struct oscar_data *odata = (struct oscar_data *)g->proto_data;
    18261823        if (odata->icq) {
    1827                 /** FIXME(wilmer): Hmm, lost the ability to get away msgs here, do we care to get that back?
    18281824                struct buddy *budlight = imcb_find_buddy(g, who);
    18291825                if (budlight)
     
    18311827                                if (budlight->caps & AIM_CAPS_ICQSERVERRELAY)
    18321828                                        aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7);
    1833                 */
    18341829        } else
    18351830                aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE);
     
    19581953static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) {
    19591954        struct im_connection *ic = sess->aux_data;
    1960         struct aim_ssi_item *curitem, *curgroup;
     1955        struct aim_ssi_item *curitem;
    19611956        int tmp;
    19621957        char *nrm;
     
    19691964                switch (curitem->type) {
    19701965                        case 0x0000: /* Buddy */
    1971                                 if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) {
     1966                                if ((curitem->name) && (!imcb_find_buddy(ic, nrm))) {
    19721967                                        char *realname = NULL;
    19731968
    19741969                                        if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1))
    19751970                                                    realname = aim_gettlv_str(curitem->data, 0x0131, 1);
    1976                                        
    1977                                         imcb_add_buddy(ic, nrm, curgroup->gid == curitem->gid ? curgroup->name : NULL);
     1971                                               
     1972                                        imcb_add_buddy(ic, nrm, NULL);
    19781973                                       
    19791974                                        if (realname) {
     
    19831978                                        }
    19841979                                }
    1985                                 break;
    1986 
    1987                         case 0x0001: /* Group */
    1988                                 curgroup = curitem;
    19891980                                break;
    19901981
     
    25292520        static int chat_id = 0;
    25302521        char * chatname;
    2531         struct groupchat *c;
    25322522       
    25332523        chatname = g_strdup_printf("%s%s_%d", isdigit(*ic->acc->user) ? "icq_" : "",
    25342524                                   ic->acc->user, chat_id++);
    2535        
    2536         c = imcb_chat_new(ic, chatname);
     2525 
    25372526        ret = oscar_chat_join(ic, chatname, NULL, NULL);
     2527
    25382528        aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0);
    25392529
  • protocols/twitter/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)protocols/twitter/
    12 endif
    1310
    1411# [SH] Program variables
     
    3633$(objects): ../../Makefile.settings Makefile
    3734
    38 $(objects): %.o: $(SRCDIR)%.c
     35$(objects): %.o: %.c
    3936        @echo '*' Compiling $<
    4037        @$(CC) -c $(CFLAGS) $< -o $@
  • protocols/twitter/twitter_lib.c

    r8b8def58 r38ff846  
    105105
    106106        // Check if the buddy is allready in the buddy list.
    107         if (!bee_user_by_handle( ic->bee, ic, name ))
     107        if (!imcb_find_buddy( ic, name ))
    108108        {
    109109                char *mode = set_getstr(&ic->acc->set, "mode");
  • protocols/yahoo/Makefile

    r8b8def58 r38ff846  
    88
    99-include ../../Makefile.settings
    10 ifdef SRCDIR
    11 SRCDIR := $(SRCDIR)protocols/yahoo/
    12 endif
    1310
    1411# [SH] Program variables
     
    3633$(objects): ../../Makefile.settings Makefile
    3734
    38 $(objects): %.o: $(SRCDIR)%.c
     35$(objects): %.o: %.c
    3936        @echo '*' Compiling $<
    4037        @$(CC) -c $(CFLAGS) $< -o $@
  • protocols/yahoo/yahoo.c

    r8b8def58 r38ff846  
    158158       
    159159        while( ic->groupchats )
    160                 imcb_chat_free( ic->groupchats->data );
     160                imcb_chat_free( ic->groupchats );
    161161       
    162162        for( l = yd->buddygroups; l; l = l->next )
     
    613613        imcb_buddy_status( ic, who, flags, state_string, msg );
    614614       
     615        /* Not implemented yet...
    615616        if( stat == YAHOO_STATUS_IDLE )
    616                 imcb_buddy_times( ic, who, 0, idle );
     617                imcb_buddy_times( ic, who, 0, away );
     618        */
    617619}
    618620
     
    684686               
    685687                inp->d = d;
    686                 d->tag = inp->h = b_input_add( fd, B_EV_IO_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d );
     688                d->tag = inp->h = b_input_add( fd, GAIM_INPUT_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d );
    687689        }
    688690        else if( cond == YAHOO_INPUT_WRITE )
     
    695697               
    696698                inp->d = d;
    697                 d->tag = inp->h = b_input_add( fd, B_EV_IO_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d );
     699                d->tag = inp->h = b_input_add( fd, GAIM_INPUT_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d );
    698700        }
    699701        else
     
    794796        struct byahoo_conf_invitation *inv = data;
    795797        struct groupchat *b;
    796         GSList *l;
    797        
    798         for( l = inv->ic->groupchats; l; l = l->next )
    799         {
    800                 b = l->data;
     798       
     799        for( b = inv->ic->groupchats; b; b = b->next )
    801800                if( b == inv->c )
    802801                        break;
    803         }
    804802       
    805803        if( b != NULL )
     
    867865{
    868866        struct im_connection *ic = byahoo_get_ic_by_id( id );
    869         struct groupchat *c = bee_chat_by_title( ic->bee, ic, room );
     867        struct groupchat *c;
     868       
     869        for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
    870870       
    871871        if( c )
     
    877877{
    878878        struct im_connection *ic = byahoo_get_ic_by_id( id );
    879         struct groupchat *c = bee_chat_by_title( ic->bee, ic, room );
     879        struct groupchat *c;
     880       
     881        for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
    880882       
    881883        if( c )
     
    887889        struct im_connection *ic = byahoo_get_ic_by_id( id );
    888890        char *m = byahoo_strip( msg );
    889         struct groupchat *c = bee_chat_by_title( ic->bee, ic, room );
     891        struct groupchat *c;
     892       
     893        for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
    890894       
    891895        if( c )
  • query.c

    r8b8def58 r38ff846  
    6464        }
    6565       
    66         if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )
     66        if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "lifo" ) == 0 || irc->queries == q )
    6767                query_display( irc, q );
    6868       
     
    179179        query_t *q;
    180180       
    181         if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "fifo" ) == 0 )
     181        if( g_strcasecmp( set_getstr( &irc->set, "query_order" ), "fifo" ) == 0 )
    182182                q = irc->queries;
    183183        else
  • root_commands.c

    r8b8def58 r38ff846  
    2626#define BITLBEE_CORE
    2727#include "commands.h"
     28#include "crypting.h"
    2829#include "bitlbee.h"
    2930#include "help.h"
     
    3233#include <string.h>
    3334
    34 void root_command_string( irc_t *irc, char *command )
    35 {
    36         root_command( irc, split_command_parts( command ) );
     35void root_command_string( irc_t *irc, user_t *u, char *command, int flags )
     36{
     37        char *cmd[IRC_MAX_ARGS];
     38        char *s;
     39        int k;
     40        char q = 0;
     41       
     42        memset( cmd, 0, sizeof( cmd ) );
     43        cmd[0] = command;
     44        k = 1;
     45        for( s = command; *s && k < ( IRC_MAX_ARGS - 1 ); s ++ )
     46                if( *s == ' ' && !q )
     47                {
     48                        *s = 0;
     49                        while( *++s == ' ' );
     50                        if( *s == '"' || *s == '\'' )
     51                        {
     52                                q = *s;
     53                                s ++;
     54                        }
     55                        if( *s )
     56                        {
     57                                cmd[k++] = s;
     58                                s --;
     59                        }
     60                        else
     61                        {
     62                                break;
     63                        }
     64                }
     65                else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
     66                {
     67                        char *cpy;
     68                       
     69                        for( cpy = s; *cpy; cpy ++ )
     70                                cpy[0] = cpy[1];
     71                }
     72                else if( *s == q )
     73                {
     74                        q = *s = 0;
     75                }
     76        cmd[k] = NULL;
     77       
     78        root_command( irc, cmd );
    3779}
    3880
     
    5193void root_command( irc_t *irc, char *cmd[] )
    5294{       
    53         int i, len;
     95        int i;
    5496       
    5597        if( !cmd[0] )
    5698                return;
    5799       
    58         len = strlen( cmd[0] );
    59100        for( i = 0; commands[i].command; i++ )
    60                 if( g_strncasecmp( commands[i].command, cmd[0], len ) == 0 )
    61                 {
    62                         if( commands[i+1].command &&
    63                             g_strncasecmp( commands[i+1].command, cmd[0], len ) == 0 )
    64                                 /* Only match on the first letters if the match is unique. */
    65                                 break;
    66                        
     101                if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 )
     102                {
    67103                        MIN_ARGS( commands[i].required_parameters );
    68104                       
     
    105141static void cmd_identify( irc_t *irc, char **cmd )
    106142{
    107         storage_status_t status;
     143        storage_status_t status = storage_load( irc, cmd[1] );
    108144        char *account_on[] = { "account", "on", NULL };
    109         gboolean load = TRUE;
    110         char *password = cmd[1];
    111        
    112         if( irc->status & USTATUS_IDENTIFIED )
     145       
     146        if( strchr( irc->umode, 'R' ) != NULL )
    113147        {
    114148                irc_usermsg( irc, "You're already logged in." );
    115149                return;
    116150        }
    117        
    118         if( strncmp( cmd[1], "-no", 3 ) == 0 )
    119         {
    120                 load = FALSE;
    121                 password = cmd[2];
    122         }
    123         else if( strncmp( cmd[1], "-force", 6 ) == 0 )
    124         {
    125                 password = cmd[2];
    126         }
    127         else if( irc->b->accounts != NULL )
    128         {
    129                 irc_usermsg( irc,
    130                              "You're trying to identify yourself, but already have "
    131                              "at least one IM account set up. "
    132                              "Use \x02identify -noload\x02 or \x02identify -force\x02 "
    133                              "instead (see \x02help identify\x02)." );
    134                 return;
    135         }
    136        
    137         if( password == NULL )
    138         {
    139                 MIN_ARGS( 2 );
    140         }
    141        
    142         if( load )
    143                 status = storage_load( irc, password );
    144         else
    145                 status = storage_check_pass( irc->user->nick, password );
    146151       
    147152        switch (status) {
     
    153158                break;
    154159        case STORAGE_OK:
    155                 irc_usermsg( irc, "Password accepted%s",
    156                              load ? ", settings and accounts loaded" : "" );
    157                 irc_setpass( irc, password );
     160                irc_usermsg( irc, "Password accepted, settings and accounts loaded" );
     161                irc_setpass( irc, cmd[1] );
    158162                irc->status |= USTATUS_IDENTIFIED;
    159163                irc_umode_set( irc, "+R", 1 );
    160                 if( load && set_getbool( &irc->b->set, "auto_connect" ) )
     164                if( set_getbool( &irc->set, "auto_connect" ) )
    161165                        cmd_account( irc, account_on );
    162166                break;
     
    198202        storage_status_t status;
    199203       
    200         status = storage_remove (irc->user->nick, cmd[1]);
     204        status = storage_remove (irc->nick, cmd[1]);
    201205        switch (status) {
    202206        case STORAGE_NO_SUCH_USER:
     
    210214                irc->status &= ~USTATUS_IDENTIFIED;
    211215                irc_umode_set( irc, "-R", 1 );
    212                 irc_usermsg( irc, "Account `%s' removed", irc->user->nick );
     216                irc_usermsg( irc, "Account `%s' removed", irc->nick );
    213217                break;
    214218        default:
     
    218222}
    219223
    220 static void cmd_save( irc_t *irc, char **cmd )
    221 {
    222         if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
    223                 irc_usermsg( irc, "Please create an account first" );
    224         else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
    225                 irc_usermsg( irc, "Configuration saved" );
    226         else
    227                 irc_usermsg( irc, "Configuration could not be saved!" );
     224struct cmd_account_del_data
     225{
     226        account_t *a;
     227        irc_t *irc;
     228};
     229
     230void cmd_account_del_yes( void *data )
     231{
     232        struct cmd_account_del_data *cad = data;
     233        account_t *a;
     234       
     235        for( a = cad->irc->accounts; a && a != cad->a; a = a->next );
     236       
     237        if( a == NULL )
     238        {
     239                irc_usermsg( cad->irc, "Account already deleted" );
     240        }
     241        else if( a->ic )
     242        {
     243                irc_usermsg( cad->irc, "Account is still logged in, can't delete" );
     244        }
     245        else
     246        {
     247                account_del( cad->irc, a );
     248                irc_usermsg( cad->irc, "Account deleted" );
     249        }
     250        g_free( data );
     251}
     252
     253void cmd_account_del_no( void *data )
     254{
     255        g_free( data );
    228256}
    229257
     
    258286                set_name = set_full;
    259287               
    260                 head = &irc->b->set;
     288                head = &irc->set;
    261289        }
    262290        else
     
    329357        account_t *a;
    330358       
    331         if( ( a = account_get( irc->b, id ) ) )
     359        if( ( a = account_get( irc, id ) ) )
    332360                return &a->set;
    333361        else
     
    377405                }
    378406
    379                 a = account_add( irc->b, prpl, cmd[3], cmd[4] );
     407                a = account_add( irc, prpl, cmd[3], cmd[4] );
    380408                if( cmd[5] )
    381409                {
     
    391419                MIN_ARGS( 2 );
    392420
    393                 if( !( a = account_get( irc->b, cmd[2] ) ) )
     421                if( !( a = account_get( irc, cmd[2] ) ) )
    394422                {
    395423                        irc_usermsg( irc, "Invalid account" );
     
    401429                else
    402430                {
    403                         account_del( irc->b, a );
    404                         irc_usermsg( irc, "Account deleted" );
     431                        struct cmd_account_del_data *cad;
     432                        char *msg;
     433                       
     434                        cad = g_malloc( sizeof( struct cmd_account_del_data ) );
     435                        cad->a = a;
     436                        cad->irc = irc;
     437                       
     438                        msg = g_strdup_printf( "If you remove this account (%s(%s)), BitlBee will "
     439                                               "also forget all your saved nicknames. If you want "
     440                                               "to change your username/password, use the `account "
     441                                               "set' command. Are you sure you want to delete this "
     442                                               "account?", a->prpl->name, a->user );
     443                        query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
     444                        g_free( msg );
    405445                }
    406446        }
     
    412452                        irc_usermsg( irc, "Account list:" );
    413453               
    414                 for( a = irc->b->accounts; a; a = a->next )
     454                for( a = irc->accounts; a; a = a->next )
    415455                {
    416456                        char *con;
     
    435475                if( cmd[2] )
    436476                {
    437                         if( ( a = account_get( irc->b, cmd[2] ) ) )
     477                        if( ( a = account_get( irc, cmd[2] ) ) )
    438478                        {
    439479                                if( a->ic )
     
    444484                                else
    445485                                {
    446                                         account_on( irc->b, a );
     486                                        account_on( irc, a );
    447487                                }
    448488                        }
     
    455495                else
    456496                {
    457                         if ( irc->b->accounts )
    458                         {
     497                        if ( irc->accounts ) {
    459498                                irc_usermsg( irc, "Trying to get all accounts connected..." );
    460499                       
    461                                 for( a = irc->b->accounts; a; a = a->next )
     500                                for( a = irc->accounts; a; a = a->next )
    462501                                        if( !a->ic && a->auto_connect )
    463                                                 account_on( irc->b, a );
     502                                                account_on( irc, a );
    464503                        }
    465504                        else
     
    475514                        irc_usermsg( irc, "Deactivating all active (re)connections..." );
    476515                       
    477                         for( a = irc->b->accounts; a; a = a->next )
     516                        for( a = irc->accounts; a; a = a->next )
    478517                        {
    479518                                if( a->ic )
    480                                         account_off( irc->b, a );
     519                                        account_off( irc, a );
    481520                                else if( a->reconnect )
    482521                                        cancel_auto_reconnect( a );
    483522                        }
    484523                }
    485                 else if( ( a = account_get( irc->b, cmd[2] ) ) )
     524                else if( ( a = account_get( irc, cmd[2] ) ) )
    486525                {
    487526                        if( a->ic )
    488527                        {
    489                                 account_off( irc->b, a );
     528                                account_off( irc, a );
    490529                        }
    491530                        else if( a->reconnect )
     
    518557}
    519558
    520 static set_t **cmd_channel_set_findhead( irc_t *irc, char *id )
    521 {
    522         irc_channel_t *ic;
    523        
    524         if( ( ic = irc_channel_get( irc, id ) ) )
    525                 return &ic->set;
    526         else
    527                 return NULL;
    528 }
    529 
    530 static void cmd_channel( irc_t *irc, char **cmd )
    531 {
    532         if( g_strcasecmp( cmd[1], "set" ) == 0 )
    533         {
    534                 MIN_ARGS( 2 );
    535                
    536                 cmd_set_real( irc, cmd + 1, cmd_channel_set_findhead, NULL );
    537         }
    538         else if( g_strcasecmp( cmd[1], "list" ) == 0 )
    539         {
    540                 GSList *l;
    541                 int i = 0;
    542                
    543                 if( strchr( irc->umode, 'b' ) )
    544                         irc_usermsg( irc, "Channel list:" );
    545                
    546                 for( l = irc->channels; l; l = l->next )
    547                 {
    548                         irc_channel_t *ic = l->data;
    549                        
    550                         irc_usermsg( irc, "%2d. %s, %s channel%s", i, ic->name,
    551                                      set_getstr( &ic->set, "type" ),
    552                                      ic->flags & IRC_CHANNEL_JOINED ? " (joined)" : "" );
    553                        
    554                         i ++;
    555                 }
    556                 irc_usermsg( irc, "End of channel list" );
    557         }
    558         else if( g_strcasecmp( cmd[1], "del" ) == 0 )
    559         {
    560                 irc_channel_t *ic;
    561                
    562                 MIN_ARGS( 2 );
    563                
    564                 if( ( ic = irc_channel_get( irc, cmd[2] ) ) &&
    565                    !( ic->flags & IRC_CHANNEL_JOINED ) &&
    566                     ic != ic->irc->default_channel )
    567                 {
    568                         irc_usermsg( irc, "Channel %s deleted.", ic->name );
    569                         irc_channel_free( ic );
    570                 }
    571                 else
    572                         irc_usermsg( irc, "Couldn't remove channel (main channel %s or "
    573                                           "channels you're still in cannot be deleted).",
    574                                           irc->default_channel->name );
    575         }
    576         else
    577         {
    578                 irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", cmd[1] );
    579         }
    580 }
    581 
    582559static void cmd_add( irc_t *irc, char **cmd )
    583560{
     
    592569        }
    593570       
    594         if( !( a = account_get( irc->b, cmd[1] ) ) )
     571        if( !( a = account_get( irc, cmd[1] ) ) )
    595572        {
    596573                irc_usermsg( irc, "Invalid account" );
     
    610587                        return;
    611588                }
    612                 else if( irc_user_by_name( irc, cmd[3] ) )
     589                else if( user_find( irc, cmd[3] ) )
    613590                {
    614591                        irc_usermsg( irc, "The requested nick `%s' already exists", cmd[3] );
     
    622599       
    623600        if( add_on_server )
    624                 a->prpl->add_buddy( a->ic, cmd[2], NULL );
    625         else
    626                 /* Only for add -tmp. For regular adds, this callback will
    627                    be called once the IM server confirms. */
    628                 bee_user_new( irc->b, a->ic, cmd[2], BEE_USER_LOCAL );
     601                a->ic->acc->prpl->add_buddy( a->ic, cmd[2], NULL );
     602        else
     603                /* Yeah, officially this is a call-*back*... So if we just
     604                   called add_buddy, we'll wait for the IM server to respond
     605                   before we do this. */
     606                imcb_add_buddy( a->ic, cmd[2], NULL );
    629607       
    630608        irc_usermsg( irc, "Adding `%s' to your contact list", cmd[2]  );
    631 }
    632 
    633 static void cmd_remove( irc_t *irc, char **cmd )
    634 {
    635         irc_user_t *iu;
    636         bee_user_t *bu;
    637         char *s;
    638        
    639         if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) )
    640         {
    641                 irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
    642                 return;
    643         }
    644         s = g_strdup( bu->handle );
    645        
    646         bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL );
    647         nick_del( bu->ic->acc, bu->handle );
    648         //TODO(wilmer): bee_user_free() and/or let the IM mod do it? irc_user_free( irc, cmd[1] );
    649        
    650         irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
    651         g_free( s );
    652        
    653         return;
    654609}
    655610
     
    661616        if( !cmd[2] )
    662617        {
    663                 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
    664                 if( !iu || !iu->bu )
     618                user_t *u = user_find( irc, cmd[1] );
     619                if( !u || !u->ic )
    665620                {
    666621                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    667622                        return;
    668623                }
    669                 ic = iu->bu->ic;
    670                 cmd[2] = iu->bu->handle;
    671         }
    672         else if( !( a = account_get( irc->b, cmd[1] ) ) )
     624                ic = u->ic;
     625                cmd[2] = u->handle;
     626        }
     627        else if( !( a = account_get( irc, cmd[1] ) ) )
    673628        {
    674629                irc_usermsg( irc, "Invalid account" );
     
    693648static void cmd_rename( irc_t *irc, char **cmd )
    694649{
    695         irc_user_t *iu;
    696        
    697         iu = irc_user_by_name( irc, cmd[1] );
    698        
    699         if( iu == NULL )
     650        user_t *u;
     651       
     652        if( g_strcasecmp( cmd[1], irc->nick ) == 0 )
     653        {
     654                irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
     655        }
     656        else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     657        {
     658                if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) )
     659                {
     660                        u = user_find( irc, irc->nick );
     661                       
     662                        irc_part( irc, u, irc->channel );
     663                        g_free( irc->channel );
     664                        irc->channel = g_strdup( cmd[2] );
     665                        irc_join( irc, u, irc->channel );
     666                       
     667                        if( strcmp( cmd[0], "set_rename" ) != 0 )
     668                                set_setstr( &irc->set, "control_channel", cmd[2] );
     669                }
     670        }
     671        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
     672        {
     673                irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
     674        }
     675        else if( !nick_ok( cmd[2] ) )
     676        {
     677                irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
     678        }
     679        else if( !( u = user_find( irc, cmd[1] ) ) )
    700680        {
    701681                irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    702682        }
    703         else if( iu == irc->user )
    704         {
    705                 irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
    706         }
    707         else if( !nick_ok( cmd[2] ) )
    708         {
    709                 irc_usermsg( irc, "Nick `%s' is invalid", cmd[2] );
    710         }
    711         else if( irc_user_by_name( irc, cmd[2] ) )
    712         {
    713                 irc_usermsg( irc, "Nick `%s' already exists", cmd[2] );
    714         }
    715         else
    716         {
    717                 if( !irc_user_set_nick( iu, cmd[2] ) )
    718                 {
    719                         irc_usermsg( irc, "Error while changing nick" );
    720                         return;
    721                 }
    722                
    723                 if( iu == irc->root )
    724                 {
     683        else
     684        {
     685                user_rename( irc, cmd[1], cmd[2] );
     686                irc_write( irc, ":%s!%s@%s NICK %s", cmd[1], u->user, u->host, cmd[2] );
     687                if( g_strcasecmp( cmd[1], irc->mynick ) == 0 )
     688                {
     689                        g_free( irc->mynick );
     690                        irc->mynick = g_strdup( cmd[2] );
     691                       
    725692                        /* If we're called internally (user did "set root_nick"),
    726693                           let's not go O(INF). :-) */
    727694                        if( strcmp( cmd[0], "set_rename" ) != 0 )
    728                                 set_setstr( &irc->b->set, "root_nick", cmd[2] );
    729                 }
    730                 else if( iu->bu )
    731                 {
    732                         nick_set( iu->bu->ic->acc, iu->bu->handle, cmd[2] );
     695                                set_setstr( &irc->set, "root_nick", cmd[2] );
     696                }
     697                else if( u->send_handler == buddy_send_handler )
     698                {
     699                        nick_set( u->ic->acc, u->handle, cmd[2] );
    733700                }
    734701               
     
    741708        irc_t *irc = set->data;
    742709       
    743         if( strcmp( irc->root->nick, new_nick ) != 0 )
    744         {
    745                 char *cmd[] = { "set_rename", irc->root->nick, new_nick, NULL };
     710        if( strcmp( irc->mynick, new_nick ) != 0 )
     711        {
     712                char *cmd[] = { "set_rename", irc->mynick, new_nick, NULL };
    746713               
    747714                cmd_rename( irc, cmd );
    748715        }
    749716       
    750         return strcmp( irc->root->nick, new_nick ) == 0 ? new_nick : SET_INVALID;
     717        return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
     718}
     719
     720char *set_eval_control_channel( set_t *set, char *new_name )
     721{
     722        irc_t *irc = set->data;
     723       
     724        if( strcmp( irc->channel, new_name ) != 0 )
     725        {
     726                char *cmd[] = { "set_rename", irc->channel, new_name, NULL };
     727               
     728                cmd_rename( irc, cmd );
     729        }
     730       
     731        return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;
     732}
     733
     734static void cmd_remove( irc_t *irc, char **cmd )
     735{
     736        user_t *u;
     737        char *s;
     738       
     739        if( !( u = user_find( irc, cmd[1] ) ) || !u->ic )
     740        {
     741                irc_usermsg( irc, "Buddy `%s' not found", cmd[1] );
     742                return;
     743        }
     744        s = g_strdup( u->handle );
     745       
     746        u->ic->acc->prpl->remove_buddy( u->ic, u->handle, NULL );
     747        nick_del( u->ic->acc, u->handle );
     748        user_del( irc, cmd[1] );
     749       
     750        irc_usermsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] );
     751        g_free( s );
     752       
     753        return;
    751754}
    752755
     
    756759        account_t *a;
    757760       
    758         if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic )
     761        if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
    759762        {
    760763                char *format;
     
    769772                for( l = a->ic->deny; l; l = l->next )
    770773                {
    771                         bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data );
    772                         irc_user_t *iu = bu ? bu->ui_data : NULL;
    773                         irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" );
     774                        user_t *u = user_findhandle( a->ic, l->data );
     775                        irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
    774776                }
    775777                irc_usermsg( irc, "End of list." );
     
    779781        else if( !cmd[2] )
    780782        {
    781                 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
    782                 if( !iu || !iu->bu )
     783                user_t *u = user_find( irc, cmd[1] );
     784                if( !u || !u->ic )
    783785                {
    784786                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    785787                        return;
    786788                }
    787                 ic = iu->bu->ic;
    788                 cmd[2] = iu->bu->handle;
    789         }
    790         else if( !( a = account_get( irc->b, cmd[1] ) ) )
     789                ic = u->ic;
     790                cmd[2] = u->handle;
     791        }
     792        else if( !( a = account_get( irc, cmd[1] ) ) )
    791793        {
    792794                irc_usermsg( irc, "Invalid account" );
     
    816818        account_t *a;
    817819       
    818         if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic )
     820        if( !cmd[2] && ( a = account_get( irc, cmd[1] ) ) && a->ic )
    819821        {
    820822                char *format;
     
    829831                for( l = a->ic->permit; l; l = l->next )
    830832                {
    831                         bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data );
    832                         irc_user_t *iu = bu ? bu->ui_data : NULL;
    833                         irc_usermsg( irc, format, l->data, iu ? iu->nick : "(none)" );
     833                        user_t *u = user_findhandle( a->ic, l->data );
     834                        irc_usermsg( irc, format, l->data, u ? u->nick : "(none)" );
    834835                }
    835836                irc_usermsg( irc, "End of list." );
     
    839840        else if( !cmd[2] )
    840841        {
    841                 irc_user_t *iu = irc_user_by_name( irc, cmd[1] );
    842                 if( !iu || !iu->bu )
     842                user_t *u = user_find( irc, cmd[1] );
     843                if( !u || !u->ic )
    843844                {
    844845                        irc_usermsg( irc, "Nick `%s' does not exist", cmd[1] );
    845846                        return;
    846847                }
    847                 ic = iu->bu->ic;
    848                 cmd[2] = iu->bu->handle;
    849         }
    850         else if( !( a = account_get( irc->b, cmd[1] ) ) )
     848                ic = u->ic;
     849                cmd[2] = u->handle;
     850        }
     851        else if( !( a = account_get( irc, cmd[1] ) ) )
    851852        {
    852853                irc_usermsg( irc, "Invalid account" );
     
    915916}
    916917
     918static void cmd_save( irc_t *irc, char **cmd )
     919{
     920        if( ( irc->status & USTATUS_IDENTIFIED ) == 0 )
     921                irc_usermsg( irc, "Please create an account first" );
     922        else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK )
     923                irc_usermsg( irc, "Configuration saved" );
     924        else
     925                irc_usermsg( irc, "Configuration could not be saved!" );
     926}
     927
    917928static void cmd_blist( irc_t *irc, char **cmd )
    918929{
    919930        int online = 0, away = 0, offline = 0;
    920         GSList *l;
     931        user_t *u;
    921932        char s[256];
    922933        char *format;
     
    939950                format = "%-16.16s  %-40.40s  %s";
    940951       
    941         irc_usermsg( irc, format, "Nick", "Handle/Account", "Status" );
    942        
    943         for( l = irc->users; l; l = l->next )
    944         {
    945                 irc_user_t *iu = l->data;
    946                 bee_user_t *bu = iu->bu;
    947                
    948                 if( !bu || ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) != BEE_USER_ONLINE )
    949                         continue;
    950                
     952        irc_usermsg( irc, format, "Nick", "User/Host/Network", "Status" );
     953       
     954        for( u = irc->users; u; u = u->next ) if( u->ic && u->online && !u->away )
     955        {
    951956                if( online == 1 )
    952957                {
    953958                        char st[256] = "Online";
    954959                       
    955                         if( bu->status_msg )
    956                                 g_snprintf( st, sizeof( st ) - 1, "Online (%s)", bu->status_msg );
    957                        
    958                         g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
    959                         irc_usermsg( irc, format, iu->nick, s, st );
     960                        if( u->status_msg )
     961                                g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );
     962                       
     963                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
     964                        irc_usermsg( irc, format, u->nick, s, st );
    960965                }
    961966               
     
    963968        }
    964969
    965         for( l = irc->users; l; l = l->next )
    966         {
    967                 irc_user_t *iu = l->data;
    968                 bee_user_t *bu = iu->bu;
    969                
    970                 if( !bu || !( bu->flags & BEE_USER_ONLINE ) || !( bu->flags & BEE_USER_AWAY ) )
    971                         continue;
    972                
     970        for( u = irc->users; u; u = u->next ) if( u->ic && u->online && u->away )
     971        {
    973972                if( away == 1 )
    974973                {
    975                         g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
    976                         irc_usermsg( irc, format, iu->nick, s, irc_user_get_away( iu ) );
     974                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
     975                        irc_usermsg( irc, format, u->nick, s, u->away );
    977976                }
    978977                n_away ++;
    979978        }
    980979       
    981         for( l = irc->users; l; l = l->next )
    982         {
    983                 irc_user_t *iu = l->data;
    984                 bee_user_t *bu = iu->bu;
    985                
    986                 if( !bu || bu->flags & BEE_USER_ONLINE )
    987                         continue;
    988                
     980        for( u = irc->users; u; u = u->next ) if( u->ic && !u->online )
     981        {
    989982                if( offline == 1 )
    990983                {
    991                         g_snprintf( s, sizeof( s ) - 1, "%s %s(%s)", bu->handle, bu->ic->acc->prpl->name, bu->ic->acc->user );
    992                         irc_usermsg( irc, format, iu->nick, s, "Offline" );
     984                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
     985                        irc_usermsg( irc, format, u->nick, s, "Offline" );
    993986                }
    994987                n_offline ++;
     
    996989       
    997990        irc_usermsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline );
     991}
     992
     993static void cmd_nick( irc_t *irc, char **cmd )
     994{
     995        account_t *a;
     996
     997        if( !cmd[1] || !( a = account_get( irc, cmd[1] ) ) )
     998        {
     999                irc_usermsg( irc, "Invalid account");
     1000        }
     1001        else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
     1002        {
     1003                irc_usermsg( irc, "That account is not on-line" );
     1004        }
     1005        else if ( !cmd[2] )
     1006        {
     1007                irc_usermsg( irc, "Your name is `%s'" , a->ic->displayname ? a->ic->displayname : "NULL" );
     1008        }
     1009        else if ( !a->prpl->set_my_name )
     1010        {
     1011                irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
     1012        }
     1013        else
     1014        {
     1015                irc_usermsg( irc, "Setting your name to `%s'", cmd[2] );
     1016               
     1017                a->prpl->set_my_name( a->ic, cmd[2] );
     1018        }
    9981019}
    9991020
     
    10181039}
    10191040
     1041static void cmd_join_chat( irc_t *irc, char **cmd )
     1042{
     1043        irc_usermsg( irc, "This command is now obsolete. "
     1044                          "Please try the `chat' command instead." );
     1045}
     1046
     1047static set_t **cmd_chat_set_findhead( irc_t *irc, char *id )
     1048{
     1049        struct chat *c;
     1050       
     1051        if( ( c = chat_get( irc, id ) ) )
     1052                return &c->set;
     1053        else
     1054                return NULL;
     1055}
     1056
    10201057static void cmd_chat( irc_t *irc, char **cmd )
    10211058{
    10221059        account_t *acc;
     1060        struct chat *c;
    10231061       
    10241062        if( g_strcasecmp( cmd[1], "add" ) == 0 )
    10251063        {
    10261064                char *channel, *s;
    1027                 struct irc_channel *ic;
    10281065               
    10291066                MIN_ARGS( 3 );
    10301067               
    1031                 if( !( acc = account_get( irc->b, cmd[2] ) ) )
     1068                if( !( acc = account_get( irc, cmd[2] ) ) )
    10321069                {
    10331070                        irc_usermsg( irc, "Invalid account" );
    1034                         return;
    1035                 }
    1036                 else if( !acc->prpl->chat_join )
    1037                 {
    1038                         irc_usermsg( irc, "Named chatrooms not supported on that account." );
    10391071                        return;
    10401072                }
     
    10531085                if( strchr( CTYPES, channel[0] ) == NULL )
    10541086                {
    1055                         s = g_strdup_printf( "#%s", channel );
     1087                        s = g_strdup_printf( "%c%s", CTYPES[0], channel );
    10561088                        g_free( channel );
    10571089                        channel = s;
    10581090                }
    10591091               
    1060                 if( ( ic = irc_channel_new( irc, channel ) ) &&
    1061                     set_setstr( &ic->set, "chat_type", "room" ) &&
    1062                     set_setstr( &ic->set, "account", cmd[2] ) &&
    1063                     set_setstr( &ic->set, "room", cmd[3] ) )
    1064                 {
    1065                         irc_usermsg( irc, "Chatroom successfully added." );
    1066                 }
    1067                 else
    1068                 {
    1069                         if( ic )
    1070                                 irc_channel_free( ic );
    1071                        
     1092                if( ( c = chat_add( irc, acc, cmd[3], channel ) ) )
     1093                        irc_usermsg( irc, "Chatroom added successfully." );
     1094                else
    10721095                        irc_usermsg( irc, "Could not add chatroom." );
    1073                 }
     1096               
    10741097                g_free( channel );
    10751098        }
     1099        else if( g_strcasecmp( cmd[1], "list" ) == 0 )
     1100        {
     1101                int i = 0;
     1102               
     1103                if( strchr( irc->umode, 'b' ) )
     1104                        irc_usermsg( irc, "Chatroom list:" );
     1105               
     1106                for( c = irc->chatrooms; c; c = c->next )
     1107                {
     1108                        irc_usermsg( irc, "%2d. %s(%s) %s, %s", i, c->acc->prpl->name,
     1109                                          c->acc->user, c->handle, c->channel );
     1110                       
     1111                        i ++;
     1112                }
     1113                irc_usermsg( irc, "End of chatroom list" );
     1114        }
     1115        else if( g_strcasecmp( cmd[1], "set" ) == 0 )
     1116        {
     1117                MIN_ARGS( 2 );
     1118               
     1119                cmd_set_real( irc, cmd + 1, cmd_chat_set_findhead, NULL );
     1120        }
     1121        else if( g_strcasecmp( cmd[1], "del" ) == 0 )
     1122        {
     1123                MIN_ARGS( 2 );
     1124               
     1125                if( ( c = chat_get( irc, cmd[2] ) ) )
     1126                {
     1127                        chat_del( irc, c );
     1128                }
     1129                else
     1130                {
     1131                        irc_usermsg( irc, "Could not remove chat." );
     1132                }
     1133        }
    10761134        else if( g_strcasecmp( cmd[1], "with" ) == 0 )
    10771135        {
    1078                 irc_user_t *iu;
     1136                user_t *u;
    10791137               
    10801138                MIN_ARGS( 2 );
    10811139               
    1082                 if( ( iu = irc_user_by_name( irc, cmd[2] ) ) &&
    1083                     iu->bu && iu->bu->ic->acc->prpl->chat_with )
    1084                 {
    1085                         if( !iu->bu->ic->acc->prpl->chat_with( iu->bu->ic, iu->bu->handle ) )
     1140                if( ( u = user_find( irc, cmd[2] ) ) && u->ic && u->ic->acc->prpl->chat_with )
     1141                {
     1142                        if( !u->ic->acc->prpl->chat_with( u->ic, u->handle ) )
    10861143                        {
    10871144                                irc_usermsg( irc, "(Possible) failure while trying to open "
    1088                                                   "a groupchat with %s.", iu->nick );
     1145                                                  "a groupchat with %s.", u->nick );
    10891146                        }
    10901147                }
     
    10941151                }
    10951152        }
    1096         else if( g_strcasecmp( cmd[1], "list" ) == 0 ||
    1097                  g_strcasecmp( cmd[1], "set" ) == 0 ||
    1098                  g_strcasecmp( cmd[1], "del" ) == 0 )
    1099         {
    1100                 irc_usermsg( irc, "Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command." );
    1101                 cmd_channel( irc, cmd );
    1102         }
    11031153        else
    11041154        {
     
    11071157}
    11081158
    1109 static void cmd_transfer( irc_t *irc, char **cmd )
    1110 {
    1111         GSList *files = irc->file_transfers;
    1112         enum { LIST, REJECT, CANCEL };
    1113         int subcmd = LIST;
    1114         int fid;
    1115 
    1116         if( !files )
    1117         {
    1118                 irc_usermsg( irc, "No pending transfers" );
    1119                 return;
    1120         }
    1121 
    1122         if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) )
    1123         {
    1124                 subcmd = REJECT;
    1125         }
    1126         else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) &&
    1127                  cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) )
    1128         {
    1129                 subcmd = CANCEL;
    1130         }
    1131 
    1132         for( ; files; files = g_slist_next( files ) )
    1133         {
    1134                 file_transfer_t *file = files->data;
    1135                
    1136                 switch( subcmd ) {
    1137                 case LIST:
    1138                         if ( file->status == FT_STATUS_LISTENING )
    1139                                 irc_usermsg( irc,
    1140                                         "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name);
    1141                         else
    1142                         {
    1143                                 int kb_per_s = 0;
    1144                                 time_t diff = time( NULL ) - file->started ? : 1;
    1145                                 if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) )
    1146                                         kb_per_s = file->bytes_transferred / 1024 / diff;
    1147                                        
    1148                                 irc_usermsg( irc,
    1149                                         "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name,
    1150                                         file->bytes_transferred/1024, file->file_size/1024, kb_per_s);
    1151                         }
    1152                         break;
    1153                 case REJECT:
    1154                         if( file->status == FT_STATUS_LISTENING )
    1155                         {
    1156                                 irc_usermsg( irc, "Rejecting file transfer for %s", file->file_name );
    1157                                 imcb_file_canceled( file->ic, file, "Denied by user" );
    1158                         }
    1159                         break;
    1160                 case CANCEL:
    1161                         if( file->local_id == fid )
    1162                         {
    1163                                 irc_usermsg( irc, "Canceling file transfer for %s", file->file_name );
    1164                                 imcb_file_canceled( file->ic, file, "Canceled by user" );
    1165                         }
    1166                         break;
    1167                 }
    1168         }
    1169 }
    1170 
    1171 /* IMPORTANT: Keep this list sorted! The short command logic needs that. */
    11721159const command_t commands[] = {
     1160        { "help",           0, cmd_help,           0 },
     1161        { "identify",       1, cmd_identify,       0 },
     1162        { "register",       1, cmd_register,       0 },
     1163        { "drop",           1, cmd_drop,           0 },
    11731164        { "account",        1, cmd_account,        0 },
    11741165        { "add",            2, cmd_add,            0 },
     1166        { "info",           1, cmd_info,           0 },
     1167        { "rename",         2, cmd_rename,         0 },
     1168        { "remove",         1, cmd_remove,         0 },
     1169        { "block",          1, cmd_block,          0 },
    11751170        { "allow",          1, cmd_allow,          0 },
    1176         { "blist",          0, cmd_blist,          0 },
    1177         { "block",          1, cmd_block,          0 },
    1178         { "channel",        1, cmd_channel,        0 },
    1179         { "chat",           1, cmd_chat,           0 },
    1180         { "drop",           1, cmd_drop,           0 },
    1181         { "ft",             0, cmd_transfer,       0 },
    1182         { "help",           0, cmd_help,           0 },
    1183         { "identify",       1, cmd_identify,       0 },
    1184         { "info",           1, cmd_info,           0 },
    1185         { "no",             0, cmd_yesno,          0 },
    1186         { "qlist",          0, cmd_qlist,          0 },
    1187         { "register",       1, cmd_register,       0 },
    1188         { "remove",         1, cmd_remove,         0 },
    1189         { "rename",         2, cmd_rename,         0 },
    11901171        { "save",           0, cmd_save,           0 },
    11911172        { "set",            0, cmd_set,            0 },
    1192         { "transfer",       0, cmd_transfer,       0 },
    11931173        { "yes",            0, cmd_yesno,          0 },
     1174        { "no",             0, cmd_yesno,          0 },
     1175        { "blist",          0, cmd_blist,          0 },
     1176        { "nick",           1, cmd_nick,           0 },
     1177        { "qlist",          0, cmd_qlist,          0 },
     1178        { "join_chat",      2, cmd_join_chat,      0 },
     1179        { "chat",           1, cmd_chat,           0 },
    11941180        { NULL }
    11951181};
  • set.c

    r8b8def58 r38ff846  
    2929char *SET_INVALID = "nee";
    3030
    31 set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, void *data )
     31set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data )
    3232{
    3333        set_t *s = set_find( head, key );
     
    6363}
    6464
    65 set_t *set_find( set_t **head, const char *key )
     65set_t *set_find( set_t **head, char *key )
    6666{
    6767        set_t *s = *head;
     
    6969        while( s )
    7070        {
    71                 if( g_strcasecmp( s->key, key ) == 0 ||
    72                     ( s->old_key && g_strcasecmp( s->old_key, key ) == 0 ) )
     71                if( g_strcasecmp( s->key, key ) == 0 )
    7372                        break;
    7473                s = s->next;
     
    7877}
    7978
    80 char *set_getstr( set_t **head, const char *key )
     79char *set_getstr( set_t **head, char *key )
    8180{
    8281        set_t *s = set_find( head, key );
     
    8887}
    8988
    90 int set_getint( set_t **head, const char *key )
     89int set_getint( set_t **head, char *key )
    9190{
    9291        char *s = set_getstr( head, key );
     
    102101}
    103102
    104 int set_getbool( set_t **head, const char *key )
     103int set_getbool( set_t **head, char *key )
    105104{
    106105        char *s = set_getstr( head, key );
     
    112111}
    113112
    114 int set_setstr( set_t **head, const char *key, char *value )
     113int set_setstr( set_t **head, char *key, char *value )
    115114{
    116115        set_t *s = set_find( head, key );
     
    151150}
    152151
    153 int set_setint( set_t **head, const char *key, int value )
     152int set_setint( set_t **head, char *key, int value )
    154153{
    155154        char s[24];     /* Not quite 128-bit clean eh? ;-) */
     
    159158}
    160159
    161 void set_del( set_t **head, const char *key )
     160void set_del( set_t **head, char *key )
    162161{
    163162        set_t *s = *head, *t = NULL;
     
    177176               
    178177                g_free( s->key );
    179                 g_free( s->old_key );
    180                 g_free( s->value );
    181                 g_free( s->def );
     178                if( s->value ) g_free( s->value );
     179                if( s->def ) g_free( s->def );
    182180                g_free( s );
    183181        }
    184182}
    185183
    186 int set_reset( set_t **head, const char *key )
     184int set_reset( set_t **head, char *key )
    187185{
    188186        set_t *s;
     
    213211{
    214212        return is_bool( value ) ? value : SET_INVALID;
    215 }
    216 
    217 char *set_eval_list( set_t *set, char *value )
    218 {
    219         GSList *options = set->eval_data, *opt;
    220        
    221         for( opt = options; opt; opt = opt->next )
    222                 if( strcmp( value, opt->data ) == 0 )
    223                         return value;
    224        
    225         /* TODO: It'd be nice to show the user a list of allowed values,
    226                  but we don't have enough context here to do that. May
    227                  want to fix that. */
    228        
    229         return NULL;
    230213}
    231214
     
    242225}
    243226
    244 /*
    245227char *set_eval_ops( set_t *set, char *value )
    246228{
     
    264246        return value;
    265247}
    266 */
  • set.h

    r8b8def58 r38ff846  
    5454       
    5555        char *key;
    56         char *old_key;  /* Previously known as; for smooth upgrades. */
    5756        char *value;
    5857        char *def;      /* Default value. If the set_setstr() function
     
    7069           set_setstr() should be able to free() the returned string! */
    7170        set_eval eval;
    72         void *eval_data;
    7371        struct set *next;
    7472} set_t;
    7573
    7674/* Should be pretty clear. */
    77 set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, void *data );
     75set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data );
    7876
    7977/* Returns the raw set_t. Might be useful sometimes. */
    80 set_t *set_find( set_t **head, const char *key );
     78set_t *set_find( set_t **head, char *key );
    8179
    8280/* Returns a pointer to the string value of this setting. Don't modify the
    8381   returned string, and don't free() it! */
    84 G_MODULE_EXPORT char *set_getstr( set_t **head, const char *key );
     82G_MODULE_EXPORT char *set_getstr( set_t **head, char *key );
    8583
    8684/* Get an integer. In previous versions set_getint() was also used to read
    8785   boolean values, but this SHOULD be done with set_getbool() now! */
    88 G_MODULE_EXPORT int set_getint( set_t **head, const char *key );
    89 G_MODULE_EXPORT int set_getbool( set_t **head, const char *key );
     86G_MODULE_EXPORT int set_getint( set_t **head, char *key );
     87G_MODULE_EXPORT int set_getbool( set_t **head, char *key );
    9088
    9189/* set_setstr() strdup()s the given value, so after using this function
    9290   you can free() it, if you want. */
    93 int set_setstr( set_t **head, const char *key, char *value );
    94 int set_setint( set_t **head, const char *key, int value );
    95 void set_del( set_t **head, const char *key );
    96 int set_reset( set_t **head, const char *key );
     91int set_setstr( set_t **head, char *key, char *value );
     92int set_setint( set_t **head, char *key, int value );
     93void set_del( set_t **head, char *key );
     94int set_reset( set_t **head, char *key );
    9795
    9896/* Two very useful generic evaluators. */
    9997char *set_eval_int( set_t *set, char *value );
    10098char *set_eval_bool( set_t *set, char *value );
    101 
    102 /* Another more complicated one. */
    103 char *set_eval_list( set_t *set, char *value );
    10499
    105100/* Some not very generic evaluators that really shouldn't be here... */
  • storage.c

    r8b8def58 r38ff846  
    2828#define BITLBEE_CORE
    2929#include "bitlbee.h"
     30#include "crypting.h"
    3031
    3132extern storage_t storage_text;
     
    6566        storage_t *storage;
    6667       
     68        register_storage_backend(&storage_text);
    6769        register_storage_backend(&storage_xml);
    6870       
  • storage_xml.c

    r8b8def58 r38ff846  
    147147                                         arc_decode( pass_cr, pass_len, &password, xd->given_pass ) )
    148148                {
    149                         xd->current_account = account_add( irc->b, prpl, handle, password );
     149                        xd->current_account = account_add( irc, prpl, handle, password );
    150150                        if( server )
    151151                                set_setstr( &xd->current_account->set, "server", server );
     
    181181                                xd->current_set_head = &xd->current_account->set;
    182182                        else
    183                                 xd->current_set_head = &xd->irc->b->set;
     183                                xd->current_set_head = &xd->irc->set;
    184184                       
    185185                        xd->current_setting = g_strdup( setting );
     
    215215                if( xd->current_account && handle && channel )
    216216                {
    217                         //xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );
     217                        xd->current_chat = chat_add( xd->irc, xd->current_account, handle, channel );
    218218                }
    219219                else
     
    353353static storage_status_t xml_load( irc_t *irc, const char *password )
    354354{
    355         return xml_load_real( irc, irc->user->nick, password, XML_PASS_UNKNOWN );
     355        return xml_load_real( irc, irc->nick, password, XML_PASS_UNKNOWN );
    356356}
    357357
     
    396396        md5_state_t md5_state;
    397397       
    398         path2 = g_strdup( irc->user->nick );
     398        path2 = g_strdup( irc->nick );
    399399        nick_lc( path2 );
    400400        g_snprintf( path, sizeof( path ) - 2, "%s%s%s", global.conf->configdir, path2, ".xml" );
     
    422422        pass_buf = base64_encode( pass_md5, 21 );
    423423       
    424         if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->user->nick, pass_buf, XML_FORMAT_VERSION ) )
     424        if( !xml_printf( fd, 0, "<user nick=\"%s\" password=\"%s\" version=\"%d\">\n", irc->nick, pass_buf, XML_FORMAT_VERSION ) )
    425425                goto write_error;
    426426       
    427427        g_free( pass_buf );
    428428       
    429         for( set = irc->b->set; set; set = set->next )
     429        for( set = irc->set; set; set = set->next )
    430430                if( set->value )
    431431                        if( !xml_printf( fd, 1, "<setting name=\"%s\">%s</setting>\n", set->key, set->value ) )
    432432                                goto write_error;
    433433       
    434         for( acc = irc->b->accounts; acc; acc = acc->next )
     434        for( acc = irc->accounts; acc; acc = acc->next )
    435435        {
    436436                unsigned char *pass_cr;
     
    470470                        goto write_error;
    471471               
    472 #if 0
    473472                for( c = irc->chatrooms; c; c = c->next )
    474473                {
     
    489488                                goto write_error;
    490489                }
    491 #endif
    492490               
    493491                if( !xml_printf( fd, 1, "</account>\n" ) )
  • tests/Makefile

    r8b8def58 r38ff846  
    11-include ../Makefile.settings
    2 ifdef SRCDIR
    3 SRCDIR := $(SRCDIR)tests/
    4 endif
    52
    63LFLAGS +=-lcheck
     
    2219        @$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(EFLAGS)
    2320
    24 %.o: $(SRCDIR)%.c
     21%.o: %.c
    2522        @echo '*' Compiling $<
    2623        @$(CC) -c $(CFLAGS) $< -o $@
  • unix.c

    r8b8def58 r38ff846  
    5656       
    5757        log_init();
    58        
    5958        global.conf_file = g_strdup( CONF_FILE_DEF );
    6059        global.conf = conf_load( argc, argv );
     
    6362       
    6463        b_main_init();
     64        nogaim_init();
    6565       
    6666        srand( time( NULL ) ^ getpid() );
    67        
    6867        global.helpfile = g_strdup( HELP_FILE );
    69         if( help_init( &global.help, global.helpfile ) == NULL )
    70                 log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE );
    71 
    72         global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage );
    73         if( global.storage == NULL )
    74         {
    75                 log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage );
    76                 return( 1 );
    77         }
    7868       
    7969        if( global.conf->runmode == RUNMODE_INETD )
     
    126116                        setuid( pw->pw_uid );
    127117                }
     118        }
     119
     120        global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage );
     121        if( global.storage == NULL )
     122        {
     123                log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage );
     124                return( 1 );
    128125        }
    129126       
     
    145142        if( !getuid() || !geteuid() )
    146143                log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" );
     144        if( help_init( &global.help, global.helpfile ) == NULL )
     145                log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE );
    147146       
    148147        b_main_run();
  • win32.c

    r8b8def58 r38ff846  
    2727#include "bitlbee.h"
    2828#include "commands.h"
     29#include "crypting.h"
    2930#include "protocols/nogaim.h"
    3031#include "help.h"
Note: See TracChangeset for help on using the changeset viewer.