Changeset 29ff5c2


Ignore:
Timestamp:
2015-11-21T00:01:50Z (4 years ago)
Author:
dequis <dx@…>
Parents:
e4f08bf (diff), 8fdeaa5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into feat/hip-cat

Files:
1 added
107 edited

Legend:

Unmodified
Added
Removed
  • .travis.yml

    re4f08bf r29ff5c2  
     1sudo: false
    12language: c
    23
     
    45 - ./configure
    56 - make check
    6  - BITLBEE_SKYPE=plugin dpkg-buildpackage -uc -us
     7 - BITLBEE_SKYPE=plugin dpkg-buildpackage -uc -us -d
    78
     9# ubuntu precise doesn't have libotr5, so extract a prebuilt version to ~/otr
    810before_install:
    9  - sudo apt-get update -qq
    10  - sudo apt-get install --no-install-recommends -qq libevent-dev libpurple-dev check
    11  - wget http://dump.dequis.org/indexed/bitlbee-travis-libs/libotr5{,-dev}_4.1.0-2~bpo70+1_amd64.deb
    12  - sudo dpkg -i *.deb
     11 - wget http://dump.dequis.org/indexed/bitlbee-travis-libs/libotr5_4.1.0_amd64_with_dev_for_travis.tar.gz -O /tmp/otr.tar.gz
     12 - echo "8424feb28a2cff3ce603ddcdff9be788701ff7e4  /tmp/otr.tar.gz" | sha1sum -c -
     13 - tar -C "$HOME" -xf /tmp/otr.tar.gz
     14 - sed -i "s#/usr#$HOME/otr/usr/#" "$HOME/otr/usr/lib/pkgconfig/libotr.pc"
     15 - echo "libotr 5 libotr" > debian/shlibs.local
    1316
    1417env:
    1518  global:
     19   - PKG_CONFIG_PATH=$HOME/otr/usr/lib/pkgconfig/
     20   - LD_LIBRARY_PATH=$HOME/otr/usr/lib/
    1621   # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
    1722   #   via the "travis encrypt" command using the project repo's public key
     
    1924
    2025addons:
     26  apt:
     27    packages:
     28    - libevent-dev
     29    - libpurple-dev
     30    - check
    2131  coverity_scan:
    2232    project:
  • Makefile

    re4f08bf r29ff5c2  
    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 $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o conf.o log.o
     12objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_cap.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o conf.o log.o
    1313headers = $(wildcard $(_SRCDIR_)*.h $(_SRCDIR_)lib/*.h $(_SRCDIR_)protocols/*.h)
    1414subdirs = lib protocols
     
    3030
    3131install: install-bin install-doc install-plugins
     32        @echo
     33        @echo Installed successfully
     34        @echo
    3235        @if ! [ -d $(DESTDIR)$(CONFIG) ]; then echo -e '\nThe configuration directory $(DESTDIR)$(CONFIG) does not exist yet, don'\''t forget to create it!'; fi
    3336        @if ! [ -e $(DESTDIR)$(ETCDIR)/bitlbee.conf ]; then echo -e '\nNo files are installed in '$(DESTDIR)$(ETCDIR)' by make install. Run make install-etc to do that.'; fi
     
    3538        @echo If you want to start BitlBee using systemd, try \"make install-systemd\".
    3639endif
    37         @echo
    38 
    39 .PHONY:   install   install-bin   install-etc   install-doc install-plugins install-systemd \
    40         uninstall uninstall-bin uninstall-etc uninstall-doc \
     40        @echo To be able to compile third party plugins, run \"make install-dev\"
     41        @echo
     42
     43.PHONY:   install   install-bin   install-etc   install-doc install-plugins install-systemd install-dev \
     44        uninstall uninstall-bin uninstall-etc uninstall-doc uninstall-etc \
    4145        all clean distclean tar $(subdirs) doc
    4246
  • README.md

    re4f08bf r29ff5c2  
    1616License: GPLv2
    1717
    18 ## Development
     18## Installation
    1919
    20 Use github pull requests against the 'develop' branch to submit patches.
     20BitlBee is available in the package managers of most distros.
    2121
    22 The 'master' branch should be stable enough to be usable by users of the APT repo, but only requires a few days of testing in the 'develop' branch.
     22For debian/ubuntu/etc you may use the nightly APT repository: http://code.bitlbee.org/debian/
    2323
    24 Building:
     24You can also use a public server (such as `im.bitlbee.org`) instead of installing it: http://bitlbee.org/main.php/servers.html
    2525
    26 ```
    27 ./configure --debug=1
    28 # or, for a local install:
    29 # ./configure --debug=1 --prefix=$HOME/bitlbee --config=$HOME/bitlbee --pidfile=$HOME/bitlbee/bitlbee.pid
     26## Compiling
    3027
    31 # Also try --asan=1 for AddressSanitizer
     28If you wish to compile it yourself, ensure you have the following packages and their headers:
    3229
    33 make
     30* glib 2.16 or newer (not to be confused with glibc)
     31* gnutls
     32* python 2 or 3 (for the user guide)
    3433
    35 BITLBEE_DEBUG=1 ./bitlbee -Dnv
    36 ```
     34Some optional features have additional dependencies, such as libpurple, libotr, libevent, etc.
     35NSS and OpenSSL are also available but not as well supported as GnuTLS.
    3736
    38 See ./doc/README and ./doc/HACKING for more details.
     37Once you have the dependencies, building should be a matter of:
    3938
    40 Mappings of bzr revisions to git commits (for historical purposes) are available in ./doc/git-bzr-rev-map
     39    ./configure
     40    make
     41    sudo make install
     42
     43## Development tips
     44
     45* To enable debug symbols: `./configure --debug=1`
     46* To get some additional debug output for some protocols: `BITLBEE_DEBUG=1 ./bitlbee -Dnv`
     47* Use github pull requests against the 'develop' branch to submit patches.
     48* The coding style based on K&R with tabs and 120 columns. See `./doc/uncrustify.cfg` for the parameters used to reformat the code.
     49* Mappings of bzr revisions to git commits (for historical purposes) are available in `./doc/git-bzr-rev-map`
     50* See also `./doc/README` and `./doc/HACKING`
    4151
    4252## Help?
    4353
    44 Join **#BitlBee** on OFTC (**irc.oftc.net**) (OFTC, *not* FreeNode!) and flame us right in the face. :-)
     54Join **#BitlBee** on OFTC (**irc.oftc.net**) (OFTC, *not* FreeNode!)
  • bitlbee.c

    re4f08bf r29ff5c2  
    311311                        b_event_remove(global.listen_watch_source_id);
    312312
     313                        /* Make a new pipe for the shutdown signal handler */
     314                        sighandler_shutdown_setup();
     315
    313316                        /* Make the connection. */
    314317                        irc = irc_new(new_socket);
  • bitlbee.h

    re4f08bf r29ff5c2  
    3636
    3737#define PACKAGE "BitlBee"
    38 #define BITLBEE_VERSION "3.4"
     38#define BITLBEE_VERSION "3.4.1"
    3939#define VERSION BITLBEE_VERSION
    4040#define BITLBEE_VER(a, b, c) (((a) << 16) + ((b) << 8) + (c))
    41 #define BITLBEE_VERSION_CODE BITLBEE_VER(3, 4, 0)
     41#define BITLBEE_VERSION_CODE BITLBEE_VER(3, 4, 1)
    4242
    4343#define MAX_STRING 511
     
    158158} global_t;
    159159
     160void sighandler_shutdown_setup(void);
     161
    160162int bitlbee_daemon_init(void);
    161163int bitlbee_inetd_init(void);
  • conf.c

    re4f08bf r29ff5c2  
    3737
    3838static int conf_loadini(conf_t *conf, char *file);
     39static void conf_free(conf_t *conf);
    3940
    4041conf_t *conf_load(int argc, char *argv[])
     
    7374        if (i == 0) {
    7475                fprintf(stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file);
     76                conf_free(conf);
    7577                return NULL;
    7678        } else if (i == -1) {
     
    104106                                g_free(global.conf_file);
    105107                                global.conf_file = g_strdup(optarg);
    106                                 g_free(conf);
     108                                conf_free(conf);
    107109                                /* Re-evaluate arguments. Don't use this option twice,
    108110                                   you'll end up in an infinite loop! Hope this trick
     
    135137                               "  -h  Show this help page.\n"
    136138                               "  -V  Show version info.\n");
     139                        conf_free(conf);
    137140                        return NULL;
    138141                } else if (opt == 'V') {
    139142                        printf("BitlBee %s\nAPI version %06x\n",
    140143                               BITLBEE_VERSION, BITLBEE_VERSION_CODE);
     144                        conf_free(conf);
    141145                        return NULL;
    142146                } else if (opt == 'u') {
     
    162166                   they're secure when in fact they're not. */
    163167                fprintf(stderr, "Error: Could not read CA file %s: %s\n", conf->cafile, strerror(errno));
     168                conf_free(conf);
    164169                return NULL;
    165170        }
    166171
    167172        return conf;
     173}
     174
     175static void conf_free(conf_t *conf)
     176{
     177        /* Free software means users have the four essential freedoms:
     178           0. to run the program,
     179           2. to study and change the program in source code form,
     180           2. to redistribute exact copies, and
     181           3. to distribute modified versions
     182        */
     183        g_free(conf->auth_pass);
     184        g_free(conf->cafile);
     185        g_free(conf->configdir);
     186        g_free(conf->ft_listen);
     187        g_free(conf->hostname);
     188        g_free(conf->iface_in);
     189        g_free(conf->iface_out);
     190        g_free(conf->motdfile);
     191        g_free(conf->oper_pass);
     192        g_free(conf->pidfile);
     193        g_free(conf->plugindir);
     194        g_free(conf->port);
     195        g_free(conf->primary_storage);
     196        g_free(conf->user);
     197        g_strfreev(conf->migrate_storage);
     198        g_strfreev(conf->protocols);
     199        g_free(conf);
     200
    168201}
    169202
     
    219252                                g_free(conf->configdir);
    220253                                conf->configdir = g_strdup(ini->value);
     254                        } else if (g_strcasecmp(ini->key, "plugindir") == 0) {
     255                                g_free(conf->plugindir);
     256                                conf->plugindir = g_strdup(ini->value);
    221257                        } else if (g_strcasecmp(ini->key, "motdfile") == 0) {
    222258                                g_free(conf->motdfile);
     
    259295                                } else if (url->proto == PROTO_SOCKS5) {
    260296                                        proxytype = PROXY_SOCKS5;
     297                                } else if (url->proto == PROTO_SOCKS4A) {
     298                                        proxytype = PROXY_SOCKS4A;
    261299                                }
    262300
  • configure

    re4f08bf r29ff5c2  
    2323pcdir='$prefix/lib/pkgconfig'
    2424systemlibdirs="/lib64 /usr/lib64 /usr/local/lib64 /lib /usr/lib /usr/local/lib"
     25sysroot=''
    2526
    2627# Set these to default-on to let it be overriden by either the user or purple
     
    5152pie=1
    5253
    53 arch=`uname -s`
    54 cpu=`uname -m`
     54arch=$(uname -s)
     55cpu=$(uname -m)
    5556
    5657GLIB_MIN_VERSION=2.16
     
    103104
    104105while [ -n "$1" ]; do
    105         e="`expr "X$1" : 'X--\(.*=.*\)'`"
     106        e="$(expr "X$1" : 'X--\(.*=.*\)')"
    106107        if [ -z "$e" ]; then
    107108                cat<<EOF
     
    149150
    150151--target=...    Cross compilation target                same as host
     152--sysroot=...   Cross compilation sysroot               $sysroot
    151153EOF
    152154                exit;
     
    157159
    158160# Expand $prefix and get rid of double slashes
    159 bindir=`eval echo "$bindir/" | sed 's/\/\{1,\}/\//g'`
    160 sbindir=`eval echo "$sbindir/" | sed 's/\/\{1,\}/\//g'`
    161 etcdir=`eval echo "$etcdir/" | sed 's/\/\{1,\}/\//g'`
    162 mandir=`eval echo "$mandir/" | sed 's/\/\{1,\}/\//g'`
    163 datadir=`eval echo "$datadir/" | sed 's/\/\{1,\}/\//g'`
    164 config=`eval echo "$config/" | sed 's/\/\{1,\}/\//g'`
    165 plugindir=`eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g'`
    166 includedir=`eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g'`
    167 libevent=`eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g'`
    168 
    169 pidfile=`eval echo "$pidfile" | sed 's/\/\{1,\}/\//g'`
    170 ipcsocket=`eval echo "$ipcsocket" | sed 's/\/\{1,\}/\//g'`
    171 pcdir=`eval echo "$pcdir" | sed 's/\/\{1,\}/\//g'`
     161bindir=$(eval echo "$bindir/" | sed 's/\/\{1,\}/\//g')
     162sbindir=$(eval echo "$sbindir/" | sed 's/\/\{1,\}/\//g')
     163etcdir=$(eval echo "$etcdir/" | sed 's/\/\{1,\}/\//g')
     164mandir=$(eval echo "$mandir/" | sed 's/\/\{1,\}/\//g')
     165datadir=$(eval echo "$datadir/" | sed 's/\/\{1,\}/\//g')
     166config=$(eval echo "$config/" | sed 's/\/\{1,\}/\//g')
     167plugindir=$(eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g')
     168includedir=$(eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g')
     169libevent=$(eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g')
     170
     171pidfile=$(eval echo "$pidfile" | sed 's/\/\{1,\}/\//g')
     172ipcsocket=$(eval echo "$ipcsocket" | sed 's/\/\{1,\}/\//g')
     173pcdir=$(eval echo "$pcdir" | sed 's/\/\{1,\}/\//g')
    172174
    173175protocols_mods=""
     
    240242
    241243if [ -n "$target" ]; then
    242         PKG_CONFIG_LIBDIR=/usr/$target/lib/pkgconfig
    243         export PKG_CONFIG_LIBDIR
    244         PATH=/usr/$target/bin:$PATH
     244        # prepend sysroot to system lib dirs
     245
     246        systemlibdirs_cross=''
     247        for i in $systemlibdirs; do
     248                systemlibdirs_cross="$systemlibdirs_cross $sysroot$i"
     249        done
     250        systemlibdirs=$systemlibdirs_cross
     251        unset systemlibdirs_cross
     252
     253        # backward compatibility
     254
     255        if [ -z "$PKG_CONFIG_LIBDIR" ]; then
     256                PKG_CONFIG_LIBDIR=/usr/$target/lib/pkgconfig
     257                export PKG_CONFIG_LIBDIR
     258        fi
     259
     260        if [ -d /usr/$target/bin ]; then
     261                PATH=/usr/$target/bin:$PATH
     262        fi
     263
     264        if [ -d /usr/$target/lib ]; then
     265                systemlibdirs="$systemlibdirs /usr/$target/lib"
     266        fi
     267
    245268        CC=$target-cc
    246269        LD=$target-ld
    247         systemlibdirs="/usr/$target/lib"
     270        STRIP=$target-strip
    248271fi
    249272
     
    308331        if $PKG_CONFIG glib-2.0 --atleast-version=$GLIB_MIN_VERSION; then
    309332                cat<<EOF >>Makefile.settings
    310 EFLAGS+=`$PKG_CONFIG --libs glib-2.0 gmodule-2.0`
    311 CFLAGS+=`$PKG_CONFIG --cflags glib-2.0 gmodule-2.0`
     333EFLAGS+=$($PKG_CONFIG --libs glib-2.0 gmodule-2.0)
     334CFLAGS+=$($PKG_CONFIG --cflags glib-2.0 gmodule-2.0)
    312335EOF
    313336        else
    314337                echo
    315                 echo 'Found glib2 '`$PKG_CONFIG glib-2.0 --modversion`', but version '$GLIB_MIN_VERSION' or newer is required.'
     338                echo 'Found glib2 '$($PKG_CONFIG glib-2.0 --modversion)', but version '$GLIB_MIN_VERSION' or newer is required.'
    316339                exit 1
    317340        fi
     
    349372        if $PKG_CONFIG --exists gnutls; then
    350373                cat <<EOF >>Makefile.settings
    351 EFLAGS+=`$PKG_CONFIG --libs gnutls` `libgcrypt-config --libs`
    352 CFLAGS+=`$PKG_CONFIG --cflags gnutls` `libgcrypt-config --cflags`
     374EFLAGS+=$($PKG_CONFIG --libs gnutls) $(libgcrypt-config --libs)
     375CFLAGS+=$($PKG_CONFIG --cflags gnutls) $(libgcrypt-config --cflags)
    353376EOF
    354377                ssl=gnutls
    355                 if ! pkg-config gnutls --atleast-version=2.8; then
     378                if ! $PKG_CONFIG gnutls --atleast-version=2.8; then
    356379                        echo
    357380                        echo 'Warning: With GnuTLS versions <2.8, certificate expire dates are not verified.'
     
    360383        elif libgnutls-config --version > /dev/null 2> /dev/null; then
    361384                cat <<EOF >>Makefile.settings
    362 EFLAGS+=`libgnutls-config --libs` `libgcrypt-config --libs`
    363 CFLAGS+=`libgnutls-config --cflags` `libgcrypt-config --cflags`
     385EFLAGS+=$(libgnutls-config --libs) $(libgcrypt-config --libs)
     386CFLAGS+=$(libgnutls-config --cflags) $(libgcrypt-config --cflags)
    364387EOF
    365388               
     
    375398        if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG nss; then
    376399                cat<<EOF >>Makefile.settings
    377 EFLAGS+=`$PKG_CONFIG --libs nss`
    378 CFLAGS+=`$PKG_CONFIG --cflags nss`
     400EFLAGS+=$($PKG_CONFIG --libs nss)
     401CFLAGS+=$($PKG_CONFIG --cflags nss)
    379402EOF
    380403               
     
    621644if [ -z "$systemdsystemunitdir" ]; then
    622645        if $PKG_CONFIG --exists systemd; then
    623                 systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd`
     646                systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
    624647        fi
    625648fi
     
    643666
    644667otrprefix=""
    645 for i in / /usr /usr/local; do
    646         if [ -f ${i}/lib/libotr.a ]; then
    647                 otrprefix=${i}
    648                 break
    649         fi
    650 done
    651668if [ "$otr" = "auto" ]; then
    652         if [ -n "$otrprefix" ]; then
    653                 otr=1
    654         else
    655                 otr=0
    656         fi
    657 fi
     669        ! $PKG_CONFIG --exists libotr
     670        otr=$?
     671fi
     672
     673if [ "$otr" != 0 ] && ! $PKG_CONFIG --atleast-version=4.0 --print-errors libotr; then
     674        exit 1
     675fi
     676
    658677if [ "$otr" = 1 ]; then
    659678        # BI == built-in
    660679        echo '#define OTR_BI' >> config.h
    661         echo "EFLAGS+=-L${otrprefix}/lib -lotr -lgcrypt" >> Makefile.settings
    662         echo "CFLAGS+=-I${otrprefix}/include" >> Makefile.settings
     680        echo "EFLAGS+=$($PKG_CONFIG --libs libotr) $(libgcrypt-config --libs)" >> Makefile.settings
     681        echo "CFLAGS+=$($PKG_CONFIG --cflags libotr) $(libgcrypt-config --cflags)" >> Makefile.settings
    663682        echo 'OTR_BI=otr.o' >> Makefile.settings
    664683elif [ "$otr" = "plugin" ]; then
     684        # for some mysterious reason beyond the comprehension of my mortal mind,
     685        # the libgcrypt flags aren't needed when building as plugin. add them anyway.
    665686        echo '#define OTR_PI' >> config.h
    666         echo "OTRFLAGS=-L${otrprefix}/lib -lotr" >> Makefile.settings
    667         echo "CFLAGS+=-I${otrprefix}/include" >> Makefile.settings
     687        echo "OTRFLAGS=$($PKG_CONFIG --libs libotr) $(libgcrypt-config --libs)" >> Makefile.settings
     688        echo "CFLAGS+=$($PKG_CONFIG --cflags libotr) $(libgcrypt-config --cflags)" >> Makefile.settings
    668689        echo 'OTR_PI=otr.so' >> Makefile.settings
    669 fi
    670 if [ "$otr" != 0 ] && ! pkg-config libotr --atleast-version=4.0; then
    671         echo
    672         echo 'WARNING: Your libotr seems to be old. BitlBee now needs at least libotr 4.0.'
    673         # Not hard-failing because the code above doesn't use pkg-config, so who knows
    674         # what's true at this point...
    675690fi
    676691
  • dcc.c

    re4f08bf r29ff5c2  
    265265                }
    266266
    267                 /* How likely is it that a 32-bit integer gets split accross
     267                /* How likely is it that a 32-bit integer gets split across
    268268                   packet boundaries? Chances are rarely 0 so let's be sure. */
    269269                if ((df->acked_len = (df->acked_len + ret) % 4) > 0) {
  • debian/changelog

    re4f08bf r29ff5c2  
    1 bitlbee (3.2.2-2) UNRELEASED; urgency=medium
     1bitlbee (3.4.1-1) unstable; urgency=medium
    22
    33  * Fix copyright info (Closes: #764181)
    4 
    5  -- Wilmer van der Gaast <wilmer@gaast.net>  Fri, 17 Oct 2014 23:25:33 +0100
     4  * "New" upstream release. Apologies for the delay.
     5  * Exclude .git not .bzr when building the source package.
     6
     7 -- Wilmer van der Gaast <wilmer@gaast.net>  Mon, 03 Aug 2015 22:33:25 +0100
    68
    79bitlbee (3.2.2-1) unstable; urgency=medium
  • debian/source/options

    re4f08bf r29ff5c2  
    1 --diff-ignore='(^|/)\.bzr'
     1--diff-ignore='(^|/)\.git'
  • doc/CHANGES

    re4f08bf r29ff5c2  
    33
    44https://github.com/bitlbee/bitlbee/commits/master
     5
     6Version 3.4.1:
     7- msn:
     8  * Upgraded protocol to MSNP21, works again (dx)
     9  * Contact list management, groupchats and skype username logins won't work.
     10    Next release!
     11- jabber:
     12  * Add "hipchat" protocol, for smoother login. Takes the same username as
     13    the official client. Note that unlike the 'hip-cat' branch, this doesn't
     14    preload channels. https://wiki.bitlbee.org/HowtoHipchat for details (dx)
     15  * Fixed a bug when receiving topics set by people who left the channel (dx)
     16  * Create fake users instead of showing "unknown participant" errors (dx)
     17  * Gmail mail notifications support (Artem Savkov)
     18  * Lowering xmpp presence priority on away (Artem Savkov)
     19- twitter:
     20  * Show quoted tweets/RTs with comment inline (wilmer)
     21  * Added "url" command, can be used to quote tweets (wilmer)
     22  * Make replies to self work (wilmer)
     23- Building documentation is now done with a python script (both 2.x/3.x work)
     24  Asciidoc/xsltproc/xmlto are no longer build dependencies (dx)
     25
     26Finished 16 Jun 2015
    527
    628Version 3.4:
     
    407429  officially be treated as case sensitive.
    408430- Fully stripping spaces from AIM screennames, this didn't happen completely
    409   which severly breaks the IRC protocol.
     431  which severely breaks the IRC protocol.
    410432- Removed all the yellow tape around daemon mode, it's pretty mature by now:
    411433  testing.bitlbee.org serves all (~30) SSL users from one daemon mode
     
    607629  some situations.
    608630- Outgoing MSN typing notifications are now understood correctly by the
    609   orignal MS Mac/Windows clients (again).
     631  original MS Mac/Windows clients (again).
    610632- Added "account add $protocol" to the documentation, got rid of a lot
    611633  of over-markup (i.e. overuse of bold-tags), reviewed some other parts.
  • doc/HACKING

    re4f08bf r29ff5c2  
    1414calls and arguments where that seemed useful, etc.
    1515
    16 However, up to late in the 1.2 series, the IRC core was still spread accross
     16However, up to late in the 1.2 series, the IRC core was still spread across
    1717several files, mostly irc.c + irc_commands.c and pieces and bits in
    1818nogaim.c. If you're looking for a textbook example of layer violation, start
  • doc/README

    re4f08bf r29ff5c2  
    88to set up the build system. If configure succeeds, run make to build BitlBee.
    99make install will move all the files to the right places.
     10
     11RUN MODES
     12=========
    1013
    1114--- (Fork)Daemon mode
     
    8992==================
    9093
    91 Cygwin NOTE: You'll need a glib installation to run BitlBee. However, Cygwin
    92 doesn't provide a glib package. You can download a binary tar.gz from:
    93 <http://my.dreamwiz.com/jbdoll/>. When you installed it, BitlBee should work
    94 fine. You'll probably like bitlbeed or xinetd to get it running on the
    95 network.
    96 
    97 On some non-Linux systems the program still suffers from some random bugs.
    98 Please do report them, we might be able to fix them if they're not too
    99 mysterious.
    100 
    101 Also, the configure script is known to not work very well with non-Bash
    102 shells, so if you experience problems, make sure you use bash to run the
    103 script. Same for the Makefile, it only works well with GNU make. (gmake on
    104 most BSD systems)
     94The configure script is may not work very well with some non-bash shells (but
     95dash is supported), so if you experience problems, make sure you use bash to
     96run the script. Same for the Makefile, it only works well with GNU make. (gmake
     97on most BSD systems)
    10598
    10699If someone can tell us how to write Makefiles that work with both/all
     
    153146=============================
    154147
    155 There used to be a note here about the simple obfuscation method used to
    156 make the passwords in the configuration files unreadable. However, BitlBee
    157 now uses a better format (and real encryption (salted MD5 and RC4)) to store
    158 the passwords. This means that people who somehow get their hands on your
    159 configuration files can't easily extract your passwords from them anymore.
     148BitlBee currently uses salted MD5 and RC4 to store the passwords. This means
     149that people who somehow get their hands on your configuration files can't
     150easily extract your passwords from them anymore.
    160151
    161152However, once you log into the BitlBee server and send your password, an
    162153intruder with tcpdump can still read your passwords. This can't really be
    163 avoided, of course. The new format is a lot more reliable (because it can't
    164 be cracked with just very basic crypto analysis anymore), but you still have
    165 to be careful. The main extra protection offered by the new format is that
    166 the files can only be cracked with some help from the user (by sending the
    167 password at login time).
    168 
    169 So if you run a public server, it's most important that you don't give root
    170 access to people who like to play with tcpdump. Also, it's a good idea to
    171 delete all *.nicks/*.accounts files as soon as BitlBee converted them to the
    172 new format (which happens as soon as the user logs in, it can't be done
    173 automatically because it needs the password for that account). You won't
    174 need them anymore (unless you want to switch back to an older BitlBee
    175 version) and they only make it easier for others to crack your passwords.
    176 
     154avoided, of course. So if you run a public server, it's most important that you
     155don't give root access to people who like to play with tcpdump.
    177156
    178157LEGAL
     
    181160BitlBee is distributed under the GPL (GNU General Public License). See the
    182161file COPYING for this license.
    183 
    184 The MD5 algorithm code is licensed under the Aladdin license. This license
    185 can be found in the files, to which this applies. The SHA1 algorithm code
    186 is licensed under the Mozilla Public License, see http://www.mozilla.org/MPL/
    187 for details.
    188162
    189163The Yahoo! library used by BitlBee is libyahoo2 <http://libyahoo2.sf.net/>,
  • doc/user-guide/Installation.xml

    re4f08bf r29ff5c2  
    7373<para>
    7474By default, BitlBee runs as the user nobody. You might want
    75 to run it as a seperate user (some computers run named or apache as nobody).
     75to run it as a separate user (some computers run named or apache as nobody).
    7676</para>
    7777
  • doc/user-guide/commands.xml

    re4f08bf r29ff5c2  
    182182                               
    183183                                <para>
    184                                         For more infomation about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>.
     184                                        For more information about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>.
    185185                                </para>
    186186                               
     
    240240                               
    241241                                <para>
    242                                         For more infomation about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>.
     242                                        For more information about a setting, see <emphasis>help set &lt;setting&gt;</emphasis>.
    243243                                </para>
    244244                               
     
    10931093                       
    10941094                        <para>
    1095                                 With modes "chat" and "many", you can send direct messages by /msg'ing your contacts directly. Note, however, that incoming DMs are not fetched yet.
     1095                                With modes "chat" and "many", you can send direct messages by /msg'ing your contacts directly. Incoming DMs are only fetched if the "stream" setting is on (default).
    10961096                        </para>
    10971097                       
     
    11861186        </bitlbee-setting>
    11871187
     1188        <bitlbee-setting name="anonymous" type="boolean" scope="account">
     1189                <default>false</default>
     1190
     1191                <description>
     1192                        <para>
     1193                                This enables SASL ANONYMOUS login for jabber accounts, as specified by XEP-0175.
     1194                        </para>
     1195
     1196                        <para>
     1197                                With this setting enabled, if the server allows this method, a password isn't required and the username part of the JID is ignored (you can use anonymous@jabber.example.com). Servers will usually assign you a random numeric username instead.
     1198                        </para>
     1199                </description>
     1200
     1201        </bitlbee-setting>
     1202
    11881203        <bitlbee-setting name="ops" type="string" scope="global">
    11891204                <default>both</default>
     
    13091324        </bitlbee-setting>
    13101325
     1326        <bitlbee-setting name="proxy" type="string" scope="account">
     1327                <default>&lt;local&gt;&lt;auto&gt;</default>
     1328
     1329                <description>
     1330                        <para>
     1331                                A list of <emphasis>file transfer proxies</emphasis> for jabber. This isn't the connection proxy. Sorry, look in bitlbee.conf for those.
     1332                        </para>
     1333
     1334                        <para>
     1335                                It's a semicolon-separated list of items that can be either <emphasis>JID,HOST,PORT</emphasis> or two special values, <emphasis>&lt;local&gt;</emphasis> (to try a direct connection first) and <emphasis>&lt;auto&gt;</emphasis> (to try to discover a proxy). For example, "&lt;local&gt;;proxy.somewhere.org,123.123.123.123,7777".
     1336                        </para>
     1337                        <para>
     1338                                The address should point to a SOCKS5 bytestreams server, usually provided by jabber servers. This is only used for sending files. Note that the host address might not match what DNS tells you, and the port isn't always the same.
     1339                        </para>
     1340                        <para>
     1341                                The correct way to get a socks proxy host/port is a mystery, and the file transfer might fail anyway. Maybe just try using dropbox instead.
     1342                        </para>
     1343                </description>
     1344        </bitlbee-setting>
     1345
    13111346        <bitlbee-setting name="query_order" type="string" scope="global">
    13121347                <default>lifo</default>
     
    13691404        </bitlbee-setting>
    13701405
     1406        <bitlbee-setting name="self_messages" type="string" scope="global">
     1407                <default>true</default>
     1408                <possible-values>true, false, prefix, prefix_notice</possible-values>
     1409
     1410                <description>
     1411                        <para>
     1412                                Change this setting to customize how (or whether) to show self-messages, which are messages sent by yourself from other locations (for example, mobile clients), for IM protocols that support it.
     1413                        </para>
     1414
     1415                        <para>
     1416                                When this is set to "true", it will send those messages in the "standard" way, which is a PRIVMSG with source and target fields swapped.
     1417                        </para>
     1418                       
     1419                        <para>
     1420                                Since this isn't very well supported by some clients (the messages might appear in the wrong window), you can set it to "prefix" to show them as a normal message prefixed with "-> ", or use "prefix_notice" which is the same thing but with a NOTICE instead.
     1421                        </para>
     1422
     1423                        <para>
     1424                                You can also set it to "false" to disable these messages completely.
     1425                        </para>
     1426
     1427                        <para>
     1428                                This setting only applies to private messages. Self messages in groupchats are always shown, since they haven't caused issues in any clients so far.
     1429                        </para>
     1430                </description>
     1431        </bitlbee-setting>
     1432
    13711433        <bitlbee-setting name="server" type="string" scope="account">
    13721434                <description>
     
    14021464
    14031465        <bitlbee-setting name="show_users" type="string" scope="channel">
    1404                 <default>online+,away</default>
     1466                <default>online+,special%,away</default>
    14051467
    14061468                <description>
     
    14091471                                and any modes they should have. The following statuses are currently
    14101472                                recognised: <emphasis>online</emphasis> (i.e. available, not
    1411                                 away), <emphasis>away</emphasis>, and <emphasis>offline</emphasis>.
     1473                                away), <emphasis>special</emphasis>, <emphasis>away</emphasis>,
     1474                                and <emphasis>offline</emphasis>.
    14121475                        </para>
    14131476                       
     
    14151478                                If a status is followed by a valid channel mode character
    14161479                                (@, % or +), it will be given to users with that status.
    1417                                 For example, <emphasis>online@,away+,offline</emphasis> will
    1418                                 show all users in the channel. Online people will
     1480                                For example, <emphasis>online@,special%,away+,offline</emphasis>
     1481                                will show all users in the channel. Online people will
    14191482                                have +o, people who are online but away will have +v,
    14201483                                and others will have no special modes.
     
    18761939
    18771940                        <description>
    1878                                 <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>
     1941                                <para>Rejects all incoming (not already transferring) file transfers. Since you probably have only one incoming transfer at a time, no id is necessary. Or is it?</para>
    18791942                        </description>
    18801943
  • doc/user-guide/misc.xml

    re4f08bf r29ff5c2  
    9090
    9191<para>
    92 Away states have different names accross different protocols. BitlBee will try to pick the best available option for every connection:
     92Away states have different names across different protocols. BitlBee will try to pick the best available option for every connection:
    9393</para>
    9494
     
    146146
    147147<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.
     148Control 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 across several channels.
    149149</para>
    150150
     
    433433</sect1>
    434434
     435<sect1 id="whatsnew030401">
     436<title>New stuff in BitlBee 3.4.1</title>
     437
     438<simplelist>
     439        <member><emphasis>msn:</emphasis> Upgraded protocol version to MSNP21, works again</member>
     440        <member><emphasis>jabber:</emphasis> Add "hipchat" protocol, for smoother login. Takes the same username as the official client. Note that unlike the 'hip-cat' branch, this doesn't preload channels. See the <emphasis>HowtoHipchat</emphasis> wiki page for details</member>
     441        <member><emphasis>jabber:</emphasis> Gmail notifications support</member>
     442        <member><emphasis>twitter:</emphasis> Show quoted tweets inline. Added "url" command, can be used to quote tweets.</member>
     443</simplelist>
     444
     445</sect1>
     446
    435447</chapter>
  • doc/user-guide/quickstart.xml

    re4f08bf r29ff5c2  
    1111
    1212<para>
    13 You need register so that all your IM settings (passwords, contacts, etc) can be saved on the BitlBee server. It's important that you pick a good password so no one else can access your account. Register with this password using the <emphasis>register</emphasis> command: <emphasis>register &lt;password&gt;</emphasis> (without the brackets!).
     13You need to register so that all your IM settings (passwords, contacts, etc) can be saved on the BitlBee server. It's important that you pick a good password so no one else can access your account. Register with this password using the <emphasis>register</emphasis> command: <emphasis>register &lt;password&gt;</emphasis> (without the brackets!).
    1414</para>
    1515
  • help.c

    re4f08bf r29ff5c2  
    146146                        if (lseek(h->fd, h->offset.file_offset, SEEK_SET) == -1 ||
    147147                            read(h->fd, s, h->length) != h->length) {
     148                                g_free(s);
    148149                                return NULL;
    149150                        }
  • ipc.c

    re4f08bf r29ff5c2  
    590590                                }
    591591
    592                                 *recv_fd = *(int *) CMSG_DATA(cmsg);
     592                                memcpy(recv_fd, CMSG_DATA(cmsg), sizeof(int));
    593593                                /*
    594594                                fprintf( stderr, "pid %d received fd %d\n", (int) getpid(), *recv_fd );
     
    758758        cmsg->cmsg_type = SCM_RIGHTS;
    759759        cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
    760         *(int *) CMSG_DATA(cmsg) = send_fd;
     760        memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(int));
    761761        msg.msg_controllen = cmsg->cmsg_len;
    762762#endif
  • irc.c

    re4f08bf r29ff5c2  
    129129        s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc);
    130130        s->flags |= SET_HIDDEN;
     131        s = set_add(&b->set, "self_messages", "true", set_eval_self_messages, irc);
    131132        s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc);
    132133        s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc);
     
    153154        set_eval_charset(set_find(&b->set, "charset"), set_getstr(&b->set, "charset"));
    154155
    155         irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on");
     156        irc_write(irc, ":%s NOTICE * :%s", irc->root->host, "BitlBee-IRCd initialized, please go on");
    156157        if (isatty(irc->fd)) {
    157                 irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host,
     158                irc_write(irc, ":%s NOTICE * :%s", irc->root->host,
    158159                          "If you read this, you most likely accidentally "
    159160                          "started BitlBee in inetd mode on the command line. "
     
    380381                                                conv = NULL;
    381382                                        } else {
    382                                                 irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host,
     383                                                irc_write(irc, ":%s NOTICE * :%s", irc->root->host,
    383384                                                          "Warning: invalid characters received at login time.");
    384385
     
    727728int irc_check_login(irc_t *irc)
    728729{
    729         if (irc->user->user && irc->user->nick) {
     730        if (irc->user->user && irc->user->nick && !(irc->status & USTATUS_CAP_PENDING)) {
    730731                if (global.conf->authmode == AUTHMODE_CLOSED && !(irc->status & USTATUS_AUTHORIZED)) {
    731732                        irc_send_num(irc, 464, ":This server is password-protected.");
  • irc.h

    re4f08bf r29ff5c2  
    4949        USTATUS_SHUTDOWN = 8,   /* Now used to indicate we're shutting down.
    5050                                   Currently just blocks irc_vawrite(). */
     51        USTATUS_CAP_PENDING = 16,
     52        USTATUS_SASL_PLAIN_PENDING = 32,
    5153
    5254        /* Not really status stuff, but other kinds of flags: For slightly
     
    6567} irc_status_t;
    6668
     69typedef enum {
     70        CAP_SASL = (1 << 0),
     71        CAP_MULTI_PREFIX = (1 << 1),
     72        CAP_EXTENDED_JOIN = (1 << 2),
     73        CAP_AWAY_NOTIFY = (1 << 3),
     74} irc_cap_flag_t;
     75
    6776struct irc_user;
    6877
     
    102111
    103112        struct bee *b;
     113        guint32 caps;
    104114} irc_t;
    105115
     
    305315gboolean irc_channel_name_hint(irc_channel_t *ic, const char *name);
    306316void irc_channel_update_ops(irc_channel_t *ic, char *value);
     317char irc_channel_user_get_prefix(irc_channel_user_t *icu);
    307318char *set_eval_irc_channel_ops(struct set *set, char *value);
    308319gboolean irc_channel_wants_user(irc_channel_t *ic, irc_user_t *iu);
     
    334345                                     irc_channel_user_flags_t old_flags, irc_channel_user_flags_t new_flags);
    335346void irc_send_invite(irc_user_t *iu, irc_channel_t *ic);
     347void irc_send_cap(irc_t *irc, char *subcommand, char *body);
     348void irc_send_away_notify(irc_user_t *iu);
    336349
    337350/* irc_user.c */
     
    347360char *set_eval_timezone(struct set *set, char *value);
    348361char *irc_format_timestamp(irc_t *irc, time_t msg_ts);
     362char *set_eval_self_messages(struct set *set, char *value);
    349363
    350364/* irc_im.c */
     
    352366void bee_irc_user_nick_reset(irc_user_t *iu);
    353367
     368/* irc_cap.c */
     369void irc_cmd_cap(irc_t *irc, char **cmd);
     370
    354371#endif
  • irc_channel.c

    re4f08bf r29ff5c2  
    429429}
    430430
     431char irc_channel_user_get_prefix(irc_channel_user_t *icu)
     432{
     433        if (icu->flags & IRC_CHANNEL_USER_OP) {
     434                return '@';
     435        } else if (icu->flags & IRC_CHANNEL_USER_HALFOP) {
     436                return '%';
     437        } else if (icu->flags & IRC_CHANNEL_USER_VOICE) {
     438                return '+';
     439        }
     440        return 0;
     441}
     442
    431443void irc_channel_auto_joins(irc_t *irc, account_t *acc)
    432444{
     
    445457                        char *acc_s;
    446458
    447                         if (!aj || (ic->flags & IRC_CHANNEL_JOINED)) {
    448                                 /* Only continue if this one's marked as auto_join
    449                                    or if we're in it already. (Possible if the
    450                                    client auto-rejoined it before identyfing.) */
     459                        if (!aj && !(ic->flags & IRC_CHANNEL_JOINED)) {
     460                                /* Only proceed if this one's marked as auto_join
     461                                   or if we're in it already. (Very likely the IRC
     462                                   client auto-(re)joining at reconnect time.) */
    451463                                continue;
    452464                        } else if (!(acc_s = set_getstr(&ic->set, "account"))) {
     
    593605
    594606        translit_name = g_convert_with_fallback(hint, -1, "ASCII//TRANSLIT", "UTF-8", "", NULL, &bytes_written, NULL);
     607
     608        if (!translit_name) {
     609                /* Same thing as in nick_gen() in nick.c, try again without //TRANSLIT */
     610                translit_name = g_convert_with_fallback(hint, -1, "ASCII", "UTF-8", "", NULL, &bytes_written, NULL);
     611        }
     612
     613        if (!translit_name) {
     614                return NULL;
     615        }
     616
    595617        if (bytes_written > MAX_NICK_LENGTH) {
    596618                translit_name[MAX_NICK_LENGTH] = '\0';
  • irc_commands.c

    re4f08bf r29ff5c2  
    2828#include "help.h"
    2929#include "ipc.h"
     30#include "base64.h"
    3031
    3132static void irc_cmd_pass(irc_t *irc, char **cmd)
     
    5556                irc_setpass(irc, cmd[1]);
    5657                irc_check_login(irc);
     58        }
     59}
     60
     61static gboolean irc_sasl_plain_parse(char *input, char **user, char **pass)
     62{
     63        int i, part, len;
     64        guint8 *decoded;
     65        char *parts[3];
     66
     67        /* bitlbee's base64_decode wrapper adds an extra null terminator at the end */
     68        len = base64_decode(input, &decoded);
     69
     70        /* this loop splits the decoded string into the parts array, like this:
     71           "username\0username\0password" -> {"username", "username", "password"} */
     72
     73        for (i = 0, part = 0; i < len && part < 3; part++) {
     74                /* set each of parts[] to point to the beginning of a string */
     75                parts[part] = (char *) decoded + i;
     76
     77                /* move the cursor forward to the next null terminator*/
     78                i += strlen(parts[part]) + 1;
     79        }
     80
     81        /* sanity checks */
     82        if (part != 3 || i != (len + 1) || (parts[0][0] && strcmp(parts[0], parts[1]) != 0)) {
     83                g_free(decoded);
     84                return FALSE;
     85        } else {
     86                *user = g_strdup(parts[1]);
     87                *pass = g_strdup(parts[2]);
     88                g_free(decoded);
     89                return TRUE;
     90        }
     91}
     92
     93static gboolean irc_sasl_check_pass(irc_t *irc, char *user, char *pass)
     94{
     95        storage_status_t status;
     96
     97        /* just check the password here to be able to reply with useful numerics
     98         * the actual identification will be handled later */
     99        status = storage_check_pass(user, pass);
     100
     101        if (status == STORAGE_OK) {
     102                if (!irc->user->nick) {
     103                        /* set the nick here so we have it for the following numeric */
     104                        irc->user->nick = g_strdup(user);
     105                }
     106                irc_send_num(irc, 903, ":Password accepted");
     107                return TRUE;
     108
     109        } else if (status == STORAGE_INVALID_PASSWORD) {
     110                irc_send_num(irc, 904, ":Incorrect password");
     111        } else if (status == STORAGE_NO_SUCH_USER) {
     112                irc_send_num(irc, 904, ":The nick is (probably) not registered");
     113        } else {
     114                irc_send_num(irc, 904, ":Unknown SASL authentication error");
     115        }
     116
     117        return FALSE;
     118}
     119
     120static void irc_cmd_authenticate(irc_t *irc, char **cmd)
     121{
     122        /* require the CAP to be enabled, and don't allow authentication before server password */
     123        if (!(irc->caps & CAP_SASL) ||
     124            (global.conf->authmode == AUTHMODE_CLOSED && !(irc->status & USTATUS_AUTHORIZED))) {
     125                return;
     126        }
     127
     128        if (irc->status & USTATUS_SASL_PLAIN_PENDING) {
     129                char *user, *pass;
     130
     131                irc->status &= ~USTATUS_SASL_PLAIN_PENDING;
     132
     133                if (!irc_sasl_plain_parse(cmd[1], &user, &pass)) {
     134                        irc_send_num(irc, 904, ":SASL authentication failed");
     135                        return;
     136                }
     137
     138                /* let's not support the nick != user case
     139                 * if NICK is received after SASL, it will just fail after registration */
     140                if (user && irc->user->nick && strcmp(user, irc->user->nick) != 0) {
     141                        irc_send_num(irc, 902, ":Your SASL username does not match your nickname");
     142
     143                } else if (irc_sasl_check_pass(irc, user, pass)) {
     144                        /* and here we do the same thing as the PASS command*/
     145                        if (irc->status & USTATUS_LOGGED_IN) {
     146                                char *send_cmd[] = { "identify", pass, NULL };
     147                                root_command(irc, send_cmd);
     148                        } else {
     149                                /* no check_login here - wait for CAP END */
     150                                irc_setpass(irc, pass);
     151                        }
     152                }
     153
     154                g_free(user);
     155                g_free(pass);
     156
     157        } else if (irc->status & USTATUS_IDENTIFIED) {
     158                irc_send_num(irc, 907, ":You have already authenticated");
     159
     160        } else if (strcmp(cmd[1], "*") == 0) {
     161                irc_send_num(irc, 906, ":SASL authentication aborted");
     162                irc->status &= ~USTATUS_SASL_PLAIN_PENDING;
     163
     164        } else if (g_strcasecmp(cmd[1], "PLAIN") == 0) {
     165                irc_write(irc, "AUTHENTICATE +");
     166                irc->status |= USTATUS_SASL_PLAIN_PENDING;
     167
     168        } else {
     169                irc_send_num(irc, 908, "PLAIN :is the available SASL mechanism");
     170                irc_send_num(irc, 904, ":SASL authentication failed");
     171                irc->status &= ~USTATUS_SASL_PLAIN_PENDING;
    57172        }
    58173}
     
    83198                        irc->status &= ~USTATUS_IDENTIFIED;
    84199                        irc_umode_set(irc, "-R", 1);
     200
     201                        if (irc->caps & CAP_SASL) {
     202                                irc_send_num(irc, 901, "%s!%s@%s :You are now logged out",
     203                                        irc->user->nick, irc->user->user, irc->user->host);
     204                        }
     205
    85206                        irc_rootmsg(irc, "Changing nicks resets your identify status. "
    86207                                    "Re-identify or register a new account if you want "
     
    685806
    686807static const command_t irc_commands[] = {
     808        { "cap",         1, irc_cmd_cap,         0 },
    687809        { "pass",        1, irc_cmd_pass,        0 },
    688810        { "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
     
    721843        { "restart",     0, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
    722844        { "kill",        2, NULL,                IRC_CMD_OPER_ONLY | IRC_CMD_TO_MASTER },
     845        { "authenticate", 1, irc_cmd_authenticate, 0 },
    723846        { NULL }
    724847};
  • irc_im.c

    re4f08bf r29ff5c2  
    118118        if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) {
    119119                iu->flags |= IRC_USER_AWAY;
     120        }
     121
     122        if ((irc->caps & CAP_AWAY_NOTIFY) &&
     123            ((bu->flags & BEE_USER_AWAY) != (old->flags & BEE_USER_AWAY) ||
     124             (bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE))) {
     125                irc_send_away_notify(iu);
    120126        }
    121127
     
    201207}
    202208
    203 static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at)
     209static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, guint32 flags, time_t sent_at)
    204210{
    205211        irc_t *irc = bee->ui_data;
    206212        irc_user_t *iu = (irc_user_t *) bu->ui_data;
     213        irc_user_t *src_iu = iu;
     214        irc_user_t *dst_iu = irc->user;
    207215        const char *dst;
    208216        char *prefix = NULL;
    209217        char *wrapped, *ts = NULL;
    210218        char *msg = g_strdup(msg_);
     219        char *message_type = "PRIVMSG";
    211220        GSList *l;
    212221
     
    216225
    217226        dst = irc_user_msgdest(iu);
    218         if (dst != irc->user->nick) {
    219                 /* if not messaging directly, call user by name */
    220                 prefix = g_strdup_printf("%s%s%s", irc->user->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
     227
     228        if (flags & OPT_SELFMESSAGE) {
     229                char *setting = set_getstr(&irc->b->set, "self_messages");
     230
     231                if (is_bool(setting)) {
     232                        if (bool2int(setting)) {
     233                                /* set to true, send it with src/dst flipped */
     234                               
     235                                dst_iu = iu;
     236                                src_iu = irc->user;
     237
     238                                if (dst == irc->user->nick) {
     239                                        dst = dst_iu->nick;
     240                                }
     241                        } else {
     242                                /* set to false, skip the message completely */
     243                                goto cleanup;
     244                        }
     245                } else if (g_strncasecmp(setting, "prefix", 6) == 0) {
     246                        /* third state, prefix, loosely imitates the znc privmsg_prefix module */
     247
     248                        g_free(msg);
     249                        if (g_strncasecmp(msg_, "/me ", 4) == 0) {
     250                                msg = g_strdup_printf("/me -> %s", msg_ + 4);
     251                        } else {
     252                                msg = g_strdup_printf("-> %s", msg_);
     253                        }
     254
     255                        if (g_strcasecmp(setting, "prefix_notice") == 0) {
     256                                message_type = "NOTICE";
     257                        }
     258                }
     259
     260        }
     261
     262        if (dst != dst_iu->nick) {
     263                /* if not messaging directly (control channel), call user by name */
     264                prefix = g_strdup_printf("%s%s%s", dst_iu->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
    221265        } else {
    222266                prefix = ts;
     
    249293
    250294        wrapped = word_wrap(msg, 425);
    251         irc_send_msg(iu, "PRIVMSG", dst, wrapped, prefix);
     295        irc_send_msg(src_iu, message_type, dst, wrapped, prefix);
    252296        g_free(wrapped);
    253297
     
    260304}
    261305
    262 static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, uint32_t flags)
     306static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, guint32 flags)
    263307{
    264308        irc_t *irc = (irc_t *) bee->ui_data;
     
    646690}
    647691
    648 static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at)
     692static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at)
    649693{
    650694        irc_t *irc = bee->ui_data;
    651         irc_user_t *iu = bu->ui_data;
     695        irc_user_t *iu = flags & OPT_SELFMESSAGE ? irc->user : bu->ui_data;
    652696        irc_channel_t *ic = c->ui_data;
    653697        char *wrapped, *ts = NULL;
     
    683727}
    684728
    685 static gboolean bee_irc_chat_remove_user(bee_t *bee, struct groupchat *c, bee_user_t *bu)
     729static gboolean bee_irc_chat_remove_user(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *reason)
    686730{
    687731        irc_t *irc = bee->ui_data;
     
    695739           using imcb_chat_free() and the channel was IRC_CHANNEL_TEMP, we get into
    696740           a broken state around here. */
    697         irc_channel_del_user(ic, bu == bee->user ? irc->user : bu->ui_data, IRC_CDU_PART, NULL);
     741        irc_channel_del_user(ic, bu == bee->user ? irc->user : bu->ui_data, IRC_CDU_PART, reason);
    698742
    699743        return TRUE;
     
    867911            (room = set_getstr(&ic->set, "room")) &&
    868912            (acc = account_get(ic->irc->b, acc_s)) &&
    869             acc->ic && acc->prpl->chat_join) {
     913            acc->ic && (acc->ic->flags & OPT_LOGGED_IN) &&
     914            acc->prpl->chat_join) {
    870915                char *nick;
    871916
     
    893938        }
    894939
    895         /* Remove the reference. We don't need it anymore. */
    896         ic->data = NULL;
     940        if (!(ic->flags & IRC_CHANNEL_TEMP)) {
     941                /* Remove the reference.
     942                 * We only need it for temp channels that are being freed */
     943                ic->data = NULL;
     944        }
    897945
    898946        return TRUE;
  • irc_send.c

    re4f08bf r29ff5c2  
    172172        irc_t *irc = ic->irc;
    173173
    174         irc_write(irc, ":%s!%s@%s JOIN :%s", iu->nick, iu->user, iu->host, ic->name);
     174        if (irc->caps & CAP_EXTENDED_JOIN) {
     175                irc_write(irc, ":%s!%s@%s JOIN %s * :%s", iu->nick, iu->user, iu->host, ic->name, iu->fullname);
     176        } else {
     177                irc_write(irc, ":%s!%s@%s JOIN :%s", iu->nick, iu->user, iu->host, ic->name);
     178        }
    175179
    176180        if (iu == irc->user) {
     
    214218                }
    215219
    216                 if (icu->flags & IRC_CHANNEL_USER_OP) {
    217                         strcat(namelist, "@");
    218                 } else if (icu->flags & IRC_CHANNEL_USER_HALFOP) {
    219                         strcat(namelist, "%");
    220                 } else if (icu->flags & IRC_CHANNEL_USER_VOICE) {
    221                         strcat(namelist, "+");
    222                 }
     220                namelist[strlen(namelist) + 1] = '\0';
     221                namelist[strlen(namelist)] = irc_channel_user_get_prefix(icu);
    223222
    224223                strcat(namelist, iu->nick);
     
    249248}
    250249
     250/* msg1 and msg2 are output parameters. If msg2 is non-null, msg1 is guaranteed to be non-null too.
     251   The idea is to defer the formatting of "$msg1 ($msg2)" to later calls to avoid a g_strdup_printf() here. */
     252static void get_status_message(bee_user_t *bu, char **msg1, char **msg2)
     253{
     254        *msg1 = NULL;
     255        *msg2 = NULL;
     256
     257        if (!(bu->flags & BEE_USER_ONLINE)) {
     258                *msg1 = "User is offline";
     259
     260        } else if ((bu->status && *bu->status) ||
     261                   (bu->status_msg && *bu->status_msg)) {
     262
     263                if (bu->status && bu->status_msg) {
     264                        *msg1 = bu->status;
     265                        *msg2 = bu->status_msg;
     266                } else {
     267                        *msg1 = bu->status ? : bu->status_msg;
     268                }
     269        }
     270
     271        if (*msg1 && !**msg1) {
     272                *msg1 = (bu->flags & BEE_USER_AWAY) ? "Away" : NULL;
     273        }
     274}
     275
    251276void irc_send_whois(irc_user_t *iu)
    252277{
     
    258283        if (iu->bu) {
    259284                bee_user_t *bu = iu->bu;
     285                char *msg1, *msg2;
     286                int num;
    260287
    261288                irc_send_num(irc, 312, "%s %s.%s :%s network", iu->nick, bu->ic->acc->user,
     
    263290                             bu->ic->acc->prpl->name);
    264291
    265                 if ((bu->status && *bu->status) ||
    266                     (bu->status_msg && *bu->status_msg)) {
    267                         int num = bu->flags & BEE_USER_AWAY ? 301 : 320;
    268 
    269                         if (bu->status && bu->status_msg) {
    270                                 irc_send_num(irc, num, "%s :%s (%s)", iu->nick, bu->status, bu->status_msg);
    271                         } else {
    272                                 irc_send_num(irc, num, "%s :%s", iu->nick, bu->status ? : bu->status_msg);
    273                         }
    274                 } else if (!(bu->flags & BEE_USER_ONLINE)) {
    275                         irc_send_num(irc, 301, "%s :%s", iu->nick, "User is offline");
     292                num = (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) ? 301 : 320;
     293
     294                get_status_message(bu, &msg1, &msg2);
     295
     296                if (msg1 && msg2) {
     297                        irc_send_num(irc, num, "%s :%s (%s)", iu->nick, msg1, msg2);
     298                } else if (msg1) {
     299                        irc_send_num(irc, num, "%s :%s", iu->nick, msg1);
    276300                }
    277301
     
    294318
    295319        while (l) {
    296                 irc_user_t *iu = l->data;
     320                irc_user_t *iu;
     321
     322                /* Null terminated string with three chars, respectively:
     323                 * { <H|G>, <@|%|+|\0>, \0 } */
     324                char status_prefix[3] = {0};
     325
    297326                if (is_channel) {
    298                         iu = ((irc_channel_user_t *) iu)->iu;
    299                 }
    300                 /* TODO(wilmer): Restore away/channel information here */
    301                 irc_send_num(irc, 352, "%s %s %s %s %s %c :0 %s",
     327                        irc_channel_user_t *icu = l->data;
     328                        status_prefix[1] = irc_channel_user_get_prefix(icu);
     329                        iu = icu->iu;
     330                } else {
     331                        iu = l->data;
     332                }
     333
     334                /* rfc1459 doesn't mention this: G means gone, H means here */
     335                status_prefix[0] = iu->flags & IRC_USER_AWAY ? 'G' : 'H';
     336
     337                irc_send_num(irc, 352, "%s %s %s %s %s %s :0 %s",
    302338                             is_channel ? channel : "*", iu->user, iu->host, irc->root->host,
    303                              iu->nick, iu->flags & IRC_USER_AWAY ? 'G' : 'H',
    304                              iu->fullname);
     339                             iu->nick, status_prefix, iu->fullname);
    305340                l = l->next;
    306341        }
     
    428463                  iu->nick, iu->user, iu->host, irc->user->nick, ic->name);
    429464}
     465
     466void irc_send_cap(irc_t *irc, char *subcommand, char *body)
     467{
     468        char *nick = irc->user->nick ? : "*";
     469
     470        irc_write(irc, ":%s CAP %s %s :%s", irc->root->host, nick, subcommand, body);
     471}
     472
     473void irc_send_away_notify(irc_user_t *iu)
     474{
     475        bee_user_t *bu = iu->bu;
     476
     477        if (!bu) {
     478                return;
     479        }
     480
     481        if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) {
     482                char *msg1, *msg2;
     483
     484                get_status_message(bu, &msg1, &msg2);
     485
     486                if (msg2) {
     487                        irc_write(iu->irc, ":%s!%s@%s AWAY :%s (%s)", iu->nick, iu->user, iu->host, msg1, msg2);
     488                } else {
     489                        irc_write(iu->irc, ":%s!%s@%s AWAY :%s", iu->nick, iu->user, iu->host, msg1);
     490                }
     491        } else {
     492                irc_write(iu->irc, ":%s!%s@%s AWAY", iu->nick, iu->user, iu->host);
     493        }
     494}
     495
  • irc_util.c

    re4f08bf r29ff5c2  
    119119        }
    120120}
     121
     122
     123char *set_eval_self_messages(set_t *set, char *value)
     124{
     125        if (is_bool(value) ||
     126            g_strcasecmp(value, "prefix") == 0 ||
     127            g_strcasecmp(value, "prefix_notice") == 0) {
     128                return value;
     129        } else {
     130                return SET_INVALID;
     131        }
     132}
  • lib/http_client.c

    re4f08bf r29ff5c2  
    162162        }
    163163
    164         req->func(req);
     164        if (req->func != NULL) {
     165                req->func(req);
     166        }
    165167        http_free(req);
    166168        return FALSE;
     
    299301        }
    300302
    301         req->func(req);
     303        if (req->func != NULL) {
     304                req->func(req);
     305        }
    302306        http_free(req);
    303307        return FALSE;
     
    412416        }
    413417
    414         if ((req->flags & HTTPC_STREAMING) && req->reply_body) {
     418        if ((req->flags & HTTPC_STREAMING) && req->reply_body && req->func != NULL) {
    415419                req->func(req);
    416420        }
     
    696700                ssl_disconnect(req->ssl);
    697701        } else {
    698                 closesocket(req->fd);
     702                proxy_disconnect(req->fd);
    699703        }
    700704
  • lib/json.c

    re4f08bf r29ff5c2  
    509509                                case ']':
    510510
    511                                         if (top->type == json_array) {
     511                                        if (top && top->type == json_array) {
    512512                                                flags = (flags & ~(flag_need_comma | flag_seek_value)) | flag_next;
    513513                                        } else {              sprintf(error, "%d:%d: Unexpected ]", cur_line, e_off);
  • lib/misc.c

    re4f08bf r29ff5c2  
    187187                                } else if (g_strncasecmp(cs + 1, "br", taglen) == 0) {
    188188                                        *(s++) = '\n';
     189                                } else if (g_strncasecmp(cs + 1, "br/", taglen) == 0) {
     190                                        *(s++) = '\n';
     191                                } else if (g_strncasecmp(cs + 1, "br /", taglen) == 0) {
     192                                        *(s++) = '\n';
    189193                                }
    190194                                in++;
     
    295299
    296300/* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */
    297 /* This fuction is safe, but make sure you call it safely as well! */
     301/* This function is safe, but make sure you call it safely as well! */
    298302void http_encode(char *s)
    299303{
  • lib/proxy.c

    re4f08bf r29ff5c2  
    5151#endif
    5252
     53static GHashTable *phb_hash = NULL;
     54
    5355struct PHB {
    5456        b_event_handler func, proxy_func;
     
    6163};
    6264
     65typedef int (*proxy_connect_func)(const char *host, unsigned short port_, struct PHB *phb);
     66
    6367static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb);
    6468
    65 static gboolean phb_close(struct PHB *phb)
    66 {
    67         close(phb->fd);
    68         phb->func(phb->data, -1, B_EV_IO_READ);
     69static gboolean phb_free(struct PHB *phb, gboolean success)
     70{
     71        g_hash_table_remove(phb_hash, &phb->fd);
     72
     73        if (!success) {
     74                if (phb->fd > 0) {
     75                        closesocket(phb->fd);
     76                }
     77                if (phb->func) {
     78                        phb->func(phb->data, -1, B_EV_IO_READ);
     79                }
     80        }
     81        if (phb->gai) {
     82                freeaddrinfo(phb->gai);
     83        }
    6984        g_free(phb->host);
    7085        g_free(phb);
     
    89104                                dup2(new_fd, source);
    90105                                closesocket(new_fd);
     106                                phb->fd = source;
    91107                                phb->inpa = b_input_add(source, B_EV_IO_WRITE, proxy_connected, phb);
    92108                                return FALSE;
     
    101117
    102118        freeaddrinfo(phb->gai);
     119        phb->gai = NULL;
     120
    103121        b_event_remove(phb->inpa);
    104122        phb->inpa = 0;
     123
    105124        if (phb->proxy_func) {
    106125                phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
    107126        } else {
    108127                phb->func(phb->data, source, B_EV_IO_READ);
    109                 g_free(phb);
     128                phb_free(phb, TRUE);
    110129        }
    111130
     
    171190
    172191        if (fd < 0 && host) {
    173                 g_free(phb);
     192                phb_free(phb, TRUE);
    174193        }
    175194
     
    204223            (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
    205224                phb->func(phb->data, source, B_EV_IO_READ);
    206                 g_free(phb->host);
    207                 g_free(phb);
    208                 return FALSE;
    209         }
    210 
    211         return phb_close(phb);
     225                return phb_free(phb, TRUE);
     226        }
     227
     228        return phb_free(phb, FALSE);
    212229}
    213230
     
    224241        len = sizeof(error);
    225242        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    226                 return phb_close(phb);
     243                return phb_free(phb, FALSE);
    227244        }
    228245        sock_make_blocking(source);
     
    231248                   phb->host, phb->port);
    232249        if (send(source, cmd, strlen(cmd), 0) < 0) {
    233                 return phb_close(phb);
     250                return phb_free(phb, FALSE);
    234251        }
    235252
     
    242259                g_free(t2);
    243260                if (send(source, cmd, strlen(cmd), 0) < 0) {
    244                         return phb_close(phb);
     261                        return phb_free(phb, FALSE);
    245262                }
    246263        }
     
    248265        g_snprintf(cmd, sizeof(cmd), "\r\n");
    249266        if (send(source, cmd, strlen(cmd), 0) < 0) {
    250                 return phb_close(phb);
     267                return phb_free(phb, FALSE);
    251268        }
    252269
     
    279296        if (read(source, packet, 9) >= 4 && packet[1] == 90) {
    280297                phb->func(phb->data, source, B_EV_IO_READ);
    281                 g_free(phb->host);
    282                 g_free(phb);
    283                 return FALSE;
    284         }
    285 
    286         return phb_close(phb);
     298                return phb_free(phb, TRUE);
     299        }
     300
     301        return phb_free(phb, FALSE);
    287302}
    288303
     
    294309        socklen_t len;
    295310        int error = ETIMEDOUT;
     311        gboolean is_socks4a = (proxytype == PROXY_SOCKS4A);
    296312
    297313        if (phb->inpa > 0) {
     
    300316        len = sizeof(error);
    301317        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    302                 return phb_close(phb);
     318                return phb_free(phb, FALSE);
    303319        }
    304320        sock_make_blocking(source);
    305321
    306         /* XXX does socks4 not support host name lookups by the proxy? */
    307         if (!(hp = gethostbyname(phb->host))) {
    308                 return phb_close(phb);
     322        if (!is_socks4a && !(hp = gethostbyname(phb->host))) {
     323                return phb_free(phb, FALSE);
    309324        }
    310325
     
    313328        packet[2] = phb->port >> 8;
    314329        packet[3] = phb->port & 0xff;
    315         packet[4] = (unsigned char) (hp->h_addr_list[0])[0];
    316         packet[5] = (unsigned char) (hp->h_addr_list[0])[1];
    317         packet[6] = (unsigned char) (hp->h_addr_list[0])[2];
    318         packet[7] = (unsigned char) (hp->h_addr_list[0])[3];
     330        if (is_socks4a) {
     331                packet[4] = 0;
     332                packet[5] = 0;
     333                packet[6] = 0;
     334                packet[7] = 1;
     335        } else {
     336                packet[4] = (unsigned char) (hp->h_addr_list[0])[0];
     337                packet[5] = (unsigned char) (hp->h_addr_list[0])[1];
     338                packet[6] = (unsigned char) (hp->h_addr_list[0])[2];
     339                packet[7] = (unsigned char) (hp->h_addr_list[0])[3];
     340        }
    319341        packet[8] = 0;
    320342        if (write(source, packet, 9) != 9) {
    321                 return phb_close(phb);
     343                return phb_free(phb, FALSE);
     344        }
     345
     346        if (is_socks4a) {
     347                size_t host_len = strlen(phb->host) + 1; /* include the \0 */
     348
     349                if (write(source, phb->host, host_len) != host_len) {
     350                        return phb_free(phb, FALSE);
     351                }
    322352        }
    323353
     
    348378
    349379        if (read(source, buf, 10) < 10) {
    350                 return phb_close(phb);
     380                return phb_free(phb, FALSE);
    351381        }
    352382        if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
    353                 return phb_close(phb);
     383                return phb_free(phb, FALSE);
    354384        }
    355385
    356386        phb->func(phb->data, source, B_EV_IO_READ);
    357         g_free(phb->host);
    358         g_free(phb);
    359 
    360         return FALSE;
     387        return phb_free(phb, TRUE);
    361388}
    362389
     
    377404
    378405        if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
    379                 phb_close(phb);
     406                phb_free(phb, FALSE);
    380407                return;
    381408        }
     
    392419
    393420        if (read(source, buf, 2) < 2) {
    394                 return phb_close(phb);
     421                return phb_free(phb, FALSE);
    395422        }
    396423
    397424        if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
    398                 return phb_close(phb);
     425                return phb_free(phb, FALSE);
    399426        }
    400427
     
    412439
    413440        if (read(source, buf, 2) < 2) {
    414                 return phb_close(phb);
     441                return phb_free(phb, FALSE);
    415442        }
    416443
    417444        if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
    418                 return phb_close(phb);
     445                return phb_free(phb, FALSE);
    419446        }
    420447
     
    427454                memcpy(buf + 2 + i + 1, proxypass, j);
    428455                if (write(source, buf, 3 + i + j) < 3 + i + j) {
    429                         return phb_close(phb);
     456                        return phb_free(phb, FALSE);
    430457                }
    431458
     
    451478        len = sizeof(error);
    452479        if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
    453                 return phb_close(phb);
     480                return phb_free(phb, FALSE);
    454481        }
    455482        sock_make_blocking(source);
     
    469496
    470497        if (write(source, buf, i) < i) {
    471                 return phb_close(phb);
     498                return phb_free(phb, FALSE);
    472499        }
    473500
     
    487514}
    488515
     516static const proxy_connect_func proxy_connect_funcs_array[] = {
     517        proxy_connect_none,   /* PROXY_NONE */
     518        proxy_connect_http,   /* PROXY_HTTP */
     519        proxy_connect_socks4, /* PROXY_SOCKS4 */
     520        proxy_connect_socks5, /* PROXY_SOCKS5 */
     521        proxy_connect_socks4, /* PROXY_SOCKS4A */
     522};
    489523
    490524/* Export functions */
     
    493527{
    494528        struct PHB *phb;
     529        proxy_connect_func fun;
     530        int fd;
     531
     532        if (!phb_hash) {
     533                phb_hash = g_hash_table_new(g_int_hash, g_int_equal);
     534        }
    495535
    496536        if (!host || port <= 0 || !func || strlen(host) > 128) {
     
    502542        phb->data = data;
    503543
    504         if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0) {
    505                 return proxy_connect_none(host, port, phb);
    506         } else if (proxytype == PROXY_HTTP) {
    507                 return proxy_connect_http(host, port, phb);
    508         } else if (proxytype == PROXY_SOCKS4) {
    509                 return proxy_connect_socks4(host, port, phb);
    510         } else if (proxytype == PROXY_SOCKS5) {
    511                 return proxy_connect_socks5(host, port, phb);
    512         }
    513 
    514         g_free(phb);
    515         return -1;
    516 }
     544        if (proxyhost[0] && proxyport > 0 && proxytype >= 0 && proxytype <= G_N_ELEMENTS(proxy_connect_funcs_array)) {
     545                fun = proxy_connect_funcs_array[proxytype];
     546        } else {
     547                fun = proxy_connect_none;
     548        }
     549
     550        fd = fun(host, port, phb);
     551
     552        if (fd != -1) {
     553                g_hash_table_insert(phb_hash, &phb->fd, phb);
     554        }
     555
     556        return fd;
     557}
     558
     559void proxy_disconnect(int fd)
     560{
     561        struct PHB *phb = g_hash_table_lookup(phb_hash, &fd);
     562
     563        if (!phb) {
     564                /* not in the early part of the connection - just close the fd */
     565                closesocket(fd);
     566                return;
     567        }
     568
     569        if (phb->inpa) {
     570                b_event_remove(phb->inpa);
     571                phb->inpa = 0;
     572        }
     573
     574        /* avoid calling the callback, which might result in double-free */
     575        phb->func = NULL;
     576
     577        /* close and free */
     578        phb_free(phb, FALSE);
     579}
  • lib/proxy.h

    re4f08bf r29ff5c2  
    4040#define PROXY_SOCKS4 2
    4141#define PROXY_SOCKS5 3
     42#define PROXY_SOCKS4A 4
    4243
    4344extern char proxyhost[128];
     
    4849
    4950G_MODULE_EXPORT int proxy_connect(const char *host, int port, b_event_handler func, gpointer data);
     51G_MODULE_EXPORT void proxy_disconnect(int fd);
    5052
    5153#endif /* _PROXY_H_ */
  • lib/ssl_gnutls.c

    re4f08bf r29ff5c2  
    455455        }
    456456
    457         closesocket(conn->fd);
     457        proxy_disconnect(conn->fd);
    458458
    459459        if (conn->session) {
  • lib/ssl_nss.c

    re4f08bf r29ff5c2  
    226226        if (conn->prfd) {
    227227                PR_Close(conn->prfd);
    228         }
    229         if (source >= 0) {
     228        } else if (source >= 0) {
     229                /* proxy_disconnect() would be redundant here */
    230230                closesocket(source);
    231231        }
     
    305305        if (conn->prfd) {
    306306                PR_Close(conn->prfd);
     307        } else if (conn->fd) {
     308                proxy_disconnect(conn->fd);
    307309        }
    308310
  • lib/ssl_openssl.c

    re4f08bf r29ff5c2  
    131131                conn->func(conn->data, 1, NULL, cond);
    132132                if (source >= 0) {
    133                         closesocket(source);
     133                        proxy_disconnect(source);
    134134                }
    135135                ssl_conn_free(conn);
     
    276276        }
    277277
    278         closesocket(conn->fd);
     278        proxy_disconnect(conn->fd);
    279279
    280280        ssl_conn_free(conn);
  • lib/url.c

    re4f08bf r29ff5c2  
    4848                } else if (g_strncasecmp(set_url, "socks5", i - set_url) == 0) {
    4949                        url->proto = PROTO_SOCKS5;
     50                } else if (g_strncasecmp(set_url, "socks4a", i - set_url) == 0) {
     51                        url->proto = PROTO_SOCKS4A;
    5052                } else {
    5153                        return 0;
  • lib/url.h

    re4f08bf r29ff5c2  
    3030#define PROTO_SOCKS4    3
    3131#define PROTO_SOCKS5    4
     32#define PROTO_SOCKS4A   5
    3233#define PROTO_DEFAULT   PROTO_HTTP
    3334
  • log.c

    re4f08bf r29ff5c2  
    5151void log_link(int level, int output)
    5252{
    53         /* I know it's ugly, but it works and I didn't feel like messing with pointer to function pointers */
     53        void (*output_function)(int level, const char *logmessage) = &log_null;
     54
     55        if (output == LOGOUTPUT_NULL) {
     56                output_function = &log_null;
     57        } else if (output == LOGOUTPUT_IRC) {
     58                output_function = &log_irc;
     59        } else if (output == LOGOUTPUT_SYSLOG) {
     60                output_function = &log_syslog;
     61        } else if (output == LOGOUTPUT_CONSOLE) {
     62                output_function = &log_console;
     63        }
    5464
    5565        if (level == LOGLVL_INFO) {
    56                 if (output == LOGOUTPUT_NULL) {
    57                         logoutput.informational = &log_null;
    58                 } else if (output == LOGOUTPUT_IRC) {
    59                         logoutput.informational = &log_irc;
    60                 } else if (output == LOGOUTPUT_SYSLOG) {
    61                         logoutput.informational = &log_syslog;
    62                 } else if (output == LOGOUTPUT_CONSOLE) {
    63                         logoutput.informational = &log_console;
    64                 }
     66                logoutput.informational = output_function;
    6567        } else if (level == LOGLVL_WARNING) {
    66                 if (output == LOGOUTPUT_NULL) {
    67                         logoutput.warning = &log_null;
    68                 } else if (output == LOGOUTPUT_IRC) {
    69                         logoutput.warning = &log_irc;
    70                 } else if (output == LOGOUTPUT_SYSLOG) {
    71                         logoutput.warning = &log_syslog;
    72                 } else if (output == LOGOUTPUT_CONSOLE) {
    73                         logoutput.warning = &log_console;
    74                 }
     68                logoutput.warning = output_function;
    7569        } else if (level == LOGLVL_ERROR) {
    76                 if (output == LOGOUTPUT_NULL) {
    77                         logoutput.error = &log_null;
    78                 } else if (output == LOGOUTPUT_IRC) {
    79                         logoutput.error = &log_irc;
    80                 } else if (output == LOGOUTPUT_SYSLOG) {
    81                         logoutput.error = &log_syslog;
    82                 } else if (output == LOGOUTPUT_CONSOLE) {
    83                         logoutput.error = &log_console;
    84                 }
     70                logoutput.error = output_function;
    8571        }
    8672#ifdef DEBUG
    8773        else if (level == LOGLVL_DEBUG) {
    88                 if (output == LOGOUTPUT_NULL) {
    89                         logoutput.debug = &log_null;
    90                 } else if (output == LOGOUTPUT_IRC) {
    91                         logoutput.debug = &log_irc;
    92                 } else if (output == LOGOUTPUT_SYSLOG) {
    93                         logoutput.debug = &log_syslog;
    94                 } else if (output == LOGOUTPUT_CONSOLE) {
    95                         logoutput.debug = &log_console;
    96                 }
     74                logoutput.debug = output_function;
    9775        }
    9876#endif
  • otr.c

    re4f08bf r29ff5c2  
    187187/* update op/voice flag of given user according to encryption state and settings
    188188   returns 0 if neither op_buddies nor voice_buddies is set to "encrypted",
    189    i.e. msgstate should be announced seperately */
     189   i.e. msgstate should be announced separately */
    190190int otr_update_modeflags(irc_t *irc, irc_user_t *u);
    191191
     
    216216void otr_disconnect_all(irc_t *irc);
    217217
     218/* modifies string in-place, replacing \x03 with '?',
     219   as a quick way to prevent remote users from messing with irc colors */
     220static char *otr_filter_colors(char *msg);
     221
    218222/* functions to be called for certain events */
    219223static const struct irc_plugin otr_plugin;
     224
     225#define OTR_COLOR_TRUSTED "03"     /* green */
     226#define OTR_COLOR_UNTRUSTED "05"   /* red */
    220227
    221228/*** routines declared in otr.h: ***/
     
    434441
    435442        /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
    436         if (ic->acc->prpl->options & OPT_NOOTR) {
     443        if (ic->acc->prpl->options & OPT_NOOTR ||
     444            iu->bu->flags & BEE_USER_NOOTR) {
    437445                return msg;
    438446        }
     
    451459        } else if (!newmsg) {
    452460                /* this was a non-OTR message */
    453                 return msg;
     461                return otr_filter_colors(msg);
    454462        } else {
    455463                /* we're done with the original msg, which will be caller-freed. */
     
    472480
    473481        /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */
    474         if (ic->acc->prpl->options & OPT_NOOTR) {
     482        if (ic->acc->prpl->options & OPT_NOOTR ||
     483            iu->bu->flags & BEE_USER_NOOTR) {
    475484                return msg;
    476485        }
     
    742751}
    743752
     753static char *otr_filter_colors(char *msg) {
     754        int i;
     755        for (i = 0; msg[i]; i++) {
     756                if (msg[i] == '\x02' || msg[i] == '\x03') {
     757                        msg[i] = '?';
     758                }
     759        }
     760        return msg;
     761}
     762
     763/* returns newly allocated string */
     764static char *otr_color_encrypted(char *msg, char *color, gboolean is_query) {
     765        char **lines;
     766        GString *out;
     767        int i;
     768
     769        lines = g_strsplit(msg, "\n", -1);
     770
     771        /* up to 4 extra chars per line (e.g., '\x03' + ("03"|"05") + ' ') */
     772        out = g_string_sized_new(strlen(msg) + g_strv_length(lines) * 4);
     773       
     774        for (i = 0; lines[i]; i++) {
     775                char *line = lines[i];
     776
     777                if (i != 0) {
     778                        g_string_append_c(out, '\n');
     779
     780                } else if (is_query && g_strncasecmp(line, "/me ", 4) == 0) {
     781                        /* in a query window, keep "/me " uncolored at the beginning */
     782                        line += 4;
     783                        g_string_append(out, "/me ");
     784                }
     785
     786                g_string_append_c(out, '\x03');
     787                g_string_append(out, color);
     788
     789                /* comma in first place could mess with the color code */
     790                if (line[0] == ',') {
     791                        /* insert a space between color spec and message */
     792                        g_string_append_c(out, ' ');
     793                }
     794
     795                g_string_append(out, otr_filter_colors(line));
     796        }
     797
     798        g_strfreev(lines);
     799
     800        return g_string_free(out, FALSE);
     801}
     802
    744803void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ,
    745804                    char **dst, const char *src)
     
    752811        if (typ == OTRL_CONVERT_RECEIVING) {
    753812                char *msg = g_strdup(src);
    754                 char *buf = msg;
    755813
    756814                /* HTML decoding */
     
    759817                    set_getbool(&ic->bee->set, "strip_html")) {
    760818                        strip_html(msg);
     819
     820                        /* msg is borrowed by *dst (unless the next if decides to color it) */
    761821                        *dst = msg;
    762822                }
     
    764824                /* coloring */
    765825                if (set_getbool(&ic->bee->set, "otr_color_encrypted")) {
    766                         int color;                /* color according to f'print trust */
    767                         char *pre = "", *sep = "";    /* optional parts */
    768826                        const char *trust = ctx->active_fingerprint->trust;
    769 
    770                         if (trust && trust[0] != '\0') {
    771                                 color = 3;   /* green */
    772                         } else {
    773                                 color = 5;   /* red */
    774 
    775                         }
    776                         /* in a query window, keep "/me " uncolored at the beginning */
    777                         if (g_strncasecmp(msg, "/me ", 4) == 0
    778                             && irc_user_msgdest(iu) == irc->user->nick) {
    779                                 msg += 4;  /* skip */
    780                                 pre = "/me ";
    781                         }
    782 
    783                         /* comma in first place could mess with the color code */
    784                         if (msg[0] == ',') {
    785                                 /* insert a space between color spec and message */
    786                                 sep = " ";
    787                         }
    788 
    789                         *dst = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre,
    790                                                color, sep, msg);
    791                         g_free(buf);
     827                        char *color = (trust && *trust) ? OTR_COLOR_TRUSTED : OTR_COLOR_UNTRUSTED;
     828                        gboolean is_query = (irc_user_msgdest(iu) == irc->user->nick);
     829
     830                        /* the return value of otr_color_encrypted() is borrowed by *dst */
     831                        *dst = otr_color_encrypted(msg, color, is_query);
     832
     833                        /* this branch doesn't need msg */
     834                        g_free(msg);
    792835                }
    793836        } else {
     
    13571400
    13581401        if (u) {
    1359                 /* display as a notice from this particular user */
    1360                 irc_usernotice(u, "%s", msg);
     1402                /* just show this as a regular message */
     1403                irc_usermsg(u, "<<\002OTR\002>> %s", msg);
    13611404        } else {
    13621405                irc_rootmsg(irc, "[otr] %s", msg);
     
    16951738        *p = '\0';
    16961739
     1740        /* remove trailing whitespace */
     1741        g_strchomp(prefix);
     1742
    16971743        /* find first key which matches the given prefix */
    16981744        n = strlen(prefix);
  • protocols/bee.h

    re4f08bf r29ff5c2  
    6262        BEE_USER_LOCAL = 256,   /* Locally-added contacts (not in real contact list) */
    6363        BEE_USER_SPECIAL = 512, /* Denotes a user as being special */
     64        BEE_USER_NOOTR = 4096,  /* Per-user version of OPT_NOOTR */
    6465} bee_user_flags_t;
    6566
     
    104105        gboolean (*user_status)(bee_t *bee, struct bee_user *bu, struct bee_user *old);
    105106        /* On every incoming message. sent_at = 0 means unknown. */
    106         gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at);
     107        gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
    107108        /* Flags currently defined (OPT_TYPING/THINKING) in nogaim.h. */
    108109        gboolean (*user_typing)(bee_t *bee, bee_user_t *bu, guint32 flags);
     
    119120        /* System messages of any kind. */
    120121        gboolean (*chat_log)(bee_t *bee, struct groupchat *c, const char *text);
    121         gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at);
     122        gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
    122123        gboolean (*chat_add_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu);
    123         gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu);
     124        gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *reason);
    124125        gboolean (*chat_topic)(bee_t *bee, struct groupchat *c, const char *new_topic, bee_user_t *bu);
    125126        gboolean (*chat_name_hint)(bee_t *bee, struct groupchat *c, const char *name);
  • protocols/bee_chat.c

    re4f08bf r29ff5c2  
    104104}
    105105
    106 void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at)
     106void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, guint32 flags, time_t sent_at)
    107107{
    108108        struct im_connection *ic = c->ic;
    109109        bee_t *bee = ic->bee;
    110110        bee_user_t *bu;
    111         gboolean temp;
     111        gboolean temp = FALSE;
    112112        char *s;
    113113
    114         /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
    115         if (handle_is_self(ic, who)) {
     114        if (handle_is_self(ic, who) && !(flags & OPT_SELFMESSAGE)) {
    116115                return;
    117116        }
     
    131130
    132131        if (bee->ui->chat_msg) {
    133                 bee->ui->chat_msg(bee, c, bu, msg, sent_at);
     132                bee->ui->chat_msg(bee, c, bu, msg, flags, sent_at);
    134133        }
    135134
     
    239238
    240239        if (bee->ui->chat_remove_user && bu) {
    241                 bee->ui->chat_remove_user(bee, c, bu);
     240                bee->ui->chat_remove_user(bee, c, bu, reason);
    242241        }
    243242}
  • protocols/bee_user.c

    re4f08bf r29ff5c2  
    247247}
    248248
    249 void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, uint32_t flags, time_t sent_at)
     249void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, guint32 flags, time_t sent_at)
    250250{
    251251        bee_t *bee = ic->bee;
     
    265265
    266266        if (bee->ui->user_msg && bu) {
    267                 bee->ui->user_msg(bee, bu, msg, sent_at);
     267                bee->ui->user_msg(bee, bu, msg, flags, sent_at);
    268268        } else {
    269269                imcb_log(ic, "Message from unknown handle %s:\n%s", handle, msg);
     
    297297}
    298298
    299 void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags)
     299void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags)
    300300{
    301301        bee_user_t *bu;
  • protocols/ft.h

    re4f08bf r29ff5c2  
    5858 *                                    | accept
    5959 *                                    V
    60  *                     /------ /-------------\                    /------------------------\
    61  *         out_of_data |       | TRANSFERING | -----------------> | TRANSFERING | CANCELED |
    62  *                     \-----> \-------------/  [canceled,]free   \------------------------/
     60 *                     /------ /-------------\                    /--------------------------\
     61 *         out_of_data |       | TRANSFERRING | -----------------> | TRANSFERRING | CANCELED |
     62 *                     \-----> \-------------/  [canceled,]free   \--------------------------/
    6363 *                                    |
    6464 *                                    | finished,free
    6565 *                                    V
    66  *                       /------------------------\
    67  *                       | TRANSFERING | FINISHED |
    68  *                       \------------------------/
     66 *                       /-------------------------\
     67 *                       | TRANSFERRING | FINISHED |
     68 *                       \-------------------------/
    6969 */
    7070typedef struct file_transfer {
     
    115115
    116116        /*
    117          * If set, called after succesful connection setup.
     117         * If set, called after successful connection setup.
    118118         */
    119119        void (*accept)(struct file_transfer *file);
  • protocols/jabber/conference.c

    re4f08bf r29ff5c2  
    2626
    2727static xt_status jabber_chat_join_failed(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
     28static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    2829
    2930struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password)
     
    127128}
    128129
     130static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)
     131{
     132        /* This is a self message sent by this bitlbee - just drop it */
     133        return XT_ABORT;
     134}
     135
    129136struct groupchat *jabber_chat_by_jid(struct im_connection *ic, const char *name)
    130137{
     
    171178        node = jabber_make_packet("message", "groupchat", jc->name, node);
    172179
    173         if (!jabber_write_packet(ic, node)) {
    174                 xt_free_node(node);
    175                 return 0;
    176         }
    177         xt_free_node(node);
    178 
    179         return 1;
     180        jabber_cache_add(ic, node, jabber_chat_self_message);
     181
     182        return !jabber_write_packet(ic, node);
    180183}
    181184
     
    299302                                        }
    300303                                }
    301 
    302                                 /* Some program-specific restrictions. */
    303                                 imcb_clean_handle(ic, bud->ext_jid);
    304304                        }
    305305                        bud->flags |= JBFLAG_IS_ANONYMOUS;
     
    331331        } else if (type) { /* type can only be NULL or "unavailable" in this function */
    332332                if ((bud->flags & JBFLAG_IS_CHATROOM) && bud->ext_jid) {
     333                        char *reason = NULL;
     334                        char *status = NULL;
     335                        char *status_text = NULL;
     336                       
     337                        if ((c = xt_find_node_by_attr(node->children, "x", "xmlns", XMLNS_MUC_USER))) {
     338                                struct xt_node *c2 = c->children;
     339
     340                                while ((c2 = xt_find_node(c2, "status"))) {
     341                                        char *code = xt_find_attr(c2, "code");
     342                                        if (g_strcmp0(code, "301") == 0) {
     343                                                status = "Banned";
     344                                                break;
     345                                        } else if (g_strcmp0(code, "303") == 0) {
     346                                                /* This could be handled in a cleverer way,
     347                                                 * but let's just show a literal part/join for now */
     348                                                status = "Changing nicks";
     349                                                break;
     350                                        } else if (g_strcmp0(code, "307") == 0) {
     351                                                status = "Kicked";
     352                                                break;
     353                                        }
     354                                        c2 = c2->next;
     355                                }
     356
     357                                /* Sometimes the status message is in presence/x/item/reason */
     358                                if ((c2 = xt_find_path(c, "item/reason")) && c2->text && c2->text_len) {
     359                                        status_text = c2->text;
     360                                }
     361                        }
     362
     363                        /* Sometimes the status message is right inside <presence> */
     364                        if ((c = xt_find_node(node->children, "status")) && c->text && c->text_len) {
     365                                status_text = c->text;
     366                        }
     367
     368                        if (status_text && status) {
     369                                reason = g_strdup_printf("%s: %s", status, status_text);
     370                        } else {
     371                                reason = g_strdup(status_text ? : status);
     372                        }
     373
    333374                        s = strchr(bud->ext_jid, '/');
    334375                        if (s) {
    335376                                *s = 0;
    336377                        }
    337                         imcb_chat_remove_buddy(chat, bud->ext_jid, NULL);
     378                        imcb_chat_remove_buddy(chat, bud->ext_jid, reason);
    338379                        if (bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS) {
    339                                 imcb_remove_buddy(ic, bud->ext_jid, NULL);
     380                                imcb_remove_buddy(ic, bud->ext_jid, reason);
    340381                        }
    341382                        if (s) {
    342383                                *s = '/';
    343384                        }
     385
     386                        g_free(reason);
    344387                }
    345388
     
    360403        char *final_from = NULL;
    361404        char *bare_jid = NULL;
     405        guint32 flags = 0;
    362406
    363407        from = (bud) ? bud->full_jid : xt_find_attr(node, "from");
     
    396440
    397441        if (subject && chat) {
    398                 char *subject_text = subject->text_len > 0 ? subject->text : NULL;
     442                char *subject_text = subject->text_len > 0 ? subject->text : "";
    399443                if (g_strcmp0(chat->topic, subject_text) != 0) {
    400444                        bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL;
     
    402446                                        jabber_get_timestamp(node));
    403447                        g_free(bare_jid);
     448                        bare_jid = NULL;
    404449                }
    405450        }
     
    422467                imcb_chat_log(chat, "From conference server: %s", body->text);
    423468                return;
    424         } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me) {
    425                 /* exclude self-messages since they would get filtered out
    426                  * but not the ones in the backlog */
     469        } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me &&
     470                   (jabber_cache_handle_packet(ic, node) == XT_ABORT)) {
     471                /* Self message marked by this bitlbee, don't show it */
    427472                return;
    428473        }
    429474
    430         if (bud && jc && bud != jc->me) {
     475        if (bud) {
    431476                bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid);
    432477                final_from = bare_jid;
     478                flags = (bud == jc->me) ? OPT_SELFMESSAGE : 0;
    433479        } else {
    434480                final_from = nick;
    435481        }
    436482
    437         imcb_chat_msg(chat, final_from, body->text, 0, jabber_get_timestamp(node));
     483        imcb_chat_msg(chat, final_from, body->text, flags, jabber_get_timestamp(node));
    438484
    439485        g_free(bare_jid);
  • protocols/jabber/io.c

    re4f08bf r29ff5c2  
    147147}
    148148
    149 static gboolean jabber_read_callback(gpointer data, gint fd, b_input_condition cond)
    150 {
    151         struct im_connection *ic = data;
    152         struct jabber_data *jd = ic->proto_data;
    153         char buf[512];
    154         int st;
    155 
    156         if (jd->fd == -1) {
    157                 return FALSE;
    158         }
    159 
    160         if (jd->ssl) {
    161                 st = ssl_read(jd->ssl, buf, sizeof(buf));
    162         } else {
    163                 st = read(jd->fd, buf, sizeof(buf));
    164         }
    165 
    166         if (st > 0) {
    167                 /* Parse. */
    168                 if (xt_feed(jd->xt, buf, st) < 0) {
     149static gboolean jabber_feed_input(struct im_connection *ic, char *buf, int size)
     150{
     151        struct jabber_data *jd = ic->proto_data;
     152
     153        /* Allow not passing a size for debugging purposes.
     154         * This never happens when reading from the socket */
     155        if (size == -1) {
     156                size = strlen(buf);
     157        }
     158
     159        /* Parse. */
     160        if (xt_feed(jd->xt, buf, size) < 0) {
     161                imcb_error(ic, "XML stream error");
     162                imc_logout(ic, TRUE);
     163                return FALSE;
     164        }
     165
     166        /* Execute all handlers. */
     167        if (!xt_handle(jd->xt, NULL, 1)) {
     168                /* Don't do anything, the handlers should have
     169                   aborted the connection already. */
     170                return FALSE;
     171        }
     172
     173        if (jd->flags & JFLAG_STREAM_RESTART) {
     174                jd->flags &= ~JFLAG_STREAM_RESTART;
     175                jabber_start_stream(ic);
     176        }
     177
     178        /* Garbage collection. */
     179        xt_cleanup(jd->xt, NULL, 1);
     180
     181        /* This is a bit hackish, unfortunately. Although xmltree
     182           has nifty event handler stuff, it only calls handlers
     183           when nodes are complete. Since the server should only
     184           send an opening <stream:stream> tag, we have to check
     185           this by hand. :-( */
     186        if (!(jd->flags & JFLAG_STREAM_STARTED) && jd->xt && jd->xt->root) {
     187                if (g_strcasecmp(jd->xt->root->name, "stream:stream") == 0) {
     188                        jd->flags |= JFLAG_STREAM_STARTED;
     189
     190                        /* If there's no version attribute, assume
     191                           this is an old server that can't do SASL
     192                           authentication. */
     193                        if (!set_getbool(&ic->acc->set, "sasl") || !sasl_supported(ic)) {
     194                                /* If there's no version= tag, we suppose
     195                                   this server does NOT implement: XMPP 1.0,
     196                                   SASL and TLS. */
     197                                if (set_getbool(&ic->acc->set, "tls")) {
     198                                        imcb_error(ic, "TLS is turned on for this "
     199                                                   "account, but is not supported by this server");
     200                                        imc_logout(ic, FALSE);
     201                                        return FALSE;
     202                                } else {
     203                                        if (!jabber_init_iq_auth(ic)) {
     204                                                return FALSE;
     205                                        }
     206                                }
     207                        }
     208                } else {
    169209                        imcb_error(ic, "XML stream error");
    170210                        imc_logout(ic, TRUE);
    171211                        return FALSE;
    172212                }
    173 
    174                 /* Execute all handlers. */
    175                 if (!xt_handle(jd->xt, NULL, 1)) {
    176                         /* Don't do anything, the handlers should have
    177                            aborted the connection already. */
     213        }
     214
     215        return TRUE;
     216}
     217
     218
     219static gboolean jabber_read_callback(gpointer data, gint fd, b_input_condition cond)
     220{
     221        struct im_connection *ic = data;
     222        struct jabber_data *jd = ic->proto_data;
     223        char buf[512];
     224        int st;
     225
     226        if (jd->fd == -1) {
     227                return FALSE;
     228        }
     229
     230        if (jd->ssl) {
     231                st = ssl_read(jd->ssl, buf, sizeof(buf));
     232        } else {
     233                st = read(jd->fd, buf, sizeof(buf));
     234        }
     235
     236        if (st > 0) {
     237                if (!jabber_feed_input(ic, buf, st)) {
    178238                        return FALSE;
    179                 }
    180 
    181                 if (jd->flags & JFLAG_STREAM_RESTART) {
    182                         jd->flags &= ~JFLAG_STREAM_RESTART;
    183                         jabber_start_stream(ic);
    184                 }
    185 
    186                 /* Garbage collection. */
    187                 xt_cleanup(jd->xt, NULL, 1);
    188 
    189                 /* This is a bit hackish, unfortunately. Although xmltree
    190                    has nifty event handler stuff, it only calls handlers
    191                    when nodes are complete. Since the server should only
    192                    send an opening <stream:stream> tag, we have to check
    193                    this by hand. :-( */
    194                 if (!(jd->flags & JFLAG_STREAM_STARTED) && jd->xt && jd->xt->root) {
    195                         if (g_strcasecmp(jd->xt->root->name, "stream:stream") == 0) {
    196                                 jd->flags |= JFLAG_STREAM_STARTED;
    197 
    198                                 /* If there's no version attribute, assume
    199                                    this is an old server that can't do SASL
    200                                    authentication. */
    201                                 if (!set_getbool(&ic->acc->set, "sasl") || !sasl_supported(ic)) {
    202                                         /* If there's no version= tag, we suppose
    203                                            this server does NOT implement: XMPP 1.0,
    204                                            SASL and TLS. */
    205                                         if (set_getbool(&ic->acc->set, "tls")) {
    206                                                 imcb_error(ic, "TLS is turned on for this "
    207                                                            "account, but is not supported by this server");
    208                                                 imc_logout(ic, FALSE);
    209                                                 return FALSE;
    210                                         } else {
    211                                                 return jabber_init_iq_auth(ic);
    212                                         }
    213                                 }
    214                         } else {
    215                                 imcb_error(ic, "XML stream error");
    216                                 imc_logout(ic, TRUE);
    217                                 return FALSE;
    218                         }
    219239                }
    220240        } else if (st == 0 || (st < 0 && !ssl_sockerr_again(jd->ssl))) {
  • protocols/jabber/iq.c

    re4f08bf r29ff5c2  
    385385        struct xt_node *response;
    386386        struct jabber_data *jd = ic->proto_data;
    387 
    388         response = jabber_make_packet("iq", "result", g_strdup_printf("%s@%s", jd->username, jd->server), NULL);
     387       
     388        response = jabber_make_packet("iq", "result", jd->me, NULL);
    389389
    390390        jabber_cache_add(ic, response, NULL);
  • protocols/jabber/jabber.c

    re4f08bf r29ff5c2  
    8585                set_setstr(&acc->set, "server", "chat.hipchat.com");
    8686        } else {
    87                 s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
     87                set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
     88
     89                /* this reuses set_eval_oauth, which clears the password */
     90                set_add(&acc->set, "anonymous", "false", set_eval_oauth, acc);
    8891        }
    8992
     
    194197        } else {
    195198                jabber_connect(ic);
     199        }
     200}
     201
     202static void jabber_xmlconsole_enable(struct im_connection *ic)
     203{
     204        struct jabber_data *jd = ic->proto_data;
     205        const char *handle = JABBER_XMLCONSOLE_HANDLE;
     206        bee_user_t *bu;
     207       
     208        jd->flags |= JFLAG_XMLCONSOLE;
     209
     210        if (!(bu = bee_user_by_handle(ic->bee, ic, handle))) {
     211                bu = bee_user_new(ic->bee, ic, handle, 0);
     212                bu->flags |= BEE_USER_NOOTR;
    196213        }
    197214}
     
    263280
    264281        if (set_getbool(&acc->set, "xmlconsole")) {
    265                 jd->flags |= JFLAG_XMLCONSOLE;
    266                 /* Shouldn't really do this at this stage already, maybe. But
    267                    I think this shouldn't break anything. */
    268                 imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL);
     282                jabber_xmlconsole_enable(ic);
    269283        }
    270284
     
    331345        }
    332346        if (jd->fd >= 0) {
    333                 closesocket(jd->fd);
     347                proxy_disconnect(jd->fd);
    334348        }
    335349
     
    342356        }
    343357
    344         jabber_buddy_remove_all(ic);
     358        if (jd->buddies) {
     359                jabber_buddy_remove_all(ic);
     360        }
    345361
    346362        xt_free(jd->xt);
     
    469485static void jabber_add_buddy(struct im_connection *ic, char *who, char *group)
    470486{
    471         struct jabber_data *jd = ic->proto_data;
    472 
    473487        if (g_strcasecmp(who, JABBER_XMLCONSOLE_HANDLE) == 0) {
    474                 jd->flags |= JFLAG_XMLCONSOLE;
    475                 imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL);
     488                jabber_xmlconsole_enable(ic);
    476489                return;
    477490        }
     
    587600{
    588601        struct jabber_data *jd = ic->proto_data;
    589         struct jabber_buddy *bud;
     602        struct jabber_buddy *bud, *bare;
    590603
    591604        /* Enable typing notification related code from now. */
    592605        jd->flags |= JFLAG_WANT_TYPING;
    593606
    594         if ((bud = jabber_buddy_by_jid(ic, who, 0)) == NULL) {
     607        if ((bud = jabber_buddy_by_jid(ic, who, 0)) == NULL ||
     608            (bare = jabber_buddy_by_jid(ic, who, GET_BUDDY_BARE)) == NULL) {
    595609                /* Sending typing notifications to unknown buddies is
    596610                   unsupported for now. Shouldn't be a problem, I think. */
     
    598612        }
    599613
    600         if (bud->flags & JBFLAG_DOES_XEP85) {
     614
     615        if (bud->flags & JBFLAG_DOES_XEP85 || bare->flags & JBFLAG_DOES_XEP85) {
    601616                /* We're only allowed to send this stuff if we know the other
    602                    side supports it. */
     617                   side supports it. If the bare JID has the flag, all other
     618                   resources get it, too (That is the case in gtalk) */
    603619
    604620                struct xt_node *node;
  • protocols/jabber/jabber_util.c

    re4f08bf r29ff5c2  
    514514                } else if (bud->resource && (flags & GET_BUDDY_EXACT)) {
    515515                        /* We want an exact match, so in thise case there shouldn't be a /resource. */
    516                         return NULL;
     516                        if (head != bud && head->resource == NULL) {
     517                                return head;
     518                        } else {
     519                                return NULL;
     520                        }
    517521                } else if (bud->resource == NULL || bud->next == NULL) {
    518522                        /* No need for selection if there's only one option. */
  • protocols/jabber/message.c

    re4f08bf r29ff5c2  
    3737        if (!from) {
    3838                return XT_HANDLED; /* Consider this packet corrupted. */
     39        }
    3940
    40         }
    41         if (request && id) {
     41        if (request && id && g_strcmp0(type, "groupchat") != 0) {
    4242                /* Send a message receipt (XEP-0184), looking like this:
    43                  * <message
    44                  *  from='kingrichard@royalty.england.lit/throne'
    45                  *  id='bi29sg183b4v'
    46                  *  to='northumberland@shakespeare.lit/westminster'>
     43                 * <message from='...' id='...' to='...'>
    4744                 *  <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/>
    48                  * </message> */
     45                 * </message>
     46                 *
     47                 * MUC messages are excluded, since receipts aren't supposed to be sent over MUCs
     48                 * (XEP-0184 section 5.3) and replying to those may result in 'forbidden' errors.
     49                 */
    4950                struct xt_node *received, *receipt;
    5051
     
    142143                        imcb_buddy_typing(ic, from, OPT_TYPING);
    143144                }
    144                 /* No need to send a "stopped typing" signal when there's a message. */
    145                 else if (xt_find_node(node->children, "active") && (body == NULL)) {
     145                else if (xt_find_node(node->children, "active")) {
    146146                        bud->flags |= JBFLAG_DOES_XEP85;
    147                         imcb_buddy_typing(ic, from, 0);
     147
     148                        /* No need to send a "stopped typing" signal when there's a message. */
     149                        if (body == NULL) {
     150                                imcb_buddy_typing(ic, from, 0);
     151                        }
    148152                } else if (xt_find_node(node->children, "paused")) {
    149153                        bud->flags |= JBFLAG_DOES_XEP85;
  • protocols/jabber/s5bytestream.c

    re4f08bf r29ff5c2  
    8585                return jabber_bs_abort(bt, msg ": %s", strerror(errno)); }
    8686
    87 gboolean jabber_bs_abort(struct bs_transfer *bt, char *format, ...);
     87gboolean jabber_bs_abort(struct bs_transfer *bt, char *format, ...) G_GNUC_PRINTF(2, 3);
    8888void jabber_bs_canceled(file_transfer_t *ft, char *reason);
    8989void jabber_bs_free_transfer(file_transfer_t *ft);
     
    536536                 * that sends atyp=0 addrlen=0 and only 6 bytes (one less than one would expect).
    537537                 * Therefore I removed the wait for more bytes. Since we don't care about what else the proxy
    538                  * is sending, it shouldnt matter */
     538                 * is sending, it should not matter */
    539539
    540540                if (bt->tf->ft->sending) {
     
    559559 * An intelligent sender would probably specify himself as the first streamhost and
    560560 * a proxy as the second (Kopete and PSI are examples here). That way, a (potentially)
    561  * slow proxy is only used if neccessary. This of course also means, that the timeout
     561 * slow proxy is only used if necessary. This of course also means, that the timeout
    562562 * per streamhost should be kept short. If one or two firewalled adresses are specified,
    563563 * they have to timeout first before a proxy is tried.
  • protocols/jabber/sasl.c

    re4f08bf r29ff5c2  
    5454        struct xt_node *c, *reply;
    5555        char *s;
    56         int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0;
    57         int want_oauth = FALSE, want_hipchat = FALSE;
     56        int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0, sup_anonymous = 0;
     57        int want_oauth = FALSE, want_hipchat = FALSE, want_anonymous = FALSE;
    5858        GString *mechs;
    5959
     
    7474        }
    7575
     76        want_anonymous = set_getbool(&ic->acc->set, "anonymous");
    7677        want_oauth = set_getbool(&ic->acc->set, "oauth");
    7778        want_hipchat = (jd->flags & JFLAG_HIPCHAT);
     
    8485                } else if (c->text && g_strcasecmp(c->text, "DIGEST-MD5") == 0) {
    8586                        sup_digest = 1;
     87                } else if (c->text && g_strcasecmp(c->text, "ANONYMOUS") == 0) {
     88                        sup_anonymous = 1;
    8689                } else if (c->text && g_strcasecmp(c->text, "X-OAUTH2") == 0) {
    8790                        sup_gtalk = 1;
     
    142145                xt_free_node(reply);
    143146                return XT_ABORT;
    144         } else if (sup_digest) {
     147        } else if (want_anonymous && sup_anonymous) {
     148                xt_add_attr(reply, "mechanism", "ANONYMOUS");
     149
     150                /* Well, that was easy. */
     151        } else if (want_anonymous) {
     152                imcb_error(ic, "Anonymous login requested, but not supported by server");
     153                imc_logout(ic, FALSE);
     154                xt_free_node(reply);
     155                return XT_ABORT;
     156        } else if (sup_digest && !(jd->ssl && sup_plain)) {
     157                /* Only try DIGEST-MD5 if there's no SSL/TLS or if PLAIN isn't supported.
     158                 * Which in practice means "don't bother with DIGEST-MD5 most of the time".
     159                 * It's weak, pointless over TLS, and often breaks with some servers (hi openfire) */
     160
    145161                xt_add_attr(reply, "mechanism", "DIGEST-MD5");
    146162
  • protocols/jabber/si.c

    re4f08bf r29ff5c2  
    186186        jd->filetransfers = g_slist_prepend(jd->filetransfers, tf);
    187187
    188         /* query buddy's features and server's streaming proxies if neccessary */
     188        /* query buddy's features and server's streaming proxies if necessary */
    189189
    190190        if (!tf->bud->features) {
     
    283283
    284284        if (requestok) {
    285                 /* Figure out who the transfer should come frome... */
     285                /* Figure out who the transfer should come from... */
    286286
    287287                ext_jid = ini_jid;
     
    403403         * <iq from=... to=... id=...>
    404404         *      <si xmlns=si>
    405          *      [       <file xmlns=ft/>    ] <-- not neccessary
     405         *      [       <file xmlns=ft/>    ] <-- not necessary
    406406         *              <feature xmlns=feature>
    407407         *                      <x xmlns=xdata type=submit>
  • protocols/msn/ns.c

    re4f08bf r29ff5c2  
    3939static void msn_ns_send_adl(struct im_connection *ic);
    4040static void msn_ns_structured_message(struct msn_data *md, char *msg, int msglen, char **cmd);
    41 static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action);
     41static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action, gboolean selfmessage);
    4242static void msn_ns_nfy(struct msn_data *md, char *who, char **parts, char *action, gboolean is_put);
    4343
     
    475475}
    476476
     477/* returns newly allocated string */
     478static char *msn_ns_parse_header_address(struct msn_data *md, char *headers, char *header_name)
     479{
     480        char *semicolon = NULL;
     481        char *header = NULL;
     482        char *address = NULL;
     483
     484        if (!(header = get_rfc822_header(headers, header_name, 0))) {
     485                return NULL;
     486        }
     487
     488        /* either the semicolon or the end of the string */
     489        semicolon = strchr(header, ';') ? : (header + strlen(header));
     490
     491        address = g_strndup(header + 2, semicolon - header - 2);
     492
     493        g_free(header);
     494        return address;
     495}
     496
    477497static void msn_ns_structured_message(struct msn_data *md, char *msg, int msglen, char **cmd)
    478498{
    479499        char **parts = NULL;
    480         char *semicolon = NULL;
    481500        char *action = NULL;
    482         char *from = NULL;
    483501        char *who = NULL;
     502        gboolean selfmessage = FALSE;
    484503
    485504        parts = g_strsplit(msg, "\r\n\r\n", 4);
    486505
    487         if (!(from = get_rfc822_header(parts[0], "From", 0))) {
     506        if (!(who = msn_ns_parse_header_address(md, parts[0], "From"))) {
    488507                goto cleanup;
    489508        }
    490509
    491         /* either the semicolon or the end of the string */
    492         semicolon = strchr(from, ';') ? : (from + strlen(from));
    493 
    494         who = g_strndup(from + 2, semicolon - from - 2);
     510        if (strcmp(who, md->ic->acc->user) == 0) {
     511                selfmessage = TRUE;
     512                g_free(who);
     513                if (!(who = msn_ns_parse_header_address(md, parts[0], "To"))) {
     514                        goto cleanup;
     515                }
     516        }
    495517
    496518        if ((strcmp(cmd[0], "SDG") == 0) && (action = get_rfc822_header(parts[2], "Message-Type", 0))) {
    497                 msn_ns_sdg(md, who, parts, action);
     519                msn_ns_sdg(md, who, parts, action, selfmessage);
    498520
    499521        } else if ((strcmp(cmd[0], "NFY") == 0) && (action = get_rfc822_header(parts[2], "Uri", 0))) {
     
    505527        g_strfreev(parts);
    506528        g_free(action);
    507         g_free(from);
    508529        g_free(who);
    509530}
    510531
    511 static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action)
     532static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action, gboolean selfmessage)
    512533{
    513534        struct im_connection *ic = md->ic;
    514535
    515         if (strcmp(action, "Control/Typing") == 0) {
     536        if (strcmp(action, "Control/Typing") == 0 && !selfmessage) {
    516537                imcb_buddy_typing(ic, who, OPT_TYPING);
    517538        } else if (strcmp(action, "Text") == 0) {
    518                 imcb_buddy_msg(ic, who, parts[3], 0, 0);
     539                imcb_buddy_msg(ic, who, parts[3], selfmessage ? OPT_SELFMESSAGE : 0, 0);
    519540        }
    520541}
     
    595616        } else {
    596617                imcb_error(ic, "Error during Passport authentication: %s", error);
    597                 imc_logout(ic, TRUE);
     618
     619                /* don't reconnect with auth errors */
     620                if (error && g_str_has_prefix(error, "wsse:FailedAuthentication")) {
     621                        imc_logout(ic, FALSE);
     622                } else {
     623                        imc_logout(ic, TRUE);
     624                }
    598625        }
    599626}
  • protocols/msn/soap.c

    re4f08bf r29ff5c2  
    327327        struct xt_node *code = xt_find_node(node->children, "faultcode");
    328328        struct xt_node *string = xt_find_node(node->children, "faultstring");
     329        struct xt_node *reqstatus = xt_find_path(node, "psf:pp/psf:reqstatus");
    329330        struct xt_node *url;
    330331
     
    335336                   url->text_len > 0) {
    336337                sd->redirect = g_strdup(url->text);
     338        } else if (reqstatus && strcmp(reqstatus->text, "0x800488fe") == 0) {
     339                char *msg = "Location blocked. Log in to live.com, go to recent activity and click 'this was me'";
     340                sd->error = g_strdup_printf("%s (%s)", code->text, msg);
    337341        } else {
    338342                sd->error = g_strdup_printf("%s (%s)", code->text, string && string->text_len ?
     
    346350        { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token },
    347351        { "S:Fault", "S:Envelope", msn_soap_passport_failure },
     352        { "S:Fault", "wst:RequestSecurityTokenResponse", msn_soap_passport_failure },
    348353        { NULL, NULL, NULL }
    349354};
  • protocols/nogaim.c

    re4f08bf r29ff5c2  
    735735}
    736736
     737/* Deprecated: using this function resulted in merging several handles accidentally
     738 * Also the irc layer handles this decently nowadays */
    737739void imcb_clean_handle(struct im_connection *ic, char *handle)
    738740{
    739         /* Accepts a handle and does whatever is necessary to make it
    740            BitlBee-friendly. Currently this means removing everything
    741            outside 33-127 (ASCII printable excl spaces), @ (only one
    742            is allowed) and ! and : */
    743         char out[strlen(handle) + 1];
    744         int s, d;
    745 
    746         s = d = 0;
    747         while (handle[s]) {
    748                 if (handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' &&
    749                     (handle[s] & 0x80) == 0) {
    750                         if (handle[s] == '@') {
    751                                 /* See if we got an @ already? */
    752                                 out[d] = 0;
    753                                 if (strchr(out, '@')) {
    754                                         continue;
    755                                 }
    756                         }
    757 
    758                         out[d++] = handle[s];
    759                 }
    760                 s++;
    761         }
    762         out[d] = handle[s];
    763 
    764         strcpy(handle, out);
    765 }
     741}
  • protocols/nogaim.h

    re4f08bf r29ff5c2  
    7070#define OPT_PONGS       0x00010000 /* Service sends us keep-alives */
    7171#define OPT_PONGED      0x00020000 /* Received a keep-alive during last interval */
     72#define OPT_SELFMESSAGE 0x00080000 /* A message sent by self from another location */
    7273
    7374/* ok. now the fun begins. first we create a connection structure */
     
    325326G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data);
    326327
    327 G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags);
     328G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags);
    328329G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle(struct im_connection *ic, const char *handle);
    329 G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle);
     330
     331G_GNUC_DEPRECATED G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle);
    330332
    331333/* Actions, or whatever. */
  • protocols/oscar/aim.h

    re4f08bf r29ff5c2  
    871871 * SNAC Family: Internal Messages
    872872 *
    873  * This isn't truely a SNAC family either, but using
     873 * This isn't truly a SNAC family either, but using
    874874 * these, we can integrated non-SNAC services into
    875875 * the SNAC-centered libfaim callback structure.
  • protocols/oscar/auth.c

    re4f08bf r29ff5c2  
    4141 * meaning you generally never call this.
    4242 *
    43  * But there are times when something might want it seperate. Specifically,
     43 * But there are times when something might want it separate. Specifically,
    4444 * libfaim sends this internally when doing SNAC login.
    4545 *
  • protocols/oscar/conn.c

    re4f08bf r29ff5c2  
    1515 * In OSCAR, every connection has a set of SNAC groups associated
    1616 * with it.  These are the groups that you can send over this connection
    17  * without being guarenteed a "Not supported" SNAC error.
     17 * without being guaranteed a "Not supported" SNAC error.
    1818 *
    1919 * The grand theory of things says that these associations transcend
     
    3636 *
    3737 * Here comes the good bit.  Without even letting anyone know, particularly
    38  * the module that decided to send this SNAC, and definitly not that twit
     38 * the module that decided to send this SNAC, and definitely not that twit
    3939 * in Greenland, you send out a service request.  In this request, you have
    4040 * marked the need for a connection supporting group 0x000e.  A few seconds
     
    317317
    318318        if (deadconn->fd >= 3) {
    319                 closesocket(deadconn->fd);
     319                proxy_disconnect(deadconn->fd);
    320320        }
    321321        deadconn->fd = -1;
  • protocols/oscar/im.c

    re4f08bf r29ff5c2  
    5050 * encoding for your message.  In UNICODE mode, _all_ characters must
    5151 * occupy 16bits, including ones that are not special.  (Remember that
    52  * the first 128 UNICODE symbols are equivelent to ASCII7, however they
     52 * the first 128 UNICODE symbols are equivalent to ASCII7, however they
    5353 * must be prefixed with a zero high order byte.)
    5454 *
     
    6464 * in all of libfaim, it is written with performance in mind.  As such,
    6565 * it is not as clear as it could be in respect to how this message is
    66  * supposed to be layed out. Most obviously, tlvlists should be used
     66 * supposed to be laid out. Most obviously, tlvlists should be used
    6767 * instead of writing out the bytes manually.
    6868 *
     
    476476 * examples of how to do this.
    477477 *
    478  * I would definitly recommend avoiding this feature unless you really
     478 * I would definitely recommend avoiding this feature unless you really
    479479 * know what you are doing, and/or you have something neat to do with it.
    480480 *
     
    638638                        }
    639639#if 0
    640                         /* XXX this isn't really necesary... */
     640                        /* XXX this isn't really necessary... */
    641641                        if (((args.flag1 != 0x0000) &&
    642642                             (args.flag1 != 0x0002) &&
     
    11611161         *
    11621162         * Channel 0x0001 is the message channel.  There are
    1163          * other channels for things called "rendevous"
     1163         * other channels for things called "rendezvous"
    11641164         * which represent chat and some of the other new
    11651165         * features of AIM2/3/3.5.
    11661166         *
    1167          * Channel 0x0002 is the Rendevous channel, which
     1167         * Channel 0x0002 is the Rendezvous channel, which
    11681168         * is where Chat Invitiations and various client-client
    11691169         * connection negotiations come from.
     
    11811181         * with the TLVs read below, they are two different pieces.  The
    11821182         * userinfo block contains the number of TLVs that contain user
    1183          * information, the rest are not even though there is no seperation.
     1183         * information, the rest are not even though there is no separation.
    11841184         * aim_extractuserinfo() returns the number of bytes used by the
    11851185         * userinfo tlvs, so you can start reading the rest of them right
     
    12531253/*
    12541254 *
    1255  * I definitly recommend sending this.  If you don't, you'll be stuck
     1255 * I definitely recommend sending this.  If you don't, you'll be stuck
    12561256 * with the rather unreasonable defaults.  You don't want those.  Send this.
    12571257 *
  • protocols/oscar/misc.c

    re4f08bf r29ff5c2  
    33 * aim_misc.c
    44 *
    5  * TODO: Seperate a lot of this into an aim_bos.c.
     5 * TODO: Separate a lot of this into an aim_bos.c.
    66 *
    77 * Other things...
  • protocols/oscar/msgcookie.c

    re4f08bf r29ff5c2  
    142142 * @cookiep: the address of a pointer to the cookie struct to remove
    143143 *
    144  * this function removes the cookie *cookie from teh list of cookies
     144 * this function removes the cookie *cookie from the list of cookies
    145145 * in sess, and then frees all memory associated with it. including
    146146 * its data! if you want to use the private data after calling this,
  • protocols/oscar/oscar.c

    re4f08bf r29ff5c2  
    456456                        b_event_remove(n->inpa);
    457457                }
     458                n->inpa = 0;
    458459                g_free(n->name);
    459460                g_free(n->show);
     
    481482        if (ic->inpa > 0) {
    482483                b_event_remove(ic->inpa);
     484                ic->inpa = 0;
    483485        }
    484486        if (odata->cnpa > 0) {
    485487                b_event_remove(odata->cnpa);
     488                odata->cnpa = 0;
    486489        }
    487490        if (odata->paspa > 0) {
    488491                b_event_remove(odata->paspa);
     492                odata->paspa = 0;
    489493        }
    490494        aim_session_kill(odata->sess);
     
    637641        aim_sendcookie(sess, bosconn, info->cookie);
    638642        b_event_remove(ic->inpa);
     643        ic->inpa = 0;
    639644
    640645        return 1;
     
    12611266        } break;
    12621267
    1263         case 2: {         /* rendevous */
     1268        case 2: {         /* rendezvous */
    12641269                struct aim_incomingim_ch2_args *args;
    12651270                args = va_arg(ap, struct aim_incomingim_ch2_args *);
     
    25862591        if (cc->inpa > 0) {
    25872592                b_event_remove(cc->inpa);
     2593                cc->inpa = 0;
    25882594        }
    25892595        aim_conn_kill(od->sess, &cc->conn);
  • protocols/oscar/rxhandlers.c

    re4f08bf r29ff5c2  
    381381        /*
    382382         * This doesn't have to be called here.  It could easily be done
    383          * by a seperate thread or something. It's an administrative operation,
     383         * by a separate thread or something. It's an administrative operation,
    384384         * and can take a while. Though the less you call it the less memory
    385385         * you'll have :)
  • protocols/oscar/rxqueue.c

    re4f08bf r29ff5c2  
    361361/*
    362362 * Grab a single command sequence off the socket, and enqueue
    363  * it in the incoming event queue in a seperate struct.
     363 * it in the incoming event queue in a separate struct.
    364364 */
    365365int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
     
    479479
    480480/*
    481  * Purge recieve queue of all handled commands (->handled==1).  Also
     481 * Purge receive queue of all handled commands (->handled==1).  Also
    482482 * allows for selective freeing using ->nofree so that the client can
    483483 * keep the data for various purposes.
  • protocols/oscar/service.c

    re4f08bf r29ff5c2  
    157157
    158158/*
    159  * OSCAR defines several 'rate classes'.  Each class has seperate
     159 * OSCAR defines several 'rate classes'.  Each class has separate
    160160 * rate limiting properties (limit level, alert level, disconnect
    161161 * level, etc), and a set of SNAC family/type pairs associated with
     
    709709 * of memory.  (I won't put it past them to start requesting data in
    710710 * less static regions -- regions that are initialized at run time, but still
    711  * before the client recieves this request.)
    712  *
    713  * When the client recieves the request, it adds it to the current ds
     711 * before the client receives this request.)
     712 *
     713 * When the client receives the request, it adds it to the current ds
    714714 * (0x00400000) and dereferences it, copying the data into a buffer which
    715715 * it then runs directly through the MD5 hasher.  The 16 byte output of
     
    723723 *     download a FREE, fully featured, and authorized client, here
    724724 *     http://www.aol.com/aim/download2.html"
    725  * The connection is then closed, recieving disconnect code 1, URL
     725 * The connection is then closed, receiving disconnect code 1, URL
    726726 * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.
    727727 *
    728728 * Note, however, that numerous inconsistencies can cause the above error,
    729  * not just sending back a bad hash.  Do not immediatly suspect this code
     729 * not just sending back a bad hash.  Do not immediately suspect this code
    730730 * if you get disconnected.  AOL and the open/free software community have
    731731 * played this game for a couple years now, generating the above message
    732  * on numerous ocassions.
     732 * on numerous occasions.
    733733 *
    734734 * Anyway, neener.  We win again.
  • protocols/oscar/tlv.c

    re4f08bf r29ff5c2  
    2525 * bstream references, so that at least the ->value portion of each
    2626 * element doesn't need to be malloc/memcpy'd.  This could prove to be
    27  * just as effecient as the in-place TLV parsing used in a couple places
     27 * just as efficient as the in-place TLV parsing used in a couple places
    2828 * in libfaim.
    2929 *
     
    135135/**
    136136 * aim_addtlvtochain_str - Add a string to a TLV chain
    137  * @list: Desination chain (%NULL pointer if empty)
     137 * @list: Designation chain (%NULL pointer if empty)
    138138 * @type: TLV type
    139139 * @str: String to add
  • protocols/oscar/txqueue.c

    re4f08bf r29ff5c2  
    6767 * The overall purpose here is to enqueue the passed in command struct
    6868 * into the outgoing (tx) queue.  Basically...
    69  *   1) Make a scope-irrelevent copy of the struct
     69 *   1) Make a scope-irrelevant copy of the struct
    7070 *   3) Mark as not-sent-yet
    7171 *   4) Enqueue the struct into the list
  • protocols/purple/purple.c

    re4f08bf r29ff5c2  
    113113           servers anyway! */
    114114        if (!dir_fixed) {
     115                PurpleCertificatePool *pool;
    115116                irc_t *irc = acc->bee->ui_data;
    116117                char *dir;
     
    122123                purple_blist_load();
    123124                purple_prefs_load();
     125
     126                if (proxytype == PROXY_SOCKS4A) {
     127                        /* do this here after loading prefs. yes, i know, it sucks */
     128                        purple_prefs_set_bool("/purple/proxy/socks4_remotedns", TRUE);
     129                }
     130
     131                /* re-create the certificate cache directory */
     132                pool = purple_certificate_find_pool("x509", "tls_peers");
     133                dir = purple_certificate_pool_mkpath(pool, NULL);
     134                purple_build_dir(dir, 0700);
     135
    124136                dir_fixed = TRUE;
    125137        }
     
    14041416                PurpleProxyInfo *pi = purple_global_proxy_get_info();
    14051417                switch (proxytype) {
     1418                case PROXY_SOCKS4A:
    14061419                case PROXY_SOCKS4:
    14071420                        purple_proxy_info_set_type(pi, PURPLE_PROXY_SOCKS4);
  • protocols/skype/README

    re4f08bf r29ff5c2  
    203203
    204204  * `account skype set skypeconsole_receive true` will make the
    205     `skypeconsole` account dump all the recieved raw traffic for you
     205    `skypeconsole` account dump all the received raw traffic for you
    206206
    207207- If you want to automatically join bookmarked groupchats right after
  • protocols/skype/skype.c

    re4f08bf r29ff5c2  
    2121
    2222#define _XOPEN_SOURCE
    23 #define _BSD_SOURCE
    2423#include <poll.h>
    2524#include <stdio.h>
     
    188187
    189188        va_start(args, fmt);
    190         vsnprintf(str, IRC_LINE_SIZE, fmt, args);
     189        g_vsnprintf(str, IRC_LINE_SIZE, fmt, args);
    191190        va_end(args);
    192191
     
    322321        }
    323322        return NULL;
     323}
     324
     325static struct groupchat *skype_chat_get_or_create(struct im_connection *ic, char *id)
     326{
     327        struct skype_data *sd = ic->proto_data;
     328        struct groupchat *gc = bee_chat_by_title(ic->bee, ic, id);
     329
     330        if (!gc) {
     331                gc = imcb_chat_new(ic, id);
     332                imcb_chat_name_hint(gc, id);
     333                imcb_chat_add_buddy(gc, sd->username);
     334
     335                skype_printf(ic, "GET CHAT %s ADDER\n", id);
     336                skype_printf(ic, "GET CHAT %s TOPIC\n", id);
     337                skype_printf(ic, "GET CHAT %s ACTIVEMEMBERS\n", id);
     338        }
     339
     340        return gc;
    324341}
    325342
     
    688705                info += 9;
    689706                if (sd->handle && sd->body && sd->type) {
    690                         struct groupchat *gc = bee_chat_by_title(ic->bee, ic, info);
     707                        struct groupchat *gc = skype_chat_get_or_create(ic, info);
    691708                        int i;
    692709                        for (i = 0; i < g_list_length(sd->body); i++) {
     
    10261043        }
    10271044        if (!strcmp(info, "STATUS MULTI_SUBSCRIBED")) {
    1028                 gc = bee_chat_by_title(ic->bee, ic, id);
    1029                 if (!gc) {
    1030                         gc = imcb_chat_new(ic, id);
    1031                         imcb_chat_name_hint(gc, id);
    1032                 }
    1033                 skype_printf(ic, "GET CHAT %s ADDER\n", id);
    1034                 skype_printf(ic, "GET CHAT %s TOPIC\n", id);
     1045                skype_chat_get_or_create(ic, id);
    10351046        } else if (!strcmp(info, "STATUS DIALOG") && sd->groupchat_with) {
    1036                 gc = imcb_chat_new(ic, id);
    1037                 imcb_chat_name_hint(gc, id);
     1047                gc = skype_chat_get_or_create(ic, id);
    10381048                /* According to the docs this
    10391049                 * is necessary. However it
     
    10461056                           sd->groupchat_with);
    10471057                imcb_chat_add_buddy(gc, buf);
    1048                 imcb_chat_add_buddy(gc, sd->username);
    10491058                g_free(sd->groupchat_with);
    10501059                sd->groupchat_with = NULL;
    1051                 skype_printf(ic, "GET CHAT %s ADDER\n", id);
    1052                 skype_printf(ic, "GET CHAT %s TOPIC\n", id);
    10531060        } else if (!strcmp(info, "STATUS UNSUBSCRIBED")) {
    10541061                gc = bee_chat_by_title(ic->bee, ic, id);
     
    12571264                }
    12581265                g_strfreev(lines);
    1259         } else if (st == 0 || (st < 0 && !sockerr_again())) {
     1266        } else if (st == 0 || (st < 0 && !ssl_sockerr_again(sd->ssl))) {
    12601267                ssl_disconnect(sd->ssl);
    12611268                sd->fd = -1;
  • protocols/skype/t/add-yes-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/added-no-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/added-yes-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/away-set-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/call-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :alice
  • protocols/skype/t/call-failed-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :alice
  • protocols/skype/t/called-no-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/called-yes-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/ctcp-help-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/filetransfer-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/group-add-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/group-read-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/groupchat-invite-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    77>> :bob!bob@skype.com JOIN :&bitlbee
    88<< PRIVMSG &bitlbee :chat with bob
    9 >> 353 alice = ##alice/$bob;a7ab206ec780 :@alice bob @root
    10 << INVITE cecil ##alice/$bob;a7ab206ec780
    11 >> cecil@skype.com JOIN :##alice/$bob;a7ab206ec780
     9>> 353 alice = ##alice/$bob;a7ab206ec78 :@alice @root
     10<< INVITE cecil ##alice/$bob;a7ab206ec78
     11>> cecil@skype.com JOIN :##alice/$bob;a7ab206ec78
  • protocols/skype/t/groupchat-invite-skyped.mock

    re4f08bf r29ff5c2  
    2626>> GET CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
    2727<< CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
     28>> GET CHAT #alice/$bob;a7ab206ec78060f1 ACTIVEMEMBERS
     29<< CHAT #alice/$bob;a7ab206ec78060f1 ACTIVEMEMBERS
    2830<< CHATMESSAGE 206 STATUS SENDING
    2931<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG
  • protocols/skype/t/groupchat-invited-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    55<< PRIVMSG &bitlbee :account add skype alice foo
    66<< PRIVMSG &bitlbee :account skype on
    7 >> JOIN :##cecil/$bob;4d8cc9965791
    8 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
     7>> JOIN :##cecil/$bob;4d8cc996579
     8>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
  • protocols/skype/t/groupchat-leave-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    66<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true
    77<< PRIVMSG &bitlbee :account skype on
    8 >> JOIN :##cecil/$bob;4d8cc9965791
    9 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
    10 << PART ##cecil/$bob;4d8cc9965791
     8>> JOIN :##cecil/$bob;4d8cc996579
     9>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
     10<< PART ##cecil/$bob;4d8cc996579
    1111>> PRIVMSG &bitlbee :alice: CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS UNSUBSCRIBED
  • protocols/skype/t/groupchat-leave-skyped.mock

    re4f08bf r29ff5c2  
    3636>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    3737<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    38 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    39 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    40 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    41 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    42 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    43 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    44 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    45 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
     38>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS
     39<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS
    4640>> GET CHATMESSAGE 188 FROM_HANDLE
    4741<< CHATMESSAGE 188 FROM_HANDLE bob
  • protocols/skype/t/groupchat-msg-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    66<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true
    77<< PRIVMSG &bitlbee :account skype on
    8 >> JOIN :##cecil/$bob;4d8cc9965791
    9 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
    10 << PRIVMSG ##cecil/$bob;4d8cc9965791 :hello
     8>> JOIN :##cecil/$bob;4d8cc996579
     9>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
     10<< PRIVMSG ##cecil/$bob;4d8cc996579 :hello
    1111>> PRIVMSG &bitlbee :alice: CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVITY_TIMESTAMP
  • protocols/skype/t/groupchat-msg-skyped.mock

    re4f08bf r29ff5c2  
    3636>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    3737<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    38 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    39 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    40 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    41 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    42 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    43 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    44 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    45 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
     38>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS
     39<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil alice
    4640>> GET CHATMESSAGE 188 FROM_HANDLE
    4741<< CHATMESSAGE 188 FROM_HANDLE bob
  • protocols/skype/t/groupchat-topic-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    55<< PRIVMSG &bitlbee :account add skype alice foo
    66<< PRIVMSG &bitlbee :account skype on
    7 >> JOIN :##cecil/$bob;4d8cc9965791
    8 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
    9 << TOPIC ##cecil/$bob;4d8cc9965791 :topic
    10 >> TOPIC ##cecil/$bob;4d8cc9965791 :topic
     7>> JOIN :##cecil/$bob;4d8cc996579
     8>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
     9<< TOPIC ##cecil/$bob;4d8cc996579 :topic
     10>> TOPIC ##cecil/$bob;4d8cc996579 :topic
  • protocols/skype/t/info-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/login-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/msg-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/set-mood-text-bitlbee.mock

    re4f08bf r29ff5c2  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/twitter/twitter.c

    re4f08bf r29ff5c2  
    678678        ic->flags &= ~OPT_LOGGED_IN;
    679679
    680         // Remove the main_loop function from the function queue.
    681         b_event_remove(td->main_loop_id);
    682 
    683         if (td->timeline_gc) {
    684                 imcb_chat_free(td->timeline_gc);
    685         }
    686 
    687680        if (td) {
     681                // Remove the main_loop function from the function queue.
     682                b_event_remove(td->main_loop_id);
     683
     684                if (td->timeline_gc) {
     685                        imcb_chat_free(td->timeline_gc);
     686                }
     687
    688688                if (td->filter_update_id > 0) {
    689689                        b_event_remove(td->filter_update_id);
     
    10121012                        twitter_log(ic, "Tweet `%s' does not exist", cmd[1]);
    10131013                } else {
    1014                         /* More common link is twitter.com/$UID/status/$ID (and that's
    1015                          * what this will 302 to) but can't generate that since for RTs,
    1016                          * bu here points at the retweeter while id contains the id of
    1017                          * the original message. */
    1018                         twitter_log(ic, "https://twitter.com/statuses/%lld", id);
     1014                        twitter_status_show_url(ic, id);
    10191015                }
    10201016                goto eof;
  • protocols/twitter/twitter_http.c

    re4f08bf r29ff5c2  
    2424/***************************************************************************\
    2525*                                                                           *
    26 *  Some funtions within this file have been copied from other files within  *
     26*  Some functions within this file have been copied from other files within  *
    2727*  BitlBee.                                                                 *
    2828*                                                                           *
     
    5353        char *tmp;
    5454        GString *request = g_string_new("");
    55         void *ret;
     55        void *ret = NULL;
    5656        char *url_arguments;
    5757        url_t *base_url = NULL;
     
    7272                base_url = g_new0(url_t, 1);
    7373                if (!url_set(base_url, url_string)) {
    74                         g_free(base_url);
    75                         return NULL;
     74                        goto error;
    7675                }
    7776        }
     
    132131        }
    133132
     133error:
    134134        g_free(url_arguments);
    135135        g_string_free(request, TRUE);
  • protocols/twitter/twitter_lib.c

    re4f08bf r29ff5c2  
    312312        td = ic->proto_data;
    313313
     314        // Parse the data.
     315        if (!(parsed = twitter_parse_response(ic, req))) {
     316                return;
     317        }
     318
    314319        txl = g_new0(struct twitter_xml_list, 1);
    315320        txl->list = td->follow_ids;
    316 
    317         // Parse the data.
    318         if (!(parsed = twitter_parse_response(ic, req))) {
    319                 return;
    320         }
    321321
    322322        twitter_xt_get_friends_id_list(parsed, txl);
     
    388388        }
    389389
     390        // Get the user list from the parsed xml feed.
     391        if (!(parsed = twitter_parse_response(ic, req))) {
     392                return;
     393        }
     394
    390395        txl = g_new0(struct twitter_xml_list, 1);
    391396        txl->list = NULL;
    392397
    393         // Get the user list from the parsed xml feed.
    394         if (!(parsed = twitter_parse_response(ic, req))) {
    395                 return;
    396         }
    397398        twitter_xt_get_users(parsed, txl);
    398399        json_value_free(parsed);
     
    13851386        td = ic->proto_data;
    13861387
    1387         txl = g_new0(struct twitter_xml_list, 1);
    1388         txl->list = NULL;
    1389 
    13901388        // The root <statuses> node should hold the list of statuses <status>
    13911389        if (!(parsed = twitter_parse_response(ic, req))) {
    13921390                goto end;
    13931391        }
     1392
     1393        txl = g_new0(struct twitter_xml_list, 1);
     1394        txl->list = NULL;
     1395
    13941396        twitter_xt_get_status_list(ic, parsed, txl);
    13951397        json_value_free(parsed);
     
    14241426        td = ic->proto_data;
    14251427
    1426         txl = g_new0(struct twitter_xml_list, 1);
    1427         txl->list = NULL;
    1428 
    14291428        // The root <statuses> node should hold the list of statuses <status>
    14301429        if (!(parsed = twitter_parse_response(ic, req))) {
    14311430                goto end;
    14321431        }
     1432
     1433        txl = g_new0(struct twitter_xml_list, 1);
     1434        txl->list = NULL;
     1435
    14331436        twitter_xt_get_status_list(ic, parsed, txl);
    14341437        json_value_free(parsed);
     
    15731576        g_free(args[1]);
    15741577}
     1578
     1579static void twitter_http_status_show_url(struct http_request *req)
     1580{
     1581        struct im_connection *ic = req->data;
     1582        json_value *parsed, *id;
     1583        const char *name;
     1584
     1585        // Check if the connection is still active.
     1586        if (!g_slist_find(twitter_connections, ic)) {
     1587                return;
     1588        }
     1589
     1590        if (!(parsed = twitter_parse_response(ic, req))) {
     1591                return;
     1592        }
     1593
     1594        /* for the parson branch:
     1595        name = json_object_dotget_string(json_object(parsed), "user.screen_name");
     1596        id = json_object_get_integer(json_object(parsed), "id");
     1597        */
     1598
     1599        name = json_o_str(json_o_get(parsed, "user"), "screen_name");
     1600        id = json_o_get(parsed, "id");
     1601
     1602        if (name && id && id->type == json_integer) {
     1603                twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id->u.integer);
     1604        } else {
     1605                twitter_log(ic, "Error: could not fetch tweet url.");
     1606        }
     1607
     1608        json_value_free(parsed);
     1609}
     1610
     1611void twitter_status_show_url(struct im_connection *ic, guint64 id)
     1612{
     1613        char *url = g_strdup_printf("%s%" G_GUINT64_FORMAT "%s", TWITTER_STATUS_SHOW_URL, id, ".json");
     1614        twitter_http(ic, url, twitter_http_status_show_url, ic, 0, NULL, 0);
     1615        g_free(url);
     1616}
  • protocols/twitter/twitter_lib.h

    re4f08bf r29ff5c2  
    9696void twitter_report_spam(struct im_connection *ic, char *screen_name);
    9797void twitter_favourite_tweet(struct im_connection *ic, guint64 id);
     98void twitter_status_show_url(struct im_connection *ic, guint64 id);
    9899
    99100#endif //_TWITTER_LIB_H
  • protocols/yahoo/libyahoo2.c

    re4f08bf r29ff5c2  
    1212 * GNU GPL.
    1313 *
    14  * This code is derivitive of Gaim <http://gaim.sourceforge.net>
     14 * This code is derivative of Gaim <http://gaim.sourceforge.net>
    1515 * copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
    1616 *             1998-1999, Adam Fritzler <afritz@marko.net>
     
    14021402
    14031403        /*
    1404          * Status updates may be spread accross multiple packets and not
     1404         * Status updates may be spread across multiple packets and not
    14051405         * even on buddy boundaries, so keeping some state is important.
    14061406         * So, continue where we left off, and only add a user entry to
  • protocols/yahoo/yahoo.c

    re4f08bf r29ff5c2  
    440440{
    441441        struct byahoo_connect_callback_data *d = data;
    442 
    443         if (!byahoo_get_ic_by_id(d->id)) {
     442        struct im_connection *ic;
     443
     444        if (!(ic = byahoo_get_ic_by_id(d->id))) {
     445                g_free(d);
     446                return;
     447        }
     448
     449        if (source == -1) {
     450                d->callback(NULL, 0, d->data);
     451                imcb_error(ic, "Could not connect to server");
     452                imc_logout(ic, TRUE);
    444453                g_free(d);
    445454                return;
  • protocols/yahoo/yahoo2_callbacks.h

    re4f08bf r29ff5c2  
    685685 * Name: ext_yahoo_connect_async
    686686 *      Connect to a host:port asynchronously. This function should return
    687  *      immediately returing a tag used to identify the connection handler,
     687 *      immediately returning a tag used to identify the connection handler,
    688688 *      or a pre-connect error (eg: host name lookup failure).
    689689 *      Once the connect completes (successfully or unsuccessfully), callback
  • root_commands.c

    re4f08bf r29ff5c2  
    163163                irc_umode_set(irc, "+R", 1);
    164164
     165                if (irc->caps & CAP_SASL) {
     166                        irc_user_t *iu = irc->user;
     167                        irc_send_num(irc, 900, "%s!%s@%s %s :You are now logged in as %s",
     168                                iu->nick, iu->user, iu->host, iu->nick, iu->nick);
     169                }
     170
    165171                bitlbee_whatsnew(irc);
    166172
     
    238244                irc->status |= USTATUS_IDENTIFIED;
    239245                irc_umode_set(irc, "+R", 1);
     246
     247                if (irc->caps & CAP_SASL) {
     248                        irc_user_t *iu = irc->user;
     249                        irc_send_num(irc, 900, "%s!%s@%s %s :You are now logged in as %s",
     250                                iu->nick, iu->user, iu->host, iu->nick, iu->nick);
     251                }
    240252
    241253                /* Set this var now, or anyone who logs in to his/her
  • tests/Makefile

    re4f08bf r29ff5c2  
    1515distclean: clean
    1616
    17 main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o
     17main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o
    1818
    1919test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_set.o check_jabber_sasl.o check_jabber_util.o
  • tests/check.c

    re4f08bf r29ff5c2  
    4242        gettimeofday(time, 0);
    4343        return((double) time->tv_sec + (double) time->tv_usec / 1000000);
     44}
     45
     46void sighandler_shutdown_setup()
     47{
     48        /* no-op. originally defined in unix.c, needed by bitlbee.c */
    4449}
    4550
  • tests/check_jabber_util.c

    re4f08bf r29ff5c2  
    3737        fail_unless(jabber_buddy_by_jid(ic, "wilmer@GAAST.NET/BitlBee", GET_BUDDY_CREAT) == budw1);
    3838
    39         fail_if(jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_EXACT));
     39        fail_unless(jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_EXACT));
    4040        fail_unless(jabber_buddy_by_jid(ic, "WILMER@gaast.net", 0) == budw3);
    4141
  • tests/check_user.c

    re4f08bf r29ff5c2  
    4646END_TEST
    4747
    48 START_TEST(test_user_del_nonexistant)
     48START_TEST(test_user_del_nonexistent)
    4949irc_t * irc = torture_irc();
    5050fail_unless(user_del(irc, "foo") == 0);
     
    7171        tcase_add_test(tc_core, test_user_add_exists);
    7272        tcase_add_test(tc_core, test_user_del_invalid);
    73         tcase_add_test(tc_core, test_user_del_nonexistant);
     73        tcase_add_test(tc_core, test_user_del_nonexistent);
    7474        tcase_add_test(tc_core, test_user_del);
    7575        tcase_add_test(tc_core, test_user_rename);
  • unix.c

    re4f08bf r29ff5c2  
    4848global_t global;        /* Against global namespace pollution */
    4949
    50 static int signal_shutdown_pipe[2] = { -1, -1 };
     50static struct {
     51        int fd[2];
     52        int tag;
     53} shutdown_pipe = {{-1 , -1}, 0};
     54
    5155static void sighandler_shutdown(int signal);
    5256static void sighandler_crash(int signal);
     
    156160        sigaction(SIGSEGV, &sig, &old);
    157161
    158         /* Use a pipe for SIGTERM/SIGINT so the actual signal handler doesn't do anything unsafe */
    159         if (pipe(signal_shutdown_pipe) == 0) {
    160                 b_input_add(signal_shutdown_pipe[0], B_EV_IO_READ, bitlbee_shutdown, NULL);
    161                 sig.sa_handler = sighandler_shutdown;
    162                 sigaction(SIGINT, &sig, &old);
    163                 sigaction(SIGTERM, &sig, &old);
    164         }
     162        sighandler_shutdown_setup();
     163
     164        sig.sa_handler = sighandler_shutdown;
     165        sigaction(SIGINT, &sig, &old);
     166        sigaction(SIGTERM, &sig, &old);
    165167
    166168        if (!getuid() || !geteuid()) {
     
    256258}
    257259
     260/* Set up a pipe for SIGTERM/SIGINT so the actual signal handler doesn't do anything unsafe */
     261void sighandler_shutdown_setup()
     262{
     263        if (shutdown_pipe.fd[0] != -1) {
     264                /* called again from a forked process, clean up to avoid propagating the signal */
     265                b_event_remove(shutdown_pipe.tag);
     266                close(shutdown_pipe.fd[0]);
     267                close(shutdown_pipe.fd[1]);
     268        }
     269
     270        if (pipe(shutdown_pipe.fd) == 0) {
     271                shutdown_pipe.tag = b_input_add(shutdown_pipe.fd[0], B_EV_IO_READ, bitlbee_shutdown, NULL);
     272        }
     273}
     274
    258275/* Signal handler for SIGTERM and SIGINT */
    259276static void sighandler_shutdown(int signal)
     
    261278        /* Write a single null byte to the pipe, just to send a message to the main loop.
    262279         * This gets handled by bitlbee_shutdown (the b_input_add callback for this pipe) */
    263         write(signal_shutdown_pipe[1], "", 1);
     280        write(shutdown_pipe.fd[1], "", 1);
    264281}
    265282
     
    275292        for (l = irc_connection_list; l; l = l->next) {
    276293                irc_t *irc = l->data;
     294                sock_make_blocking(irc->fd);
    277295                write(irc->fd, message, len);
    278296        }
Note: See TracChangeset for help on using the changeset viewer.