Changes in / [5f8ab6a9:814aa52]


Ignore:
Files:
8 added
37 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r5f8ab6a9 r814aa52  
    128128ctags:
    129129        ctags `find . -name "*.c"` `find . -name "*.h"`
     130
     131# Using this as a bogus Make target to test if a GNU-compatible version of
     132# make is available.
     133helloworld:
     134        @echo Hello World
  • bitlbee.c

    r5f8ab6a9 r814aa52  
    3636static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition );
    3737
     38static gboolean try_listen( struct addrinfo *res )
     39{
     40        int i;
     41       
     42        global.listen_socket = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
     43        if( global.listen_socket < 0 )
     44        {
     45                log_error( "socket" );
     46                return FALSE;
     47        }
     48
     49#ifdef IPV6_V6ONLY             
     50        if( res->ai_family == AF_INET6 )
     51        {
     52                i = 0;
     53                setsockopt( global.listen_socket, IPPROTO_IPV6, IPV6_V6ONLY,
     54                            (char *) &i, sizeof( i ) );
     55        }
     56#endif
     57
     58        /* TIME_WAIT (?) sucks.. */
     59        i = 1;
     60        setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
     61
     62        i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen );
     63        if( i == -1 )
     64        {
     65                closesocket( global.listen_socket );
     66                global.listen_socket = -1;
     67               
     68                log_error( "bind" );
     69                return FALSE;
     70        }
     71       
     72        return TRUE;
     73}
     74
    3875int bitlbee_daemon_init()
    3976{
     
    4279        FILE *fp;
    4380       
    44         log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG );
    45         log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG );
     81        log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE );
     82        log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE );
    4683       
    4784        memset( &hints, 0, sizeof( hints ) );
     
    63100
    64101        global.listen_socket = -1;
    65 
     102       
     103        /* Try IPv6 first (which will become an IPv6+IPv4 socket). */
    66104        for( res = addrinfo_bind; res; res = res->ai_next )
    67         {
    68                 global.listen_socket = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
    69                 if( global.listen_socket < 0 )
    70                         continue;
    71 
    72                 /* TIME_WAIT (?) sucks.. */
    73                 i = 1;
    74                 setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
    75 
    76                 i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen );
    77                 if( i == -1 )
    78                 {
    79                         log_error( "bind" );
    80                         return( -1 );
    81                 }
    82 
    83                 break;
    84         }
    85 
     105                if( res->ai_family == AF_INET6 && try_listen( res ) )
     106                        break;
     107       
     108        /* The rest (so IPv4, I guess). */
     109        if( res == NULL )
     110                for( res = addrinfo_bind; res; res = res->ai_next )
     111                        if( res->ai_family != AF_INET6 && try_listen( res ) )
     112                                break;
     113       
    86114        freeaddrinfo( addrinfo_bind );
    87115
     
    107135                        exit( 0 );
    108136               
     137                setsid();
    109138                chdir( "/" );
    110139               
     
    137166#endif
    138167       
     168        if( !global.conf->nofork )
     169        {
     170                log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG );
     171                log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG );
     172        }
     173       
    139174        return( 0 );
    140175}
  • bitlbee.h

    r5f8ab6a9 r814aa52  
    3838
    3939#define PACKAGE "BitlBee"
    40 #define BITLBEE_VERSION "1.2.5"
     40#define BITLBEE_VERSION "1.2.6"
    4141#define VERSION BITLBEE_VERSION
     42#define BITLBEE_VER(a,b,c) (((a) << 16) + ((b) << 8) + (c))
     43#define BITLBEE_VERSION_CODE BITLBEE_VER(1, 2, 6)
    4244
    4345#define MAX_STRING 511
     
    168170
    169171char *set_eval_root_nick( set_t *set, char *new_nick );
     172char *set_eval_control_channel( set_t *set, char *new_name );
    170173
    171174extern global_t global;
  • conf.c

    r5f8ab6a9 r814aa52  
    8080        }
    8181       
    82         while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:" ) ) >= 0 )
     82        while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hR:u:V" ) ) >= 0 )
    8383        /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
    8484        {
     
    146146                                "  -d  Specify alternative user configuration directory\n"
    147147                                "  -x  Command-line interface to password encryption/hashing\n"
    148                                 "  -h  Show this help page.\n" );
     148                                "  -h  Show this help page.\n"
     149                                "  -V  Show version info.\n" );
     150                        return NULL;
     151                }
     152                else if( opt == 'V' )
     153                {
     154                        printf( "BitlBee %s\nAPI version %06x\n",
     155                                BITLBEE_VERSION, BITLBEE_VERSION_CODE );
    149156                        return NULL;
    150157                }
  • configure

    r5f8ab6a9 r814aa52  
    2020ipcsocket='/var/run/bitlbee.sock'
    2121pcdir='$prefix/lib/pkgconfig'
    22 systemlibdirs="/lib /usr/lib /usr/local/lib"
     22systemlibdirs="/lib /lib64 /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64"
    2323
    2424msn=1
     
    2626oscar=1
    2727yahoo=1
     28twitter=1
    2829
    2930debug=0
     
    6768--oscar=0/1     Disable/enable Oscar part (ICQ, AIM)    $oscar
    6869--yahoo=0/1     Disable/enable Yahoo part               $yahoo
     70--twitter=0/1 Disable/enable Twitter part               $twitter
    6971
    7072--debug=0/1     Disable/enable debugging                $debug
     
    158160
    159161echo CFLAGS=$CFLAGS >> Makefile.settings
    160 echo CFLAGS+=-I`pwd` -iquote`pwd`/lib -iquote`pwd`/protocols -I. >> Makefile.settings
     162echo CFLAGS+=-I`pwd` -I`pwd`/lib -I`pwd`/protocols -I. >> Makefile.settings
    161163
    162164echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings
     
    269271detect_ldap()
    270272{
    271         TMPFILE=$(mktemp)
     273        TMPFILE=$(mktemp /tmp/bitlbee-configure.XXXXXX)
    272274        if $CC -o $TMPFILE -shared -lldap 2>/dev/null >/dev/null; then
    273275                cat<<EOF>>Makefile.settings
     
    297299detect_resolv_dynamic()
    298300{
    299         echo "$RESOLV_TESTCODE" | $CC -o /dev/null -x c - -lresolv >/dev/null 2>/dev/null
     301        TMPFILE=$(mktemp /tmp/bitlbee-configure.XXXXXX)
     302        ret=1
     303        echo "$RESOLV_TESTCODE" | $CC -o $TMPFILE -x c - -lresolv >/dev/null 2>/dev/null
    300304        if [ "$?" = "0" ]; then
    301305                echo 'EFLAGS+=-lresolv' >> Makefile.settings
    302                 return 0
    303         fi
    304 
    305         return 1
     306                ret=0
     307        fi
     308
     309        rm -f $TMPFILE
     310        return $ret
    306311}
    307312
    308313detect_resolv_static()
    309314{
     315        TMPFILE=$(mktemp /tmp/bitlbee-configure.XXXXXX)
     316        ret=1
    310317        for i in $systemlibdirs; do
    311318                if [ -f $i/libresolv.a ]; then
    312                         echo "$RESOLV_TESTCODE" | $CC -o /dev/null -x c - -Wl,$i/libresolv.a >/dev/null 2>/dev/null
     319                        echo "$RESOLV_TESTCODE" | $CC -o $TMPFILE -x c - -Wl,$i/libresolv.a >/dev/null 2>/dev/null
    313320                        if [ "$?" = "0" ]; then
    314321                                echo 'EFLAGS+='$i'/libresolv.a' >> Makefile.settings
    315                                 return 0
     322                                ret=0
    316323                        fi
    317324                fi
    318325        done
    319326
    320         return 1
     327        rm -f $TMPFILE
     328        return $ret
    321329}
    322330
     
    494502fi
    495503
     504if ! make helloworld > /dev/null 2>&1; then
     505        echo "WARNING: Your version of make (BSD make?) does not support BitlBee's makefiles."
     506        echo "BitlBee needs GNU make to build properly. On most systems GNU make is available"
     507        echo "under the name 'gmake'."
     508        echo
     509        if gmake helloworld > /dev/null 2>&1; then
     510                echo "gmake seems to be available on your machine, great."
     511                echo
     512        else
     513                echo "gmake is not installed (or not working). Please try to install it."
     514                echo
     515        fi
     516fi
     517
    496518cat <<EOF>bitlbee.pc
    497519prefix=$prefix
     
    542564fi
    543565
     566if [ "$twitter" = 0 ]; then
     567        echo '#undef WITH_TWITTER' >> config.h
     568else
     569        echo '#define WITH_TWITTER' >> config.h
     570        protocols=$protocols'twitter '
     571        protoobjs=$protoobjs'twitter_mod.o '
     572fi
     573
    544574if [ "$protocols" = "PROTOCOLS = " ]; then
    545575        echo "Warning: You haven't selected any communication protocol to compile!"
  • debian/bitlbee.init

    r5f8ab6a9 r814aa52  
    3838d_start() {
    3939        # Make sure BitlBee can actually write its PID...
    40         touch /var/run/bitlbee.pid
    41         chown bitlbee: /var/run/bitlbee.pid
     40        touch $PIDFILE
     41        chown bitlbee: $PIDFILE
    4242       
    43         # Clean up after the bug between 1.2-5 and 1.2.1-2 where BitlBee ran
    44         # as root. (#494656 and #495877) Fixing this in the postinst script
    45         # is not enough since the user will restart his BitlBee after up-
    46         # grading the package, and the BitlBee running as root will then
    47         # save its settings, re-setting ownership of the file to root.
    48         # TODO: Remove this after a few revisions.
    49         find /var/lib/bitlbee -uid 0 -name '*.xml' -exec chown bitlbee: {} \;
    50 
    51         start-stop-daemon --start --quiet \
     43        start-stop-daemon --start --quiet --pidfile $PIDFILE \
    5244                --exec $DAEMON -- -p $BITLBEE_PORT -P $PIDFILE $BITLBEE_OPTS
    5345}
  • debian/changelog

    r5f8ab6a9 r814aa52  
     1bitlbee (1.2.5-1) unstable; urgency=low
     2
     3  * New upstream version.
     4  * Fixed issues with server-side MSN nickname corruption. (Closes: #538756)
     5  * Debconf translation fixes/additions. (Closes: #541754, #563504)
     6
     7 -- Wilmer van der Gaast <wilmer@gaast.net>  Wed, 17 Mar 2010 14:59:27 +0000
     8
     9bitlbee (1.2.4-2) unstable; urgency=low
     10
     11  * Merging in some changes from bzr-head:
     12  * Use libresolv.so where possible. (Closes: #551775)
     13  * Some include file changes that make the bitlbee-dev package useful again.
     14
     15 -- Wilmer van der Gaast <wilmer@gaast.net>  Thu, 19 Nov 2009 23:02:43 +0000
     16
     17bitlbee (1.2.4-1) unstable; urgency=low
     18
     19  * New upstream version.
     20  * Fixed issues with Yahoo! (Closes: #536178)
     21
     22 -- Wilmer van der Gaast <wilmer@gaast.net>  Sat, 17 Oct 2009 18:12:45 +0100
     23
     24bitlbee (1.2.3-2) unstable; urgency=low
     25
     26  * Fixed bitblee typo in prerm (introduced by NMU 1.2.1-1.1).
     27    (Closes: #531287)
     28  * Fixed bitlbee.deb dep in bitlbee-dev to deal with binary NMUs.
     29    (Closes: #531219)
     30  * Fixed free port detection code in debian/config which was a bit limited
     31    and also buggy.
     32  * Removing code that edits bitlbee.conf from postinst (and chown code in
     33    the init script), it's not really necessary anymore; bitlbee may only
     34    still run as root if the admin doesn't read conffile diffs.
     35    (Closes: #514572)
     36  * No longer overwriting port number info in /etc/default/bitlbee with
     37    what's in debconf. (Closes: #514148)
     38  * Added notes about the above two changes to bitlbee.conf.
     39
     40 -- Wilmer van der Gaast <wilmer@gaast.net>  Sun, 07 Jun 2009 21:17:39 +0100
     41
     42bitlbee (1.2.3-1) unstable; urgency=critical
     43
     44  * New upstream version.
     45  * Fixes another account hijacking issue. (Closes: #498159)
     46  * Restored --pidfile argument to start-stop-daemon, otherwise the init
     47    script fails to restart BitlBee when users are connected.
     48
     49 -- Wilmer van der Gaast <wilmer@gaast.net>  Sun, 07 Sep 2008 18:53:04 +0100
     50
    151bitlbee (1.2.2-1) unstable; urgency=critical
    252
  • debian/config

    r5f8ab6a9 r814aa52  
    22
    33. /usr/share/debconf/confmodule
     4[ -f /etc/default/bitlbee ] && . /etc/default/bitlbee
    45
    56db_title BitlBee
    67
    7 db_get bitlbee/serveport
    8 if [ "$RET" = "stillhavetoask" ]; then
    9         if netstat -ltn | grep ':6667' 2> /dev/null > /dev/null; then
    10                 port=6668;
    11         else
    12                 port=6667;
     8if [ -n "$BITLBEE_PORT" ]; then
     9        db_set bitlbee/serveport "$BITLBEE_PORT"
     10else
     11        db_get bitlbee/serveport
     12        if [ "$RET" = "stillhavetoask" ]; then
     13                listens=$(netstat -ltn | awk '{print $4}')
     14                for port in 6667 6666 6668 6669; do
     15                        if [ $(expr "$listens " : ".*:$port\s") = "0" ]; then
     16                                break
     17                        fi
     18                done
     19                db_set bitlbee/serveport $port;
    1320        fi
    14         db_set bitlbee/serveport $port;
    1521fi
    1622
  • debian/control

    r5f8ab6a9 r814aa52  
    1919Package: bitlbee-dev
    2020Architecture: all
    21 Depends: bitlbee (= ${binary:Version})
     21Depends: bitlbee (>= ${source:Version}), bitlbee (<< ${source:Version}.1~)
    2222Description: An IRC to other chat networks gateway
    2323 This program can be used as an IRC server which forwards everything you
  • debian/patches/bitlbee.conf.diff

    r5f8ab6a9 r814aa52  
    1 === modified file 'bitlbee.conf'
    2 --- debian/bitlbee/etc/bitlbee/bitlbee.conf     2008-08-26 22:33:54 +0000
    3 +++ debian/bitlbee/etc/bitlbee/bitlbee.conf     2008-08-27 23:18:13 +0000
    4 @@ -23,7 +23,7 @@
     1--- debian/bitlbee/etc/bitlbee/bitlbee.conf     2009-06-01 00:20:24.000000000 +0100
     2+++ debian/bitlbee/etc/bitlbee/bitlbee.conf     2009-06-07 21:16:19.000000000 +0100
     3@@ -23,13 +23,18 @@
    54 ## If BitlBee is started by root as a daemon, it can drop root privileges,
    65 ## and change to the specified user.
    76 ##
    87-# User = bitlbee
     8+## DEBIAN NOTE: Without this, BitlBee will run as root!
     9+##
    910+User = bitlbee
    1011 
    1112 ## DaemonPort/DaemonInterface:
    1213 ##
    13 
     14 ## For daemon mode, you can specify on what interface and port the daemon
     15 ## should be listening for connections.
     16 ##
     17+## DEBIAN NOTE: The init script passes the -p flag to use the port number
     18+## set using debconf, this overrides the DaemonPort setting here.
     19+##
     20 # DaemonInterface = 0.0.0.0
     21 # DaemonPort = 6667
     22 
  • debian/po/POTFILES.in

    r5f8ab6a9 r814aa52  
    1 [type: gettext/rfc822deb] bitlbee.templates.master
     1[type: gettext/rfc822deb] templates
  • debian/postinst

    r5f8ab6a9 r814aa52  
    3333## /etc/default/bitlbee: Auto-generated/updated script.
    3434##
    35 ## Don't edit this line, use dpkg-reconfigure bitlbee
     35## If running in (fork)daemon mode, listen on this TCP port.
    3636BITLBEE_PORT="$PORT"
    3737
     
    6161        else
    6262                mv /usr/share/bitlbee/help.upgrading /usr/share/bitlbee/help.txt
    63         fi
    64 fi
    65 
    66 if ! grep -qi '^User *= *' /etc/bitlbee/bitlbee.conf; then
    67         echo 'Updating configuration file, enabling User-setting...'
    68         if ! sed -i -e 's/# *User *= *.*/User = bitlbee/i' /etc/bitlbee/bitlbee.conf; then
    69                 echo 'Failed! BitlBee may run as root now, please check your configs.'
    7063        fi
    7164fi
  • debian/prerm

    r5f8ab6a9 r814aa52  
    1111else
    1212        if which invoke-rc.d >/dev/null 2>&1; then
    13                 invoke-rc.d bitblee stop || exit 0
     13                invoke-rc.d bitlbee stop || exit 0
    1414        else
    1515                /etc/init.d/bitlbee stop || exit 0
  • doc/CHANGES

    r5f8ab6a9 r814aa52  
    33
    44http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on
     5
     6Version 1.2.6:
     7- Native (very basic) support for Twitter, implemented by Geert Mulders.
     8  Currently supported are posting tweets, reading the ones of people you
     9  follow, and sending (not yet receiving!) direct messages.
     10- Fixed format of status messages in /WHOIS to improve IRC client
     11  compatibility.
     12- Show timestamps of offline messages/channel backlogs.
     13- Allow saving MSN display names locally since sometimes this stuff breaks
     14  server-side. (Use the local_display_name per-account setting.)
     15- Suppress empty "Headline:" messages for certain new XMPP broadcast
     16  messages.
     17- Better handling of XMPP contacts with multiple resources on-line. Default
     18  behaviour now is to write to wherever the last message came from, or to
     19  the bare JID (usually becomes a broadcast) if there wasn't any recent msg.
     20- Added a switchboard_keepalives setting which should solve some issues with
     21  talking to offline MSN contacts. (Although full support for offline
     22  messages is not ready yet!)
     23- The usual misc. bug fixes.
     24
     25Finished 19 Apr 2010
    526
    627Version 1.2.5:
     
    2344  the main client).
    2445
    25 Fixed 17 Mar 2010
     46Finished 17 Mar 2010
    2647
    2748Version 1.2.4:
  • doc/user-guide/commands.xml

    r5f8ab6a9 r814aa52  
    2121                        <description>
    2222                                <para>
    23                                         Adds an account on the given server with the specified protocol, username and password to the account list. Supported protocols right now are: Jabber, MSN, OSCAR (AIM/ICQ) and Yahoo. For more information about adding an account, see <emphasis>help account add &lt;protocol&gt;</emphasis>.
     23                                        Adds an account on the given server with the specified protocol, username and password to the account list. Supported protocols right now are: Jabber, MSN, OSCAR (AIM/ICQ), Yahoo and Twitter. For more information about adding an account, see <emphasis>help account add &lt;protocol&gt;</emphasis>.
    2424                                </para>
    2525                        </description>
     
    6363                                </ircexample>
    6464                        </bitlbee-command>
     65                       
     66                        <bitlbee-command name="twitter">
     67                                <syntax>account add twitter &lt;handle&gt; &lt;password&gt;</syntax>
     68
     69                                <description>
     70                                        <para>
     71                                                This module gives you simple access to Twitter. Although it uses the Twitter API, only Twitter itself is supported at the moment.
     72                                        </para>
     73                                       
     74                                        <para>
     75                                                By default all your Twitter contacts will come from a contact called twitter_(yourusername). You can change this behaviour using the <emphasis>mode</emphasis> setting (see <emphasis>help set mode</emphasis>).
     76                                        </para>
     77                                       
     78                                        <para>
     79                                                To send tweets yourself, send them to the twitter_(yourusername) contact, or just write in the groupchat channel if you enabled that option.
     80                                        </para>
     81                                </description>
     82                        </bitlbee-command>
    6583
    6684                        <bitlbee-command name="yahoo">
     
    550568
    551569        <bitlbee-setting name="auto_reconnect" type="boolean" scope="both">
    552                 <default>false</default>
     570                <default>true</default>
    553571
    554572                <description>
     
    668686                        </para>
    669687                </description>
    670 
     688        </bitlbee-setting>
     689
     690        <bitlbee-setting name="control_channel" type="string" scope="global">
     691                <default>&amp;bitlbee</default>
     692
     693                <description>
     694                        <para>
     695                                Normally the control channel where you can see all your contacts is called "&amp;bitlbee". 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.
     696                        </para>
     697                </description>
    671698        </bitlbee-setting>
    672699
     
    706733                        <para>
    707734                                With this option enabled, root will inform you when someone in your buddy list changes his/her "friendly name".
     735                        </para>
     736                </description>
     737        </bitlbee-setting>
     738
     739        <bitlbee-setting name="display_timestamps" type="boolean" scope="global">
     740                <default>true</default>
     741
     742                <description>
     743                        <para>
     744                                When incoming messages are old (i.e. offline messages and channel backlogs), BitlBee will prepend them with a timestamp. If you find them ugly or useless, you can use this setting to hide them.
    708745                        </para>
    709746                </description>
     
    750787                        </para>
    751788                </description>
    752 
     789        </bitlbee-setting>
     790
     791        <bitlbee-setting name="ignore_auth_requests" type="boolean" scope="account">
     792                <default>true</default>
     793
     794                <description>
     795                        <para>
     796                                Only supported by OSCAR so far, you can use this setting to ignore ICQ authorization requests, which are hardly used for legitimate (i.e. non-spam) reasons anymore.
     797                        </para>
     798                </description>
    753799        </bitlbee-setting>
    754800
     
    759805                        <para>
    760806                                Hereby you can change whether you want all lower case nick names or leave the case as it intended by your peer.
     807                        </para>
     808                </description>
     809
     810        </bitlbee-setting>
     811
     812        <bitlbee-setting name="local_display_name" type="boolean" scope="account">
     813                <default>false</default>
     814
     815                <description>
     816                        <para>
     817                                Mostly meant to work around a bug in MSN servers (forgetting the display name set by the user), this setting tells BitlBee to store your display name locally and set this name on the MSN servers when connecting.
    761818                        </para>
    762819                </description>
     
    825882        </bitlbee-setting>
    826883
     884        <bitlbee-setting name="mode" type="string" scope="account">
     885                <possible-values>one, many, chat</possible-values>
     886                <default>one</default>
     887
     888                <description>
     889                        <para>
     890                                By default, everything from the Twitter module will come from one nick, twitter_(yourusername). If you prefer to have individual nicks for everyone, you can set this setting to "many" instead.
     891                        </para>
     892                       
     893                        <para>
     894                                If you prefer to have all your Twitter things in a separate channel, you can set this setting to "chat".
     895                        </para>
     896                       
     897                        <para>
     898                                In the last two modes, you can send direct messages by /msg'ing your contacts directly. Note, however, that incoming DMs are not fetched yet.
     899                        </para>
     900                </description>
     901        </bitlbee-setting>
     902
    827903        <bitlbee-setting name="nick" type="string" scope="chat">
    828904
     
    10291105                        <para>
    10301106                                If BitlBee fails to detect this sometimes (most likely in AIM messages over an ICQ connection), you can set this setting to <emphasis>always</emphasis>, but this might sometimes accidentally strip non-HTML things too.
     1107                        </para>
     1108                </description>
     1109        </bitlbee-setting>
     1110
     1111        <bitlbee-setting name="switchboard_keepalives" type="boolean" scope="account">
     1112                <default>false</default>
     1113
     1114                <description>
     1115                        <para>
     1116                                Turn on this flag if you have difficulties talking to offline/invisible contacts.
     1117                        </para>
     1118                       
     1119                        <para>
     1120                                With this setting enabled, BitlBee will send keepalives to MSN switchboards with offline/invisible contacts every twenty seconds. This should keep the server and client on the other side from shutting it down.
     1121                        </para>
     1122                       
     1123                        <para>
     1124                                This is useful because BitlBee doesn't support MSN offline messages yet and the MSN servers won't let the user reopen switchboards to offline users. Once offline messaging is supported, this flag might be removed.
     1125                        </para>
     1126                </description>
     1127        </bitlbee-setting>
     1128
     1129        <bitlbee-setting name="timezone" type="string" scope="global">
     1130                <default>local</default>
     1131                <possible-values>local, utc, gmt, timezone-spec</possible-values>
     1132
     1133                <description>
     1134                        <para>
     1135                                If message timestamps are available for offline messages or chatroom backlogs, BitlBee will display them as part of the message. By default it will use the local timezone. If you're not in the same timezone as the BitlBee server, you can adjust the timestamps using this setting.
     1136                        </para>
     1137
     1138                        <para>
     1139                                Values local/utc/gmt should be self-explanatory. timezone-spec is a time offset in hours:minutes, for example: -8 for Pacific Standard Time, +2 for Central European Summer Time, +5:30 for Indian Standard Time.
    10311140                        </para>
    10321141                </description>
  • irc.c

    r5f8ab6a9 r814aa52  
    5555{
    5656        irc_t *irc = set->data;
     57        char *test;
     58        gsize test_bytes = 0;
    5759        GIConv ic, oc;
    5860
     
    6062                value = g_strdup( "utf-8" );
    6163
     64        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     65        {
     66                return NULL;
     67        }
     68       
     69        /* Do a test iconv to see if the user picked an IRC-compatible
     70           charset (for example utf-16 goes *horribly* wrong). */
     71        if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL ||
     72            test_bytes > 1 )
     73        {
     74                g_free( test );
     75                g_iconv_close( oc );
     76                irc_usermsg( irc, "Unsupported character set: The IRC protocol "
     77                                  "only supports 8-bit character sets." );
     78                return NULL;
     79        }
     80        g_free( test );
     81       
    6282        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
    6383        {
    64                 return NULL;
    65         }
    66         if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
    67         {
    68                 g_iconv_close( ic );
     84                g_iconv_close( oc );
    6985                return NULL;
    7086        }
     
    175191        s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
    176192        s = set_add( &irc->set, "color_encrypted", "true", set_eval_bool, irc );
     193        s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc );
    177194        s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
    178195        s = set_add( &irc->set, "default_target", "root", NULL, irc );
    179196        s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
     197        s = set_add( &irc->set, "display_timestamps", "true", set_eval_bool, irc );
    180198        s = set_add( &irc->set, "handle_unknown", "root", NULL, irc );
    181199        s = set_add( &irc->set, "halfop_buddies", "encrypted", set_eval_halfop_buddies, irc );
     
    192210        s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
    193211        s = set_add( &irc->set, "strip_html", "true", NULL, irc );
     212        s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc );
    194213        s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
    195214        s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
  • irc_commands.c

    r5f8ab6a9 r814aa52  
    498498                        irc_reply( irc, 301, "%s :%s", u->nick, u->away );
    499499                if( u->status_msg )
    500                         irc_reply( irc, 333, "%s :Status: %s", u->nick, u->status_msg );
     500                        irc_reply( irc, 320, "%s :%s", u->nick, u->status_msg );
    501501               
    502502                irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
  • lib/misc.c

    r5f8ab6a9 r814aa52  
    7777       
    7878        return mktime(&tm);
     79}
     80
     81time_t mktime_utc( struct tm *tp )
     82{
     83        struct tm utc;
     84        time_t res, tres;
     85       
     86        tp->tm_isdst = -1;
     87        res = mktime( tp );
     88        /* Problem is, mktime() just gave us the GMT timestamp for the
     89           given local time... While the given time WAS NOT local. So
     90           we should fix this now.
     91           
     92           Now I could choose between messing with environment variables
     93           (kludgy) or using timegm() (not portable)... Or doing the
     94           following, which I actually prefer...
     95           
     96           tzset() may also work but in other places I actually want to
     97           use local time.
     98           
     99           FFFFFFFFFFFFFFFFFFFFFUUUUUUUUUUUUUUUUUUUU!! */
     100        gmtime_r( &res, &utc );
     101        utc.tm_isdst = -1;
     102        if( utc.tm_hour == tp->tm_hour && utc.tm_min == tp->tm_min )
     103                /* Sweet! We're in UTC right now... */
     104                return res;
     105       
     106        tres = mktime( &utc );
     107        res += res - tres;
     108       
     109        /* Yes, this is a hack. And it will go wrong around DST changes.
     110           BUT this is more likely to be threadsafe than messing with
     111           environment variables, and possibly more portable... */
     112       
     113        return res;
    79114}
    80115
  • lib/misc.h

    r5f8ab6a9 r814aa52  
    4343
    4444G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec );
     45G_MODULE_EXPORT time_t mktime_utc( struct tm *tp );
    4546double gettime( void );
    4647
  • log.c

    r5f8ab6a9 r814aa52  
    172172                fprintf(stdout, "Debug: %s\n", message);
    173173#endif
     174        /* Always log stuff in syslogs too. */
     175        log_syslog(level, message);
    174176        return;
    175177}
  • protocols/jabber/jabber.c

    r5f8ab6a9 r814aa52  
    5757        set_t *s;
    5858        char str[16];
     59       
     60        s = set_add( &acc->set, "activity_timeout", "600", set_eval_int, acc );
    5961       
    6062        g_snprintf( str, sizeof( str ), "%d", jabber_port_list[0] );
     
    307309                bud = jabber_buddy_by_ext_jid( ic, who, 0 );
    308310        else
    309                 bud = jabber_buddy_by_jid( ic, who, 0 );
     311                bud = jabber_buddy_by_jid( ic, who, GET_BUDDY_BARE_OK );
    310312       
    311313        node = xt_new_node( "body", message, NULL );
     
    352354static void jabber_get_info( struct im_connection *ic, char *who )
    353355{
    354         struct jabber_data *jd = ic->proto_data;
    355356        struct jabber_buddy *bud;
    356357       
    357         if( strchr( who, '/' ) )
    358                 bud = jabber_buddy_by_jid( ic, who, 0 );
    359         else
    360         {
    361                 char *s = jabber_normalize( who );
    362                 bud = g_hash_table_lookup( jd->buddies, s );
    363                 g_free( s );
    364         }
     358        bud = jabber_buddy_by_jid( ic, who, GET_BUDDY_FIRST );
    365359       
    366360        while( bud )
  • protocols/jabber/jabber.h

    r5f8ab6a9 r814aa52  
    108108};
    109109
     110/* Somewhat messy data structure: We have a hash table with the bare JID as
     111   the key and the head of a struct jabber_buddy list as the value. The head
     112   is always a bare JID. If the JID has other resources (often the case,
     113   except for some transports that don't support multiple resources), those
     114   follow. In that case, the bare JID at the beginning doesn't actually
     115   refer to a real session and should only be used for operations that
     116   support incomplete JIDs. */
    110117struct jabber_buddy
    111118{
     
    121128        char *away_message;
    122129       
    123         time_t last_act;
     130        time_t last_msg;
    124131        jabber_buddy_flags_t flags;
    125132       
     
    209216        GET_BUDDY_EXACT = 2,    /* Get an exact match (only makes sense with bare JIDs). */
    210217        GET_BUDDY_FIRST = 4,    /* No selection, simply get the first resource for this JID. */
     218        GET_BUDDY_BARE = 8,     /* Get the bare version of the JID (possibly inexistent). */
     219        GET_BUDDY_BARE_OK = 16, /* Allow returning a bare JID if that seems better. */
    211220} get_buddy_flags_t;
    212221
  • protocols/jabber/jabber_util.c

    r5f8ab6a9 r814aa52  
    44*  Jabber module - Misc. stuff                                              *
    55*                                                                           *
    6 *  Copyright 2006 Wilmer van der Gaast <wilmer@gaast.net>                   *
     6*  Copyright 2006-2010 Wilmer van der Gaast <wilmer@gaast.net>             
    77*                                                                           *
    88*  This program is free software; you can redistribute it and/or modify     *
     
    345345        if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
    346346        {
     347                /* The first entry is always a bare JID. If there are more, we
     348                   should ignore the first one here. */
     349                if( bud->next )
     350                        bud = bud->next;
     351               
    347352                /* If this is a transport buddy or whatever, it can't have more
    348353                   than one instance, so this is always wrong: */
     
    379384        else
    380385        {
    381                 /* Keep in mind that full_jid currently isn't really
    382                    a full JID... */
    383                 new->bare_jid = g_strdup( full_jid );
     386                new->full_jid = new->bare_jid = g_strdup( full_jid );
    384387                g_hash_table_insert( jd->buddies, new->bare_jid, new );
     388               
     389                if( s )
     390                {
     391                        new->next = g_new0( struct jabber_buddy, 1 );
     392                        new->next->bare_jid = new->bare_jid;
     393                        new = new->next;
     394                }
    385395        }
    386396       
     
    408418{
    409419        struct jabber_data *jd = ic->proto_data;
    410         struct jabber_buddy *bud;
     420        struct jabber_buddy *bud, *head;
    411421        char *s, *jid;
    412422       
     
    420430                if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
    421431                {
     432                        bare_exists = 1;
     433                       
     434                        if( bud->next )
     435                                bud = bud->next;
     436                       
    422437                        /* Just return the first one for this bare JID. */
    423438                        if( flags & GET_BUDDY_FIRST )
     
    441456                                        break;
    442457                }
    443                 else
    444                 {
    445                         /* This variable tells the if down here that the bare
    446                            JID already exists and we should feel free to add
    447                            more resources, if the caller asked for that. */
    448                         bare_exists = 1;
    449                 }
    450458               
    451459                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
    452                     ( !bare_exists || imcb_find_buddy( ic, jid ) ) )
     460                    ( bare_exists || imcb_find_buddy( ic, jid ) ) )
    453461                {
    454462                        *s = '/';
     
    464472                char *set;
    465473               
    466                 bud = g_hash_table_lookup( jd->buddies, jid );
     474                head = g_hash_table_lookup( jd->buddies, jid );
     475                bud = ( head && head->next ) ? head->next : head;
    467476               
    468477                g_free( jid );
     
    481490                        /* Looks like the caller doesn't care about details. */
    482491                        return bud;
     492                else if( flags & GET_BUDDY_BARE )
     493                        return head;
    483494               
    484495                best_prio = best_time = bud;
     
    487498                        if( bud->priority > best_prio->priority )
    488499                                best_prio = bud;
    489                         if( bud->last_act > best_time->last_act )
     500                        if( bud->last_msg > best_time->last_msg )
    490501                                best_time = bud;
    491502                }
     
    493504                if( ( set = set_getstr( &ic->acc->set, "resource_select" ) ) == NULL )
    494505                        return NULL;
    495                 else if( strcmp( set, "activity" ) == 0 )
     506                else if( strcmp( set, "priority" ) == 0 )
     507                        return best_prio;
     508                else if( flags & GET_BUDDY_BARE_OK ) /* && strcmp( set, "activity" ) == 0 */
     509                {
     510                        if( best_time->last_msg + set_getint( &ic->acc->set, "activity_timeout" ) >= time( NULL ) )
     511                                return best_time;
     512                        else
     513                                return head;
     514                }
     515                else
    496516                        return best_time;
    497                 else /* if( strcmp( set, "priority" ) == 0 ) */
    498                         return best_prio;
    499517        }
    500518}
     
    538556{
    539557        struct jabber_data *jd = ic->proto_data;
    540         struct jabber_buddy *bud, *prev, *bi;
     558        struct jabber_buddy *bud, *prev = NULL, *bi;
    541559        char *s, *full_jid;
    542560       
     
    548566        if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
    549567        {
     568                if( bud->next )
     569                        bud = (prev=bud)->next;
     570               
    550571                /* If there's only one item in the list (and if the resource
    551572                   matches), removing it is simple. (And the hash reference
     
    555576                      ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) )
    556577                {
    557                         g_hash_table_remove( jd->buddies, bud->bare_jid );
    558                         g_free( bud->bare_jid );
    559                         g_free( bud->ext_jid );
    560                         g_free( bud->full_jid );
    561                         g_free( bud->away_message );
    562                         g_free( bud );
    563                        
    564                         g_free( full_jid );
    565                        
    566                         return 1;
     578                        return jabber_buddy_remove_bare( ic, full_jid );
    567579                }
    568580                else if( s == NULL || bud->resource == NULL )
     
    575587                else
    576588                {
    577                         for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next )
     589                        for( bi = bud; bi; bi = (prev=bi)->next )
    578590                                if( strcmp( bi->resource, s + 1 ) == 0 )
    579591                                        break;
     
    586598                                        prev->next = bi->next;
    587599                                else
    588                                         /* The hash table should point at the second
    589                                            item, because we're removing the first. */
     600                                        /* Don't think this should ever happen anymore. */
    590601                                        g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next );
    591602                               
     
    656667time_t jabber_get_timestamp( struct xt_node *xt )
    657668{
    658         struct tm tp, utc;
    659669        struct xt_node *c;
    660         time_t res, tres;
    661670        char *s = NULL;
     671        struct tm tp;
    662672       
    663673        for( c = xt->children; ( c = xt_find_node( c, "x" ) ); c = c->next )
     
    677687        tp.tm_year -= 1900;
    678688        tp.tm_mon --;
    679         tp.tm_isdst = -1; /* GRRRRRRRRRRR */
    680        
    681         res = mktime( &tp );
    682         /* Problem is, mktime() just gave us the GMT timestamp for the
    683            given local time... While the given time WAS NOT local. So
    684            we should fix this now.
    685        
    686            Now I could choose between messing with environment variables
    687            (kludgy) or using timegm() (not portable)... Or doing the
    688            following, which I actually prefer... */
    689         gmtime_r( &res, &utc );
    690         utc.tm_isdst = -1; /* Once more: GRRRRRRRRRRRRRRRRRR!!! */
    691         if( utc.tm_hour == tp.tm_hour && utc.tm_min == tp.tm_min )
    692                 /* Sweet! We're in UTC right now... */
    693                 return res;
    694        
    695         tres = mktime( &utc );
    696         res += res - tres;
    697        
    698         /* Yes, this is a hack. And it will go wrong around DST changes.
    699            BUT this is more likely to be threadsafe than messing with
    700            environment variables, and possibly more portable... */
    701        
    702         return res;
     689       
     690        return mktime_utc( &tp );
    703691}
    704692
  • protocols/jabber/message.c

    r5f8ab6a9 r814aa52  
    7171                        if( bud )
    7272                        {
    73                                 bud->last_act = time( NULL );
     73                                bud->last_msg = time( NULL );
    7474                                from = bud->ext_jid ? : bud->bare_jid;
    7575                        }
     
    8080                if( type && strcmp( type, "headline" ) == 0 )
    8181                {
    82                         c = xt_find_node( node->children, "subject" );
    83                         g_string_append_printf( fullmsg, "Headline: %s\n", c && c->text_len > 0 ? c->text : "" );
     82                        if( ( c = xt_find_node( node->children, "subject" ) ) && c->text_len > 0 )
     83                                g_string_append_printf( fullmsg, "Headline: %s\n", c->text );
    8484                       
    8585                        /* <x xmlns="jabber:x:oob"><url>http://....</url></x> can contain a URL, it seems. */
  • protocols/jabber/presence.c

    r5f8ab6a9 r814aa52  
    6868                {
    6969                        bud->away_state = NULL;
    70                         /* Let's only set last_act if there's *no* away state,
    71                            since it could be some auto-away thingy. */
    72                         bud->last_act = time( NULL );
    7370                }
    7471               
  • protocols/msn/msn.c

    r5f8ab6a9 r814aa52  
    3131GSList *msn_switchboards;
    3232
    33 static char *msn_set_display_name( set_t *set, char *value );
     33static char *set_eval_display_name( set_t *set, char *value );
    3434
    3535static void msn_init( account_t *acc )
    3636{
    37         set_t *s;
    38        
    39         s = set_add( &acc->set, "display_name", NULL, msn_set_display_name, acc );
    40         s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
    41 
    42         s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
     37        set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc );
     38        set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc );
     39        set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
     40        set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc );
    4341}
    4442
     
    167165static void msn_set_my_name( struct im_connection *ic, char *info )
    168166{
    169         msn_set_display_name( set_find( &ic->acc->set, "display_name" ), info );
     167        msn_set_display_name( ic, info );
    170168}
    171169
     
    283281}
    284282
    285 static char *msn_set_display_name( set_t *set, char *value )
     283static char *set_eval_display_name( set_t *set, char *value )
    286284{
    287285        account_t *acc = set->data;
    288286        struct im_connection *ic = acc->ic;
    289         struct msn_data *md;
    290         char buf[1024], *fn;
    291        
    292         /* Double-check. */
     287       
     288        /* Allow any name if we're offline. */
    293289        if( ic == NULL )
    294                 return NULL;
    295        
    296         md = ic->proto_data;
     290                return value;
    297291       
    298292        if( strlen( value ) > 129 )
     
    301295                return NULL;
    302296        }
    303        
    304         fn = msn_http_encode( value );
    305        
    306         g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn );
    307         msn_write( ic, buf, strlen( buf ) );
    308         g_free( fn );
    309297       
    310298        /* Returning NULL would be better, because the server still has to
    311299           confirm the name change. However, it looks a bit confusing to the
    312300           user. */
    313         return value;
     301        return msn_set_display_name( ic, value ) ? value : NULL;
    314302}
    315303
  • protocols/msn/msn.h

    r5f8ab6a9 r814aa52  
    3131#define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r"
    3232#define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r"
     33#define SB_KEEPALIVE_MESSAGE "\r\r\rDONT HANG UP ON ME!\r\r\r"
    3334
    3435#ifdef DEBUG_MSN
     
    5354                           "TypingUser: %s\r\n" \
    5455                           "\r\n\r\n"
     56
     57#define SB_KEEPALIVE_HEADERS "MIME-Version: 1.0\r\n" \
     58                             "Content-Type: text/x-ping\r\n" \
     59                             "\r\n\r\n"
    5560
    5661#define PROFILE_URL "http://members.msn.com/"
     
    8388        gint inp;
    8489        struct msn_handler_data *handler;
     90        gint keepalive;
    8591       
    8692        int trId;
     
    161167char *msn_http_encode( const char *input );
    162168void msn_msgq_purge( struct im_connection *ic, GSList **list );
     169gboolean msn_set_display_name( struct im_connection *ic, const char *rawname );
    163170
    164171/* tables.c */
     
    179186gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond );
    180187int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m );
     188void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial );
     189void msn_sb_stop_keepalives( struct msn_switchboard *sb );
    181190
    182191#endif //_MSN_H
  • protocols/msn/msn_util.c

    r5f8ab6a9 r814aa52  
    3838                imcb_error( ic, "Short write() to main server" );
    3939                imc_logout( ic, TRUE );
    40                 return( 0 );
    41         }
    42        
    43         return( 1 );
     40                return 0;
     41        }
     42       
     43        return 1;
    4444}
    4545
     
    377377        g_string_free( ret, TRUE );
    378378}
     379
     380gboolean msn_set_display_name( struct im_connection *ic, const char *rawname )
     381{
     382        char *fn = msn_http_encode( rawname );
     383        struct msn_data *md = ic->proto_data;
     384        char buf[1024];
     385       
     386        g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn );
     387        g_free( fn );
     388       
     389        return msn_write( ic, buf, strlen( buf ) ) != 0;
     390}
  • protocols/msn/ns.c

    r5f8ab6a9 r814aa52  
    3535
    3636static void msn_auth_got_passport_token( struct msn_auth_data *mad );
     37static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name );
    3738
    3839gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
     
    231232                else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 )
    232233                {
    233                         set_t *s;
    234                        
    235234                        if( num_parts == 7 )
    236                         {
    237                                 http_decode( cmd[4] );
    238                                
    239                                 strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
    240                                 ic->displayname[sizeof(ic->displayname)-1] = 0;
    241                                
    242                                 if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
    243                                 {
    244                                         g_free( s->value );
    245                                         s->value = g_strdup( cmd[4] );
    246                                 }
    247                         }
     235                                msn_ns_got_display_name( ic, cmd[4] );
    248236                        else
    249                         {
    250237                                imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
    251                         }
    252238                       
    253239                        imcb_log( ic, "Authenticated, getting buddy list" );
     
    422408        else if( strcmp( cmd[0], "FLN" ) == 0 )
    423409        {
    424                 if( cmd[1] )
    425                         imcb_buddy_status( ic, cmd[1], 0, NULL, NULL );
     410                if( cmd[1] == NULL )
     411                        return 1;
     412               
     413                imcb_buddy_status( ic, cmd[1], 0, NULL, NULL );
     414               
     415                msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE );
    426416        }
    427417        else if( strcmp( cmd[0], "NLN" ) == 0 )
     
    449439                                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
    450440                                   st->name, NULL );
     441               
     442                msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) );
    451443        }
    452444        else if( strcmp( cmd[0], "RNG" ) == 0 )
     
    553545                return( 0 );
    554546        }
     547#if 0
     548        /* Discard this one completely for now since I don't care about the ack
     549           and since MSN servers can apparently screw up the formatting. */
    555550        else if( strcmp( cmd[0], "REA" ) == 0 )
    556551        {
     
    583578                }
    584579        }
     580#endif
    585581        else if( strcmp( cmd[0], "IPG" ) == 0 )
    586582        {
     
    732728        }
    733729}
     730
     731static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
     732{
     733        set_t *s;
     734       
     735        if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL )
     736                return FALSE; /* Shouldn't happen.. */
     737       
     738        http_decode( name );
     739       
     740        if( s->value && strcmp( s->value, name ) == 0 )
     741        {
     742                return TRUE;
     743                /* The names match, nothing to worry about. */
     744        }
     745        else if( s->value != NULL &&
     746                 ( strcmp( name, ic->acc->user ) == 0 ||
     747                   set_getbool( &ic->acc->set, "local_display_name" ) ) )
     748        {
     749                /* The server thinks our display name is our e-mail address
     750                   which is probably wrong, or the user *wants* us to do this:
     751                   Always use the locally set display_name. */
     752                return msn_set_display_name( ic, s->value );
     753        }
     754        else
     755        {
     756                if( s->value && *s->value )
     757                        imcb_log( ic, "BitlBee thinks your display name is `%s' but "
     758                                      "the MSN server says it's `%s'. Using the MSN "
     759                                      "server's name. Set local_display_name to true "
     760                                      "to use the local name.", s->value, name );
     761               
     762                if( g_utf8_validate( name, -1, NULL ) )
     763                {
     764                        g_free( s->value );
     765                        s->value = g_strdup( name );
     766                }
     767                else
     768                {
     769                        imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
     770                }
     771               
     772                return TRUE;
     773        }
     774}
  • protocols/msn/sb.c

    r5f8ab6a9 r814aa52  
    168168               
    169169                /* Build the message. Convert LF to CR-LF for normal messages. */
    170                 if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 )
     170                if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
     171                {
     172                        i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
     173                        buf = g_new0( char, i );
     174                        i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
     175                }
     176                else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 )
     177                {
     178                        buf = g_strdup( SB_KEEPALIVE_HEADERS );
     179                        i = strlen( buf );
     180                }
     181                else
    171182                {
    172183                        buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
     
    182193                        }
    183194                }
    184                 else
    185                 {
    186                         i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
    187                         buf = g_new0( char, i );
    188                         i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
    189                 }
    190195               
    191196                /* Build the final packet (MSG command + the message). */
     
    250255       
    251256        msn_msgq_purge( ic, &sb->msgq );
     257        msn_sb_stop_keepalives( sb );
    252258       
    253259        if( sb->key ) g_free( sb->key );
     
    471477               
    472478                sb->ready = 1;
     479               
     480                msn_sb_start_keepalives( sb, FALSE );
    473481        }
    474482        else if( strcmp( cmd[0], "CAL" ) == 0 )
     
    520528                        }
    521529                       
     530                        msn_sb_start_keepalives( sb, FALSE );
     531                       
    522532                        return( st );
    523533                }
     
    581591                if( sb->who )
    582592                {
     593                        msn_sb_stop_keepalives( sb );
     594                       
    583595                        /* This is a single-person chat, and the other person is leaving. */
    584596                        g_free( sb->who );
     
    764776        return( 1 );
    765777}
     778
     779static gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond )
     780{
     781        struct msn_switchboard *sb = data;
     782        return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE );
     783}
     784
     785void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial )
     786{
     787        struct buddy *b;
     788       
     789        if( sb && sb->who && sb->keepalive == 0 &&
     790            ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present &&
     791            set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) )
     792        {
     793                if( initial )
     794                        msn_sb_keepalive( sb, 0, 0 );
     795               
     796                sb->keepalive = b_timeout_add( 20000, msn_sb_keepalive, sb );
     797        }
     798}
     799
     800void msn_sb_stop_keepalives( struct msn_switchboard *sb )
     801{
     802        if( sb && sb->keepalive > 0 )
     803        {
     804                b_event_remove( sb->keepalive );
     805                sb->keepalive = 0;
     806        }
     807}
  • protocols/nogaim.c

    r5f8ab6a9 r814aa52  
    3939
    4040static int remove_chat_buddy_silent( struct groupchat *b, const char *handle );
     41static char *format_timestamp( irc_t *irc, time_t msg_ts );
    4142
    4243GSList *connections;
     
    132133        extern void byahoo_initmodule();
    133134        extern void jabber_initmodule();
     135        extern void twitter_initmodule();
    134136
    135137#ifdef WITH_MSN
     
    147149#ifdef WITH_JABBER
    148150        jabber_initmodule();
     151#endif
     152
     153#ifdef WITH_TWITTER
     154        twitter_initmodule();
    149155#endif
    150156
     
    727733{
    728734        irc_t *irc = ic->irc;
    729         char *wrapped;
     735        char *wrapped, *ts = NULL;
    730736        user_t *u;
    731737
     
    776782            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
    777783                strip_html( msg );
    778 
     784       
     785        if( set_getbool( &ic->irc->set, "display_timestamps" ) &&
     786            ( ts = format_timestamp( irc, sent_at ) ) )
     787        {
     788                char *new = g_strconcat( ts, msg, NULL );
     789                g_free( ts );
     790                ts = msg = new;
     791        }
     792       
    779793        wrapped = word_wrap( msg, 425 );
    780794        irc_msgfrom( irc, u->nick, wrapped );
    781795        g_free( wrapped );
    782796        g_free( msg );
     797        g_free( ts );
    783798}
    784799
     
    822837       
    823838        return c;
     839}
     840
     841void imcb_chat_name_hint( struct groupchat *c, const char *name )
     842{
     843        if( !c->joined )
     844        {
     845                struct im_connection *ic = c->ic;
     846                char stripped[MAX_NICK_LENGTH+1], *full_name;
     847               
     848                strncpy( stripped, name, MAX_NICK_LENGTH );
     849                stripped[MAX_NICK_LENGTH] = '\0';
     850                nick_strip( stripped );
     851                if( set_getbool( &ic->irc->set, "lcnicks" ) )
     852                        nick_lc( stripped );
     853               
     854                full_name = g_strdup_printf( "&%s", stripped );
     855               
     856                if( stripped[0] &&
     857                    nick_cmp( stripped, ic->irc->channel + 1 ) != 0 &&
     858                    irc_chat_by_channel( ic->irc, full_name ) == NULL )
     859                {
     860                        g_free( c->channel );
     861                        c->channel = full_name;
     862                }
     863                else
     864                {
     865                        g_free( full_name );
     866                }
     867        }
    824868}
    825869
     
    884928        if( c && u )
    885929        {
    886                 irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", wrapped );
     930                char *ts = NULL;
     931                if( set_getbool( &ic->irc->set, "display_timestamps" ) )
     932                        ts = format_timestamp( ic->irc, sent_at );
     933                irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped );
     934                g_free( ts );
    887935        }
    888936        else
     
    10211069
    10221070
     1071/* Misc. BitlBee stuff which shouldn't really be here */
     1072
     1073char *set_eval_timezone( set_t *set, char *value )
     1074{
     1075        char *s;
     1076       
     1077        if( strcmp( value, "local" ) == 0 ||
     1078            strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 )
     1079                return value;
     1080       
     1081        /* Otherwise: +/- at the beginning optional, then one or more numbers,
     1082           possibly followed by a colon and more numbers. Don't bother bound-
     1083           checking them since users are free to shoot themselves in the foot. */
     1084        s = value;
     1085        if( *s == '+' || *s == '-' )
     1086                s ++;
     1087       
     1088        /* \d+ */
     1089        if( !isdigit( *s ) )
     1090                return SET_INVALID;
     1091        while( *s && isdigit( *s ) ) s ++;
     1092       
     1093        /* EOS? */
     1094        if( *s == '\0' )
     1095                return value;
     1096       
     1097        /* Otherwise, colon */
     1098        if( *s != ':' )
     1099                return SET_INVALID;
     1100        s ++;
     1101       
     1102        /* \d+ */
     1103        if( !isdigit( *s ) )
     1104                return SET_INVALID;
     1105        while( *s && isdigit( *s ) ) s ++;
     1106       
     1107        /* EOS */
     1108        return *s == '\0' ? value : SET_INVALID;
     1109}
     1110
     1111static char *format_timestamp( irc_t *irc, time_t msg_ts )
     1112{
     1113        time_t now_ts = time( NULL );
     1114        struct tm now, msg;
     1115        char *set;
     1116       
     1117        /* If the timestamp is <= 0 or less than a minute ago, discard it as
     1118           it doesn't seem to add to much useful info and/or might be noise. */
     1119        if( msg_ts <= 0 || msg_ts > now_ts - 60 )
     1120                return NULL;
     1121       
     1122        set = set_getstr( &irc->set, "timezone" );
     1123        if( strcmp( set, "local" ) == 0 )
     1124        {
     1125                localtime_r( &now_ts, &now );
     1126                localtime_r( &msg_ts, &msg );
     1127        }
     1128        else
     1129        {
     1130                int hr, min = 0, sign = 60;
     1131               
     1132                if( set[0] == '-' )
     1133                {
     1134                        sign *= -1;
     1135                        set ++;
     1136                }
     1137                else if( set[0] == '+' )
     1138                {
     1139                        set ++;
     1140                }
     1141               
     1142                if( sscanf( set, "%d:%d", &hr, &min ) >= 1 )
     1143                {
     1144                        msg_ts += sign * ( hr * 60 + min );
     1145                        now_ts += sign * ( hr * 60 + min );
     1146                }
     1147               
     1148                gmtime_r( &now_ts, &now );
     1149                gmtime_r( &msg_ts, &msg );
     1150        }
     1151       
     1152        if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday )
     1153                return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
     1154                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1155        else
     1156                return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
     1157                                        "%02d:%02d:%02d\x02]\x02 ",
     1158                                        msg.tm_year + 1900, msg.tm_mon, msg.tm_mday,
     1159                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1160}
     1161
    10231162/* The plan is to not allow straight calls to prpl functions anymore, but do
    10241163   them all from some wrappers. We'll start to define some down here: */
     
    10631202{
    10641203        char *away, *msg = NULL;
     1204       
     1205        if( ic->acc->prpl->away_states == NULL ||
     1206            ic->acc->prpl->set_away == NULL )
     1207                return 0;
    10651208       
    10661209        away = set_getstr( &ic->acc->set, "away" ) ?
  • protocols/nogaim.h

    r5f8ab6a9 r814aa52  
    306306 *   user, too. */
    307307G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle );
     308G_MODULE_EXPORT void imcb_chat_name_hint( struct groupchat *c, const char *name );
    308309G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, const char *handle );
    309310/* To remove a handle from a group chat. Reason can be NULL. */
     
    328329
    329330/* Misc. stuff */
     331char *set_eval_timezone( set_t *set, char *value );
    330332gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond );
    331333void cancel_auto_reconnect( struct account *a );
  • protocols/oscar/oscar.c

    r5f8ab6a9 r814aa52  
    373373        set_t *s;
    374374       
    375         s = set_add( &acc->set, "server", AIM_DEFAULT_LOGIN_SERVER, set_eval_account, acc );
     375        if (isdigit(acc->user[0])) {
     376                set_add(&acc->set, "ignore_auth_requests", "false", set_eval_bool, acc);
     377        }
     378       
     379        s = set_add(&acc->set, "server", AIM_DEFAULT_LOGIN_SERVER, set_eval_account, acc);
    376380        s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
    377381       
    378         if (isdigit(acc->user[0])) {
    379                 s = set_add( &acc->set, "web_aware", "false", set_eval_bool, acc );
     382        if(isdigit(acc->user[0])) {
     383                s = set_add(&acc->set, "web_aware", "false", set_eval_bool, acc);
    380384                s->flags |= ACC_SET_OFFLINE_ONLY;
    381385        }
     
    12121216 */
    12131217static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg) {
    1214         struct icq_auth *data = g_new(struct icq_auth, 1);
     1218        struct icq_auth *data;
    12151219        char *reason = NULL;
    12161220        char *dialog_msg;
    1217        
     1221
     1222        if (set_getbool(&ic->acc->set, "ignore_auth_requests"))
     1223                return;
     1224       
     1225        data = g_new(struct icq_auth, 1);
     1226
    12181227        if (strlen(msg) > 6)
    12191228                reason = msg + 6;
  • root_commands.c

    r5f8ab6a9 r814aa52  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    659659                irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
    660660        }
     661        else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     662        {
     663                if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) )
     664                {
     665                        u = user_find( irc, irc->nick );
     666                       
     667                        irc_part( irc, u, irc->channel );
     668                        g_free( irc->channel );
     669                        irc->channel = g_strdup( cmd[2] );
     670                        irc_join( irc, u, irc->channel );
     671                       
     672                        if( strcmp( cmd[0], "set_rename" ) != 0 )
     673                                set_setstr( &irc->set, "control_channel", cmd[2] );
     674                }
     675        }
    661676        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
    662677        {
     
    706721       
    707722        return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
     723}
     724
     725char *set_eval_control_channel( set_t *set, char *new_name )
     726{
     727        irc_t *irc = set->data;
     728       
     729        if( strcmp( irc->channel, new_name ) != 0 )
     730        {
     731                char *cmd[] = { "set_rename", irc->channel, new_name, NULL };
     732               
     733                cmd_rename( irc, cmd );
     734        }
     735       
     736        return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;
    708737}
    709738
  • storage_xml.c

    r5f8ab6a9 r814aa52  
    496496                goto write_error;
    497497       
     498        fsync( fd );
    498499        close( fd );
    499500       
  • tests/check_jabber_util.c

    r5f8ab6a9 r814aa52  
    1414       
    1515        budw1 = jabber_buddy_add( ic, "wilmer@gaast.net/BitlBee" );
    16         budw1->last_act = time( NULL ) - 100;
     16        budw1->last_msg = time( NULL ) - 100;
    1717        budw2 = jabber_buddy_add( ic, "WILMER@gaast.net/Telepathy" );
    1818        budw2->priority = 2;
    19         budw2->last_act = time( NULL );
     19        budw2->last_msg = time( NULL );
    2020        budw3 = jabber_buddy_add( ic, "wilmer@GAAST.NET/bitlbee" );
    21         budw3->last_act = time( NULL ) - 200;
     21        budw3->last_msg = time( NULL ) - 200;
    2222        budw3->priority = 4;
    2323        /* TODO(wilmer): Shouldn't this just return budw3? */
     
    6060        fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/Telepathy" ) );
    6161        fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/telepathy" ) );
    62         fail_unless( jabber_buddy_by_jid( ic, "wilmer@gaast.net", 0 ) == budw1 );
     62       
     63        /* Test activity_timeout and GET_BUDDY_BARE_OK. */
     64        fail_unless( jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK ) == budw1 );
     65        budw1->last_msg -= 50;
     66        fail_unless( ( bud = jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK ) ) != NULL );
     67        fail_unless( strcmp( bud->full_jid, "wilmer@gaast.net" ) == 0 );
    6368       
    6469        fail_if( jabber_buddy_remove( ic, "wilmer@gaast.net" ) );
    6570        fail_unless( jabber_buddy_by_jid( ic, "wilmer@gaast.net", 0 ) == budw1 );
    6671       
     72        fail_if( jabber_buddy_remove( ic, "wilmer@gaast.net" ) );
     73        fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/bitlbee" ) );
     74        fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/BitlBee" ) );
     75        fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK ) );
     76       
    6777        /* Check if remove_bare() indeed gets rid of all. */
     78        /* disable this one for now.
    6879        fail_unless( jabber_buddy_remove_bare( ic, "wilmer@gaast.net" ) );
    6980        fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net", 0 ) );
     81        */
    7082
    7183        fail_if( jabber_buddy_remove( ic, "nekkid@lamejab.net/Illegal" ) );
    7284        fail_unless( jabber_buddy_remove( ic, "nekkid@lamejab.net" ) );
    7385        fail_if( jabber_buddy_by_jid( ic, "nekkid@lamejab.net", 0 ) );
     86       
     87        /* Fixing a bug in this branch that caused information to get lost when
     88           removing the first full JID from a list. */
     89        jabber_buddy_add( ic, "bugtest@google.com/A" );
     90        jabber_buddy_add( ic, "bugtest@google.com/B" );
     91        jabber_buddy_add( ic, "bugtest@google.com/C" );
     92        fail_unless( jabber_buddy_remove( ic, "bugtest@google.com/A" ) );
     93        fail_unless( jabber_buddy_remove( ic, "bugtest@google.com/B" ) );
     94        fail_unless( jabber_buddy_remove( ic, "bugtest@google.com/C" ) );
    7495}
    7596
     
    85106        jd->buddies = g_hash_table_new( g_str_hash, g_str_equal );
    86107        set_add( &ic->acc->set, "resource_select", "priority", NULL, ic->acc );
     108        set_add( &ic->acc->set, "activity_timeout", "120", NULL, ic->acc );
    87109       
    88110        suite_add_tcase (s, tc_core);
  • unix.c

    r5f8ab6a9 r814aa52  
    8383       
    8484                i = bitlbee_inetd_init();
    85                 log_message( LOGLVL_INFO, "Bitlbee %s starting in inetd mode.", BITLBEE_VERSION );
     85                log_message( LOGLVL_INFO, "BitlBee %s starting in inetd mode.", BITLBEE_VERSION );
    8686
    8787        }
    8888        else if( global.conf->runmode == RUNMODE_DAEMON )
    8989        {
    90                 log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG );
    91                 log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG );
     90                log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE );
     91                log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE );
    9292
    9393                i = bitlbee_daemon_init();
    94                 log_message( LOGLVL_INFO, "Bitlbee %s starting in daemon mode.", BITLBEE_VERSION );
     94                log_message( LOGLVL_INFO, "BitlBee %s starting in daemon mode.", BITLBEE_VERSION );
    9595        }
    9696        else if( global.conf->runmode == RUNMODE_FORKDAEMON )
    9797        {
     98                log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE );
     99                log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE );
     100
    98101                /* In case the operator requests a restart, we need this. */
    99102                old_cwd = g_malloc( 256 );
     
    106109               
    107110                i = bitlbee_daemon_init();
    108                 log_message( LOGLVL_INFO, "Bitlbee %s starting in forking daemon mode.", BITLBEE_VERSION );
     111                log_message( LOGLVL_INFO, "BitlBee %s starting in forking daemon mode.", BITLBEE_VERSION );
    109112        }
    110113        if( i != 0 )
Note: See TracChangeset for help on using the changeset viewer.