Changeset b79308b


Ignore:
Timestamp:
2008-04-14T13:10:53Z (16 years ago)
Author:
ulim <a.sporto+bee@…>
Branches:
master
Children:
0cab388
Parents:
6cac643 (diff), aa31117 (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:

merged in upstream r379 (somewhere after 1.2-3).
Just one trivial conflict in the jabber Makefile, went smoothly.

Files:
3 added
70 edited
2 moved

Legend:

Unmodified
Added
Removed
  • Makefile

    r6cac643 rb79308b  
    5050        $(MAKE) -C tests
    5151
    52 lcov:
    5352gcov: check
    5453        gcov *.c
  • account.c

    r6cac643 rb79308b  
    182182        account_t *a, *l = NULL;
    183183       
     184        if( acc->ic )
     185                /* Caller should have checked, accounts still in use can't be deleted. */
     186                return;
     187       
    184188        for( a = irc->accounts; a; a = (l=a)->next )
    185189                if( a == acc )
    186190                {
    187                         if( a->ic ) return; /* Caller should have checked, accounts still in use can't be deleted. */
    188                        
    189191                        if( l )
    190                         {
    191192                                l->next = a->next;
    192                         }
    193193                        else
    194                         {
    195194                                irc->accounts = a->next;
    196                         }
    197195                       
    198196                        while( a->set )
     
    203201                        g_free( a->user );
    204202                        g_free( a->pass );
    205                         if( a->server ) g_free( a->server );
     203                        g_free( a->server );
    206204                        if( a->reconnect )      /* This prevents any reconnect still queued to happen */
    207205                                cancel_auto_reconnect( a );
  • bitlbee.c

    r6cac643 rb79308b  
    226226        if( st == size )
    227227        {
    228                 g_free( irc->sendbuffer );
    229                 irc->sendbuffer = NULL;
    230                 irc->w_watch_source_id = 0;
    231                
    232228                if( irc->status & USTATUS_SHUTDOWN )
     229                {
    233230                        irc_free( irc );
     231                }
     232                else
     233                {
     234                        g_free( irc->sendbuffer );
     235                        irc->sendbuffer = NULL;
     236                        irc->w_watch_source_id = 0;
     237                }
    234238               
    235239                return FALSE;
  • bitlbee.conf

    r6cac643 rb79308b  
    4949##
    5050## Password the user should enter when logging into a closed BitlBee server.
     51## You can also have an MD5-encrypted password here. Format: "md5:", followed
     52## by a hash as generated for the <user password=""> attribute in a BitlBee
     53## XML file (for now there's no easier way to generate the hash).
    5154##
    5255# AuthPassword = ItllBeBitlBee   ## Heh.. Our slogan. ;-)
     56## or
     57# AuthPassword = md5:gzkK0Ox/1xh+1XTsQjXxBJ571Vgl
    5358
    5459## OperPassword
     
    5762##
    5863# OperPassword = ChangeMe!
     64## or
     65# OperPassword = md5:I0mnZbn1t4R731zzRdDN2/pK7lRX
    5966
    6067## HostName
  • bitlbee.h

    r6cac643 rb79308b  
    3030
    3131#define PACKAGE "BitlBee"
    32 #define BITLBEE_VERSION "1.1.1dev"
     32#define BITLBEE_VERSION "1.2"
    3333#define VERSION BITLBEE_VERSION
    3434
    35 #define MAX_STRING 128
     35#define MAX_STRING 511
    3636
    3737#if HAVE_CONFIG_H
     
    160160gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond );
    161161
     162char *set_eval_root_nick( set_t *set, char *new_nick );
     163
    162164extern global_t global;
    163165
  • conf.c

    r6cac643 rb79308b  
    253253                        {
    254254                                g_strfreev( conf->migrate_storage );
    255                                 conf->migrate_storage = g_strsplit( ini->value, " \t,;", -1 );
     255                                conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 );
    256256                        }
    257257                        else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
  • debian/README.Debian

    r6cac643 rb79308b  
    1                    *** NEWS (Version 1.1 and later) ***
     1                   *** NEWS (Version 1.2 and later) ***
    22
    3 Starting from version 1.1, BitlBee has a forking daemon mode. The Debian
     3Starting from version 1.2, BitlBee has a forking daemon mode. The Debian
    44package now uses this mode by default, instead of inetd mode. If you don't
    55want to use this, you can disable the init scripts (best way to do this is
     
    77should be necessary only once, it won't be touched during upgrades.
    88
    9 --------------------------------------------------------------------------
     9Another important change in BitlBee 1.2 is the file format used for your
     10personal settings. Everything's now saved in a single .xml (per account,
     11of course) file instead of $nick.accounts and $nick.nicks. One advantage
     12of this new format is that the passwords are actually encrypted instead of
     13just vaguely obfuscated. BitlBee can still read the old files, and will
     14save things in the new format when you save/disconnect. After that, you
     15can safely remove the old-style files (this is recommended).
     16
     17I tried making this transition (the new file format but especially, in this
     18case, the inetd->forkdaemon mode change) as smooth as possible, but I'm
     19aware that many BitlBee users will have their own hacks already to run the
     20program. I hope the package won't break any of this for anyone. 1.2-2
     21should fix at least some of the issues.
     22
     23---------------------------------------------------------------------------
    1024
    1125Debconf should have asked you on what port you want BitlBee to run. If it
  • debian/bitlbee.init

    r6cac643 rb79308b  
    11#! /bin/sh
     2### BEGIN INIT INFO
     3# Provides:          bitlbee
     4# Required-Start:    $remote_fs $syslog
     5# Required-Stop:     $remote_fs $syslog
     6# Default-Start:     2 3 4 5
     7# Default-Stop:      1
     8### END INIT INFO
    29#
    310# Init script for BitlBee Debian package. Based on skeleton init script:
     
    1825# Default value
    1926BITLBEE_PORT=6667
    20 DAEMON_OPT=-F
     27BITLBEE_OPTS=-F
    2128
    2229# Read config file if it is present.
     
    3744       
    3845        start-stop-daemon --start --quiet --pidfile $PIDFILE \
    39                 -c bitlbee -g nogroup \
    40                 --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $DAEMON_OPT
     46                -c bitlbee: \
     47                --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $BITLBEE_OPTS
    4148}
    4249
  • debian/changelog

    r6cac643 rb79308b  
    1 bitlbee (1.1.1dev-0pre) unstable; urgency=low
    2 
     1bitlbee (1.2-4) unstable; urgency=low
     2
     3  * Not a real release, just a placeholder for the changelog.
     4  * Fixed init script to use the BITLBEE_OPTS variable, not an undefined
     5    DAEMON_OPT.
     6  * Added dependency information to the init script. (Closes: #472567)
     7
     8 -- Wilmer van der Gaast <wilmer@gaast.net>  Sat, 29 Mar 2008 21:10:33 +0000
     9
     10bitlbee (1.2-3) unstable; urgency=low
     11
     12  * Removed DEB_BUILD_OPTIONS again (forgot to apply that change to the 1.2
     13    branch when I finished 1.0.4-2, things diverged too much anyway.)
     14    Closes: #472540.
     15
     16 -- Wilmer van der Gaast <wilmer@gaast.net>  Mon, 24 Mar 2008 21:10:14 +0000
     17
     18bitlbee (1.2-2) unstable; urgency=low
     19
     20  * Fixed some packaging issues reported by IRC and e-mail. (Closes: #472373)
     21  * Fixed proxy support. (Closes: #472395)
     22  * Added a BitlBee group so only root can edit the configs and BitlBee can
     23    just *read* it.
     24  * Manually deleting /var/lib/bitlbee/ when purging, deluser doesn't want to
     25    do it.
     26
     27 -- Wilmer van der Gaast <wilmer@gaast.net>  Mon, 24 Mar 2008 19:48:24 +0000
     28
     29bitlbee (1.2-1) unstable; urgency=low
     30
     31  * New upstream release. (Closes: #325017, #386914, #437515)
     32  * With hopefully completely sane charset handling (Closes: #296145)
    333  * Switched to the new forking daemon mode. Added /etc/default/bitlbee
    434    file, an init script. People who want to stick with inetd can do so, see
    535    the defaults file.
     36    (Closes: #460741, #466171, #294585, #345038, #306452, #392682)
    637  * Got rid of debconf Woody compatibility stuff.
    738  * No more MPL code in BitlBee, thanks to the Jabber module rewrite!
    8 
    9  -- Wilmer van der Gaast <wilmer@gaast.net>  Fri, 06 Jul 2007 09:09:36 +0100
     39  * Added Italian translation, sorry for taking so long! (Closes: #448238)
     40  * Added libevent dependency (more reliable event handling).
     41  * Removed GLib 1.x dependency because BitlBee really requires GLib >=2.4.
     42
     43 -- Wilmer van der Gaast <wilmer@gaast.net>  Tue, 18 Mar 2008 23:44:19 +0000
     44
     45bitlbee (1.0.4-2) unstable; urgency=low
     46
     47  * Removed $DEB_BUILD_OPTIONS because apparently buildds fill it with crap.
     48    (Closes: #458717)
     49
     50 -- Wilmer van der Gaast <wilmer@gaast.net>  Mon, 11 Feb 2008 19:15:33 +0000
     51
     52bitlbee (1.0.4-1) unstable; urgency=low
     53
     54  * New upstream release.
     55  * Changed libnss-dev dependency. (Closes: #370442)
     56  * Added build-indep rule to debian/rules. (Closes: #395673)
     57
     58 -- Wilmer van der Gaast <wilmer@gaast.net>  Wed, 29 Aug 2007 20:24:28 +0100
    1059
    1160bitlbee (1.0.3-1.3) unstable; urgency=low
  • debian/conffiles

    r6cac643 rb79308b  
    11/etc/bitlbee/motd.txt
    22/etc/bitlbee/bitlbee.conf
     3/etc/init.d/bitlbee
  • debian/control

    r6cac643 rb79308b  
    44Maintainer: Wilmer van der Gaast <wilmer@gaast.net>
    55Standards-Version: 3.5.9
    6 Build-Depends: libglib2.0-dev | libglib-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf
     6Build-Depends: libglib2.0-dev (>= 2.4), libevent-dev, libgnutls-dev | libnss-dev (>= 1.6), debconf-2.0, po-debconf
    77
    88Package: bitlbee
  • debian/postinst

    r6cac643 rb79308b  
    1414BITLBEE_DISABLED=0
    1515BITLBEE_UPGRADE_DONT_RESTART=0
    16 [ -r /etc/default/bitlbee ] && source /etc/default/bitlbee
     16[ -r /etc/default/bitlbee ] && . /etc/default/bitlbee
    1717
    18 if [ "$BITLBEE_DISABLED" = "0" ]; then
    19         ## In case it's still there (if we're upgrading right now)
     18if [ "$BITLBEE_DISABLED" = "0" ] && type update-inetd > /dev/null 2> /dev/null &&
     19   ( expr "$2" : '0\..*' > /dev/null || expr "$2" : '1\.0\..*' > /dev/null ); then
     20        ## Make sure the inetd entry is gone (can still be there from a
     21        ## previous version.
    2022        update-inetd --remove '.*/usr/sbin/bitlbee'
     23        if grep -q /usr/sbin/bitlbee /etc/inetd.conf 2> /dev/null; then
     24                # Thanks for breaking update-inetd! (bugs.debian.org/311111)
     25                # I hope that it works at least with xinetd, because this
     26                # emergency hack doesn't:
     27                perl -pi -e 's:^[^#].*/usr/sbin/bitlbee$:## Now using daemon mode\: # $&:' /etc/inetd.conf
     28                killall -HUP inetd || true
     29        fi
    2130fi
    2231
     
    6574fi
    6675
    67 adduser --system --home /var/lib/bitlbee/ --disabled-login --disabled-password bitlbee
     76adduser --system --group --disabled-login --disabled-password --home /var/lib/bitlbee/ bitlbee
    6877chmod 700 /var/lib/bitlbee/
    6978
    7079## Can't do this in packaging phase: Don't know the UID yet. Access to
    71 ## the file should be limited, now that it stores passwords.
    72 chmod 600 /etc/bitlbee/bitlbee.conf
    73 chown bitlbee /etc/bitlbee/bitlbee.conf
     80## the file should be limited, now that it stores passwords. Added
     81## --group later for a little more security, but have to see if I can
     82## apply this change to existing installations on upgrades. Will think
     83## about that later.
     84if getent group bitlbee > /dev/null; then
     85        chmod 640 /etc/bitlbee/bitlbee.conf
     86        chown root:bitlbee /etc/bitlbee/bitlbee.conf
     87else
     88        chmod 600 /etc/bitlbee/bitlbee.conf
     89        chown bitlbee /etc/bitlbee/bitlbee.conf
     90fi
    7491
    7592if [ -z "$2" ]; then
  • debian/postrm

    r6cac643 rb79308b  
    99
    1010update-rc.d bitlbee remove > /dev/null 2>&1 || true
    11 deluser --remove-home bitlbee || true
     11rm -f /etc/default/bitlbee
     12
     13deluser --system --remove-home bitlbee || true
     14rm -rf /var/lib/bitlbee ## deluser doesn't seem to do this for homedirs in /var
  • debian/rules

    r6cac643 rb79308b  
    33DEBUG ?= 0
    44
     5ifdef BITLBEE_VERSION
     6BITLBEE_FORCE_VERSION=1
     7else
    58# Want to use the full package version number instead of just the release.
    69BITLBEE_VERSION ?= "$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')"
    710export BITLBEE_VERSION
    8 
     11endif
    912
    1013build-arch: build-arch-stamp
    1114build-arch-stamp:
    1215        if [ ! -d debian ]; then exit 1; fi
    13         ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee $(DEB_BUILD_OPTIONS)
     16        ./configure --debug=$(DEBUG) --prefix=/usr --etcdir=/etc/bitlbee --events=libevent
    1417        $(MAKE)
    1518#       $(MAKE) -C doc/ all
     
    6669                find usr -type f -exec md5sum {} \; > DEBIAN/md5sums
    6770        dpkg-shlibdeps -Tdebian/bitlbee.substvars -dDepends debian/bitlbee/usr/sbin/bitlbee
    68 ifdef BITLBEE_VERSION
     71ifdef BITLBEE_FORCE_VERSION
    6972        dpkg-gencontrol -ldebian/changelog -isp -pbitlbee -Tdebian/bitlbee.substvars -Pdebian/bitlbee -v1:$(BITLBEE_VERSION)-0 -V'debconf-depends=debconf (>= 1.2.0) | debconf-2.0'
    7073else
  • doc/CHANGES

    r6cac643 rb79308b  
     1Version 1.2.1:
     2- Fixed proxy support.
     3- Fixed stalling issues while connecting to Jabber when using the OpenSSL
     4  module.
     5- Fixed problem with GLib and ForkDaemon where processes didn't die when
     6  the client disconnects.
     7- Fixed handling of "set charset none". (Which pretty much breaks the account
     8  completely in 1.2.)
     9- You can now automatically identify yourself to BitlBee by setting a server
     10  password in your IRC client.
     11- Compatible with all crazy kinds of line endings that clients can send.
     12
     13Finished ...
     14
    115Version 1.2:
    2 - First BitlBee development/testing RELEASE. This should be quite stable
    3   though (and for most people more stable than 1.0.x). It just has a couple
    4   of rough edges and needs a bit more testing.
    516- Added ForkDaemon mode next to the existing Daemon- and inetd modes. With
    617  ForkDaemon you can run BitlBee as a stand-alone daemon and every connection
     
    2132  1.x is so old that supporting it really isn't necessary anymore.
    2233- Many, many, MANY little changes, improvements, fixes. Using non-blocking
    23   I/O as much as possible, fixed lots of little bugs (including bugs that
    24   affected daemon mode stability). See the bzr logs for more information.
    25 - Added units tests, will have to add some more before the real release.
     34  I/O as much as possible, replaced the Gaim (0.59, IOW heavily outdated)
     35  API, fixed lots of little bugs (including bugs that affected daemon mode
     36  stability). See the bzr logs for more information.
     37- One of the user-visible changes from the API change: You can finally see
     38  all away states/messages properly.
     39- Added units tests. Test coverage is very minimal for now.
     40- Better charset handling: Everything is just converted from/to UTF-8 right
     41  in the IRC core, and charset mismatches are detected (if possible) and the
     42  user is asked to resolve this before continuing. Also, UTF-8 is the default
     43  setting now, since that's how the world seems to work these days.
     44- One can now keep hashed passwords in bitlbee.conf instead of the cleartext
     45  version.
    2646- Most important change: New file format for user data (accounts, nicks and
    2747  settings). Migration to the new format should happen transparently,
     
    6989  * An XML console (add xmlconsole to your contact list or see "help set
    7090    xmlconsole" if you want it permanently).
    71 
    72 Finished ???
     91- The Yahoo! module now says it supports YMSG protocol version 12, which will
     92  hopefully keep the Yahoo module working after 2008-04-02 (when Yahoo! is
     93  dropping support for version 6.x of their client).
     94- MSN switchboard handling changes. Hopefully less messages will get lost now,
     95  although things are still not perfect.
     96
     97Finished 17 Mar 2008
    7398
    7499Version 1.0.4:
  • doc/README

    r6cac643 rb79308b  
    4141by default) and chown it to the UID BitlBee is running as. Make sure this
    4242directory is read-/writable by this user only.
     43
     44--- (Fork)Daemon mode
     45
     46If you don't want to run any inetd daemon, you can run BitlBee in Daemon
     47mode. Right now, daemon mode may be a bad idea on servers with multiple
     48users, since possible fatal BitlBee bugs will crash the BitlBee process and
     49disconnect all connected users at once. Instead, you can use ForkDaemon
     50mode, which serves every user from a separate process, without depending on
     51an inetd daemon.
     52
     53To use BitlBee in daemon mode, just start it with the right flags or enable
     54it in bitlbee.conf. You probably want to write an init script to start
     55BitlBee automatically after a reboot. (This is where you realise using
     56a package from your distro would've been a better idea. :-P)
    4357
    4458
  • doc/user-guide/Support.xml

    r6cac643 rb79308b  
    44
    55<sect1>
    6 <title>BitlBee is beta software</title>
     6<title>Disclaimer</title>
    77
    88<para>
    9 Although BitlBee has quite some functionality it is still beta. That means it
    10 can crash at any time, corrupt your data or whatever. Don't use it in
    11 any production environment and don't rely on it.
     9BitlBee doesn't come with a warranty and is still (and will probably always
     10be) under development. That means it can crash at any time, corrupt your
     11data or whatever. Don't use it in any production environment and don't rely
     12on it, or at least don't blame us if things blow up. :-)
    1213</para>
    1314
  • doc/user-guide/commands.xml

    r6cac643 rb79308b  
    163163
    164164                        <para>
    165                                 If you want, you can also tell BitlBee what nick to give the new contact. Of course you can also use the <emphasis>rename</emphasis> command for that, but sometimes this might be more convenient.
    166                         </para>
    167                        
    168                         <para>
    169                                 Adding -tmp adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by <emphasis>set handle_unknown add</emphasis>). This allows you to talk to people who are not in your contact list.
     165                                If you want, you can also tell BitlBee what nick to give the new contact. The -tmp option adds the buddy to the internal BitlBee structures only, not to the real contact list (like done by <emphasis>set handle_unknown add</emphasis>). This allows you to talk to people who are not in your contact list. This normally won't show you any presence notifications.
    170166                        </para>
    171167                </description>
     
    383379
    384380        <bitlbee-setting name="charset" type="string" scope="global">
    385                 <default>iso8859-1</default>
     381                <default>utf-8</default>
    386382                <possible-values>you can get a list of all possible values by doing 'iconv -l' in a shell</possible-values>
    387383
    388384                <description>
    389385                        <para>
    390                                 The charset setting enables you to use different character sets in BitlBee. These get converted to UTF-8 before sending and from UTF-8 when receiving.
    391                         </para>
    392 
    393                         <para>
    394                                 If you don't know what's the best value for this, at least iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://czyborra.com/charsets/iso8859.html
     386                                This setting tells BitlBee what your IRC client sends and expects. It should be equal to the charset setting of your IRC client if you want to be able to send and receive non-ASCII text properly.
     387                        </para>
     388
     389                        <para>
     390                                Most systems use UTF-8 these days. On older systems, an iso8859 charset may work better. For example, iso8859-1 is the best choice for most Western countries. You can try to find what works best for you on http://www.unicodecharacter.com/charsets/iso8859.html
    395391                        </para>
    396392                </description>
     
    593589        </bitlbee-setting>
    594590
     591        <bitlbee-setting name="root_nick" type="string" scope="global">
     592                <default>root</default>
     593
     594                <description>
     595                        <para>
     596                                Normally the "bot" that takes all your BitlBee commands is called "root". If you don't like this name, you can rename it to anything else using the <emphasis>rename</emphasis> command, or by changing this setting.
     597                        </para>
     598                </description>
     599        </bitlbee-setting>
     600
    595601        <bitlbee-setting name="save_on_quit" type="boolean" scope="global">
    596602                <default>true</default>
     
    677683                <description>
    678684                        <para>
    679                                 Sends you a /notice when a user starts typing a message (if the protocol supports it, MSN for example). This is a bug, not a feature. (But please don't report it.. ;-) You don't want to use it. Really. In fact the typing-notification is just one of the least useful 'innovations' ever. It's just there because some guy will probably ask me about it anyway. ;-)
     685                                Sends you a /notice when a user starts typing a message (if supported by the IM protocol and the user's client). To use this, you most likely want to use a script in your IRC client to show this information in a more sensible way.
    680686                        </para>
    681687                </description>
     
    830836                <short-description>Change friendly name, nick</short-description>
    831837                <syntax>nick &lt;connection&gt; [&lt;new nick&gt;]</syntax>
    832                 <syntax>nick</syntax>
    833 
    834                 <description>
    835                         <para>
    836                                 This command allows to set the friendly name of an im account. If no new name is specified the command will report the current name. When the name contains spaces, don't forget to quote the whole nick in double quotes. Currently this command is only supported by the MSN protocol.
    837                         </para>
    838 
    839                         <para>
    840                                 It is recommended to use the per-account <emphasis>display_name</emphasis> setting to read and change this information. The <emphasis>nick</emphasis> command is deprecated.
     838                <syntax>nick &lt;connection&gt;</syntax>
     839
     840                <description>
     841                        <para>
     842                                Deprecated: Use the per-account <emphasis>display_name</emphasis> setting to read and change this information.
    841843                        </para>
    842844                </description>
    843845
    844846                <ircexample>
    845                         <ircline nick="wouter">nick 1 "Wouter Paesen"</ircline>
    846                         <ircline nick="root">Setting your name on connection 1 to `Wouter Paesen'</ircline>
     847                        <ircline nick="wouter">account set 1/display_name "The majestik møøse"</ircline>
     848                        <ircline nick="root">display_name = `The majestik møøse'</ircline>
    847849                </ircexample>
    848850
  • doc/user-guide/misc.xml

    r6cac643 rb79308b  
    4747</variablelist>
    4848
    49 <para>
    50 This list was extracted from <ulink url="http://help.msn.com/!data/en_us/data/messengerv50.its51/$content$/EMOTICONS.HTM?H_APP=">http://help.msn.com/!data/en_us/data/messengerv50.its51/$content$/EMOTICONS.HTM?H_APP=</ulink>.
    51 </para>
    52 
    5349</sect1>
    5450
     
    5652<title>Groupchats</title>
    5753<para>
    58 Since version 0.8x, BitlBee supports groupchats on the MSN and Yahoo! networks. This text will try to explain you how they work.
     54BitlBee now supports groupchats on all IM networks. This text will try to explain you how they work.
    5955</para>
    6056
     
    7369
    7470<para>
    75 If you want to start a groupchat with the person <emphasis>jim_msn</emphasis> in it, just join the channel <emphasis>#jim_msn</emphasis>. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and jim_msn in it.
     71If you want to start a groupchat with the person <emphasis>lisa_msn</emphasis> in it, just join the channel <emphasis>#lisa_msn</emphasis>. BitlBee will refuse to join you to the channel with that name, but it will create a new virtual channel with root, you and lisa_msn in it.
    7672</para>
    7773
     
    8278<para>
    8379Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>join_chat</emphasis> command to join them. See <emphasis>help join_chat</emphasis> for more information.
    84 </para>
    85 
    86 <para>
    87 This is all you'll probably need to know. If you have any problems, please read <emphasis>help groupchats3</emphasis>.
    88 </para>
    89 
    90 </sect1>
    91 
    92 <sect1 id="groupchats3">
    93 <title>Groupchat channel names</title>
    94 
    95 <para>
    96 Obviously the (numbered) channel names don't make a lot of sense. Problem is that groupchats usually don't have names at all in the IM-world, while IRC insists on a name. So BitlBee just generates something random, just don't pay attention to it. :-)
    97 </para>
    98 
    99 <para>
    100 Please also note that BitlBee doesn't support groupchats for all protocols yet. BitlBee will tell you so. Support for other protocols will hopefully come later.
    10180</para>
    10281
     
    121100        <member>On the phone, Phone, On phone</member>
    122101        <member>Out to lunch, Lunch, Food</member>
     102        <member>Invisible, Hidden</member>
    123103</simplelist>
    124104
     
    128108
    129109<para>
    130 You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Protocols like Yahoo! and Jabber will also show this complete away message to your buddies.
     110You can also add more information to your away message. Setting it to "Busy - Fixing BitlBee bugs" will set your IM-away-states to Busy, but your away message will be more descriptive for people on IRC. Most IM-protocols can also show this additional information to your buddies.
    131111</para>
    132112
  • doc/user-guide/quickstart.xml

    r6cac643 rb79308b  
    6161
    6262<para>
    63 For most protocols (currently MSN, Jabber, Yahoo and AOL) BitlBee can download the contact list automatically from the IM server and all the on-line users should appear in the control channel when you log in.
     63Now BitlBee logs in and downloads the contact list from the IM server. In a few seconds, all your on-line buddies should show up in the control channel.
    6464</para>
    6565
    6666<para>
    67 BitlBee will convert names into irc-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo.
     67BitlBee will convert names into IRC-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo.
    6868</para>
    6969
     
    127127<ircexample>
    128128        <ircline nick="you">tux: hey, how's the weather down there?</ircline>
    129         <ircline nick="tux"> you: a bit chilly!</ircline>
     129        <ircline nick="tux">you: a bit chilly!</ircline>
    130130</ircexample>
    131131
    132132<para>
    133 If you'd rather chat with them in a separate window use the <emphasis>/msg</emphasis> or <emphasis>/query</emphasis> command, just like you would for a private message in IRC.  If you want to have messages automatically come up in private messages rather than in the &amp;bitlbee channel, use the <emphasis>set private</emphasis> command: <emphasis>set private true</emphasis> (<emphasis>set private false</emphasis> to change back).
     133Note that, although all contacts are in the &amp;bitlbee channel, only tux will actually receive this message. The &amp;bitlbee channel shouldn't be confused with a real IRC channel.
     134</para>
     135
     136<para>
     137If you prefer chatting in a separate window, use the <emphasis>/msg</emphasis> or <emphasis>/query</emphasis> command, just like on real IRC. BitlBee will remember how you talk to someone and show his/her responses the same way. If you want to change the default behaviour (for people you haven't talked to yet), see <emphasis>help set private</emphasis>.
    134138</para>
    135139
  • ipc.c

    r6cac643 rb79308b  
    258258        else
    259259        {
     260                ipc_master_free_fd( source );
     261        }
     262       
     263        return TRUE;
     264}
     265
     266gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond )
     267{
     268        char *buf, **cmd;
     269       
     270        if( ( buf = ipc_readline( source ) ) )
     271        {
     272                cmd = irc_parse_line( buf );
     273                if( cmd )
     274                        ipc_command_exec( data, cmd, ipc_child_commands );
     275        }
     276        else
     277        {
     278                ipc_child_disable();
     279        }
     280       
     281        return TRUE;
     282}
     283
     284void ipc_to_master( char **cmd )
     285{
     286        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     287        {
     288                char *s = irc_build_line( cmd );
     289                ipc_to_master_str( "%s", s );
     290                g_free( s );
     291        }
     292        else if( global.conf->runmode == RUNMODE_DAEMON )
     293        {
     294                ipc_command_exec( NULL, cmd, ipc_master_commands );
     295        }
     296}
     297
     298void ipc_to_master_str( char *format, ... )
     299{
     300        char *msg_buf;
     301        va_list params;
     302
     303        va_start( params, format );
     304        msg_buf = g_strdup_vprintf( format, params );
     305        va_end( params );
     306       
     307        if( strlen( msg_buf ) > 512 )
     308        {
     309                /* Don't send it, it's too long... */
     310        }
     311        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
     312        {
     313                if( global.listen_socket >= 0 )
     314                        if( write( global.listen_socket, msg_buf, strlen( msg_buf ) ) <= 0 )
     315                                ipc_child_disable();
     316        }
     317        else if( global.conf->runmode == RUNMODE_DAEMON )
     318        {
     319                char **cmd, *s;
     320               
     321                if( ( s = strchr( msg_buf, '\r' ) ) )
     322                        *s = 0;
     323               
     324                cmd = irc_parse_line( msg_buf );
     325                ipc_command_exec( NULL, cmd, ipc_master_commands );
     326                g_free( cmd );
     327        }
     328       
     329        g_free( msg_buf );
     330}
     331
     332void ipc_to_children( char **cmd )
     333{
     334        if( global.conf->runmode == RUNMODE_FORKDAEMON )
     335        {
     336                char *msg_buf = irc_build_line( cmd );
     337                ipc_to_children_str( "%s", msg_buf );
     338                g_free( msg_buf );
     339        }
     340        else if( global.conf->runmode == RUNMODE_DAEMON )
     341        {
    260342                GSList *l;
    261                 struct bitlbee_child *c;
    262                
    263                 for( l = child_list; l; l = l->next )
     343               
     344                for( l = irc_connection_list; l; l = l->next )
     345                        ipc_command_exec( l->data, cmd, ipc_child_commands );
     346        }
     347}
     348
     349void ipc_to_children_str( char *format, ... )
     350{
     351        char *msg_buf;
     352        va_list params;
     353
     354        va_start( params, format );
     355        msg_buf = g_strdup_vprintf( format, params );
     356        va_end( params );
     357       
     358        if( strlen( msg_buf ) > 512 )
     359        {
     360                /* Don't send it, it's too long... */
     361        }
     362        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
     363        {
     364                int msg_len = strlen( msg_buf );
     365                GSList *l, *next;
     366               
     367                for( l = child_list; l; l = next )
    264368                {
    265                         c = l->data;
    266                         if( c->ipc_fd == source )
     369                        struct bitlbee_child *c = l->data;
     370                       
     371                        next = l->next;
     372                        if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 )
    267373                        {
    268374                                ipc_master_free_one( c );
    269375                                child_list = g_slist_remove( child_list, c );
    270                                 break;
    271376                        }
    272                 }
    273         }
    274        
    275         return TRUE;
    276 }
    277 
    278 gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond )
    279 {
    280         char *buf, **cmd;
    281        
    282         if( ( buf = ipc_readline( source ) ) )
    283         {
    284                 cmd = irc_parse_line( buf );
    285                 if( cmd )
    286                         ipc_command_exec( data, cmd, ipc_child_commands );
    287         }
    288         else
    289         {
    290                 b_event_remove( global.listen_watch_source_id );
    291                 close( global.listen_socket );
    292                
    293                 global.listen_socket = -1;
    294         }
    295        
    296         return TRUE;
    297 }
    298 
    299 void ipc_to_master( char **cmd )
    300 {
    301         if( global.conf->runmode == RUNMODE_FORKDAEMON )
    302         {
    303                 char *s = irc_build_line( cmd );
    304                 ipc_to_master_str( "%s", s );
    305                 g_free( s );
    306         }
    307         else if( global.conf->runmode == RUNMODE_DAEMON )
    308         {
    309                 ipc_command_exec( NULL, cmd, ipc_master_commands );
    310         }
    311 }
    312 
    313 void ipc_to_master_str( char *format, ... )
    314 {
    315         char *msg_buf;
    316         va_list params;
    317 
    318         va_start( params, format );
    319         msg_buf = g_strdup_vprintf( format, params );
    320         va_end( params );
    321        
    322         if( strlen( msg_buf ) > 512 )
    323         {
    324                 /* Don't send it, it's too long... */
    325         }
    326         else if( global.conf->runmode == RUNMODE_FORKDAEMON )
    327         {
    328                 write( global.listen_socket, msg_buf, strlen( msg_buf ) );
    329         }
    330         else if( global.conf->runmode == RUNMODE_DAEMON )
    331         {
    332                 char **cmd, *s;
    333                
    334                 if( ( s = strchr( msg_buf, '\r' ) ) )
    335                         *s = 0;
    336                
    337                 cmd = irc_parse_line( msg_buf );
    338                 ipc_command_exec( NULL, cmd, ipc_master_commands );
    339                 g_free( cmd );
    340         }
    341        
    342         g_free( msg_buf );
    343 }
    344 
    345 void ipc_to_children( char **cmd )
    346 {
    347         if( global.conf->runmode == RUNMODE_FORKDAEMON )
    348         {
    349                 char *msg_buf = irc_build_line( cmd );
    350                 ipc_to_children_str( "%s", msg_buf );
    351                 g_free( msg_buf );
    352         }
    353         else if( global.conf->runmode == RUNMODE_DAEMON )
    354         {
    355                 GSList *l;
    356                
    357                 for( l = irc_connection_list; l; l = l->next )
    358                         ipc_command_exec( l->data, cmd, ipc_child_commands );
    359         }
    360 }
    361 
    362 void ipc_to_children_str( char *format, ... )
    363 {
    364         char *msg_buf;
    365         va_list params;
    366 
    367         va_start( params, format );
    368         msg_buf = g_strdup_vprintf( format, params );
    369         va_end( params );
    370        
    371         if( strlen( msg_buf ) > 512 )
    372         {
    373                 /* Don't send it, it's too long... */
    374         }
    375         else if( global.conf->runmode == RUNMODE_FORKDAEMON )
    376         {
    377                 int msg_len = strlen( msg_buf );
    378                 GSList *l;
    379                
    380                 for( l = child_list; l; l = l->next )
    381                 {
    382                         struct bitlbee_child *c = l->data;
    383                         write( c->ipc_fd, msg_buf, msg_len );
    384377                }
    385378        }
     
    410403}
    411404
     405void ipc_master_free_fd( int fd )
     406{
     407        GSList *l;
     408        struct bitlbee_child *c;
     409       
     410        for( l = child_list; l; l = l->next )
     411        {
     412                c = l->data;
     413                if( c->ipc_fd == fd )
     414                {
     415                        ipc_master_free_one( c );
     416                        child_list = g_slist_remove( child_list, c );
     417                        break;
     418                }
     419        }
     420}
     421
    412422void ipc_master_free_all()
    413423{
     
    419429        g_slist_free( child_list );
    420430        child_list = NULL;
     431}
     432
     433void ipc_child_disable()
     434{
     435        b_event_remove( global.listen_watch_source_id );
     436        close( global.listen_socket );
     437       
     438        global.listen_socket = -1;
    421439}
    422440
  • ipc.h

    r6cac643 rb79308b  
    4444
    4545void ipc_master_free_one( struct bitlbee_child *child );
     46void ipc_master_free_fd( int fd );
    4647void ipc_master_free_all();
     48
     49void ipc_child_disable();
    4750
    4851void ipc_to_master( char **cmd );
  • irc.c

    r6cac643 rb79308b  
    4646}
    4747
     48static char *set_eval_charset( set_t *set, char *value )
     49{
     50        irc_t *irc = set->data;
     51        GIConv ic, oc;
     52
     53        if( g_strcasecmp( value, "none" ) == 0 )
     54                value = g_strdup( "utf-8" );
     55
     56        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
     57        {
     58                return NULL;
     59        }
     60        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     61        {
     62                g_iconv_close( ic );
     63                return NULL;
     64        }
     65       
     66        if( irc->iconv != (GIConv) -1 )
     67                g_iconv_close( irc->iconv );
     68        if( irc->oconv != (GIConv) -1 )
     69                g_iconv_close( irc->oconv );
     70       
     71        irc->iconv = ic;
     72        irc->oconv = oc;
     73
     74        return value;
     75}
     76
    4877irc_t *irc_new( int fd )
    4978{
     
    6897        irc->mynick = g_strdup( ROOT_NICK );
    6998        irc->channel = g_strdup( ROOT_CHAN );
     99       
     100        irc->iconv = (GIConv) -1;
     101        irc->oconv = (GIConv) -1;
    70102       
    71103        if( global.conf->hostname )
     
    123155        set_add( &irc->set, "private", "true", set_eval_bool, irc );
    124156        set_add( &irc->set, "query_order", "lifo", NULL, irc );
     157        set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
    125158        set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
    126159        set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
     
    131164        conf_loaddefaults( irc );
    132165       
     166        /* Evaluator sets the iconv/oconv structures. */
     167        set_eval_charset( set_find( &irc->set, "charset" ), set_getstr( &irc->set, "charset" ) );
     168       
    133169        return( irc );
    134170}
     
    168204        if( irc->sendbuffer && !immed )
    169205        {
    170                 /* We won't read from this socket anymore. Instead, we'll connect a timer
    171                    to it that should shut down the connection in a second, just in case
    172                    bitlbee_.._write doesn't do it first. */
     206                /* Set up a timeout event that should shut down the connection
     207                   in a second, just in case ..._write doesn't do it first. */
    173208               
    174209                b_event_remove( irc->r_watch_source_id );
    175                 irc->r_watch_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
     210                irc->r_watch_source_id = 0;
     211               
     212                b_event_remove( irc->ping_source_id );
     213                irc->ping_source_id = b_timeout_add( 1000, (b_event_handler) irc_free, irc );
    176214        }
    177215        else
     
    189227
    190228/* Because we have no garbage collection, this is quite annoying */
    191 void irc_free(irc_t * irc)
    192 {
    193         account_t *account;
     229void irc_free( irc_t * irc )
     230{
    194231        user_t *user, *usertmp;
    195232       
     
    200237                        irc_usermsg( irc, "Error while saving settings!" );
    201238       
    202         closesocket( irc->fd );
    203        
    204         if( irc->ping_source_id > 0 )
    205                 b_event_remove( irc->ping_source_id );
    206         b_event_remove( irc->r_watch_source_id );
    207         if( irc->w_watch_source_id > 0 )
    208                 b_event_remove( irc->w_watch_source_id );
    209        
    210239        irc_connection_list = g_slist_remove( irc_connection_list, irc );
    211240       
    212         for (account = irc->accounts; account; account = account->next) {
    213                 if (account->ic) {
    214                         imc_logout(account->ic, TRUE);
    215                 } else if (account->reconnect) {
    216                         cancel_auto_reconnect(account);
    217                 }
    218         }
    219        
    220         g_free(irc->sendbuffer);
    221         g_free(irc->readbuffer);
    222        
    223         g_free(irc->nick);
    224         g_free(irc->user);
    225         g_free(irc->host);
    226         g_free(irc->realname);
    227         g_free(irc->password);
    228        
    229         g_free(irc->myhost);
    230         g_free(irc->mynick);
    231        
    232         g_free(irc->channel);
    233        
    234         while (irc->queries != NULL)
    235                 query_del(irc, irc->queries);
    236        
    237         while (irc->accounts)
    238                 if (irc->accounts->ic == NULL)
    239                         account_del(irc, irc->accounts);
     241        while( irc->accounts )
     242        {
     243                if( irc->accounts->ic )
     244                        imc_logout( irc->accounts->ic, FALSE );
     245                else if( irc->accounts->reconnect )
     246                        cancel_auto_reconnect( irc->accounts );
     247               
     248                if( irc->accounts->ic == NULL )
     249                        account_del( irc, irc->accounts );
    240250                else
    241251                        /* Nasty hack, but account_del() doesn't work in this
    242252                           case and we don't want infinite loops, do we? ;-) */
    243253                        irc->accounts = irc->accounts->next;
    244        
    245         while (irc->set)
    246                 set_del(&irc->set, irc->set->key);
    247        
    248         if (irc->users != NULL) {
     254        }
     255       
     256        while( irc->queries != NULL )
     257                query_del( irc, irc->queries );
     258       
     259        while( irc->set )
     260                set_del( &irc->set, irc->set->key );
     261       
     262        if (irc->users != NULL)
     263        {
    249264                user = irc->users;
    250                 while (user != NULL) {
    251                         g_free(user->nick);
    252                         g_free(user->away);
    253                         g_free(user->handle);
    254                         if(user->user!=user->nick) g_free(user->user);
    255                         if(user->host!=user->nick) g_free(user->host);
    256                         if(user->realname!=user->nick) g_free(user->realname);
    257                         b_event_remove(user->sendbuf_timer);
     265                while( user != NULL )
     266                {
     267                        g_free( user->nick );
     268                        g_free( user->away );
     269                        g_free( user->handle );
     270                        if( user->user != user->nick ) g_free( user->user );
     271                        if( user->host != user->nick ) g_free( user->host );
     272                        if( user->realname != user->nick ) g_free( user->realname );
     273                        b_event_remove( user->sendbuf_timer );
    258274                                       
    259275                        usertmp = user;
    260276                        user = user->next;
    261                         g_free(usertmp);
    262                 }
    263         }
    264        
    265         g_hash_table_foreach_remove(irc->userhash, irc_free_hashkey, NULL);
    266         g_hash_table_destroy(irc->userhash);
    267        
    268         g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);
    269         g_hash_table_destroy(irc->watches);
    270        
    271         g_free(irc);
     277                        g_free( usertmp );
     278                }
     279        }
     280       
     281        if( irc->ping_source_id > 0 )
     282                b_event_remove( irc->ping_source_id );
     283        if( irc->r_watch_source_id > 0 )
     284                b_event_remove( irc->r_watch_source_id );
     285        if( irc->w_watch_source_id > 0 )
     286                b_event_remove( irc->w_watch_source_id );
     287       
     288        closesocket( irc->fd );
     289        irc->fd = -1;
     290       
     291        g_hash_table_foreach_remove( irc->userhash, irc_free_hashkey, NULL );
     292        g_hash_table_destroy( irc->userhash );
     293       
     294        g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL );
     295        g_hash_table_destroy( irc->watches );
     296       
     297        if( irc->iconv != (GIConv) -1 )
     298                g_iconv_close( irc->iconv );
     299        if( irc->oconv != (GIConv) -1 )
     300                g_iconv_close( irc->oconv );
     301       
     302        g_free( irc->sendbuffer );
     303        g_free( irc->readbuffer );
     304       
     305        g_free( irc->nick );
     306        g_free( irc->user );
     307        g_free( irc->host );
     308        g_free( irc->realname );
     309        g_free( irc->password );
     310       
     311        g_free( irc->myhost );
     312        g_free( irc->mynick );
     313       
     314        g_free( irc->channel );
     315       
     316        g_free( irc->last_target );
     317       
     318        g_free( irc );
    272319       
    273320        if( global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON )
     
    290337void irc_process( irc_t *irc )
    291338{
    292         char **lines, *temp, **cmd, *cs;
     339        char **lines, *temp, **cmd;
    293340        int i;
    294341
     
    299346                for( i = 0; *lines[i] != '\0'; i ++ )
    300347                {
    301                         char conv[IRC_MAX_LINE+1];
     348                        char *conv = NULL;
    302349                       
    303                         /* [WvG] Because irc_tokenize splits at every newline, the lines[] list
    304                             should end with an empty string. This is why this actually works.
    305                             Took me a while to figure out, Maurits. :-P */
     350                        /* [WvG] If the last line isn't empty, it's an incomplete line and we
     351                           should wait for the rest to come in before processing it. */
    306352                        if( lines[i+1] == NULL )
    307353                        {
     
    313359                        }
    314360                       
    315                         if( ( cs = set_getstr( &irc->set, "charset" ) ) )
    316                         {
    317                                 conv[IRC_MAX_LINE] = 0;
    318                                 if( do_iconv( cs, "UTF-8", lines[i], conv, 0, IRC_MAX_LINE - 2 ) == -1 )
     361                        if( irc->iconv != (GIConv) -1 )
     362                        {
     363                                gsize bytes_read, bytes_written;
     364                               
     365                                conv = g_convert_with_iconv( lines[i], -1, irc->iconv,
     366                                                             &bytes_read, &bytes_written, NULL );
     367                               
     368                                if( conv == NULL || bytes_read != strlen( lines[i] ) )
    319369                                {
    320370                                        /* GLib can do strange things if things are not in the expected charset,
     
    328378                                                                  "expect by changing the charset setting. See "
    329379                                                                  "`help set charset' for more information. Your "
    330                                                                   "message was ignored.", cs );
    331                                                 *conv = 0;
     380                                                                  "message was ignored.",
     381                                                                  set_getstr( &irc->set, "charset" ) );
     382                                               
     383                                                g_free( conv );
     384                                                conv = NULL;
    332385                                        }
    333386                                        else
    334387                                        {
    335388                                                irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost,
    336                                                            "Warning: invalid (non-UTF8) characters received at login time." );
     389                                                           "Warning: invalid characters received at login time." );
    337390                                               
    338                                                 strncpy( conv, lines[i], IRC_MAX_LINE );
     391                                                conv = g_strdup( lines[i] );
    339392                                                for( temp = conv; *temp; temp ++ )
    340393                                                        if( *temp & 0x80 )
     
    345398                        }
    346399                       
    347                         if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
    348                                 continue;
    349                         irc_exec( irc, cmd );
     400                        if( lines[i] )
     401                        {
     402                                if( ( cmd = irc_parse_line( lines[i] ) ) == NULL )
     403                                        continue;
     404                                irc_exec( irc, cmd );
     405                                g_free( cmd );
     406                        }
    350407                       
    351                         g_free( cmd );
     408                        g_free( conv );
    352409                       
    353410                        /* Shouldn't really happen, but just in case... */
     
    373430char **irc_tokenize( char *buffer )
    374431{
    375         int i, j;
     432        int i, j, n = 3;
    376433        char **lines;
    377434
    378         /* Count the number of elements we're gonna need. */
    379         for( i = 0, j = 1; buffer[i] != '\0'; i ++ )
    380         {
    381                 if( buffer[i] == '\n' )
    382                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    383                                 j ++;
    384         }
    385        
    386         /* Allocate j+1 elements. */
    387         lines = g_new( char *, j + 1 );
     435        /* Allocate n+1 elements. */
     436        lines = g_new( char *, n + 1 );
     437       
     438        lines[0] = buffer;
     439       
     440        /* Split the buffer in several strings, and accept any kind of line endings,
     441         * knowing that ERC on Windows may send something interesting like \r\r\n,
     442         * and surely there must be clients that think just \n is enough... */
     443        for( i = 0, j = 0; buffer[i] != '\0'; i ++ )
     444        {
     445                if( buffer[i] == '\r' || buffer[i] == '\n' )
     446                {
     447                        while( buffer[i] == '\r' || buffer[i] == '\n' )
     448                                buffer[i++] = '\0';
     449                       
     450                        lines[++j] = buffer + i;
     451                       
     452                        if( j >= n )
     453                        {
     454                                n *= 2;
     455                                lines = g_renew( char *, lines, n + 1 );
     456                        }
     457
     458                        if( buffer[i] == '\0' )
     459                                break;
     460                }
     461        }
    388462       
    389463        /* NULL terminate our list. */
    390         lines[j] = NULL;
    391        
    392         lines[0] = buffer;
    393        
    394         /* Split the buffer in several strings, using \r\n as our seperator, where \r is optional.
    395          * Although this is not in the RFC, some braindead ircds (newnet's) use this, so some clients might too.
    396          */
    397         for( i = 0, j = 0; buffer[i] != '\0'; i ++)
    398         {
    399                 if( buffer[i] == '\n' )
    400                 {
    401                         buffer[i] = '\0';
    402                        
    403                         if( i > 0 && buffer[i-1] == '\r' )
    404                                 buffer[i-1] = '\0';
    405                         if( buffer[i+1] != '\r' && buffer[i+1] != '\n' )
    406                                 lines[++j] = buffer + i + 1;
    407                 }
    408         }
    409        
    410         return( lines );
     464        lines[++j] = NULL;
     465       
     466        return lines;
    411467}
    412468
     
    542598
    543599        return;
    544 
    545600}
    546601
     
    548603{
    549604        int size;
    550         char line[IRC_MAX_LINE+1], *cs;
     605        char line[IRC_MAX_LINE+1];
    551606               
    552607        /* Don't try to write anything new anymore when shutting down. */
     
    554609                return;
    555610       
    556         line[IRC_MAX_LINE] = 0;
     611        memset( line, 0, sizeof( line ) );
    557612        g_vsnprintf( line, IRC_MAX_LINE - 2, format, params );
    558        
    559613        strip_newlines( line );
    560         if( ( cs = set_getstr( &irc->set, "charset" ) ) && ( g_strcasecmp( cs, "utf-8" ) != 0 ) )
    561         {
    562                 char conv[IRC_MAX_LINE+1];
    563                
    564                 conv[IRC_MAX_LINE] = 0;
    565                 if( do_iconv( "UTF-8", cs, line, conv, 0, IRC_MAX_LINE - 2 ) != -1 )
    566                         strcpy( line, conv );
    567         }
    568         strcat( line, "\r\n" );
     614       
     615        if( irc->oconv != (GIConv) -1 )
     616        {
     617                gsize bytes_read, bytes_written;
     618                char *conv;
     619               
     620                conv = g_convert_with_iconv( line, -1, irc->oconv,
     621                                             &bytes_read, &bytes_written, NULL );
     622
     623                if( bytes_read == strlen( line ) )
     624                        strncpy( line, conv, IRC_MAX_LINE - 2 );
     625               
     626                g_free( conv );
     627        }
     628        g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 );
    569629       
    570630        if( irc->sendbuffer != NULL )
     
    739799        irc_spawn( irc, u );
    740800       
    741         irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\nIf you've never used BitlBee before, please do read the help information using the \x02help\x02 command. Lots of FAQs are answered there." );
     801        irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
     802                          "If you've never used BitlBee before, please do read the help "
     803                          "information using the \x02help\x02 command. Lots of FAQs are "
     804                          "answered there.\n"
     805                          "If you already have an account on this server, just use the "
     806                          "\x02identify\x02 command to identify yourself." );
    742807       
    743808        if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
     
    745810       
    746811        irc->status |= USTATUS_LOGGED_IN;
     812       
     813        /* This is for bug #209 (use PASS to identify to NickServ). */
     814        if( irc->password != NULL )
     815        {
     816                char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
     817               
     818                irc_setpass( irc, NULL );
     819                root_command( irc, send_cmd );
     820                g_free( send_cmd[1] );
     821        }
    747822}
    748823
  • irc.h

    r6cac643 rb79308b  
    6161        char *sendbuffer;
    6262        char *readbuffer;
     63        GIConv iconv, oconv;
    6364
    6465        int sentbytes;
     
    6970        char *host;
    7071        char *realname;
    71         char *password;
     72        char *password; /* HACK: Used to save the user's password, but before
     73                           logging in, this may contain a password we should
     74                           send to identify after USER/NICK are received. */
    7275
    7376        char umode[8];
  • irc_commands.c

    r6cac643 rb79308b  
    3030static void irc_cmd_pass( irc_t *irc, char **cmd )
    3131{
    32         if( global.conf->auth_pass && strcmp( cmd[1], global.conf->auth_pass ) == 0 )
     32        if( irc->status & USTATUS_LOGGED_IN )
     33        {
     34                char *send_cmd[] = { "identify", cmd[1], NULL };
     35               
     36                /* We're already logged in, this client seems to send the PASS
     37                   command last. (Possibly it won't send it at all if it turns
     38                   out we don't require it, which will break this feature.)
     39                   Try to identify using the given password. */
     40                return root_command( irc, send_cmd );
     41        }
     42        /* Handling in pre-logged-in state, first see if this server is
     43           password-protected: */
     44        else if( global.conf->auth_pass &&
     45            ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ?
     46                md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 :
     47                strcmp( cmd[1], global.conf->auth_pass ) == 0 ) )
    3348        {
    3449                irc->status |= USTATUS_AUTHORIZED;
    3550                irc_check_login( irc );
    3651        }
    37         else
     52        else if( global.conf->auth_pass )
    3853        {
    3954                irc_reply( irc, 464, ":Incorrect password" );
     55        }
     56        else
     57        {
     58                /* Remember the password and try to identify after USER/NICK. */
     59                irc_setpass( irc, cmd[1] );
     60                irc_check_login( irc );
    4061        }
    4162}
     
    88109static void irc_cmd_oper( irc_t *irc, char **cmd )
    89110{
    90         if( global.conf->oper_pass && strcmp( cmd[2], global.conf->oper_pass ) == 0 )
     111        if( global.conf->oper_pass &&
     112            ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ?
     113                md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 :
     114                strcmp( cmd[2], global.conf->oper_pass ) == 0 ) )
    91115        {
    92116                irc_umode_set( irc, "+o", 1 );
     
    254278                        if( cmd[1] != irc->last_target )
    255279                        {
    256                                 if( irc->last_target )
    257                                         g_free( irc->last_target );
     280                                g_free( irc->last_target );
    258281                                irc->last_target = g_strdup( cmd[1] );
    259282                        }
     
    575598
    576599static const command_t irc_commands[] = {
    577         { "pass",        1, irc_cmd_pass,        IRC_CMD_PRE_LOGIN },
     600        { "pass",        1, irc_cmd_pass,        0 },
    578601        { "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
    579602        { "nick",        1, irc_cmd_nick,        0 },
  • lib/Makefile

    r6cac643 rb79308b  
    1010
    1111# [SH] Program variables
    12 objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o
     12objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
    1313
    1414CFLAGS += -Wall
     
    1818all: lib.o
    1919check: all
    20 lcov:
     20lcov: check
    2121gcov:
    2222        gcov *.c
  • lib/arc.c

    r6cac643 rb79308b  
    131131   
    132132   Both functions return the number of bytes in the result string.
     133   
     134   Note that if you use the pad_to argument, you will need zero-termi-
     135   nation to find back the original string length after decryption. So
     136   it shouldn't be used if your string contains \0s by itself!
    133137*/
    134138
    135 int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password )
     139int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to )
    136140{
    137141        struct arc_state *st;
    138142        unsigned char *key;
    139         int key_len, i;
     143        char *padded = NULL;
     144        int key_len, i, padded_len;
    140145       
    141146        key_len = strlen( password ) + ARC_IV_LEN;
    142147        if( clear_len <= 0 )
    143148                clear_len = strlen( clear );
     149       
     150        /* Pad the string to the closest multiple of pad_to. This makes it
     151           impossible to see the exact length of the password. */
     152        if( pad_to > 0 && ( clear_len % pad_to ) > 0 )
     153        {
     154                padded_len = clear_len + pad_to - ( clear_len % pad_to );
     155                padded = g_malloc( padded_len );
     156                memcpy( padded, clear, clear_len );
     157               
     158                /* First a \0 and then random data, so we don't have to do
     159                   anything special when decrypting. */
     160                padded[clear_len] = 0;
     161                random_bytes( (unsigned char*) padded + clear_len + 1, padded_len - clear_len - 1 );
     162               
     163                clear = padded;
     164                clear_len = padded_len;
     165        }
    144166       
    145167        /* Prepare buffers and the key + IV */
     
    161183       
    162184        g_free( st );
     185        g_free( padded );
    163186       
    164187        return clear_len + ARC_IV_LEN;
  • lib/arc.h

    r6cac643 rb79308b  
    3131};
    3232
    33 struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles );
     33#ifndef G_GNUC_MALLOC
     34#define G_GNUC_MALLOC
     35#endif
     36
     37G_GNUC_MALLOC struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles );
    3438unsigned char arc_getbyte( struct arc_state *st );
    35 int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password );
     39int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to );
    3640int arc_decode( unsigned char *crypt, int crypt_len, char **clear, char *password );
  • lib/base64.c

    r6cac643 rb79308b  
    118118        int i, outlen = 0;
    119119       
    120         for( i = 0; in[i]; i += 4 )
     120        for( i = 0; in[i] && in[i+1] && in[i+2] && in[i+3]; i += 4 )
    121121        {
    122122                int sx;
  • lib/events_glib.c

    r6cac643 rb79308b  
    5151} GaimIOClosure;
    5252
    53 static GMainLoop *loop;
     53static GMainLoop *loop = NULL;
    5454
    5555void b_main_init()
    5656{
    57         loop = g_main_new( FALSE );
     57        if( loop == NULL )
     58                loop = g_main_new( FALSE );
    5859}
    5960
  • lib/misc.c

    r6cac643 rb79308b  
    3333#define BITLBEE_CORE
    3434#include "nogaim.h"
     35#include "base64.h"
    3536#include <stdio.h>
    3637#include <stdlib.h>
     
    597598                return sockerr_again();
    598599}
     600
     601/* Returns values: -1 == Failure (base64-decoded to something unexpected)
     602                    0 == Okay
     603                    1 == Password doesn't match the hash. */
     604int md5_verify_password( char *password, char *hash )
     605{
     606        md5_byte_t *pass_dec = NULL;
     607        md5_byte_t pass_md5[16];
     608        md5_state_t md5_state;
     609        int ret, i;
     610       
     611        if( base64_decode( hash, &pass_dec ) != 21 )
     612        {
     613                ret = -1;
     614        }
     615        else
     616        {
     617                md5_init( &md5_state );
     618                md5_append( &md5_state, (md5_byte_t*) password, strlen( password ) );
     619                md5_append( &md5_state, (md5_byte_t*) pass_dec + 16, 5 ); /* Hmmm, salt! */
     620                md5_finish( &md5_state, pass_md5 );
     621               
     622                for( i = 0; i < 16; i ++ )
     623                {
     624                        if( pass_dec[i] != pass_md5[i] )
     625                        {
     626                                ret = 1;
     627                                break;
     628                        }
     629                }
     630               
     631                /* If we reached the end of the loop, it was a match! */
     632                if( i == 16 )
     633                        ret = 0;
     634        }
     635       
     636        g_free( pass_dec );
     637
     638        return ret;
     639}
  • lib/misc.h

    r6cac643 rb79308b  
    6767G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl );
    6868
     69G_MODULE_EXPORT int md5_verify_password( char *password, char *hash );
     70
    6971#endif
  • lib/proxy.c

    r6cac643 rb79308b  
    530530        struct PHB *phb;
    531531       
    532         if (!host || !port || (port == -1) || !func || strlen(host) > 128) {
     532        if (!host || port <= 0 || !func || strlen(host) > 128) {
    533533                return -1;
    534534        }
     
    538538        phb->data = data;
    539539       
    540         if ((proxytype == PROXY_NONE) || strlen(proxyhost) > 0 || !proxyport || (proxyport == -1))
     540        if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0)
    541541                return proxy_connect_none(host, port, phb);
    542542        else if (proxytype == PROXY_HTTP)
  • lib/ssl_client.h

    r6cac643 rb79308b  
    6060G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len );
    6161
     62/* See ssl_openssl.c for an explanation. */
     63G_MODULE_EXPORT int ssl_pending( void *conn );
     64
    6265/* Abort the SSL connection and disconnect the socket. Do not use close()
    6366   directly, both the SSL library and the peer will be unhappy! */
  • lib/ssl_gnutls.c

    r6cac643 rb79308b  
    211211}
    212212
     213/* See ssl_openssl.c for an explanation. */
     214int ssl_pending( void *conn )
     215{
     216        return 0;
     217}
     218
    213219void ssl_disconnect( void *conn_ )
    214220{
  • lib/ssl_nss.c

    r6cac643 rb79308b  
    169169}
    170170
     171/* See ssl_openssl.c for an explanation. */
     172int ssl_pending( void *conn )
     173{
     174        return 0;
     175}
     176
    171177void ssl_disconnect( void *conn_ )
    172178{
  • lib/ssl_openssl.c

    r6cac643 rb79308b  
    6262       
    6363        conn->fd = proxy_connect( host, port, ssl_connected, conn );
     64        if( conn->fd < 0 )
     65        {
     66                g_free( conn );
     67                return NULL;
     68        }
     69       
    6470        conn->func = func;
    6571        conn->data = data;
    6672        conn->inpa = -1;
    67        
    68         if( conn->fd < 0 )
    69         {
    70                 g_free( conn );
    71                 return NULL;
    72         }
    7373       
    7474        return conn;
     
    231231}
    232232
     233/* Only OpenSSL *really* needs this (and well, maybe NSS). See for more info:
     234   http://www.gnu.org/software/gnutls/manual/gnutls.html#index-gnutls_005frecord_005fcheck_005fpending-209
     235   http://www.openssl.org/docs/ssl/SSL_pending.html
     236   
     237   Required because OpenSSL empties the TCP buffer completely but doesn't
     238   necessarily give us all the unencrypted data.
     239   
     240   Returns 0 if there's nothing left or if we don't have to care (GnuTLS),
     241   1 if there's more data. */
     242int ssl_pending( void *conn )
     243{
     244        return ( ((struct scd*)conn) && ((struct scd*)conn)->established ) ?
     245               SSL_pending( ((struct scd*)conn)->ssl ) > 0 : 0;
     246}
     247
    233248void ssl_disconnect( void *conn_ )
    234249{
  • lib/url.c

    r6cac643 rb79308b  
    2626#include "url.h"
    2727
    28 /* Convert an URL to a url_t structure                                  */
     28/* Convert an URL to a url_t structure */
    2929int url_set( url_t *url, char *set_url )
    3030{
    31         char s[MAX_STRING];
     31        char s[MAX_STRING+1];
    3232        char *i;
    3333       
    34         /* protocol://                                                  */
     34        memset( url, 0, sizeof( url_t ) );
     35        memset( s, 0, sizeof( s ) );
     36       
     37        /* protocol:// */
    3538        if( ( i = strstr( set_url, "://" ) ) == NULL )
    3639        {
     
    4952                        url->proto = PROTO_SOCKS5;
    5053                else
    51                 {
    52                         return( 0 );
    53                 }
     54                        return 0;
     55               
    5456                strncpy( s, i + 3, MAX_STRING );
    5557        }
    5658       
    57         /* Split                                                        */
     59        /* Split */
    5860        if( ( i = strchr( s, '/' ) ) == NULL )
    5961        {
     
    6769        strncpy( url->host, s, MAX_STRING );
    6870       
    69         /* Check for username in host field                             */
     71        /* Check for username in host field */
    7072        if( strrchr( url->host, '@' ) != NULL )
    7173        {
     
    7678                *url->pass = 0;
    7779        }
    78         /* If not: Fill in defaults                                     */
     80        /* If not: Fill in defaults */
    7981        else
    8082        {
     
    8284        }
    8385       
    84         /* Password?                                                    */
     86        /* Password? */
    8587        if( ( i = strchr( url->user, ':' ) ) != NULL )
    8688        {
     
    8890                strcpy( url->pass, i + 1 );
    8991        }
    90         /* Port number?                                                 */
     92        /* Port number? */
    9193        if( ( i = strchr( url->host, ':' ) ) != NULL )
    9294        {
  • lib/url.h

    r6cac643 rb79308b  
    2626#include "bitlbee.h"
    2727
    28 #define PROTO_HTTP              2
    29 #define PROTO_HTTPS             5
    30 #define PROTO_SOCKS4    3
    31 #define PROTO_SOCKS5    4
    32 #define PROTO_DEFAULT   PROTO_HTTP
     28#define PROTO_HTTP      2
     29#define PROTO_HTTPS     5
     30#define PROTO_SOCKS4    3
     31#define PROTO_SOCKS5    4
     32#define PROTO_DEFAULT   PROTO_HTTP
    3333
    3434typedef struct url
     
    3636        int proto;
    3737        int port;
    38         char host[MAX_STRING];
    39         char file[MAX_STRING];
    40         char user[MAX_STRING];
    41         char pass[MAX_STRING];
     38        char host[MAX_STRING+1];
     39        char file[MAX_STRING+1];
     40        char user[MAX_STRING+1];
     41        char pass[MAX_STRING+1];
    4242} url_t;
    4343
  • lib/xmltree.c

    r6cac643 rb79308b  
    111111};
    112112
    113 struct xt_parser *xt_new( gpointer data )
     113struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data )
    114114{
    115115        struct xt_parser *xt = g_new0( struct xt_parser, 1 );
    116116       
    117117        xt->data = data;
     118        xt->handlers = handlers;
    118119        xt_reset( xt );
    119120       
  • lib/xmltree.h

    r6cac643 rb79308b  
    7171        struct xt_node *cur;
    7272       
    73         struct xt_handler_entry *handlers;
     73        const struct xt_handler_entry *handlers;
    7474        gpointer data;
    7575       
     
    7777};
    7878
    79 struct xt_parser *xt_new( gpointer data );
     79struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data );
    8080void xt_reset( struct xt_parser *xt );
    8181int xt_feed( struct xt_parser *xt, char *text, int text_len );
  • protocols/Makefile

    r6cac643 rb79308b  
    2727all: protocols.o
    2828check: all
    29 lcov:
     29lcov: check
    3030gcov:
    3131        gcov *.c
  • protocols/jabber/Makefile

    r6cac643 rb79308b  
    1010
    1111# [SH] Program variables
    12 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o si.o s5bytestream.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o si.o s5bytestream.o
    1313
    1414CFLAGS += -Wall
     
    1818all: jabber_mod.o
    1919check: all
    20 lcov:
     20lcov: check
    2121gcov:
    2222        gcov *.c
  • protocols/jabber/io.c

    r6cac643 rb79308b  
    241241        }
    242242       
    243         /* EAGAIN/etc or a successful read. */
    244         return TRUE;
     243        if( ssl_pending( jd->ssl ) )
     244                /* OpenSSL empties the TCP buffers completely but may keep some
     245                   data in its internap buffers. select() won't see that, but
     246                   ssl_pending() does. */
     247                return jabber_read_callback( data, fd, cond );
     248        else
     249                return TRUE;
    245250}
    246251
     
    521526           from the server too. */
    522527        xt_free( jd->xt );      /* In case we're RE-starting. */
    523         jd->xt = xt_new( ic );
    524         jd->xt->handlers = (struct xt_handler_entry*) jabber_handlers;
     528        jd->xt = xt_new( jabber_handlers, ic );
    525529       
    526530        if( jd->r_inpa <= 0 )
  • protocols/jabber/iq.c

    r6cac643 rb79308b  
    534534}
    535535
     536static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig );
     537
    536538int jabber_add_to_roster( struct im_connection *ic, char *handle, char *name )
    537539{
     
    549551        xt_add_attr( node, "xmlns", XMLNS_ROSTER );
    550552        node = jabber_make_packet( "iq", "set", NULL, node );
     553        jabber_cache_add( ic, node, jabber_add_to_roster_callback );
    551554       
    552555        st = jabber_write_packet( ic, node );
    553556       
    554         xt_free_node( node );
    555557        return st;
     558}
     559
     560static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
     561{
     562        char *s, *jid = NULL;
     563        struct xt_node *c;
     564       
     565        if( ( c = xt_find_node( orig->children, "query" ) ) &&
     566            ( c = xt_find_node( c->children, "item" ) ) &&
     567            ( jid = xt_find_attr( c, "jid" ) ) &&
     568            ( s = xt_find_attr( node, "type" ) ) &&
     569            strcmp( s, "result" ) == 0 )
     570        {
     571                if( imcb_find_buddy( ic, jid ) == NULL )
     572                        imcb_add_buddy( ic, jid, NULL );
     573        }
     574        else
     575        {
     576                imcb_log( ic, "Error while adding `%s' to your contact list.",
     577                          jid ? jid : "(unknown handle)" );
     578        }
     579       
     580        return XT_HANDLED;
    556581}
    557582
  • protocols/jabber/jabber.c

    r6cac643 rb79308b  
    267267        xt_free( jd->xt );
    268268       
     269        g_free( jd->cached_id_prefix );
    269270        g_free( jd->away_message );
    270271        g_free( jd->username );
  • protocols/jabber/jabber_util.c

    r6cac643 rb79308b  
    250250};
    251251
    252 static void jabber_buddy_ask_yes( gpointer w, struct jabber_buddy_ask_data *bla )
    253 {
     252static void jabber_buddy_ask_yes( void *data )
     253{
     254        struct jabber_buddy_ask_data *bla = data;
     255       
    254256        presence_send_request( bla->ic, bla->handle, "subscribed" );
    255257       
     
    261263}
    262264
    263 static void jabber_buddy_ask_no( gpointer w, struct jabber_buddy_ask_data *bla )
    264 {
     265static void jabber_buddy_ask_no( void *data )
     266{
     267        struct jabber_buddy_ask_data *bla = data;
     268       
    265269        presence_send_request( bla->ic, bla->handle, "subscribed" );
    266270       
  • protocols/jabber/sasl.c

    r6cac643 rb79308b  
    2121*                                                                           *
    2222\***************************************************************************/
     23
     24#include <ctype.h>
    2325
    2426#include "jabber.h"
     
    107109}
    108110
    109 static char *sasl_get_part( char *data, char *field )
     111/* Non-static function, but not mentioned in jabber.h because it's for internal
     112   use, just that the unittest should be able to reach it... */
     113char *sasl_get_part( char *data, char *field )
    110114{
    111115        int i, len;
    112116       
    113117        len = strlen( field );
     118       
     119        while( isspace( *data ) || *data == ',' )
     120                data ++;
    114121       
    115122        if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' )
     
    129136                        }
    130137                       
    131                         /* If we got a comma, we got a new field. Check it. */
    132                         if( data[i] == ',' &&
    133                             g_strncasecmp( data + i + 1, field, len ) == 0 &&
    134                             data[i+len+1] == '=' )
     138                        /* If we got a comma, we got a new field. Check it,
     139                           find the next key after it. */
     140                        if( data[i] == ',' )
    135141                        {
    136                                 i += len + 2;
    137                                 break;
     142                                while( isspace( data[i] ) || data[i] == ',' )
     143                                        i ++;
     144                               
     145                                if( g_strncasecmp( data + i, field, len ) == 0 &&
     146                                    data[i+len] == '=' )
     147                                {
     148                                        i += len + 1;
     149                                        break;
     150                                }
    138151                        }
    139152                }
  • protocols/msn/Makefile

    r6cac643 rb79308b  
    1818all: msn_mod.o
    1919check: all
    20 lcov:
     20lcov: check
    2121gcov:
    2222        gcov *.c
  • protocols/msn/msn.h

    r6cac643 rb79308b  
    2929#define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r"
    3030
    31 #ifdef DEBUG
     31#ifdef DEBUG_MSN
    3232#define debug( text... ) imcb_log( ic, text );
    3333#else
  • protocols/msn/msn_util.c

    r6cac643 rb79308b  
    9090};
    9191
    92 static void msn_buddy_ask_yes( gpointer w, struct msn_buddy_ask_data *bla )
    93 {
     92static void msn_buddy_ask_yes( void *data )
     93{
     94        struct msn_buddy_ask_data *bla = data;
     95       
    9496        msn_buddy_list_add( bla->ic, "AL", bla->handle, bla->realname );
    9597       
     
    102104}
    103105
    104 static void msn_buddy_ask_no( gpointer w, struct msn_buddy_ask_data *bla )
    105 {
     106static void msn_buddy_ask_no( void *data )
     107{
     108        struct msn_buddy_ask_data *bla = data;
     109       
    106110        msn_buddy_list_add( bla->ic, "BL", bla->handle, bla->realname );
    107111       
  • protocols/msn/ns.c

    r6cac643 rb79308b  
    3434static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts );
    3535
    36 static void msn_auth_got_passport_id( struct passport_reply *rep );
     36static void msn_auth_got_passport_token( struct msn_auth_data *mad );
    3737
    3838gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
     
    214214                {
    215215                        /* Time for some Passport black magic... */
    216                         if( !passport_get_id( msn_auth_got_passport_id, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )
     216                        if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) )
    217217                        {
    218218                                imcb_error( ic, "Error while contacting Passport server" );
     
    674674}
    675675
    676 static void msn_auth_got_passport_id( struct passport_reply *rep )
     676static void msn_auth_got_passport_token( struct msn_auth_data *mad )
    677677{
    678         struct im_connection *ic = rep->data;
    679         struct msn_data *md = ic->proto_data;
    680         char *key = rep->result;
    681         char buf[1024];
    682        
    683         if( key == NULL )
    684         {
    685                 imcb_error( ic, "Error during Passport authentication (%s)",
    686                                rep->error_string ? rep->error_string : "Unknown error" );
     678        struct im_connection *ic = mad->data;
     679        struct msn_data *md;
     680       
     681        /* Dead connection? */
     682        if( g_slist_find( msn_connections, ic ) == NULL )
     683                return;
     684       
     685        md = ic->proto_data;
     686        if( mad->token )
     687        {
     688                char buf[1024];
     689               
     690                g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );
     691                msn_write( ic, buf, strlen( buf ) );
     692        }
     693        else
     694        {
     695                imcb_error( ic, "Error during Passport authentication: %s", mad->error );
    687696                imc_logout( ic, TRUE );
    688697        }
    689         else
    690         {
    691                 g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, key );
    692                 msn_write( ic, buf, strlen( buf ) );
    693         }
    694698}
  • protocols/msn/passport.c

    r6cac643 rb79308b  
    1 /* passport.c
     1/** passport.c
    22 *
    3  * Functions to login to microsoft passport service for Messenger
    4  * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>
    5  * Copyright (C) 2004 Wilmer van der Gaast <wilmer@gaast.net>
     3 * Functions to login to Microsoft Passport service for Messenger
     4 * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>
    65 *
    76 * This program is free software; you can redistribute it and/or modify             
     
    2423#include "msn.h"
    2524#include "bitlbee.h"
     25#include "url.h"
     26#include "misc.h"
     27#include "xmltree.h"
    2628#include <ctype.h>
    2729#include <errno.h>
    2830
    29 #define MSN_BUF_LEN 8192
     31static int passport_get_token_real( struct msn_auth_data *mad );
     32static void passport_get_token_ready( struct http_request *req );
    3033
    31 static char *prd_cached = NULL;
    32 
    33 static int passport_get_id_real( gpointer func, gpointer data, char *header );
    34 static void passport_get_id_ready( struct http_request *req );
    35 
    36 static int passport_retrieve_dalogin( gpointer data, gpointer func, char *header );
    37 static void passport_retrieve_dalogin_ready( struct http_request *req );
    38 
    39 static char *passport_create_header( char *cookie, char *email, char *pwd );
    40 static void destroy_reply( struct passport_reply *rep );
    41 
    42 int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie )
     34int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie )
    4335{
    44         char *header = passport_create_header( cookie, username, password );
     36        struct msn_auth_data *mad = g_new0( struct msn_auth_data, 1 );
     37        int i;
    4538       
    46         if( prd_cached == NULL )
    47                 return passport_retrieve_dalogin( func, data, header );
    48         else
    49                 return passport_get_id_real( func, data, header );
     39        mad->username = g_strdup( username );
     40        mad->password = g_strdup( password );
     41        mad->cookie = g_strdup( cookie );
     42       
     43        mad->callback = func;
     44        mad->data = data;
     45       
     46        mad->url = g_strdup( SOAP_AUTHENTICATION_URL );
     47        mad->ttl = 3; /* Max. # of redirects. */
     48       
     49        /* HTTP-escape stuff and s/,/&/ */
     50        http_decode( mad->cookie );
     51        for( i = 0; mad->cookie[i]; i ++ )
     52                if( mad->cookie[i] == ',' )
     53                        mad->cookie[i] = '&';
     54       
     55        /* Microsoft doesn't allow password longer than 16 chars and silently
     56           fails authentication if you give the "full version" of your passwd. */
     57        if( strlen( mad->password ) > MAX_PASSPORT_PWLEN )
     58                mad->password[MAX_PASSPORT_PWLEN] = 0;
     59       
     60        return passport_get_token_real( mad );
    5061}
    5162
    52 static int passport_get_id_real( gpointer func, gpointer data, char *header )
     63static int passport_get_token_real( struct msn_auth_data *mad )
    5364{
    54         struct passport_reply *rep;
    55         char *server, *dummy, *reqs;
     65        char *post_payload, *post_request;
    5666        struct http_request *req;
     67        url_t url;
    5768       
    58         rep = g_new0( struct passport_reply, 1 );
    59         rep->data = data;
    60         rep->func = func;
    61         rep->header = header;
     69        url_set( &url, mad->url );
    6270       
    63         server = g_strdup( prd_cached );
    64         dummy = strchr( server, '/' );
     71        post_payload = g_markup_printf_escaped( SOAP_AUTHENTICATION_PAYLOAD,
     72                                                mad->username,
     73                                                mad->password,
     74                                                mad->cookie );
    6575       
    66         if( dummy == NULL )
    67         {
    68                 destroy_reply( rep );
    69                 return( 0 );
    70         }
     76        post_request = g_strdup_printf( SOAP_AUTHENTICATION_REQUEST,
     77                                        url.file, url.host,
     78                                        (int) strlen( post_payload ),
     79                                        post_payload );
     80                                       
     81        req = http_dorequest( url.host, url.port, 1, post_request,
     82                              passport_get_token_ready, mad );
    7183       
    72         reqs = g_strdup_printf( "GET %s HTTP/1.0\r\n%s\r\n\r\n", dummy, header );
     84        g_free( post_request );
     85        g_free( post_payload );
    7386       
    74         *dummy = 0;
    75         req = http_dorequest( server, 443, 1, reqs, passport_get_id_ready, rep );
    76        
    77         g_free( server );
    78         g_free( reqs );
    79        
    80         if( req == NULL )
    81                 destroy_reply( rep );
    82        
    83         return( req != NULL );
     87        return req != NULL;
    8488}
    8589
    86 static void passport_get_id_ready( struct http_request *req )
     90static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data );
     91static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data );
     92
     93static const struct xt_handler_entry passport_xt_handlers[] = {
     94        { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", passport_xt_extract_token },
     95        { "S:Fault",                  "S:Envelope",                 passport_xt_handle_fault  },
     96        { NULL,                       NULL,                         NULL                      }
     97};
     98
     99static void passport_get_token_ready( struct http_request *req )
    87100{
    88         struct passport_reply *rep = req->data;
     101        struct msn_auth_data *mad = req->data;
     102        struct xt_parser *parser;
    89103       
    90         if( !g_slist_find( msn_connections, rep->data ) )
     104        g_free( mad->url );
     105        g_free( mad->error );
     106        mad->url = mad->error = NULL;
     107       
     108        if( req->status_code == 200 )
    91109        {
    92                 destroy_reply( rep );
    93                 return;
    94         }
    95        
    96         if( req->finished && req->reply_headers && req->status_code == 200 )
    97         {
    98                 char *dummy;
    99                
    100                 if( ( dummy = strstr( req->reply_headers, "from-PP='" ) ) )
    101                 {
    102                         char *responseend;
    103                        
    104                         dummy += strlen( "from-PP='" );
    105                         responseend = strchr( dummy, '\'' );
    106                         if( responseend )
    107                                 *responseend = 0;
    108                        
    109                         rep->result = g_strdup( dummy );
    110                 }
    111                 else
    112                 {
    113                         rep->error_string = g_strdup( "Could not parse Passport server response" );
    114                 }
     110                parser = xt_new( passport_xt_handlers, mad );
     111                xt_feed( parser, req->reply_body, req->body_size );
     112                xt_handle( parser, NULL, -1 );
     113                xt_free( parser );
    115114        }
    116115        else
    117116        {
    118                 rep->error_string = g_strdup_printf( "HTTP error: %s",
    119                                       req->status_string ? req->status_string : "Unknown error" );
     117                mad->error = g_strdup_printf( "HTTP error %d (%s)", req->status_code,
     118                                              req->status_string ? req->status_string : "unknown" );
    120119        }
    121120       
    122         rep->func( rep );
    123         destroy_reply( rep );
     121        if( mad->error == NULL && mad->token == NULL )
     122                mad->error = g_strdup( "Could not parse Passport server response" );
     123       
     124        if( mad->url && mad->token == NULL )
     125        {
     126                passport_get_token_real( mad );
     127        }
     128        else
     129        {
     130                mad->callback( mad );
     131               
     132                g_free( mad->url );
     133                g_free( mad->username );
     134                g_free( mad->password );
     135                g_free( mad->cookie );
     136                g_free( mad->token );
     137                g_free( mad->error );
     138                g_free( mad );
     139        }
    124140}
    125141
    126 static char *passport_create_header( char *cookie, char *email, char *pwd )
     142static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data )
    127143{
    128         char *buffer;
    129         char *currenttoken;
    130         char *email_enc, *pwd_enc;
     144        struct msn_auth_data *mad = data;
     145        char *s;
    131146       
    132         currenttoken = strstr( cookie, "lc=" );
    133         if( currenttoken == NULL )
    134                 return NULL;
     147        if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 )
     148                mad->token = g_memdup( node->text, node->text_len + 1 );
    135149       
    136         email_enc = g_new0( char, strlen( email ) * 3 + 1 );
    137         strcpy( email_enc, email );
    138         http_encode( email_enc );
    139        
    140         pwd_enc = g_new0( char, strlen( pwd ) * 3 + 1 );
    141         strcpy( pwd_enc, pwd );
    142         http_encode( pwd_enc );
    143        
    144         buffer = g_strdup_printf( "Authorization: Passport1.4 OrgVerb=GET,"
    145                                   "OrgURL=http%%3A%%2F%%2Fmessenger%%2Emsn%%2Ecom,"
    146                                   "sign-in=%s,pwd=%s,%s", email_enc, pwd_enc,
    147                                   currenttoken );
    148        
    149         g_free( email_enc );
    150         g_free( pwd_enc );
    151        
    152         return buffer;
     150        return XT_HANDLED;
    153151}
    154152
    155 static int passport_retrieve_dalogin( gpointer func, gpointer data, char *header )
     153static xt_status passport_xt_handle_fault( struct xt_node *node, gpointer data )
    156154{
    157         struct passport_reply *rep = g_new0( struct passport_reply, 1 );
    158         struct http_request *req;
     155        struct msn_auth_data *mad = data;
     156        struct xt_node *code = xt_find_node( node->children, "faultcode" );
     157        struct xt_node *string = xt_find_node( node->children, "faultstring" );
     158        struct xt_node *redirect = xt_find_node( node->children, "psf:redirectUrl" );
    159159       
    160         rep->data = data;
    161         rep->func = func;
    162         rep->header = header;
     160        if( redirect && redirect->text_len && mad->ttl-- > 0 )
     161                mad->url = g_memdup( redirect->text, redirect->text_len + 1 );
    163162       
    164         req = http_dorequest_url( "https://nexus.passport.com/rdr/pprdr.asp", passport_retrieve_dalogin_ready, rep );
     163        if( code == NULL || code->text_len == 0 )
     164                mad->error = g_strdup( "Unknown error" );
     165        else
     166                mad->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ?
     167                                              string->text : "no description available" );
    165168       
    166         if( !req )
    167                 destroy_reply( rep );
    168        
    169         return( req != NULL );
     169        return XT_HANDLED;
    170170}
    171 
    172 static void passport_retrieve_dalogin_ready( struct http_request *req )
    173 {
    174         struct passport_reply *rep = req->data;
    175         char *dalogin;
    176         char *urlend;
    177        
    178         if( !g_slist_find( msn_connections, rep->data ) )
    179         {
    180                 destroy_reply( rep );
    181                 return;
    182         }
    183        
    184         if( !req->finished || !req->reply_headers || req->status_code != 200 )
    185         {
    186                 rep->error_string = g_strdup_printf( "HTTP error while fetching DALogin: %s",
    187                                         req->status_string ? req->status_string : "Unknown error" );
    188                 goto failure;
    189         }
    190        
    191         dalogin = strstr( req->reply_headers, "DALogin=" );     
    192        
    193         if( !dalogin )
    194         {
    195                 rep->error_string = g_strdup( "Parse error while fetching DALogin" );
    196                 goto failure;
    197         }
    198        
    199         dalogin += strlen( "DALogin=" );
    200         urlend = strchr( dalogin, ',' );
    201         if( urlend )
    202                 *urlend = 0;
    203        
    204         /* strip the http(s):// part from the url */
    205         urlend = strstr( urlend, "://" );
    206         if( urlend )
    207                 dalogin = urlend + strlen( "://" );
    208        
    209         if( prd_cached == NULL )
    210                 prd_cached = g_strdup( dalogin );
    211        
    212         if( passport_get_id_real( rep->func, rep->data, rep->header ) )
    213         {
    214                 rep->header = NULL;
    215                 destroy_reply( rep );
    216                 return;
    217         }
    218        
    219 failure:       
    220         rep->func( rep );
    221         destroy_reply( rep );
    222 }
    223 
    224 static void destroy_reply( struct passport_reply *rep )
    225 {
    226         g_free( rep->result );
    227         g_free( rep->header );
    228         g_free( rep->error_string );
    229         g_free( rep );
    230 }
  • protocols/msn/passport.h

    r6cac643 rb79308b  
    1 #ifndef __PASSPORT_H__
    2 #define __PASSPORT_H__
    31/* passport.h
    42 *
    5  * Functions to login to Microsoft Passport Service for Messenger
    6  * Copyright (C) 2004 Wouter Paesen <wouter@blue-gate.be>,
    7  *                    Wilmer van der Gaast <wilmer@gaast.net>
     3 * Functions to login to Microsoft Passport service for Messenger
     4 * Copyright (C) 2004-2008 Wilmer van der Gaast <wilmer@gaast.net>
    85 *
    96 * This program is free software; you can redistribute it and/or modify             
     
    1815 * You should have received a copy of the GNU General Public License               
    1916 * along with this program; if not, write to the Free Software                     
    20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
     17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA         
    2118 */
     19
     20/* Thanks to http://msnpiki.msnfanatic.com/index.php/MSNP13:SOAPTweener
     21   for the specs! */
     22
     23#ifndef __PASSPORT_H__
     24#define __PASSPORT_H__
    2225
    2326#include <stdio.h>
     
    3336#include "nogaim.h"
    3437
    35 struct passport_reply
     38#define MAX_PASSPORT_PWLEN 16
     39
     40struct msn_auth_data
    3641{
    37         void (*func)( struct passport_reply * );
    38         void *data;
    39         char *result;
    40         char *header;
    41         char *error_string;
     42        char *url;
     43        int ttl;
     44       
     45        char *username;
     46        char *password;
     47        char *cookie;
     48       
     49        /* The end result, the only thing we'll really be interested in
     50           once finished. */
     51        char *token;
     52        char *error; /* Yeah, or that... */
     53       
     54        void (*callback)( struct msn_auth_data *mad );
     55        gpointer data;
    4256};
    4357
    44 int passport_get_id( gpointer func, gpointer data, char *username, char *password, char *cookie );
     58#define SOAP_AUTHENTICATION_URL "https://loginnet.passport.com/RST.srf"
     59
     60#define SOAP_AUTHENTICATION_REQUEST \
     61"POST %s HTTP/1.0\r\n" \
     62"Accept: text/*\r\n" \
     63"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \
     64"Host: %s\r\n" \
     65"Content-Length: %d\r\n" \
     66"Cache-Control: no-cache\r\n" \
     67"\r\n" \
     68"%s"
     69
     70#define SOAP_AUTHENTICATION_PAYLOAD \
     71"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
     72"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">" \
     73  "<Header>" \
     74    "<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">" \
     75      "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \
     76      "<ps:BinaryVersion>4</ps:BinaryVersion>" \
     77      "<ps:UIVersion>1</ps:UIVersion>" \
     78      "<ps:Cookies></ps:Cookies>" \
     79      "<ps:RequestParams>AQAAAAIAAABsYwQAAAAzMDg0</ps:RequestParams>" \
     80    "</ps:AuthInfo>" \
     81    "<wsse:Security>" \
     82       "<wsse:UsernameToken Id=\"user\">" \
     83         "<wsse:Username>%s</wsse:Username>" \
     84         "<wsse:Password>%s</wsse:Password>" \
     85       "</wsse:UsernameToken>" \
     86    "</wsse:Security>" \
     87  "</Header>" \
     88  "<Body>" \
     89    "<ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">" \
     90      "<wst:RequestSecurityToken Id=\"RST0\">" \
     91        "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \
     92        "<wsp:AppliesTo>" \
     93          "<wsa:EndpointReference>" \
     94            "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \
     95          "</wsa:EndpointReference>" \
     96        "</wsp:AppliesTo>" \
     97      "</wst:RequestSecurityToken>" \
     98      "<wst:RequestSecurityToken Id=\"RST1\">" \
     99       "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \
     100        "<wsp:AppliesTo>" \
     101          "<wsa:EndpointReference>" \
     102            "<wsa:Address>messenger.msn.com</wsa:Address>" \
     103          "</wsa:EndpointReference>" \
     104        "</wsp:AppliesTo>" \
     105        "<wsse:PolicyReference URI=\"?%s\"></wsse:PolicyReference>" \
     106      "</wst:RequestSecurityToken>" \
     107    "</ps:RequestMultipleSecurityTokens>" \
     108  "</Body>" \
     109"</Envelope>"
     110
     111int passport_get_token( gpointer func, gpointer data, char *username, char *password, char *cookie );
    45112
    46113#endif /* __PASSPORT_H__ */
  • protocols/nogaim.c

    r6cac643 rb79308b  
    343343/* dialogs.c */
    344344
    345 void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont )
     345void imcb_ask( struct im_connection *ic, char *msg, void *data,
     346               query_callback doit, query_callback dont )
    346347{
    347348        query_add( ic->irc, ic, msg, doit, dont, data );
     
    495496};
    496497
    497 void show_got_added_no( gpointer w, struct show_got_added_data *data )
    498 {
    499         g_free( data->handle );
     498void show_got_added_no( void *data )
     499{
     500        g_free( ((struct show_got_added_data*)data)->handle );
    500501        g_free( data );
    501502}
    502503
    503 void show_got_added_yes( gpointer w, struct show_got_added_data *data )
    504 {
    505         data->ic->acc->prpl->add_buddy( data->ic, data->handle, NULL );
    506         /* imcb_add_buddy( data->ic, NULL, data->handle, data->handle ); */
    507        
    508         return show_got_added_no( w, data );
     504void show_got_added_yes( void *data )
     505{
     506        struct show_got_added_data *sga = data;
     507       
     508        sga->ic->acc->prpl->add_buddy( sga->ic, sga->handle, NULL );
     509        /* imcb_add_buddy( sga->ic, NULL, sga->handle, sga->handle ); */
     510       
     511        return show_got_added_no( data );
    509512}
    510513
  • protocols/nogaim.h

    r6cac643 rb79308b  
    4242#include "account.h"
    4343#include "proxy.h"
     44#include "query.h"
    4445#include "md5.h"
    4546#include "ft.h"
     
    265266 * - 'doit' or 'dont' will be called depending of the answer of the user.
    266267 */
    267 G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, void *doit, void *dont );
     268G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, query_callback doit, query_callback dont );
    268269G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, char *handle, const char *realname );
    269270
  • protocols/oscar/Makefile

    r6cac643 rb79308b  
    1818all: oscar_mod.o
    1919check: all
    20 lcov:
     20lcov: check
    2121gcov:
    2222        gcov *.c
  • protocols/oscar/oscar.c

    r6cac643 rb79308b  
    10841084}
    10851085
    1086 void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv);
    1087 void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv);
     1086void oscar_accept_chat(void *data);
     1087void oscar_reject_chat(void *data);
    10881088       
    10891089static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) {
     
    11191119}
    11201120
    1121 static void gaim_icq_authgrant(gpointer w, struct icq_auth *data) {
     1121static void gaim_icq_authgrant(void *data_) {
     1122        struct icq_auth *data = data_;
    11221123        char *uin, message;
    11231124        struct oscar_data *od = (struct oscar_data *)data->ic->proto_data;
     
    11341135}
    11351136
    1136 static void gaim_icq_authdeny(gpointer w, struct icq_auth *data) {
     1137static void gaim_icq_authdeny(void *data_) {
     1138        struct icq_auth *data = data_;
    11371139        char *uin, *message;
    11381140        struct oscar_data *od = (struct oscar_data *)data->ic->proto_data;
     
    25882590}
    25892591
    2590 void oscar_accept_chat(gpointer w, struct aim_chat_invitation * inv)
     2592void oscar_accept_chat(void *data)
    25912593{
     2594        struct aim_chat_invitation * inv = data;
     2595       
    25922596        oscar_chat_join(inv->ic, inv->name, NULL, NULL);
    25932597        g_free(inv->name);
     
    25952599}
    25962600
    2597 void oscar_reject_chat(gpointer w, struct aim_chat_invitation * inv)
     2601void oscar_reject_chat(void *data)
    25982602{
     2603        struct aim_chat_invitation * inv = data;
     2604       
    25992605        g_free(inv->name);
    26002606        g_free(inv);
  • protocols/yahoo/Makefile

    r6cac643 rb79308b  
    1818all: yahoo_mod.o
    1919check: all
    20 lcov:
     20lcov: check
    2121gcov:
    2222        gcov *.c
  • protocols/yahoo/libyahoo2.c

    r6cac643 rb79308b  
    737737
    738738        memcpy(data + pos, "YMSG", 4); pos += 4;
    739         pos += yahoo_put16(data + pos, 0x0a00);
     739        pos += yahoo_put16(data + pos, 0x000c);
    740740        pos += yahoo_put16(data + pos, 0x0000);
    741741        pos += yahoo_put16(data + pos, pktlen + extra_pad);
     
    33513351                                        break;
    33523352                                case 5:
    3353                                         if(cp != "\005")
     3353                                        if(strcmp(cp, "5") != 0)
    33543354                                                yct->location = cp;
    33553355                                        k = 0;
  • protocols/yahoo/yahoo.c

    r6cac643 rb79308b  
    315315        struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data;
    316316       
    317         yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg );
     317        yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ? msg : "" );
    318318}
    319319
     
    797797}
    798798
    799 static void byahoo_accept_conf( gpointer w, struct byahoo_conf_invitation *inv )
    800 {
     799static void byahoo_accept_conf( void *data )
     800{
     801        struct byahoo_conf_invitation *inv = data;
     802       
    801803        yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name );
    802804        imcb_chat_add_buddy( inv->c, inv->ic->acc->user );
     
    805807}
    806808
    807 static void byahoo_reject_conf( gpointer w, struct byahoo_conf_invitation *inv )
    808 {
     809static void byahoo_reject_conf( void *data )
     810{
     811        struct byahoo_conf_invitation *inv = data;
     812       
    809813        yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" );
    810814        imcb_chat_free( inv->c );
  • query.c

    r6cac643 rb79308b  
    3030static query_t *query_default( irc_t *irc );
    3131
    32 query_t *query_add( irc_t *irc, struct im_connection *ic, char *question, void *yes, void *no, void *data )
     32query_t *query_add( irc_t *irc, struct im_connection *ic, char *question,
     33                    query_callback yes, query_callback no, void *data )
    3334{
    3435        query_t *q = g_new0( query_t, 1 );
     
    140141        if( ans )
    141142        {
    142                 imcb_log( q->ic, "Accepted: %s", q->question );
    143                 q->yes( NULL, q->data );
     143                if( q->ic )
     144                        imcb_log( q->ic, "Accepted: %s", q->question );
     145                else
     146                        irc_usermsg( irc, "Accepted: %s", q->question );
     147                q->yes( q->data );
    144148        }
    145149        else
    146150        {
    147                 imcb_log( q->ic, "Rejected: %s", q->question );
    148                 q->no( NULL, q->data );
     151                if( q->ic )
     152                        imcb_log( q->ic, "Rejected: %s", q->question );
     153                else
     154                        irc_usermsg( irc, "Rejected: %s", q->question );
     155                q->no( q->data );
    149156        }
    150157        q->data = NULL;
  • query.h

    r6cac643 rb79308b  
    2727#define _QUERY_H
    2828
     29typedef void (*query_callback) ( void *data );
     30
    2931typedef struct query
    3032{
    3133        struct im_connection *ic;
    3234        char *question;
    33         void (* yes) ( gpointer w, void *data );
    34         void (* no) ( gpointer w, void *data );
     35        query_callback yes, no;
    3536        void *data;
    3637        struct query *next;
    3738} query_t;
    3839
    39 query_t *query_add( irc_t *irc, struct im_connection *ic, char *question, void *yes, void *no, void *data );
     40query_t *query_add( irc_t *irc, struct im_connection *ic, char *question,
     41                    query_callback yes, query_callback no, void *data );
    4042void query_del( irc_t *irc, query_t *q );
    4143void query_del_by_conn( irc_t *irc, struct im_connection *ic );
  • root_commands.c

    r6cac643 rb79308b  
    204204}
    205205
     206struct cmd_account_del_data
     207{
     208        account_t *a;
     209        irc_t *irc;
     210};
     211
     212void cmd_account_del_yes( void *data )
     213{
     214        struct cmd_account_del_data *cad = data;
     215        account_t *a;
     216       
     217        for( a = cad->irc->accounts; a && a != cad->a; a = a->next );
     218       
     219        if( a == NULL )
     220        {
     221                irc_usermsg( cad->irc, "Account already deleted" );
     222        }
     223        else if( a->ic )
     224        {
     225                irc_usermsg( cad->irc, "Account is still logged in, can't delete" );
     226        }
     227        else
     228        {
     229                account_del( cad->irc, a );
     230                irc_usermsg( cad->irc, "Account deleted" );
     231        }
     232        g_free( data );
     233}
     234
     235void cmd_account_del_no( void *data )
     236{
     237        g_free( data );
     238}
     239
    206240static void cmd_account( irc_t *irc, char **cmd )
    207241{
     
    258292                else
    259293                {
    260                         account_del( irc, a );
    261                         irc_usermsg( irc, "Account deleted" );
     294                        struct cmd_account_del_data *cad;
     295                        char *msg;
     296                       
     297                        cad = g_malloc( sizeof( struct cmd_account_del_data ) );
     298                        cad->a = a;
     299                        cad->irc = irc;
     300                       
     301                        msg = g_strdup_printf( "If you remove this account (%s(%s)), BitlBee will "
     302                                               "also forget all your saved nicknames. If you want "
     303                                               "to change your username/password, use the `account "
     304                                               "set' command. Are you sure you want to delete this "
     305                                               "account?", a->prpl->name, a->user );
     306                        query_add( irc, NULL, msg, cmd_account_del_yes, cmd_account_del_no, cad );
     307                        g_free( msg );
    262308                }
    263309        }
     
    557603                        g_free( irc->mynick );
    558604                        irc->mynick = g_strdup( cmd[2] );
     605                       
     606                        if( strcmp( cmd[0], "set_rename" ) != 0 )
     607                                set_setstr( &irc->set, "root_nick", cmd[2] );
    559608                }
    560609                else if( u->send_handler == buddy_send_handler )
     
    565614                irc_usermsg( irc, "Nick successfully changed" );
    566615        }
     616}
     617
     618char *set_eval_root_nick( set_t *set, char *new_nick )
     619{
     620        irc_t *irc = set->data;
     621       
     622        if( strcmp( irc->mynick, new_nick ) != 0 )
     623        {
     624                char *cmd[] = { "set_rename", irc->mynick, new_nick, NULL };
     625               
     626                cmd_rename( irc, cmd );
     627        }
     628       
     629        return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : NULL;
    567630}
    568631
     
    769832                else
    770833                        irc_usermsg( irc, "%s is empty", set_name );
     834
     835                if( strchr( set_name, '/' ) )
     836                        irc_usermsg( irc, "Warning: / found in setting name, you're probably looking for the `account set' command." );
    771837        }
    772838        else
  • set.c

    r6cac643 rb79308b  
    230230        return value;
    231231}
    232 
    233 char *set_eval_charset( set_t *set, char *value )
    234 {
    235         GIConv cd;
    236 
    237         if ( g_strncasecmp( value, "none", 4 ) == 0 )
    238                 return value;
    239 
    240         cd = g_iconv_open( "UTF-8", value );
    241         if( cd == (GIConv) -1 )
    242                 return NULL;
    243 
    244         g_iconv_close( cd );
    245         return value;
    246 }
  • set.h

    r6cac643 rb79308b  
    9797char *set_eval_to_char( set_t *set, char *value );
    9898char *set_eval_ops( set_t *set, char *value );
    99 char *set_eval_charset( set_t *set, char *value );
    10099
    101100#endif /* __SET_H__ */
  • storage_xml.c

    r6cac643 rb79308b  
    8080                char *nick = xml_attr( attr_names, attr_values, "nick" );
    8181                char *pass = xml_attr( attr_names, attr_values, "password" );
    82                 md5_byte_t *pass_dec = NULL;
     82                int st;
    8383               
    8484                if( !nick || !pass )
     
    8787                                     "Missing attributes for %s element", element_name );
    8888                }
    89                 else if( base64_decode( pass, &pass_dec ) != 21 )
    90                 {
     89                else if( ( st = md5_verify_password( xd->given_pass, pass ) ) == -1 )
     90                {
     91                        xd->pass_st = XML_PASS_WRONG;
    9192                        g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
    9293                                     "Error while decoding password attribute" );
    9394                }
     95                else if( st == 0 )
     96                {
     97                        if( xd->pass_st != XML_PASS_CHECK_ONLY )
     98                                xd->pass_st = XML_PASS_OK;
     99                }
    94100                else
    95101                {
    96                         md5_byte_t pass_md5[16];
    97                         md5_state_t md5_state;
    98                         int i;
    99                        
    100                         md5_init( &md5_state );
    101                         md5_append( &md5_state, (md5_byte_t*) xd->given_pass, strlen( xd->given_pass ) );
    102                         md5_append( &md5_state, (md5_byte_t*) pass_dec + 16, 5 ); /* Hmmm, salt! */
    103                         md5_finish( &md5_state, pass_md5 );
    104                        
    105                         for( i = 0; i < 16; i ++ )
    106                         {
    107                                 if( pass_dec[i] != pass_md5[i] )
    108                                 {
    109                                         xd->pass_st = XML_PASS_WRONG;
    110                                         g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
    111                                                      "Password mismatch" );
    112                                         break;
    113                                 }
    114                         }
    115                        
    116                         /* If we reached the end of the loop, it was a match! */
    117                         if( i == 16 )
    118                         {
    119                                 if( xd->pass_st != XML_PASS_CHECK_ONLY )
    120                                         xd->pass_st = XML_PASS_OK;
    121                         }
    122                 }
    123                
    124                 g_free( pass_dec );
     102                        xd->pass_st = XML_PASS_WRONG;
     103                        g_set_error( error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
     104                                     "Password mismatch" );
     105                }
    125106        }
    126107        else if( xd->pass_st < XML_PASS_OK )
     
    428409                int pass_len;
    429410               
    430                 pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password );
     411                pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password, 12 );
    431412                pass_b64 = base64_encode( pass_cr, pass_len );
    432413                g_free( pass_cr );
  • tests/Makefile

    r6cac643 rb79308b  
    1111distclean: clean
    1212
    13 main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o 
     13main_objs = account.o bitlbee.o conf.o crypting.o help.o ipc.o irc.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o storage_text.o user.o
    1414
    15 test_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_crypting.o check_set.o
     15test_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_crypting.o check_set.o check_jabber_sasl.o
    1616
    1717check: $(test_objs) $(addprefix ../, $(main_objs)) ../protocols/protocols.o ../lib/lib.o
  • tests/check.c

    r6cac643 rb79308b  
    6666Suite *set_suite(void);
    6767
     68/* From check_jabber_sasl.c */
     69Suite *jabber_sasl_suite(void);
     70
    6871int main (int argc, char **argv)
    6972{
     
    111114        srunner_add_suite(sr, crypting_suite());
    112115        srunner_add_suite(sr, set_suite());
     116        srunner_add_suite(sr, jabber_sasl_suite());
    113117        if (no_fork)
    114118                srunner_set_fork_status(sr, CK_NOFORK);
  • tests/check_arc.c

    r6cac643 rb79308b  
    77#include "arc.h"
    88
    9 char *password = "TotT";
     9char *password = "ArcVier";
    1010
    1111char *clear_tests[] =
     
    1414        "ItllBeBitlBee",
    1515        "One more boring password",
     16        "Hoi hoi",
    1617        NULL
    1718};
     
    2829                int len;
    2930               
    30                 len = arc_encode( clear_tests[i], 0, &crypted, password );
     31                len = arc_encode( clear_tests[i], 0, &crypted, password, 12 );
    3132                len = arc_decode( crypted, len, &decrypted, password );
    3233               
     
    4142struct
    4243{
    43         unsigned char crypted[24];
     44        unsigned char crypted[30];
    4445        int len;
    4546        char *decrypted;
    4647} decrypt_tests[] = {
     48        /* One block with padding. */
    4749        {
    4850                {
    49                         0xc3, 0x0d, 0x43, 0xc3, 0xee, 0x80, 0xe2, 0x8c, 0x0b, 0x29, 0x32, 0x7e,
    50                         0x38, 0x05, 0x82, 0x10, 0x21, 0x1c, 0x4a, 0x00, 0x2c
    51                 }, 21, "Debugging sucks"
     51                        0x3f, 0x79, 0xb0, 0xf5, 0x91, 0x56, 0xd2, 0x1b, 0xd1, 0x4b, 0x67, 0xac,
     52                        0xb1, 0x31, 0xc9, 0xdb, 0xf9, 0xaa
     53                }, 18, "short pass"
    5254        },
     55       
     56        /* Two blocks with padding. */
    5357        {
    5458                {
    55                         0xb0, 0x00, 0x57, 0x0d, 0x0d, 0x0d, 0x70, 0xe1, 0xc0, 0x00, 0xa4, 0x25,
    56                         0x7d, 0xbe, 0x03, 0xcc, 0x24, 0xd1, 0x0c
    57                 }, 19, "Testing rocks"
     59                        0xf9, 0xa6, 0xec, 0x5d, 0xc7, 0x06, 0xb8, 0x6b, 0x63, 0x9f, 0x2d, 0xb5,
     60                        0x7d, 0xaa, 0x32, 0xbb, 0xd8, 0x08, 0xfd, 0x81, 0x2e, 0xca, 0xb4, 0xd7,
     61                        0x2f, 0x36, 0x9c, 0xac, 0xa0, 0xbc
     62                }, 30, "longer password"
    5863        },
     64
     65        /* This string is exactly two "blocks" long, to make sure unpadded strings also decrypt
     66           properly. */
    5967        {
    6068                {
    61                         0xb6, 0x92, 0x59, 0xe4, 0xf9, 0xc1, 0x7a, 0xf6, 0xf3, 0x18, 0xea, 0x28,
    62                         0x73, 0x6d, 0xb3, 0x0a, 0x6f, 0x0a, 0x2b, 0x43, 0x57, 0xe9, 0x3e, 0x63
    63                 }, 24, "OSCAR is creepy..."
    64         }
     69                        0x95, 0x4d, 0xcf, 0x4d, 0x5e, 0x6c, 0xcf, 0xef, 0xb9, 0x80, 0x00, 0xef,
     70                        0x25, 0xe9, 0x17, 0xf6, 0x29, 0x6a, 0x82, 0x79, 0x1c, 0xca, 0x68, 0xb5,
     71                        0x4e, 0xd0, 0xc1, 0x41, 0x8e, 0xe6
     72                }, 30, "OSCAR is really creepy.."
     73        },
     74        { "", 0, NULL }
    6575};
    6676
     
    6979        int i;
    7080       
    71         for( i = 0; clear_tests[i]; i++ )
     81        for( i = 0; decrypt_tests[i].len; i++ )
    7282        {
    7383                tcase_fn_start (decrypt_tests[i].decrypted, __FILE__, __LINE__);
     
    7989               
    8090                fail_if( strcmp( decrypt_tests[i].decrypted, decrypted ) != 0,
    81                          "%s didn't decrypt properly", clear_tests[i] );
     91                         "`%s' didn't decrypt properly", decrypt_tests[i].decrypted );
    8292               
    8393                g_free( decrypted );
  • tests/check_help.c

    r6cac643 rb79308b  
    77#include "help.h"
    88
    9 START_TEST(test_help_none)
     9START_TEST(test_help_initfree)
    1010        help_t *h, *r;
    1111        r = help_init(&h, "/dev/null");
    1212        fail_if(r == NULL);
    1313        fail_if(r != h);
     14       
     15        help_free(&h);
     16        fail_if(h != NULL);
    1417END_TEST
    1518
     
    2528        TCase *tc_core = tcase_create("Core");
    2629        suite_add_tcase (s, tc_core);
    27         tcase_add_test (tc_core, test_help_none);
     30        tcase_add_test (tc_core, test_help_initfree);
    2831        tcase_add_test (tc_core, test_help_nonexistent);
    2932        return s;
  • tests/check_irc.c

    r6cac643 rb79308b  
    3737        irc = irc_new(g_io_channel_unix_get_fd(ch1));
    3838
    39         fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\n"
    40                         "USER a a a a\r\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL);
     39        fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\r\n"
     40                        "USER a a a a\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL);
    4141        fail_unless(g_io_channel_flush(ch2, NULL) == G_IO_STATUS_NORMAL);
    4242
Note: See TracChangeset for help on using the changeset viewer.