Changes in / [1014cab:123cac7]


Ignore:
Files:
1 added
47 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    r1014cab r123cac7  
    4949
    5050clean: $(subdirs)
    51         rm -f *.o $(OUTFILE) core utils/bitlbeed encode decode
     51        rm -f *.o $(OUTFILE) core utils/bitlbeed
    5252        $(MAKE) -C tests clean
    5353
     
    124124endif
    125125
    126 encode: crypting.c
    127         $(CC) crypting.c lib/md5.c $(CFLAGS) -o encode -DCRYPTING_MAIN $(CFLAGS) $(EFLAGS) $(LFLAGS)
    128 
    129 decode: encode
    130         cp encode decode
    131 
    132126ctags:
    133127        ctags `find . -name "*.c"` `find . -name "*.h"`
  • account.c

    r1014cab r123cac7  
    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
     
    5555        s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a );
    5656       
     57        s = set_add( &a->set, "nick_source", "handle", NULL, a );
     58       
    5759        s = set_add( &a->set, "password", NULL, set_eval_account, a );
    5860        s->flags |= ACC_SET_NOSAVE | SET_NULL_OK;
     
    6971                prpl->init( a );
    7072       
    71         return( a );
     73        s = set_add( &a->set, "away", NULL, set_eval_account, a );
     74        s->flags |= SET_NULL_OK;
     75       
     76        if( a->flags & ACC_FLAG_STATUS_MESSAGE )
     77        {
     78                s = set_add( &a->set, "status", NULL, set_eval_account, a );
     79                s->flags |= SET_NULL_OK;
     80        }
     81       
     82        return a;
    7283}
    7384
     
    121132               
    122133                acc->auto_connect = bool2int( value );
     134                return value;
     135        }
     136        else if( strcmp( set->key, "away" ) == 0 ||
     137                 strcmp( set->key, "status" ) == 0 )
     138        {
     139                if( acc->ic && acc->ic->flags & OPT_LOGGED_IN )
     140                {
     141                        /* If we're currently on-line, set the var now already
     142                           (bit of a hack) and send an update. */
     143                        g_free( set->value );
     144                        set->value = g_strdup( value );
     145                       
     146                        imc_away_send_update( acc->ic );
     147                }
     148               
    123149                return value;
    124150        }
     
    267293        p->max = 86400;
    268294       
    269         /* Format: /[0-9]+([*+][0-9]+(<[0-9+]))/ */
     295        /* Format: /[0-9]+([*+][0-9]+(<[0-9+])?)?/ */
    270296        while( *value && isdigit( *value ) )
    271297                p->start = p->start * 10 + *value++ - '0';
  • account.h

    r1014cab r123cac7  
    3737        int auto_reconnect_delay;
    3838        int reconnect;
     39        int flags;
    3940       
    4041        set_t *set;
     
    5657int account_reconnect_delay( account_t *a );
    5758
    58 #define ACC_SET_NOSAVE          0x01
    59 #define ACC_SET_OFFLINE_ONLY    0x02
    60 #define ACC_SET_ONLINE_ONLY     0x04
     59typedef enum
     60{
     61        ACC_SET_NOSAVE = 0x01,          /* Don't save this setting (i.e. stored elsewhere). */
     62        ACC_SET_OFFLINE_ONLY = 0x02,    /* Allow changes only if the acct is offline. */
     63        ACC_SET_ONLINE_ONLY = 0x04,     /* Allow changes only if the acct is online. */
     64} account_set_flag_t;
     65
     66typedef enum
     67{
     68        ACC_FLAG_AWAY_MESSAGE = 0x01,   /* Supports away messages instead of just states. */
     69        ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */
     70} account_flag_t;
    6171
    6272#endif
  • bitlbee.c

    r1014cab r123cac7  
    7070                        continue;
    7171
     72#ifdef IPV6_V6ONLY             
     73                if( res->ai_family == AF_INET6 )
     74                {
     75                        i = 0;
     76                        setsockopt( global.listen_socket, IPPROTO_IPV6, IPV6_V6ONLY,
     77                                    (char *) &i, sizeof( i ) );
     78                }
     79#endif
     80
    7281                /* TIME_WAIT (?) sucks.. */
    7382                i = 1;
     
    8089                        return( -1 );
    8190                }
    82 
    8391                break;
    8492        }
     
    109117                chdir( "/" );
    110118               
    111                 /* Sometimes std* are already closed (for example when we're in a RESTARTed
    112                    BitlBee process. So let's only close TTY-fds. */
    113                 if( isatty( 0 ) ) close( 0 );
    114                 if( isatty( 1 ) ) close( 1 );
    115                 if( isatty( 2 ) ) close( 2 );
     119                if( getenv( "_BITLBEE_RESTART_STATE" ) == NULL )
     120                        for( i = 0; i < 3; i ++ )
     121                                if( close( i ) == 0 )
     122                                {
     123                                        /* Keep something bogus on those fd's just in case. */
     124                                        open( "/dev/null", O_WRONLY );
     125                                }
    116126        }
    117127#endif
  • bitlbee.conf

    r1014cab r123cac7  
    5555##
    5656## Password the user should enter when logging into a closed BitlBee server.
    57 ## You can also have an MD5-encrypted password here. Format: "md5:", followed
    58 ## by a hash as generated for the <user password=""> attribute in a BitlBee
    59 ## XML file (for now there's no easier way to generate the hash).
     57## You can also have a BitlBee-style MD5 hash here. Format: "md5:", followed
     58## by a hash as generated by "bitlbee -x hash <password>".
    6059##
    6160# AuthPassword = ItllBeBitlBee   ## Heh.. Our slogan. ;-)
     
    121120## Proxy = socks5://socksproxy.localnet.com
    122121
     122## Protocols offered by bitlbee
     123##
     124## As recompiling may be quite unpractical for some people, this option
     125## allows to remove the support of protocol, even if compiled in. If
     126## nothing is given, there are no restrictions.
     127##
     128## Protocols = jabber yahoo
     129
    123130
    124131[defaults]
  • bitlbee.h

    r1014cab r123cac7  
    2727#define _BITLBEE_H
    2828
     29#ifndef _GNU_SOURCE
    2930#define _GNU_SOURCE /* Stupid GNU :-P */
     31#endif
    3032
    3133/* Depend on Windows 2000 for now since we need getaddrinfo() */
     
    3335
    3436#define PACKAGE "BitlBee"
    35 #define BITLBEE_VERSION "1.2.4"
     37#define BITLBEE_VERSION "1.2.5"
    3638#define VERSION BITLBEE_VERSION
    3739
     
    161163
    162164char *set_eval_root_nick( set_t *set, char *new_nick );
     165char *set_eval_control_channel( set_t *set, char *new_name );
    163166
    164167extern global_t global;
  • conf.c

    r1014cab r123cac7  
    6363        conf->ping_timeout = 300;
    6464        conf->user = NULL;
     65        conf->protocols = NULL;
    6566        proxytype = 0;
    6667       
     
    127128                {
    128129                        printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
    129                                 "               [-c <file>] [-d <dir>] [-h]\n"
     130                                "               [-c <file>] [-d <dir>] [-x] [-h]\n"
    130131                                "\n"
    131132                                "An IRC-to-other-chat-networks gateway\n"
     
    143144                                "  -c  Load alternative configuration file\n"
    144145                                "  -d  Specify alternative user configuration directory\n"
     146                                "  -x  Command-line interface to password encryption/hashing\n"
    145147                                "  -h  Show this help page.\n" );
    146148                        return NULL;
     
    306308                                conf->user = g_strdup( ini->value );
    307309                        }
     310                        else if( g_strcasecmp( ini->key, "protocols" ) == 0 )
     311                        {
     312                                g_strfreev( conf->protocols );
     313                                conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 );
     314                        }
    308315                        else
    309316                        {
  • conf.h

    r1014cab r123cac7  
    5050        int ping_timeout;
    5151        char *user;
     52        char **protocols;
    5253} conf_t;
    5354
  • configure

    r1014cab r123cac7  
    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
     
    297297detect_resolv_dynamic()
    298298{
    299         echo "$RESOLV_TESTCODE" | $CC -o /dev/null -x c - -lresolv >/dev/null 2>/dev/null
     299        TMPFILE=$(mktemp)
     300        ret=1
     301        echo "$RESOLV_TESTCODE" | $CC -o $TMPFILE -x c - -lresolv >/dev/null 2>/dev/null
    300302        if [ "$?" = "0" ]; then
    301303                echo 'EFLAGS+=-lresolv' >> Makefile.settings
    302                 return 0
    303         fi
    304 
    305         return 1
     304                ret=0
     305        fi
     306
     307        rm -f $TMPFILE
     308        return $ret
    306309}
    307310
    308311detect_resolv_static()
    309312{
     313        TMPFILE=$(mktemp)
     314        ret=1
    310315        for i in $systemlibdirs; do
    311316                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
     317                        echo "$RESOLV_TESTCODE" | $CC -o $TMPFILE -x c - -Wl,$i/libresolv.a >/dev/null 2>/dev/null
    313318                        if [ "$?" = "0" ]; then
    314319                                echo 'EFLAGS+='$i'/libresolv.a' >> Makefile.settings
    315                                 return 0
     320                                ret=0
    316321                        fi
    317322                fi
    318323        done
    319324
    320         return 1
     325        rm -f $TMPFILE
     326        return $ret
    321327}
    322328
     
    362368       
    363369        ## Yes, you, at the console! How can you authenticate if you don't have any SSL!?
    364         if [ "$msn" = "1" ]; then
     370        if [ "$msn" = "1" -o "$yahoo" = "1" ]; then
    365371                echo
    366                 echo 'Real SSL support is necessary for MSN authentication, will build without'
    367                 echo 'MSN protocol support.'
     372                echo 'WARNING: The MSN and Yahoo! modules will not work without SSL. Disabling.'
    368373                msn=0
     374                yahoo=0
    369375        fi
    370376       
     
    446452fi
    447453
     454if [ ! -e doc/user-guide/help.txt ] && ! type xmlto > /dev/null 2> /dev/null; then
     455        echo
     456        echo 'WARNING: Building from an unreleased source tree without prebuilt helpfile.'
     457        echo 'Install xmlto if you want online help to work.'
     458fi
     459
    448460echo
    449461if [ -z "$BITLBEE_VERSION" -a -d .bzr ] && type bzr > /dev/null 2> /dev/null; then
     
    539551;;
    540552Darwin )
     553        echo 'STRIP=\# skip strip' >> Makefile.settings
    541554;;
    542555IRIX )
  • crypting.c

    r1014cab r123cac7  
    132132        return (rv);
    133133}
    134 
    135 #ifdef CRYPTING_MAIN
    136 
    137 /* A little main() function for people who want a stand-alone program to
    138    encode/decode BitlCrypted files. */
    139 
    140 int main( int argc, char *argv[] )
    141 {
    142         char *hash, *action, line[256];
    143         char* (*func)( char *, const char * );
    144        
    145         if( argc < 2 )
    146         {
    147                 fprintf( stderr, "Usage: %s <password>\n\n"
    148                                  "Reads from stdin, writes to stdout.\n"
    149                                  "Call as \"encode\" to encode, \"decode\" to decode.\n", argv[0] );
    150                 return( 1 );
    151         }
    152        
    153         hash = hashpass( argv[1] );
    154         action = argv[0] + strlen( argv[0] ) - strlen( "encode" );
    155        
    156         if( strcmp( action, "encode" ) == 0 )
    157         {
    158                 fwrite( hash, 32, 1, stdout );
    159                 func = obfucrypt;
    160         }
    161         else if( strcmp( action, "decode" ) == 0 )
    162         {
    163                 char hash2[32];
    164                
    165                 fread( hash2, 32, 1, stdin );
    166                 if( memcmp( hash, hash2, 32 ) != 0 )
    167                 {
    168                         fprintf( stderr, "Passwords don't match. Can't decode.\n" );
    169                         return( 1 );
    170                 }
    171                 func = deobfucrypt;
    172         }
    173         else
    174         {
    175                 return( main( 0, NULL ) );
    176         }
    177        
    178         while( fscanf( stdin, "%[^\n]255s", line ) > 0 )
    179         {
    180                 char *out;
    181                
    182                 /* Flush the newline */
    183                 fgetc( stdin );
    184                
    185                 out = func( line, argv[1] );
    186                 printf( "%s\n", out );
    187                 g_free( out );
    188         }
    189        
    190         return( 0 );
    191 }
    192 
    193 #endif
  • debian/bitlbee.init

    r1014cab r123cac7  
    4141        chown bitlbee: /var/run/bitlbee.pid
    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

    r1014cab r123cac7  
     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

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    1 [type: gettext/rfc822deb] bitlbee.templates.master
     1[type: gettext/rfc822deb] templates
  • debian/postinst

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    33
    44http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on
     5
     6Version 1.2.5:
     7- Many bug fixes, including a fix for MSN login issues, Jabber login timing
     8  issues, Yahoo! crashes at login time with huge contact lists,
     9- Avoid linking in a static version of libresolv now that glibc has all
     10  relevant functions available in the dynamic version.
     11- Improved away state code and added the ability to set (non-away) status
     12  messages using "set status" (also possible per account) and see them in
     13  blist and /whois output.
     14- Added a post-1.2 equivalent of encode/decode to quickly encrypt/decrypt
     15  passwords in a way that BitlBee can read them.
     16- Allow using the full name for generating nicknames, instead of just the
     17  handle. This is especially useful when using the Facebook XMPP server.
     18- Auto reconnect is now enabled by default since all protocols can properly
     19  detect cases where auto reconnect should be avoided (i.e. concurrent
     20  logins).
     21- Changed the default resource_select setting which should reduce message
     22  routing issues on Jabber (i.e. messages going someone's phone instead of
     23  the main client).
     24
     25Fixed 17 Mar 2010
    526
    627Version 1.2.4:
  • doc/user-guide/commands.xml

    r1014cab r123cac7  
    436436        </bitlbee-setting>
    437437
     438        <bitlbee-setting name="away" type="string" scope="both">
     439                <description>
     440                        <para>
     441                                To mark yourself as away, it is recommended to just use <emphasis>/away</emphasis>, like on normal IRC networks. If you want to mark yourself as away on only one IM network, you can use this per-account setting.
     442                        </para>
     443
     444                        <para>
     445                                You can set it to any value and BitlBee will try to map it to the most appropriate away state for every open IM connection, or set it as a free-form away message where possible.
     446                        </para>
     447
     448                        <para>
     449                                Any per-account away setting will override globally set away states. To un-set the setting, use <emphasis>set -del away</emphasis>.
     450                        </para>
     451                </description>
     452        </bitlbee-setting>
     453
    438454        <bitlbee-setting name="away_devoice" type="boolean" scope="global">
    439455                <default>true</default>
     
    493509                </description>
    494510
     511        </bitlbee-setting>
     512
     513        <bitlbee-setting name="control_channel" type="string" scope="global">
     514                <default>&amp;bitlbee</default>
     515
     516                <description>
     517                        <para>
     518                                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.
     519                        </para>
     520                </description>
    495521        </bitlbee-setting>
    496522
     
    561587        </bitlbee-setting>
    562588
     589        <bitlbee-setting name="ignore_auth_requests" type="boolean" scope="account">
     590                <default>true</default>
     591
     592                <description>
     593                        <para>
     594                                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.
     595                        </para>
     596                </description>
     597
     598        </bitlbee-setting>
     599
    563600        <bitlbee-setting name="lcnicks" type="boolean" scope="global">
    564601                <default>true</default>
     
    572609        </bitlbee-setting>
    573610
     611        <bitlbee-setting name="local_display_name" type="boolean" scope="account">
     612                <default>false</default>
     613
     614                <description>
     615                        <para>
     616                                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.
     617                        </para>
     618                </description>
     619
     620        </bitlbee-setting>
     621
    574622        <bitlbee-setting name="mail_notifications" type="boolean" scope="account">
    575623                <default>false</default>
     
    588636                        <para>
    589637                                You can use this option to set your nickname in a chatroom. You won't see this nickname yourself, but other people in the room will. By default, BitlBee will use your username as the chatroom nickname.
     638                        </para>
     639                </description>
     640        </bitlbee-setting>
     641
     642        <bitlbee-setting name="nick_source" type="string" scope="account">
     643                <default>handle</default>
     644                <possible-values>handle, full_name, first_name</possible-values>
     645
     646                <description>
     647                        <para>
     648                                By default, BitlBee generates a nickname for every contact by taking its handle and chopping off everything after the @. In some cases, this gives very inconvenient nicknames. The Facebook XMPP server is a good example, as all Facebook XMPP handles are numeric.
     649                        </para>
     650
     651                        <para>
     652                                With this setting set to <emphasis>full_name</emphasis>, the person's full name is used to generate a nickname. Or if you don't like long nicknames, set this setting to <emphasis>first_name</emphasis> instead and only the first word will be used. Note that the full name can be full of non-ASCII characters which will be stripped off.
    590653                        </para>
    591654                </description>
     
    685748
    686749        <bitlbee-setting name="resource_select" type="string" scope="account">
    687                 <default>priority</default>
     750                <default>activity</default>
    688751                <possible-values>priority, activity</possible-values>
    689752
     
    747810        </bitlbee-setting>
    748811
     812        <bitlbee-setting name="status" type="string" scope="both">
     813                <description>
     814                        <para>
     815                                Certain protocols (like Jabber/XMPP) support status messages, similar to away messages. They can be used to indicate things like your location or activity, without showing up as away/busy.
     816                        </para>
     817
     818                        <para>
     819                                This setting can be used to set such a message. It will be available as a per-account setting for protocols that support it, and also as a global setting (which will then automatically be used for all protocols that support it).
     820                        </para>
     821
     822                        <para>
     823                                Away states set using <emphasis>/away</emphasis> or the <emphasis>away</emphasis> setting will override this setting. To un-set the setting, use <emphasis>set -del status</emphasis>.
     824                        </para>
     825                </description>
     826        </bitlbee-setting>
     827
    749828        <bitlbee-setting name="strip_html" type="boolean" scope="global">
    750829                <default>true</default>
     
    756835                        <para>
    757836                                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.
     837                        </para>
     838                </description>
     839        </bitlbee-setting>
     840
     841        <bitlbee-setting name="timezone" type="string" scope="global">
     842                <default>local</default>
     843                <possible-values>local, utc, gmt, timezone-spec</possible-values>
     844
     845                <description>
     846                        <para>
     847                                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.
     848                        </para>
     849
     850                        <para>
     851                                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.
    758852                        </para>
    759853                </description>
  • doc/user-guide/misc.xml

    r1014cab r123cac7  
    8686
    8787<para>
    88 As you might've expected, you can just use the <emphasis>/away</emphasis> command in your IRC client to set an away-state. BitlBee supports most away-states supported by the protocols.
     88To mark yourself as away, you can just use the <emphasis>/away</emphasis> command in your IRC client. BitlBee supports most away-states supported by the protocols.
    8989</para>
    9090
    9191<para>
    92 Not all away states are supported by all protocols, and some protocols have different names for them. BitlBee will try to pick the best available alias from this list for every connection:
     92Away states have different names accross different protocols. BitlBee will try to pick the best available option for every connection:
    9393</para>
    9494
    9595<simplelist>
    96         <member>Away from computer, Away, Extended away</member>
    97         <member>NA, N/A, Not available</member>
    98         <member>Busy, Do not disturb, DND, Occupied</member>
    99         <member>Be right back, BRB</member>
    100         <member>On the phone, Phone, On phone</member>
    101         <member>Out to lunch, Lunch, Food</member>
     96        <member>Away</member>
     97        <member>NA</member>
     98        <member>Busy, DND</member>
     99        <member>BRB</member>
     100        <member>Phone</member>
     101        <member>Lunch, Food</member>
    102102        <member>Invisible, Hidden</member>
    103103</simplelist>
    104104
    105105<para>
    106 So <emphasis>/away Food</emphasis> will set your state to "Out to lunch" on your MSN connection, and for most other connections the default, "Away" or "Away from computer" will be chosen.
     106So <emphasis>/away Food</emphasis> will set your state to "Out to lunch" on your MSN connection, and for most other connections the default, "Away" will be chosen.
    107107</para>
    108108
     
    111111</para>
    112112
     113<para>
     114If you want to set an away state for only one of your connections, you can use the per-account <emphasis>away</emphasis> setting. See <emphasis>help set away</emphasis>.
     115</para>
     116
    113117</sect1>
    114118
  • irc.c

    r1014cab r123cac7  
    5252{
    5353        irc_t *irc = set->data;
     54        char *test;
     55        gsize test_bytes = 0;
    5456        GIConv ic, oc;
    5557
     
    5759                value = g_strdup( "utf-8" );
    5860
     61        if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
     62        {
     63                return NULL;
     64        }
     65        if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL ||
     66            test_bytes > 1 )
     67        {
     68                g_free( test );
     69                g_iconv_close( oc );
     70                irc_usermsg( irc, "Unsupported character set: The IRC protocol "
     71                                  "only supports 8-bit character sets." );
     72                return NULL;
     73        }
    5974        if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 )
    6075        {
    61                 return NULL;
    62         }
    63         if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 )
    64         {
    65                 g_iconv_close( ic );
     76                g_iconv_close( oc );
    6677                return NULL;
    6778        }
     
    7889}
    7990
     91static char *set_eval_away_status( set_t *set, char *value )
     92{
     93        irc_t *irc = set->data;
     94        account_t *a;
     95       
     96        g_free( set->value );
     97        set->value = g_strdup( value );
     98       
     99        for( a = irc->accounts; a; a = a->next )
     100        {
     101                struct im_connection *ic = a->ic;
     102               
     103                if( ic && ic->flags & OPT_LOGGED_IN )
     104                        imc_away_send_update( ic );
     105        }
     106       
     107        return value;
     108}
     109
    80110irc_t *irc_new( int fd )
    81111{
     
    143173        irc_connection_list = g_slist_append( irc_connection_list, irc );
    144174       
     175        s = set_add( &irc->set, "away", NULL,  set_eval_away_status, irc );
     176        s->flags |= SET_NULL_OK;
    145177        s = set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
    146178        s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
    147         s = set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );
     179        s = set_add( &irc->set, "auto_reconnect", "true", set_eval_bool, irc );
    148180        s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
    149181        s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
    150182        s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
    151183        s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
     184        s = set_add( &irc->set, "control_channel", irc->channel, set_eval_control_channel, irc );
    152185        s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
    153186        s = set_add( &irc->set, "default_target", "root", NULL, irc );
     
    163196        s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
    164197        s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
     198        s = set_add( &irc->set, "status", NULL,  set_eval_away_status, irc );
     199        s->flags |= SET_NULL_OK;
    165200        s = set_add( &irc->set, "strip_html", "true", NULL, irc );
     201        s = set_add( &irc->set, "timezone", "local", set_eval_timezone, irc );
    166202        s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
    167203        s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
  • irc_commands.c

    r1014cab r123cac7  
    448448        user_t *u = user_find( irc, irc->nick );
    449449        char *away = cmd[1];
    450         account_t *a;
    451450       
    452451        if( !u ) return;
     
    475474        }
    476475       
    477         for( a = irc->accounts; a; a = a->next )
    478         {
    479                 struct im_connection *ic = a->ic;
    480                
    481                 if( ic && ic->flags & OPT_LOGGED_IN )
    482                         imc_set_away( ic, u->away );
    483         }
     476        set_setstr( &irc->set, "away", u->away );
    484477}
    485478
     
    504497                else if( u->away )
    505498                        irc_reply( irc, 301, "%s :%s", u->nick, u->away );
     499                if( u->status_msg )
     500                        irc_reply( irc, 333, "%s :Status: %s", u->nick, u->status_msg );
    506501               
    507502                irc_reply( irc, 318, "%s :End of /WHOIS list", nick );
  • lib/misc.c

    r1014cab r123cac7  
    3434#include "nogaim.h"
    3535#include "base64.h"
     36#include "md5.h"
    3637#include <stdio.h>
    3738#include <stdlib.h>
     
    8990        { "gt",     ">" },
    9091        { "amp",    "&" },
     92        { "apos",   "'" },
    9193        { "quot",   "\"" },
    9294        { "aacute", "á" },
     
    522524
    523525/* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */
    524 char *word_wrap( char *msg, int line_len )
     526char *word_wrap( const char *msg, int line_len )
    525527{
    526528        GString *ret = g_string_sized_new( strlen( msg ) + 16 );
  • lib/misc.h

    r1014cab r123cac7  
    6262G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain );
    6363
    64 G_MODULE_EXPORT char *word_wrap( char *msg, int line_len );
     64G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len );
    6565
    6666G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl );
  • protocols/jabber/io.c

    r1014cab r123cac7  
    375375       
    376376        if( ( c = xt_find_node( node->children, "bind" ) ) )
    377         {
    378                 reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
    379                 xt_add_attr( reply, "xmlns", XMLNS_BIND );
    380                 reply = jabber_make_packet( "iq", "set", NULL, reply );
    381                 jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
    382                
    383                 if( !jabber_write_packet( ic, reply ) )
    384                         return XT_ABORT;
    385                
    386                 jd->flags |= JFLAG_WAIT_BIND;
    387         }
     377                jd->flags |= JFLAG_WANT_BIND;
    388378       
    389379        if( ( c = xt_find_node( node->children, "session" ) ) )
    390         {
    391                 reply = xt_new_node( "session", NULL, NULL );
    392                 xt_add_attr( reply, "xmlns", XMLNS_SESSION );
    393                 reply = jabber_make_packet( "iq", "set", NULL, reply );
    394                 jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
    395                
    396                 if( !jabber_write_packet( ic, reply ) )
    397                         return XT_ABORT;
    398                
    399                 jd->flags |= JFLAG_WAIT_SESSION;
    400         }
    401        
    402         /* This flag is already set if we authenticated via SASL, so now
    403            we can resume the session in the new stream, if we don't have
    404            to bind/initialize the session. */
    405         if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
    406         {
    407                 if( !jabber_get_roster( ic ) )
    408                         return XT_ABORT;
    409         }
     380                jd->flags |= JFLAG_WANT_SESSION;
     381       
     382        if( jd->flags & JFLAG_AUTHENTICATED )
     383                return jabber_pkt_bind_sess( ic, NULL, NULL );
    410384       
    411385        return XT_HANDLED;
     
    441415        imcb_log( ic, "Converting stream to TLS" );
    442416       
     417        jd->flags |= JFLAG_STARTTLS_DONE;
    443418        jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic );
    444419       
     
    531506                jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );
    532507       
    533         greet = g_strdup_printf( "<?xml version='1.0' ?>"
    534                                  "<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
    535                                   "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server );
     508        greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
     509                                  "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">",
     510                                  ( jd->flags & JFLAG_STARTTLS_DONE ) ? "" : "<?xml version='1.0' ?>",
     511                                  jd->server );
    536512       
    537513        st = jabber_write( ic, greet, strlen( greet ) );
  • protocols/jabber/iq.c

    r1014cab r123cac7  
    298298{
    299299        struct jabber_data *jd = ic->proto_data;
    300         struct xt_node *c;
     300        struct xt_node *c, *reply = NULL;
    301301        char *s;
    302302       
    303         if( ( c = xt_find_node( node->children, "bind" ) ) )
     303        if( node && ( c = xt_find_node( node->children, "bind" ) ) )
    304304        {
    305305                c = xt_find_node( c->children, "jid" );
     
    307307                    strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 )
    308308                        imcb_log( ic, "Server changed session resource string to `%s'", s + 1 );
    309                
    310                 jd->flags &= ~JFLAG_WAIT_BIND;
    311         }
    312         else
    313         {
    314                 jd->flags &= ~JFLAG_WAIT_SESSION;
    315         }
    316        
    317         if( ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
     309        }
     310       
     311        if( jd->flags & JFLAG_WANT_BIND )
     312        {
     313                reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
     314                xt_add_attr( reply, "xmlns", XMLNS_BIND );
     315                jd->flags &= ~JFLAG_WANT_BIND;
     316        }
     317        else if( jd->flags & JFLAG_WANT_SESSION )
     318        {
     319                reply = xt_new_node( "session", NULL, NULL );
     320                xt_add_attr( reply, "xmlns", XMLNS_SESSION );
     321                jd->flags &= ~JFLAG_WANT_SESSION;
     322        }
     323       
     324        if( reply != NULL )
     325        {
     326                reply = jabber_make_packet( "iq", "set", NULL, reply );
     327                jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
     328               
     329                if( !jabber_write_packet( ic, reply ) )
     330                        return XT_ABORT;
     331        }
     332        else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 )
    318333        {
    319334                if( !jabber_get_roster( ic ) )
  • protocols/jabber/jabber.c

    r1014cab r123cac7  
    5858        char str[16];
    5959       
     60        s = set_add( &acc->set, "activity_timeout", "600", set_eval_int, acc );
     61       
    6062        g_snprintf( str, sizeof( str ), "%d", jabber_port_list[0] );
    6163        s = set_add( &acc->set, "port", str, set_eval_int, acc );
     
    6769        s->flags |= ACC_SET_OFFLINE_ONLY;
    6870       
    69         s = set_add( &acc->set, "resource_select", "priority", NULL, acc );
     71        s = set_add( &acc->set, "resource_select", "activity", NULL, acc );
    7072       
    7173        s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
     
    8082        s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );
    8183        s->flags |= ACC_SET_OFFLINE_ONLY;
     84       
     85        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
    8286}
    8387
     
    305309                bud = jabber_buddy_by_ext_jid( ic, who, 0 );
    306310        else
    307                 bud = jabber_buddy_by_jid( ic, who, 0 );
     311                bud = jabber_buddy_by_jid( ic, who, GET_BUDDY_BARE_OK );
    308312       
    309313        node = xt_new_node( "body", message, NULL );
     
    350354static void jabber_get_info( struct im_connection *ic, char *who )
    351355{
     356        struct jabber_buddy *bud;
     357       
     358        bud = jabber_buddy_by_jid( ic, who, GET_BUDDY_FIRST );
     359       
     360        while( bud )
     361        {
     362                imcb_log( ic, "Buddy %s (%d) information:", bud->full_jid, bud->priority );
     363                if( bud->away_state )
     364                        imcb_log( ic, "Away state: %s", bud->away_state->full_name );
     365                imcb_log( ic, "Status message: %s", bud->away_message ? : "(none)" );
     366               
     367                bud = bud->next;
     368        }
     369       
     370        jabber_get_vcard( ic, bud ? bud->full_jid : who );
     371}
     372
     373static void jabber_set_away( struct im_connection *ic, char *state_txt, char *message )
     374{
    352375        struct jabber_data *jd = ic->proto_data;
    353         struct jabber_buddy *bud;
    354        
    355         if( strchr( who, '/' ) )
    356                 bud = jabber_buddy_by_jid( ic, who, 0 );
    357         else
    358         {
    359                 char *s = jabber_normalize( who );
    360                 bud = g_hash_table_lookup( jd->buddies, s );
    361                 g_free( s );
    362         }
    363        
    364         while( bud )
    365         {
    366                 imcb_log( ic, "Buddy %s (%d) information:\nAway state: %s\nAway message: %s",
    367                                    bud->full_jid, bud->priority,
    368                                    bud->away_state ? bud->away_state->full_name : "(none)",
    369                                    bud->away_message ? : "(none)" );
    370                 bud = bud->next;
    371         }
    372        
    373         jabber_get_vcard( ic, bud ? bud->full_jid : who );
    374 }
    375 
    376 static void jabber_set_away( struct im_connection *ic, char *state_txt, char *message )
    377 {
    378         struct jabber_data *jd = ic->proto_data;
    379         struct jabber_away_state *state;
    380        
    381         /* Save all this info. We need it, for example, when changing the priority setting. */
    382         state = (void *) jabber_away_state_by_name( state_txt );
    383         jd->away_state = state ? state : (void *) jabber_away_state_list; /* Fall back to "Away" if necessary. */
     376       
     377        /* state_txt == NULL -> Not away.
     378           Unknown state -> fall back to the first defined away state. */
     379        jd->away_state = state_txt ? jabber_away_state_by_name( state_txt )
     380                         ? : jabber_away_state_list : NULL;
     381       
    384382        g_free( jd->away_message );
    385383        jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL;
  • protocols/jabber/jabber.h

    r1014cab r123cac7  
    4040        JFLAG_STREAM_RESTART = 4,       /* Set when we want to restart the stream (after
    4141                                           SASL or TLS). */
    42         JFLAG_WAIT_SESSION = 8,         /* Set if we sent a <session> tag and need a reply
     42        JFLAG_WANT_SESSION = 8,         /* Set if the server wants a <session/> tag
    4343                                           before we continue. */
    44         JFLAG_WAIT_BIND = 16,           /* ... for <bind> tag. */
     44        JFLAG_WANT_BIND = 16,           /* ... for <bind> tag. */
    4545        JFLAG_WANT_TYPING = 32,         /* Set if we ever sent a typing notification, this
    4646                                           activates all XEP-85 related code. */
    4747        JFLAG_XMLCONSOLE = 64,          /* If the user added an xmlconsole buddy. */
     48        JFLAG_STARTTLS_DONE = 128,      /* If a plaintext session was converted to TLS. */
    4849} jabber_flags_t;
    4950
     
    8485        /* After changing one of these two (or the priority setting), call
    8586           presence_send_update() to inform the server about the changes. */
    86         struct jabber_away_state *away_state;
     87        const struct jabber_away_state *away_state;
    8788        char *away_message;
    8889       
     
    107108};
    108109
     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. */
    109117struct jabber_buddy
    110118{
     
    120128        char *away_message;
    121129       
    122         time_t last_act;
     130        time_t last_msg;
    123131        jabber_buddy_flags_t flags;
    124132       
     
    208216        GET_BUDDY_EXACT = 2,    /* Get an exact match (only makes sense with bare JIDs). */
    209217        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. */
    210220} get_buddy_flags_t;
    211221
  • protocols/jabber/jabber_util.c

    r1014cab r123cac7  
    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     *
     
    228228{
    229229        { "away",  "Away" },
    230         { "chat",  "Free for Chat" },
     230        { "chat",  "Free for Chat" },   /* WTF actually uses this? */
    231231        { "dnd",   "Do not Disturb" },
    232232        { "xa",    "Extended Away" },
    233         { "",      "Online" },
    234233        { "",      NULL }
    235234};
     
    238237{
    239238        int i;
     239       
     240        if( code == NULL )
     241                return NULL;
    240242       
    241243        for( i = 0; jabber_away_state_list[i].full_name; i ++ )
     
    249251{
    250252        int i;
     253       
     254        if( name == NULL )
     255                return NULL;
    251256       
    252257        for( i = 0; jabber_away_state_list[i].full_name; i ++ )
     
    340345        if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
    341346        {
     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               
    342352                /* If this is a transport buddy or whatever, it can't have more
    343353                   than one instance, so this is always wrong: */
     
    374384        else
    375385        {
    376                 /* Keep in mind that full_jid currently isn't really
    377                    a full JID... */
    378                 new->bare_jid = g_strdup( full_jid );
     386                new->full_jid = new->bare_jid = g_strdup( full_jid );
    379387                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                }
    380395        }
    381396       
     
    403418{
    404419        struct jabber_data *jd = ic->proto_data;
    405         struct jabber_buddy *bud;
     420        struct jabber_buddy *bud, *head;
    406421        char *s, *jid;
    407422       
     
    415430                if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
    416431                {
     432                        bare_exists = 1;
     433                       
     434                        if( bud->next )
     435                                bud = bud->next;
     436                       
    417437                        /* Just return the first one for this bare JID. */
    418438                        if( flags & GET_BUDDY_FIRST )
     
    436456                                        break;
    437457                }
    438                 else
    439                 {
    440                         /* This variable tells the if down here that the bare
    441                            JID already exists and we should feel free to add
    442                            more resources, if the caller asked for that. */
    443                         bare_exists = 1;
    444                 }
    445458               
    446459                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) &&
    447                     ( !bare_exists || imcb_find_buddy( ic, jid ) ) )
     460                    ( bare_exists || imcb_find_buddy( ic, jid ) ) )
    448461                {
    449462                        *s = '/';
     
    459472                char *set;
    460473               
    461                 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;
    462476               
    463477                g_free( jid );
     
    476490                        /* Looks like the caller doesn't care about details. */
    477491                        return bud;
     492                else if( flags & GET_BUDDY_BARE )
     493                        return head;
    478494               
    479495                best_prio = best_time = bud;
     
    482498                        if( bud->priority > best_prio->priority )
    483499                                best_prio = bud;
    484                         if( bud->last_act > best_time->last_act )
     500                        if( bud->last_msg > best_time->last_msg )
    485501                                best_time = bud;
    486502                }
     
    488504                if( ( set = set_getstr( &ic->acc->set, "resource_select" ) ) == NULL )
    489505                        return NULL;
    490                 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
    491516                        return best_time;
    492                 else /* if( strcmp( set, "priority" ) == 0 ) */
    493                         return best_prio;
    494517        }
    495518}
     
    533556{
    534557        struct jabber_data *jd = ic->proto_data;
    535         struct jabber_buddy *bud, *prev, *bi;
     558        struct jabber_buddy *bud, *prev = NULL, *bi;
    536559        char *s, *full_jid;
    537560       
     
    543566        if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) )
    544567        {
     568                if( bud->next )
     569                        bud = (prev=bud)->next;
     570               
    545571                /* If there's only one item in the list (and if the resource
    546572                   matches), removing it is simple. (And the hash reference
     
    550576                      ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) )
    551577                {
    552                         g_hash_table_remove( jd->buddies, bud->bare_jid );
    553                         g_free( bud->bare_jid );
    554                         g_free( bud->ext_jid );
    555                         g_free( bud->full_jid );
    556                         g_free( bud->away_message );
    557                         g_free( bud );
    558                        
    559                         g_free( full_jid );
    560                        
    561                         return 1;
     578                        return jabber_buddy_remove_bare( ic, full_jid );
    562579                }
    563580                else if( s == NULL || bud->resource == NULL )
     
    570587                else
    571588                {
    572                         for( bi = bud, prev = NULL; bi; bi = (prev=bi)->next )
     589                        for( bi = bud; bi; bi = (prev=bi)->next )
    573590                                if( strcmp( bi->resource, s + 1 ) == 0 )
    574591                                        break;
     
    581598                                        prev->next = bi->next;
    582599                                else
    583                                         /* The hash table should point at the second
    584                                            item, because we're removing the first. */
     600                                        /* Don't think this should ever happen anymore. */
    585601                                        g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next );
    586602                               
  • protocols/jabber/message.c

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    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               
     
    190187                int is_away = 0;
    191188
    192                 if( send_presence->away_state && !( *send_presence->away_state->code == 0 ||
    193                     strcmp( send_presence->away_state->code, "chat" ) == 0 ) )
     189                if( send_presence->away_state &&
     190                    strcmp( send_presence->away_state->code, "chat" ) != 0 )
    194191                        is_away = OPT_AWAY;
    195192
    196193                imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away,
    197                                    ( is_away && send_presence->away_state ) ?
    198                                    send_presence->away_state->full_name : NULL,
     194                                   is_away ? send_presence->away_state->full_name : NULL,
    199195                                   send_presence->away_message );
    200196        }
     
    209205        struct jabber_data *jd = ic->proto_data;
    210206        struct xt_node *node, *cap;
    211         char *show = jd->away_state->code;
    212         char *status = jd->away_message;
    213207        struct groupchat *c;
    214208        int st;
     
    216210        node = jabber_make_packet( "presence", NULL, NULL, NULL );
    217211        xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) );
    218         if( show && *show )
    219                 xt_add_child( node, xt_new_node( "show", show, NULL ) );
    220         if( status )
    221                 xt_add_child( node, xt_new_node( "status", status, NULL ) );
     212        if( jd->away_state )
     213                xt_add_child( node, xt_new_node( "show", jd->away_state->code, NULL ) );
     214        if( jd->away_message )
     215                xt_add_child( node, xt_new_node( "status", jd->away_message, NULL ) );
    222216       
    223217        /* This makes the packet slightly bigger, but clients interested in
  • protocols/msn/msn.c

    r1014cab r123cac7  
    2727#include "msn.h"
    2828
    29 static char *msn_set_display_name( set_t *set, char *value );
     29int msn_chat_id;
     30GSList *msn_connections;
     31GSList *msn_switchboards;
     32
     33static char *set_eval_display_name( set_t *set, char *value );
    3034
    3135static void msn_init( account_t *acc )
    3236{
    33         set_t *s;
    34        
    35         s = set_add( &acc->set, "display_name", NULL, msn_set_display_name, acc );
    36         s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY;
    37 
    38         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 );
    3940}
    4041
     
    139140       
    140141        if( l == NULL )
    141                 for( i = 0; msn_away_state_list[i].number > -1; i ++ )
    142                         l = g_list_append( l, (void*) msn_away_state_list[i].name );
     142                for( i = 0; *msn_away_state_list[i].code; i ++ )
     143                        if( *msn_away_state_list[i].name )
     144                                l = g_list_append( l, (void*) msn_away_state_list[i].name );
    143145       
    144146        return l;
     
    149151        char buf[1024];
    150152        struct msn_data *md = ic->proto_data;
    151         const struct msn_away_state *st;
    152        
    153         if( strcmp( state, GAIM_AWAY_CUSTOM ) == 0 )
    154                 st = msn_away_state_by_name( "Away" );
     153       
     154        if( state )
     155                md->away_state = msn_away_state_by_name( state ) ? :
     156                                 msn_away_state_list + 1;
    155157        else
    156                 st = msn_away_state_by_name( state );
    157        
    158         if( !st ) st = msn_away_state_list;
    159         md->away_state = st;
    160        
    161         g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, st->code );
     158                md->away_state = msn_away_state_list;
     159       
     160        g_snprintf( buf, sizeof( buf ), "CHG %d %s\r\n", ++md->trId, md->away_state->code );
    162161        msn_write( ic, buf, strlen( buf ) );
    163162}
     
    165164static void msn_set_my_name( struct im_connection *ic, char *info )
    166165{
    167         msn_set_display_name( set_find( &ic->acc->set, "display_name" ), info );
     166        msn_set_display_name( ic, info );
    168167}
    169168
     
    281280}
    282281
    283 static char *msn_set_display_name( set_t *set, char *value )
     282static char *set_eval_display_name( set_t *set, char *value )
    284283{
    285284        account_t *acc = set->data;
    286285        struct im_connection *ic = acc->ic;
    287         struct msn_data *md;
    288         char buf[1024], *fn;
    289        
    290         /* Double-check. */
     286       
     287        /* Allow any name if we're offline. */
    291288        if( ic == NULL )
    292                 return NULL;
    293        
    294         md = ic->proto_data;
     289                return value;
    295290       
    296291        if( strlen( value ) > 129 )
     
    299294                return NULL;
    300295        }
    301        
    302         fn = msn_http_encode( value );
    303        
    304         g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn );
    305         msn_write( ic, buf, strlen( buf ) );
    306         g_free( fn );
    307296       
    308297        /* Returning NULL would be better, because the server still has to
    309298           confirm the name change. However, it looks a bit confusing to the
    310299           user. */
    311         return value;
     300        return msn_set_display_name( ic, value ) ? value : NULL;
    312301}
    313302
  • protocols/msn/msn.h

    r1014cab r123cac7  
    9797struct msn_away_state
    9898{
    99         int number;
    10099        char code[4];
    101100        char name[16];
     
    136135#define STATUS_SB_CHAT_SPARE    8       /* Same, but also for groupchats (not used yet). */
    137136
    138 int msn_chat_id;
     137extern int msn_chat_id;
    139138extern const struct msn_away_state msn_away_state_list[];
    140139extern const struct msn_status_code msn_status_code_list[];
     
    145144   connection), the callback should check whether it's still listed here
    146145   before doing *anything* else. */
    147 GSList *msn_connections;
    148 GSList *msn_switchboards;
     146extern GSList *msn_connections;
     147extern GSList *msn_switchboards;
    149148
    150149/* ns.c */
     
    162161char *msn_http_encode( const char *input );
    163162void msn_msgq_purge( struct im_connection *ic, GSList **list );
     163gboolean msn_set_display_name( struct im_connection *ic, const char *rawname );
    164164
    165165/* tables.c */
  • protocols/msn/msn_util.c

    r1014cab r123cac7  
    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
     
    171171               
    172172                /* End of headers? */
    173                 if( strncmp( text + i - 2, "\n\n", 2 ) == 0 ||
    174                     strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 ||
    175                     strncmp( text + i - 2, "\r\r", 2 ) == 0 )
     173                if( ( i >= 4 && strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 ) ||
     174                    ( i >= 2 && ( strncmp( text + i - 2, "\n\n", 2 ) == 0 ||   
     175                                  strncmp( text + i - 2, "\r\r", 2 ) == 0 ) ) )
    176176                {
    177177                        break;
     
    374374        *list = NULL;
    375375       
    376         imcb_log( ic, ret->str );
     376        imcb_log( ic, "%s", ret->str );
    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

    r1014cab r123cac7  
    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 )
     
    229230                        }
    230231                }
    231                 else if( num_parts == 7 && strcmp( cmd[2], "OK" ) == 0 )
    232                 {
    233                         set_t *s;
    234                        
    235                         http_decode( cmd[4] );
    236                        
    237                         strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );
    238                         ic->displayname[sizeof(ic->displayname)-1] = 0;
    239                        
    240                         if( ( s = set_find( &ic->acc->set, "display_name" ) ) )
    241                         {
    242                                 g_free( s->value );
    243                                 s->value = g_strdup( cmd[4] );
    244                         }
     232                else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 )
     233                {
     234                        if( num_parts == 7 )
     235                                msn_ns_got_display_name( ic, cmd[4] );
     236                        else
     237                                imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
    245238                       
    246239                        imcb_log( ic, "Authenticated, getting buddy list" );
     
    420413                {
    421414                        /* FIXME: Warn/Bomb about unknown away state? */
    422                         st = msn_away_state_list;
    423                 }
    424                
    425                 imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN |
    426                                    ( st->number ? OPT_AWAY : 0 ), st->name, NULL );
     415                        st = msn_away_state_list + 1;
     416                }
     417               
     418                imcb_buddy_status( ic, cmd[3], OPT_LOGGED_IN |
     419                                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
     420                                   st->name, NULL );
    427421        }
    428422        else if( strcmp( cmd[0], "FLN" ) == 0 )
     
    449443                {
    450444                        /* FIXME: Warn/Bomb about unknown away state? */
    451                         st = msn_away_state_list;
    452                 }
    453                
    454                 imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |
    455                                    ( st->number ? OPT_AWAY : 0 ), st->name, NULL );
     445                        st = msn_away_state_list + 1;
     446                }
     447               
     448                imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |
     449                                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
     450                                   st->name, NULL );
    456451        }
    457452        else if( strcmp( cmd[0], "RNG" ) == 0 )
     
    558553                return( 0 );
    559554        }
     555#if 0
     556        /* Discard this one completely for now since I don't care about the ack
     557           and since MSN servers can apparently screw up the formatting. */
    560558        else if( strcmp( cmd[0], "REA" ) == 0 )
    561559        {
     
    588586                }
    589587        }
     588#endif
    590589        else if( strcmp( cmd[0], "IPG" ) == 0 )
    591590        {
     
    663662                                }
    664663                               
    665                                 if( arg1 ) g_free( arg1 );
    666                                 if( mtype ) g_free( mtype );
     664                                g_free( arg1 );
     665                                g_free( mtype );
    667666                        }
    668667                        else if( g_strncasecmp( ct, "text/x-msmsgsprofile", 20 ) == 0 )
     
    672671                        else if( g_strncasecmp( ct, "text/x-msmsgsinitialemailnotification", 37 ) == 0 )
    673672                        {
    674                                 char *inbox = msn_findheader( body, "Inbox-Unread:", blen );
    675                                 char *folders = msn_findheader( body, "Folders-Unread:", blen );
    676                                
    677                                 if( inbox && folders && set_getbool( &ic->acc->set, "mail_notifications" ) )
     673                                if( set_getbool( &ic->acc->set, "mail_notifications" ) )
    678674                                {
    679                                         imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );
     675                                        char *inbox = msn_findheader( body, "Inbox-Unread:", blen );
     676                                        char *folders = msn_findheader( body, "Folders-Unread:", blen );
     677
     678                                        if( inbox && folders )
     679                                                imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders );
     680                                       
     681                                        g_free( inbox );
     682                                        g_free( folders );
    680683                                }
    681                                
    682                                 g_free( inbox );
    683                                 g_free( folders );
    684684                        }
    685685                        else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 )
    686686                        {
    687                                 char *from = msn_findheader( body, "From-Addr:", blen );
    688                                 char *fromname = msn_findheader( body, "From:", blen );
    689                                
    690                                 if( from && fromname && set_getbool( &ic->acc->set, "mail_notifications" ) )
     687                                if( set_getbool( &ic->acc->set, "mail_notifications" ) )
    691688                                {
    692                                         imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from );
     689                                        char *from = msn_findheader( body, "From-Addr:", blen );
     690                                        char *fromname = msn_findheader( body, "From:", blen );
     691                                       
     692                                        if( from && fromname )
     693                                                imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from );
     694
     695                                        g_free( from );
     696                                        g_free( fromname );
    693697                                }
    694698                        }
     
    732736        }
    733737}
     738
     739static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name )
     740{
     741        set_t *s;
     742       
     743        if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL )
     744                return FALSE; /* Shouldn't happen.. */
     745       
     746        http_decode( name );
     747       
     748        if( s->value && strcmp( s->value, name ) == 0 )
     749        {
     750                return TRUE;
     751                /* The names match, nothing to worry about. */
     752        }
     753        else if( s->value != NULL &&
     754                 ( strcmp( name, ic->acc->user ) == 0 ||
     755                   set_getbool( &ic->acc->set, "local_display_name" ) ) )
     756        {
     757                /* The server thinks our display name is our e-mail address
     758                   which is probably wrong, or the user *wants* us to do this:
     759                   Always use the locally set display_name. */
     760                return msn_set_display_name( ic, s->value );
     761        }
     762        else
     763        {
     764                if( s->value && *s->value )
     765                        imcb_log( ic, "BitlBee thinks your display name is `%s' but "
     766                                      "the MSN server says it's `%s'. Using the MSN "
     767                                      "server's name. Set local_display_name to true "
     768                                      "to use the local name.", s->value, name );
     769               
     770                if( g_utf8_validate( name, -1, NULL ) )
     771                {
     772                        g_free( s->value );
     773                        s->value = g_strdup( name );
     774                }
     775                else
     776                {
     777                        imcb_log( ic, "Warning: Friendly name in server response was corrupted" );
     778                }
     779               
     780                return TRUE;
     781        }
     782}
  • protocols/msn/tables.c

    r1014cab r123cac7  
    2929const struct msn_away_state msn_away_state_list[] =
    3030{
    31         {  0, "NLN", "Available" },
    32         {  1, "BSY", "Busy" },
    33         {  3, "IDL", "Idle" },
    34         {  5, "BRB", "Be Right Back" },
    35         {  7, "AWY", "Away" },
    36         {  9, "PHN", "On the Phone" },
    37         { 11, "LUN", "Out to Lunch" },
    38         { 13, "HDN", "Hidden" },
    39         { -1, "",    "" }
     31        { "NLN", "" },
     32        { "AWY", "Away" },
     33        { "BSY", "Busy" },
     34        { "IDL", "Idle" },
     35        { "BRB", "Be Right Back" },
     36        { "PHN", "On the Phone" },
     37        { "LUN", "Out to Lunch" },
     38        { "HDN", "Hidden" },
     39        { "",    "" }
    4040};
    41 
    42 const struct msn_away_state *msn_away_state_by_number( int number )
    43 {
    44         int i;
    45        
    46         for( i = 0; msn_away_state_list[i].number > -1; i ++ )
    47                 if( msn_away_state_list[i].number == number )
    48                         return( msn_away_state_list + i );
    49        
    50         return( NULL );
    51 }
    5241
    5342const struct msn_away_state *msn_away_state_by_code( char *code )
     
    5544        int i;
    5645       
    57         for( i = 0; msn_away_state_list[i].number > -1; i ++ )
     46        for( i = 0; *msn_away_state_list[i].code; i ++ )
    5847                if( g_strcasecmp( msn_away_state_list[i].code, code ) == 0 )
    5948                        return( msn_away_state_list + i );
    6049       
    61         return( NULL );
     50        return NULL;
    6251}
    6352
     
    6655        int i;
    6756       
    68         for( i = 0; msn_away_state_list[i].number > -1; i ++ )
     57        for( i = 0; *msn_away_state_list[i].code; i ++ )
    6958                if( g_strcasecmp( msn_away_state_list[i].name, name ) == 0 )
    7059                        return( msn_away_state_list + i );
    7160       
    72         return( NULL );
     61        return NULL;
    7362}
    7463
  • protocols/nogaim.c

    r1014cab r123cac7  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2006 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2010 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    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;
     
    9899void register_protocol (struct prpl *p)
    99100{
    100         protocols = g_list_append(protocols, p);
     101        int i;
     102        gboolean refused = global.conf->protocols != NULL;
     103 
     104        for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++)
     105        {
     106                if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0)
     107                        refused = FALSE;
     108        }
     109
     110        if (refused)
     111                log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name);
     112        else
     113                protocols = g_list_append(protocols, p);
    101114}
    102115
     
    273286        ic->flags |= OPT_LOGGED_IN;
    274287       
    275         /* Also necessary when we're not away, at least for some of the
    276            protocols. */
    277         imc_set_away( ic, u->away );
     288        /* Necessary to send initial presence status, even if we're not away. */
     289        imc_away_send_update( ic );
    278290       
    279291        /* Apparently we're connected successfully, so reset the
     
    377389/* list.c */
    378390
    379 void imcb_add_buddy( struct im_connection *ic, char *handle, char *group )
     391void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group )
    380392{
    381393        user_t *u;
     
    451463}
    452464
    453 void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname )
     465void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname )
    454466{
    455467        user_t *u = user_findhandle( ic, handle );
     468        char *set;
    456469       
    457470        if( !u || !realname ) return;
     
    466479                        imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
    467480        }
    468 }
    469 
    470 void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group )
     481       
     482        set = set_getstr( &ic->acc->set, "nick_source" );
     483        if( strcmp( set, "handle" ) != 0 )
     484        {
     485                char *name = g_strdup( realname );
     486               
     487                if( strcmp( set, "first_name" ) == 0 )
     488                {
     489                        int i;
     490                        for( i = 0; name[i] && !isspace( name[i] ); i ++ ) {}
     491                        name[i] = '\0';
     492                }
     493               
     494                imcb_buddy_nick_hint( ic, handle, name );
     495               
     496                g_free( name );
     497        }
     498}
     499
     500void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group )
    471501{
    472502        user_t *u;
     
    478508/* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM
    479509   modules to suggest a nickname for a handle. */
    480 void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick )
     510void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick )
    481511{
    482512        user_t *u = user_findhandle( ic, handle );
     
    623653        oo = u->online;
    624654       
    625         if( u->away )
    626         {
    627                 g_free( u->away );
    628                 u->away = NULL;
    629         }
     655        g_free( u->away );
     656        g_free( u->status_msg );
     657        u->away = u->status_msg = NULL;
    630658       
    631659        if( ( flags & OPT_LOGGED_IN ) && !u->online )
     
    665693                }
    666694        }
    667         /* else waste_any_state_information_for_now(); */
     695        else
     696        {
     697                u->status_msg = g_strdup( message );
     698        }
    668699       
    669700        /* LISPy... */
     
    690721}
    691722
    692 void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at )
     723void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at )
    693724{
    694725        irc_t *irc = ic->irc;
    695         char *wrapped;
     726        char *wrapped, *ts;
    696727        user_t *u;
    697728       
     
    735766            ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->irc->set, "strip_html" ) ) )
    736767                strip_html( msg );
    737 
     768       
     769        if( ( ts = format_timestamp( irc, sent_at ) ) )
     770        {
     771                char *new = g_strconcat( ts, msg, NULL );
     772                g_free( ts );
     773                ts = msg = new;
     774        }
     775       
    738776        wrapped = word_wrap( msg, 425 );
    739777        irc_msgfrom( irc, u->nick, wrapped );
    740778        g_free( wrapped );
     779        g_free( ts );
    741780}
    742781
     
    823862}
    824863
    825 void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at )
     864void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at )
    826865{
    827866        struct im_connection *ic = c->ic;
     
    842881        if( c && u )
    843882        {
    844                 irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, "", wrapped );
     883                char *ts = format_timestamp( ic->irc, sent_at );
     884                irc_privmsg( ic->irc, u, "PRIVMSG", c->channel, ts ? : "", wrapped );
     885                g_free( ts );
    845886        }
    846887        else
     
    895936/* buddy_chat.c */
    896937
    897 void imcb_chat_add_buddy( struct groupchat *b, char *handle )
     938void imcb_chat_add_buddy( struct groupchat *b, const char *handle )
    898939{
    899940        user_t *u = user_findhandle( b->ic, handle );
     
    930971
    931972/* This function is one BIG hack... :-( EREWRITE */
    932 void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason )
     973void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason )
    933974{
    934975        user_t *u;
     
    10361077}
    10371078
    1038 
    1039 
     1079char *set_eval_timezone( set_t *set, char *value )
     1080{
     1081        char *s;
     1082       
     1083        if( strcmp( value, "local" ) == 0 ||
     1084            strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 )
     1085                return value;
     1086       
     1087        /* Otherwise: +/- at the beginning optional, then one or more numbers,
     1088           possibly followed by a colon and more numbers. Don't bother bound-
     1089           checking them since users are free to shoot themselves in the foot. */
     1090        s = value;
     1091        if( *s == '+' || *s == '-' )
     1092                s ++;
     1093       
     1094        /* \d+ */
     1095        if( !isdigit( *s ) )
     1096                return SET_INVALID;
     1097        while( *s && isdigit( *s ) ) s ++;
     1098       
     1099        /* EOS? */
     1100        if( *s == '\0' )
     1101                return value;
     1102       
     1103        /* Otherwise, colon */
     1104        if( *s != ':' )
     1105                return SET_INVALID;
     1106        s ++;
     1107       
     1108        /* \d+ */
     1109        if( !isdigit( *s ) )
     1110                return SET_INVALID;
     1111        while( *s && isdigit( *s ) ) s ++;
     1112       
     1113        /* EOS */
     1114        return *s == '\0' ? value : SET_INVALID;
     1115}
     1116
     1117static char *format_timestamp( irc_t *irc, time_t msg_ts )
     1118{
     1119        time_t now_ts = time( NULL );
     1120        struct tm now, msg;
     1121        char *set;
     1122       
     1123        /* If the timestamp is <= 0 or less than a minute ago, discard it as
     1124           it doesn't seem to add to much useful info and/or might be noise. */
     1125        if( msg_ts <= 0 || msg_ts > now_ts - 60 )
     1126                return NULL;
     1127       
     1128        set = set_getstr( &irc->set, "timezone" );
     1129        if( strcmp( set, "local" ) == 0 )
     1130        {
     1131                localtime_r( &now_ts, &now );
     1132                localtime_r( &msg_ts, &msg );
     1133        }
     1134        else
     1135        {
     1136                int hr, min = 0, sign = 60;
     1137               
     1138                if( set[0] == '-' )
     1139                {
     1140                        sign *= -1;
     1141                        set ++;
     1142                }
     1143                else if( set[0] == '+' )
     1144                {
     1145                        set ++;
     1146                }
     1147               
     1148                if( sscanf( set, "%d:%d", &hr, &min ) >= 1 )
     1149                {
     1150                        msg_ts += sign * ( hr * 60 + min );
     1151                        now_ts += sign * ( hr * 60 + min );
     1152                }
     1153               
     1154                gmtime_r( &now_ts, &now );
     1155                gmtime_r( &msg_ts, &msg );
     1156        }
     1157       
     1158        if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday )
     1159                return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ",
     1160                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1161        else
     1162                return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d "
     1163                                        "%02d:%02d:%02d\x02]\x02 ",
     1164                                        msg.tm_year + 1900, msg.tm_mon, msg.tm_mday,
     1165                                        msg.tm_hour, msg.tm_min, msg.tm_sec );
     1166}
    10401167
    10411168/* The plan is to not allow straight calls to prpl functions anymore, but do
     
    10751202}
    10761203
    1077 static char *imc_away_alias_find( GList *gcm, char *away );
    1078 
    1079 int imc_set_away( struct im_connection *ic, char *away )
    1080 {
    1081         GList *m, *ms;
    1082         char *s;
    1083        
    1084         if( !away ) away = "";
    1085         ms = m = ic->acc->prpl->away_states( ic );
    1086        
    1087         while( m )
    1088         {
    1089                 if( *away )
    1090                 {
    1091                         if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 )
    1092                                 break;
    1093                 }
    1094                 else
    1095                 {
    1096                         if( g_strcasecmp( m->data, "Available" ) == 0 )
    1097                                 break;
    1098                         if( g_strcasecmp( m->data, "Online" ) == 0 )
    1099                                 break;
    1100                 }
    1101                 m = m->next;
    1102         }
    1103        
    1104         if( m )
    1105         {
    1106                 ic->acc->prpl->set_away( ic, m->data, *away ? away : NULL );
    1107         }
    1108         else
    1109         {
    1110                 s = imc_away_alias_find( ms, away );
    1111                 if( s )
    1112                 {
    1113                         ic->acc->prpl->set_away( ic, s, away );
    1114                         if( set_getbool( &ic->irc->set, "debug" ) )
    1115                                 imcb_log( ic, "Setting away state to %s", s );
    1116                 }
    1117                 else
    1118                         ic->acc->prpl->set_away( ic, GAIM_AWAY_CUSTOM, away );
    1119         }
    1120        
    1121         return( 1 );
     1204static char *imc_away_state_find( GList *gcm, char *away, char **message );
     1205
     1206int imc_away_send_update( struct im_connection *ic )
     1207{
     1208        char *away, *msg = NULL;
     1209       
     1210        away = set_getstr( &ic->acc->set, "away" ) ?
     1211             : set_getstr( &ic->irc->set, "away" );
     1212        if( away && *away )
     1213        {
     1214                GList *m = ic->acc->prpl->away_states( ic );
     1215                msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL;
     1216                away = imc_away_state_find( m, away, &msg ) ? : m->data;
     1217        }
     1218        else if( ic->acc->flags & ACC_FLAG_STATUS_MESSAGE )
     1219        {
     1220                away = NULL;
     1221                msg = set_getstr( &ic->acc->set, "status" ) ?
     1222                    : set_getstr( &ic->irc->set, "status" );
     1223        }
     1224       
     1225        ic->acc->prpl->set_away( ic, away, msg );
     1226       
     1227        return 1;
    11221228}
    11231229
     
    11341240};
    11351241
    1136 static char *imc_away_alias_find( GList *gcm, char *away )
     1242static char *imc_away_state_find( GList *gcm, char *away, char **message )
    11371243{
    11381244        GList *m;
    11391245        int i, j;
    11401246       
     1247        for( m = gcm; m; m = m->next )
     1248                if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 )
     1249                {
     1250                        /* At least the Yahoo! module works better if message
     1251                           contains no data unless it adds something to what
     1252                           we have in state already. */
     1253                        if( strlen( m->data ) == strlen( away ) )
     1254                                *message = NULL;
     1255                       
     1256                        return m->data;
     1257                }
     1258       
    11411259        for( i = 0; *imc_away_alias_list[i]; i ++ )
    11421260        {
     1261                int keep_message;
     1262               
    11431263                for( j = 0; imc_away_alias_list[i][j]; j ++ )
    11441264                        if( g_strncasecmp( away, imc_away_alias_list[i][j], strlen( imc_away_alias_list[i][j] ) ) == 0 )
     1265                        {
     1266                                keep_message = strlen( away ) != strlen( imc_away_alias_list[i][j] );
    11451267                                break;
     1268                        }
    11461269               
    11471270                if( !imc_away_alias_list[i][j] )        /* If we reach the end, this row */
     
    11511274                for( j = 0; imc_away_alias_list[i][j]; j ++ )
    11521275                {
    1153                         m = gcm;
    1154                         while( m )
    1155                         {
     1276                        for( m = gcm; m; m = m->next )
    11561277                                if( g_strcasecmp( imc_away_alias_list[i][j], m->data ) == 0 )
    1157                                         return( imc_away_alias_list[i][j] );
    1158                                 m = m->next;
    1159                         }
    1160                 }
    1161         }
    1162        
    1163         return( NULL );
     1278                                {
     1279                                        if( !keep_message )
     1280                                                *message = NULL;
     1281                                       
     1282                                        return imc_away_alias_list[i][j];
     1283                                }
     1284                }
     1285               
     1286                /* No need to look further, apparently this state doesn't
     1287                   have any good alias for this protocol. */
     1288                break;
     1289        }
     1290       
     1291        return NULL;
    11641292}
    11651293
  • protocols/nogaim.h

    r1014cab r123cac7  
    4949
    5050#define WEBSITE "http://www.bitlbee.org/"
    51 #define GAIM_AWAY_CUSTOM "Custom"
    5251
    5352/* Sharing flags between all kinds of things. I just hope I won't hit any
     
    218217       
    219218        /* You can tell what away states your protocol supports, so that
    220          * BitlBee will try to map the IRC away reasons to them, or use
    221          * GAIM_AWAY_CUSTOM when calling skype_set_away(). */
     219         * BitlBee will try to map the IRC away reasons to them. If your
     220         * protocol doesn't have any, just return one generic "Away". */
    222221        GList *(* away_states)(struct im_connection *ic);
    223222       
     
    276275 * user, usually after a login, or if the user added a buddy and the IM
    277276 * server confirms that the add was successful. Don't forget to do this! */
    278 G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, char *handle, char *group );
    279 G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group );
     277G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group );
     278G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group );
    280279G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle );
    281 G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname );
    282 G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick );
     280G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname );
     281G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick );
    283282
    284283/* Buddy activity */
     
    290289/* Not implemented yet! */ G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle );
    291290/* Call when a handle says something. 'flags' and 'sent_at may be just 0. */
    292 G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, uint32_t flags, time_t sent_at );
     291G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at );
    293292G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, uint32_t flags );
    294293G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
     
    303302 *   user, too. */
    304303G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle );
    305 G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, char *handle );
     304G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *b, const char *handle );
    306305/* To remove a handle from a group chat. Reason can be NULL. */
    307 G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason );
     306G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *b, const char *handle, const char *reason );
    308307/* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */
    309 G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, uint32_t flags, time_t sent_at );
     308G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at );
    310309/* System messages specific to a groupchat, so they can be displayed in the right context. */
    311310G_MODULE_EXPORT void imcb_chat_log( struct groupchat *c, char *format, ... ) G_GNUC_PRINTF( 2, 3 );
     
    315314
    316315/* Actions, or whatever. */
    317 int imc_set_away( struct im_connection *ic, char *away );
     316int imc_away_send_update( struct im_connection *ic );
    318317int imc_buddy_msg( struct im_connection *ic, char *handle, char *msg, int flags );
    319318int imc_chat_msg( struct groupchat *c, char *msg, int flags );
     
    325324
    326325/* Misc. stuff */
     326char *set_eval_timezone( set_t *set, char *value );
    327327char *set_eval_away_devoice( set_t *set, char *value );
    328328gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond );
  • protocols/oscar/oscar.c

    r1014cab r123cac7  
    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        }
     386       
     387        acc->flags |= ACC_FLAG_AWAY_MESSAGE;
    382388}
    383389
     
    12101216 */
    12111217static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg) {
    1212         struct icq_auth *data = g_new(struct icq_auth, 1);
     1218        struct icq_auth *data;
    12131219        char *reason = NULL;
    12141220        char *dialog_msg;
    1215        
     1221
     1222        if (set_getbool(&ic->acc->set, "ignore_auth_requests"))
     1223                return;
     1224       
     1225        data = g_new(struct icq_auth, 1);
     1226
    12161227        if (strlen(msg) > 6)
    12171228                reason = msg + 6;
     
    19521963static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message)
    19531964{
     1965        if (state == NULL)
     1966                state = "";
    19541967
    19551968        if (!g_strcasecmp(state, _("Visible"))) {
     
    19591972                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);
    19601973                return;
    1961         } /* else... */
     1974        } else if (message == NULL) {
     1975                message = state;
     1976        }
    19621977
    19631978        if (od->rights.maxawaymsglen == 0)
     
    20022017        }
    20032018
    2004         if (!g_strcasecmp(state, "Online")) {
     2019        if (state == NULL) {
    20052020                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
    20062021        } else if (!g_strcasecmp(state, "Away")) {
     
    20272042                aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);
    20282043                ic->away = g_strdup(msg);
    2029         } else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) {
     2044        } else {
    20302045                if (no_message) {
    20312046                        aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
     
    22762291{
    22772292        struct oscar_data *od = ic->proto_data;
    2278         GList *m = NULL;
    2279 
    2280         if (!od->icq)
    2281                 return g_list_append(m, GAIM_AWAY_CUSTOM);
    2282 
    2283         m = g_list_append(m, "Online");
    2284         m = g_list_append(m, "Away");
    2285         m = g_list_append(m, "Do Not Disturb");
    2286         m = g_list_append(m, "Not Available");
    2287         m = g_list_append(m, "Occupied");
    2288         m = g_list_append(m, "Free For Chat");
    2289         m = g_list_append(m, "Invisible");
    2290 
    2291         return m;
     2293
     2294        if (od->icq) {
     2295                static GList *m = NULL;
     2296                m = g_list_append(m, "Away");
     2297                m = g_list_append(m, "Do Not Disturb");
     2298                m = g_list_append(m, "Not Available");
     2299                m = g_list_append(m, "Occupied");
     2300                m = g_list_append(m, "Free For Chat");
     2301                m = g_list_append(m, "Invisible");
     2302                return m;
     2303        } else {
     2304                static GList *m = NULL;
     2305                m = g_list_append(m, "Away");
     2306                return m;
     2307        }
    22922308}
    22932309
  • protocols/yahoo/libyahoo2.c

    r1014cab r123cac7  
    855855}
    856856
    857 static YList * bud_str2list(char *rawlist)
    858 {
    859         YList * l = NULL;
    860 
    861         char **lines;
    862         char **split;
    863         char **buddies;
    864         char **tmp, **bud;
    865 
    866         lines = y_strsplit(rawlist, "\n", -1);
    867         for (tmp = lines; *tmp; tmp++) {
    868                 struct yahoo_buddy *newbud;
    869 
    870                 split = y_strsplit(*tmp, ":", 2);
    871                 if (!split)
    872                         continue;
    873                 if (!split[0] || !split[1]) {
    874                         y_strfreev(split);
    875                         continue;
    876                 }
    877                 buddies = y_strsplit(split[1], ",", -1);
    878 
    879                 for (bud = buddies; bud && *bud; bud++) {
    880                         newbud = y_new0(struct yahoo_buddy, 1);
    881                         newbud->id = strdup(*bud);
    882                         newbud->group = strdup(split[0]);
    883 
    884                         if(y_list_find_custom(l, newbud, is_same_bud)) {
    885                                 FREE(newbud->id);
    886                                 FREE(newbud->group);
    887                                 FREE(newbud);
    888                                 continue;
    889                         }
    890 
    891                         newbud->real_name = NULL;
    892 
    893                         l = y_list_append(l, newbud);
    894 
    895                         NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group));
    896                 }
    897 
    898                 y_strfreev(buddies);
    899                 y_strfreev(split);
    900         }
    901         y_strfreev(lines);
    902 
    903         return l;
    904 }
    905 
    906857static char * getcookie(char *rawcookie)
    907858{
     
    13601311}
    13611312
    1362 
    1363 static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1313static void yahoo_process_status(struct yahoo_input_data *yid,
     1314        struct yahoo_packet *pkt)
    13641315{
    13651316        YList *l;
    13661317        struct yahoo_data *yd = yid->yd;
    13671318
    1368         struct user
    1369         {
    1370                 char *name;     /* 7    name */
    1371                 int   state;    /* 10   state */
    1372                 int   flags;    /* 13   flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
    1373                 int   mobile;   /* 60   mobile */
    1374                 char *msg;      /* 19   custom status message */
    1375                 int   away;     /* 47   away (or invisible)*/
    1376                 int   buddy_session;    /* 11   state */
    1377                 int   f17;      /* 17   in chat? then what about flags? */
    1378                 int   idle;     /* 137  seconds idle */
    1379                 int   f138;     /* 138  state */
    1380                 char *f184;     /* 184  state */
    1381                 int   f192;     /* 192  state */
    1382                 int   f10001;   /* 10001        state */
    1383                 int   f10002;   /* 10002        state */
    1384                 int   f198;     /* 198  state */
    1385                 char *f197;     /* 197  state */
    1386                 char *f205;     /* 205  state */
    1387                 int   f213;     /* 213  state */
    1388         } *u;
     1319        struct yahoo_process_status_entry *u;
    13891320
    13901321        YList *users = 0;
    1391        
     1322
    13921323        if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
    1393                 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL);
    1394                 return;
    1395         }
     1324                YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
     1325                        YAHOO_LOGIN_DUPL, NULL);
     1326                return;
     1327        }
     1328
     1329        /* Status updates may be spread accross multiple packets and not
     1330           even on buddy boundaries, so keeping some state is important.
     1331           So, continue where we left off, and only add a user entry to
     1332           the list once it's complete (301-315 End buddy). */
     1333        u = yd->half_user;
    13961334
    13971335        for (l = pkt->hash; l; l = l->next) {
     
    13991337
    14001338                switch (pair->key) {
    1401                 case 0: /* we won't actually do anything with this */
     1339                case 300:       /* Begin buddy */
     1340                        if (!strcmp(pair->value, "315") && !u) {
     1341                                u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1);
     1342                        }
     1343                        break;
     1344                case 301:       /* End buddy */
     1345                        if (!strcmp(pair->value, "315") && u) {
     1346                                /* Sometimes user info comes in an odd format with no
     1347                                   "begin buddy" but *with* an "end buddy". Don't add
     1348                                   it twice. */
     1349                                if (!y_list_find(users, u))
     1350                                        users = y_list_prepend(users, u);
     1351                                u = yd->half_user = NULL;
     1352                        }
     1353                        break;
     1354                case 0: /* we won't actually do anything with this */
    14021355                        NOTICE(("key %d:%s", pair->key, pair->value));
    14031356                        break;
    1404                 case 1: /* we don't get the full buddy list here. */
     1357                case 1: /* we don't get the full buddy list here. */
    14051358                        if (!yd->logged_in) {
    1406                                 yd->logged_in = TRUE;
    1407                                 if(yd->current_status < 0)
     1359                                yd->logged_in = 1;
     1360                                if (yd->current_status < 0)
    14081361                                        yd->current_status = yd->initial_status;
    1409                                 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
     1362                                YAHOO_CALLBACK(ext_yahoo_login_response) (yd->
     1363                                        client_id, YAHOO_LOGIN_OK, NULL);
    14101364                        }
    14111365                        break;
    1412                 case 8: /* how many online buddies we have */
     1366                case 8: /* how many online buddies we have */
    14131367                        NOTICE(("key %d:%s", pair->key, pair->value));
    14141368                        break;
    1415                 case 7: /* the current buddy */
    1416                         u = y_new0(struct user, 1);
     1369                case 7: /* the current buddy */
     1370                        if (!u) {
     1371                                /* This will only happen in case of a single level message */
     1372                                u = y_new0(struct yahoo_process_status_entry, 1);
     1373                                users = y_list_prepend(users, u);
     1374                        }
    14171375                        u->name = pair->value;
    1418                         users = y_list_prepend(users, u);
    1419                         break;
    1420                 case 10: /* state */
    1421                         ((struct user*)users->data)->state = strtol(pair->value, NULL, 10);
    1422                         break;
    1423                 case 19: /* custom status message */
    1424                         ((struct user*)users->data)->msg = pair->value;
    1425                         break;
    1426                 case 47: /* is it an away message or not */
    1427                         ((struct user*)users->data)->away = atoi(pair->value);
    1428                         break;
    1429                 case 137: /* seconds idle */
    1430                         ((struct user*)users->data)->idle = atoi(pair->value);
    1431                         break;
    1432                 case 11: /* this is the buddy's session id */
    1433                         ((struct user*)users->data)->buddy_session = atoi(pair->value);
    1434                         break;
    1435                 case 17: /* in chat? */
    1436                         ((struct user*)users->data)->f17 = atoi(pair->value);
    1437                         break;
    1438                 case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
    1439                         ((struct user*)users->data)->flags = atoi(pair->value);
    1440                         break;
    1441                 case 60: /* SMS -> 1 MOBILE USER */
     1376                        break;
     1377                case 10:        /* state */
     1378                        u->state = strtol(pair->value, NULL, 10);
     1379                        break;
     1380                case 19:        /* custom status message */
     1381                        u->msg = pair->value;
     1382                        break;
     1383                case 47:        /* is it an away message or not. Not applicable for YMSG16 anymore */
     1384                        u->away = atoi(pair->value);
     1385                        break;
     1386                case 137:       /* seconds idle */
     1387                        u->idle = atoi(pair->value);
     1388                        break;
     1389                case 11:        /* this is the buddy's session id */
     1390                        u->buddy_session = atoi(pair->value);
     1391                        break;
     1392                case 17:        /* in chat? */
     1393                        u->f17 = atoi(pair->value);
     1394                        break;
     1395                case 13:        /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
     1396                        u->flags = atoi(pair->value);
     1397                        break;
     1398                case 60:        /* SMS -> 1 MOBILE USER */
    14421399                        /* sometimes going offline makes this 2, but invisible never sends it */
    1443                         ((struct user*)users->data)->mobile = atoi(pair->value);
     1400                        u->mobile = atoi(pair->value);
    14441401                        break;
    14451402                case 138:
    1446                         ((struct user*)users->data)->f138 = atoi(pair->value);
     1403                        u->f138 = atoi(pair->value);
    14471404                        break;
    14481405                case 184:
    1449                         ((struct user*)users->data)->f184 = pair->value;
     1406                        u->f184 = pair->value;
    14501407                        break;
    14511408                case 192:
    1452                         ((struct user*)users->data)->f192 = atoi(pair->value);
     1409                        u->f192 = atoi(pair->value);
    14531410                        break;
    14541411                case 10001:
    1455                         ((struct user*)users->data)->f10001 = atoi(pair->value);
     1412                        u->f10001 = atoi(pair->value);
    14561413                        break;
    14571414                case 10002:
    1458                         ((struct user*)users->data)->f10002 = atoi(pair->value);
     1415                        u->f10002 = atoi(pair->value);
    14591416                        break;
    14601417                case 198:
    1461                         ((struct user*)users->data)->f198 = atoi(pair->value);
     1418                        u->f198 = atoi(pair->value);
    14621419                        break;
    14631420                case 197:
    1464                         ((struct user*)users->data)->f197 = pair->value;
     1421                        u->f197 = pair->value;
    14651422                        break;
    14661423                case 205:
    1467                         ((struct user*)users->data)->f205 = pair->value;
     1424                        u->f205 = pair->value;
    14681425                        break;
    14691426                case 213:
    1470                         ((struct user*)users->data)->f213 = atoi(pair->value);
    1471                         break;
    1472                 case 16: /* Custom error message */
    1473                         YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM);
     1427                        u->f213 = atoi(pair->value);
     1428                        break;
     1429                case 16:        /* Custom error message */
     1430                        YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id,
     1431                                pair->value, 0, E_CUSTOM);
    14741432                        break;
    14751433                default:
    1476                         WARNING(("unknown status key %d:%s", pair->key, pair->value));
    1477                         break;
    1478                 }
    1479         }
    1480        
     1434                        WARNING(("unknown status key %d:%s", pair->key,
     1435                                        pair->value));
     1436                        break;
     1437                }
     1438        }
     1439
    14811440        while (users) {
    14821441                YList *t = users;
    1483                 struct user *u = users->data;
     1442                struct yahoo_process_status_entry *u = users->data;
    14841443
    14851444                if (u->name != NULL) {
    1486                         if (pkt->service == YAHOO_SERVICE_LOGOFF) { /* || u->flags == 0) { Not in YMSG16 */
    1487                                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
     1445                        if (pkt->service ==
     1446                                YAHOO_SERVICE_LOGOFF
     1447                                /*|| u->flags == 0 No flags for YMSG16 */ ) {
     1448                                YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->
     1449                                        client_id, u->name,
     1450                                        YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
    14881451                        } else {
    14891452                                /* Key 47 always seems to be 1 for YMSG16 */
    1490                                 if(!u->state)
     1453                                if (!u->state)
    14911454                                        u->away = 0;
    14921455                                else
    14931456                                        u->away = 1;
    14941457
    1495                                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile);
     1458                                YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->
     1459                                        client_id, u->name, u->state, u->msg,
     1460                                        u->away, u->idle, u->mobile);
    14961461                        }
    14971462                }
     
    15031468}
    15041469
    1505 static void yahoo_process_buddy_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1470static void yahoo_process_buddy_list(struct yahoo_input_data *yid,
     1471        struct yahoo_packet *pkt)
    15061472{
    15071473        struct yahoo_data *yd = yid->yd;
     
    15151481                struct yahoo_pair *pair = l->data;
    15161482
    1517                 switch(pair->key) {
     1483                switch (pair->key) {
    15181484                case 300:
    15191485                case 301:
    15201486                case 302:
     1487                        break;  /* Separators. Our logic does not need them */
    15211488                case 303:
    1522                         if ( 315 == atoi(pair->value) )
     1489                        if (318 == atoi(pair->value))
    15231490                                last_packet = 1;
    15241491                        break;
    15251492                case 65:
    1526                         g_free(cur_group);
    15271493                        cur_group = strdup(pair->value);
    15281494                        break;
     
    15301496                        newbud = y_new0(struct yahoo_buddy, 1);
    15311497                        newbud->id = strdup(pair->value);
    1532                         if(cur_group)
     1498                        if (cur_group)
    15331499                                newbud->group = strdup(cur_group);
    1534                         else {
    1535                                 struct yahoo_buddy *lastbud = (struct yahoo_buddy *)y_list_nth(
    1536                                                                 yd->buddies, y_list_length(yd->buddies)-1)->data;
     1500                        else if (yd->buddies) {
     1501                                struct yahoo_buddy *lastbud =
     1502                                        (struct yahoo_buddy *)y_list_nth(yd->
     1503                                        buddies,
     1504                                        y_list_length(yd->buddies) - 1)->data;
    15371505                                newbud->group = strdup(lastbud->group);
    1538                         }
     1506                        } else
     1507                                newbud->group = strdup("Buddies");
    15391508
    15401509                        yd->buddies = y_list_append(yd->buddies, newbud);
     
    15431512                }
    15441513        }
    1545        
    1546         g_free(cur_group);
    15471514
    15481515        /* we could be getting multiple packets here */
    1549         if (last_packet)
    1550                 return;
    1551 
    1552         YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
    1553 
    1554         /*** We login at the very end of the packet communication */
     1516        if (pkt->hash && !last_packet)
     1517                return;
     1518
     1519        YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies);
     1520
     1521        /* Logged in */
    15551522        if (!yd->logged_in) {
    1556                 yd->logged_in = TRUE;
    1557                 if(yd->current_status < 0)
     1523                yd->logged_in = 1;
     1524                if (yd->current_status < 0)
    15581525                        yd->current_status = yd->initial_status;
    1559                 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
    1560         }
    1561 }
    1562 
    1563 static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1526                YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id,
     1527                        YAHOO_LOGIN_OK, NULL);
     1528
     1529                /*
     1530                yahoo_set_away(yd->client_id, yd->initial_status, NULL,
     1531                        (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1);
     1532
     1533                yahoo_get_yab(yd->client_id);
     1534                */
     1535        }
     1536
     1537}
     1538
     1539static void yahoo_process_list(struct yahoo_input_data *yid,
     1540        struct yahoo_packet *pkt)
    15641541{
    15651542        struct yahoo_data *yd = yid->yd;
    15661543        YList *l;
    15671544
    1568         if (!yd->logged_in) {
    1569                 yd->logged_in = TRUE;
    1570                 if(yd->current_status < 0)
    1571                         yd->current_status = yd->initial_status;
    1572                 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
    1573         }
    1574 
     1545        /* we could be getting multiple packets here */
    15751546        for (l = pkt->hash; l; l = l->next) {
    15761547                struct yahoo_pair *pair = l->data;
    15771548
    1578                 switch(pair->key) {
    1579                 case 87: /* buddies */
    1580                         if(!yd->rawbuddylist)
    1581                                 yd->rawbuddylist = strdup(pair->value);
    1582                         else {
    1583                                 yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value);
     1549                switch (pair->key) {
     1550                case 89:        /* identities */
     1551                        {
     1552                                char **identities =
     1553                                        y_strsplit(pair->value, ",", -1);
     1554                                int i;
     1555                                for (i = 0; identities[i]; i++)
     1556                                        yd->identities =
     1557                                                y_list_append(yd->identities,
     1558                                                strdup(identities[i]));
     1559                                y_strfreev(identities);
    15841560                        }
    1585                         break;
    1586 
    1587                 case 88: /* ignore list */
    1588                         if(!yd->ignorelist)
    1589                                 yd->ignorelist = strdup("Ignore:");
    1590                         yd->ignorelist = y_string_append(yd->ignorelist, pair->value);
    1591                         break;
    1592 
    1593                 case 89: /* identities */
    1594                         {
    1595                         char **identities = y_strsplit(pair->value, ",", -1);
    1596                         int i;
    1597                         for(i=0; identities[i]; i++)
    1598                                 yd->identities = y_list_append(yd->identities,
    1599                                                 strdup(identities[i]));
    1600                         y_strfreev(identities);
    1601                         }
    1602                         YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities);
    1603                         break;
    1604                 case 59: /* cookies */
    1605                         if(yd->ignorelist) {
    1606                                 yd->ignore = bud_str2list(yd->ignorelist);
    1607                                 FREE(yd->ignorelist);
    1608                                 YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore);
    1609                         }
    1610                         if(yd->rawbuddylist) {
    1611                                 yd->buddies = bud_str2list(yd->rawbuddylist);
    1612                                 FREE(yd->rawbuddylist);
    1613                                 YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
    1614                         }
    1615 
    1616                         if(pair->value[0]=='Y') {
     1561                        YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id,
     1562                                yd->identities);
     1563                        break;
     1564                case 59:        /* cookies */
     1565                        if (pair->value[0] == 'Y') {
    16171566                                FREE(yd->cookie_y);
    16181567                                FREE(yd->login_cookie);
     
    16211570                                yd->login_cookie = getlcookie(yd->cookie_y);
    16221571
    1623                         } else if(pair->value[0]=='T') {
     1572                        } else if (pair->value[0] == 'T') {
    16241573                                FREE(yd->cookie_t);
    16251574                                yd->cookie_t = getcookie(pair->value);
    16261575
    1627                         } else if(pair->value[0]=='C') {
     1576                        } else if (pair->value[0] == 'C') {
    16281577                                FREE(yd->cookie_c);
    16291578                                yd->cookie_c = getcookie(pair->value);
    1630                         } 
    1631 
    1632                         if(yd->cookie_y && yd->cookie_t)
    1633                                 YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id);
    1634 
    1635                         break;
    1636                 case 3: /* my id */
    1637                 case 90: /* 1 */
    1638                 case 100: /* 0 */
    1639                 case 101: /* NULL */
    1640                 case 102: /* NULL */
    1641                 case 93: /* 86400/1440 */
    1642                         break;
    1643                 }
    1644         }
     1579                        }
     1580
     1581                        break;
     1582                case 3: /* my id */
     1583                case 90:        /* 1 */
     1584                case 100:       /* 0 */
     1585                case 101:       /* NULL */
     1586                case 102:       /* NULL */
     1587                case 93:        /* 86400/1440 */
     1588                        break;
     1589                }
     1590        }
     1591
     1592        if (yd->cookie_y && yd->cookie_t)       /* We don't get cookie_c anymore */
     1593                YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id);
    16451594}
    16461595
     
    23932342{
    23942343        struct yahoo_https_auth_data *had = req->data;
    2395         struct yahoo_input_data *yid = had->yid;
    2396         struct yahoo_data *yd = yid->yd;
     2344        struct yahoo_input_data *yid;
     2345        struct yahoo_data *yd;
    23972346        int st;
     2347       
     2348        if (y_list_find(inputs, had->yid) == NULL)
     2349                return;
     2350       
     2351        yid = had->yid;
     2352        yd = yid->yd;
    23982353       
    23992354        if (req->status_code != 200) {
     
    24362391{
    24372392        struct yahoo_https_auth_data *had = req->data;
    2438         struct yahoo_input_data *yid = had->yid;
    2439         struct yahoo_data *yd = yid->yd;
     2393        struct yahoo_input_data *yid;
     2394        struct yahoo_data *yd;
    24402395        struct yahoo_packet *pack;
    2441         char *crumb;
     2396        char *crumb = NULL;
    24422397        int st;
     2398       
     2399        if (y_list_find(inputs, had->yid) == NULL)
     2400                return;
     2401       
     2402        yid = had->yid;
     2403        yd = yid->yd;
    24432404       
    24442405        md5_byte_t result[16];
     
    40804041
    40814042        yd = yid->yd;
    4082 
    40834043        old_status = yd->current_status;
    4084 
    4085         if (msg && strncmp(msg,"Invisible",9)) {
    4086                 yd->current_status = YAHOO_STATUS_CUSTOM;
    4087         } else {
    4088                 yd->current_status = state;
    4089         }
     4044        yd->current_status = state;
    40904045
    40914046        /* Thank you libpurple :) */
     
    41024057        snprintf(s, sizeof(s), "%d", yd->current_status);
    41034058        yahoo_packet_hash(pkt, 10, s);
    4104          
    4105         if (yd->current_status == YAHOO_STATUS_CUSTOM) {
    4106                 yahoo_packet_hash(pkt, 19, msg);
    4107         } else {
    4108                 yahoo_packet_hash(pkt, 19, "");
    4109         }
    4110        
     4059        yahoo_packet_hash(pkt, 19, msg && state == YAHOO_STATUS_CUSTOM ? msg : "");
    41114060        yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
    4112 
    41134061        yahoo_send_packet(yid, pkt, 0);
    41144062        yahoo_packet_free(pkt);
  • protocols/yahoo/yahoo.c

    r1014cab r123cac7  
    130130{
    131131        set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
     132       
     133        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;
    132134}
    133135
     
    197199{
    198200        struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data;
    199         char *away;
    200        
    201         away = NULL;
    202        
    203         if( state && msg && g_strcasecmp( state, msg ) != 0 )
    204         {
    205                 yd->current_status = YAHOO_STATUS_CUSTOM;
    206                 away = "";
    207         }
    208         else if( state )
    209         {
    210                 /* Set msg to NULL since (if it isn't NULL already) it's equal
    211                    to state. msg must be empty if we want to use an existing
    212                    away state. */
    213                 msg = NULL;
    214                
    215                 away = "";
    216                 if( g_strcasecmp( state, "Available" ) == 0 )
    217                 {
    218                         yd->current_status = YAHOO_STATUS_AVAILABLE;
    219                         away = NULL;
    220                 }
    221                 else if( g_strcasecmp( state, "Be Right Back" ) == 0 )
     201       
     202        if( state && msg == NULL )
     203        {
     204                /* Use these states only if msg doesn't contain additional
     205                   info since away messages are only supported with CUSTOM. */
     206                if( g_strcasecmp( state, "Be Right Back" ) == 0 )
    222207                        yd->current_status = YAHOO_STATUS_BRB;
    223208                else if( g_strcasecmp( state, "Busy" ) == 0 )
     
    239224                else if( g_strcasecmp( state, "Invisible" ) == 0 )
    240225                        yd->current_status = YAHOO_STATUS_INVISIBLE;
    241                 else if( g_strcasecmp( state, GAIM_AWAY_CUSTOM ) == 0 )
    242                 {
    243                         yd->current_status = YAHOO_STATUS_AVAILABLE;
    244                        
    245                         away = NULL;
    246                 }
    247         }
     226                else
     227                        yd->current_status = YAHOO_STATUS_CUSTOM;
     228        }
     229        else if( msg )
     230                yd->current_status = YAHOO_STATUS_CUSTOM;
    248231        else
    249232                yd->current_status = YAHOO_STATUS_AVAILABLE;
    250233       
    251         yahoo_set_away( yd->y2_id, yd->current_status, msg, away != NULL ? 2 : 0 );
     234        yahoo_set_away( yd->y2_id, yd->current_status, msg, state ? 2 : 0 );
    252235}
    253236
     
    258241        if( m == NULL )
    259242        {
    260                 m = g_list_append( m, "Available" );
    261243                m = g_list_append( m, "Be Right Back" );
    262244                m = g_list_append( m, "Busy" );
     
    269251                m = g_list_append( m, "Stepped Out" );
    270252                m = g_list_append( m, "Invisible" );
    271                 m = g_list_append( m, GAIM_AWAY_CUSTOM );
    272253        }
    273254       
  • protocols/yahoo/yahoo2_types.h

    r1014cab r123cac7  
    196196
    197197        void  *server_settings;
     198       
     199        struct yahoo_process_status_entry *half_user;
    198200};
    199201
     
    261263};
    262264
     265struct yahoo_process_status_entry {
     266        char *name;     /* 7      name */
     267        int state;      /* 10     state */
     268        int flags;      /* 13     flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
     269        int mobile;     /* 60     mobile */
     270        char *msg;      /* 19     custom status message */
     271        int away;       /* 47     away (or invisible) */
     272        int buddy_session; /* 11  state */
     273        int f17;        /* 17     in chat? then what about flags? */
     274        int idle;       /* 137    seconds idle */
     275        int f138;       /* 138    state */
     276        char *f184;     /* 184    state */
     277        int f192;       /* 192    state */
     278        int f10001;     /* 10001  state */
     279        int f10002;     /* 10002  state */
     280        int f198;       /* 198    state */
     281        char *f197;     /* 197    state */
     282        char *f205;     /* 205    state */
     283        int f213;       /* 213    state */
     284};
     285
    263286#ifdef __cplusplus
    264287}
  • root_commands.c

    r1014cab r123cac7  
    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
     
    143143        storage_status_t status = storage_load( irc, cmd[1] );
    144144        char *account_on[] = { "account", "on", NULL };
     145       
     146        if( strchr( irc->umode, 'R' ) != NULL )
     147        {
     148                irc_usermsg( irc, "You're already logged in." );
     149                return;
     150        }
    145151       
    146152        switch (status) {
     
    648654                irc_usermsg( irc, "Nick `%s' can't be changed", cmd[1] );
    649655        }
     656        else if( g_strcasecmp( cmd[1], irc->channel ) == 0 )
     657        {
     658                if( strchr( CTYPES, cmd[2][0] ) && nick_ok( cmd[2] + 1 ) )
     659                {
     660                        u = user_find( irc, irc->nick );
     661                       
     662                        irc_part( irc, u, irc->channel );
     663                        g_free( irc->channel );
     664                        irc->channel = g_strdup( cmd[2] );
     665                        irc_join( irc, u, irc->channel );
     666                       
     667                        if( strcmp( cmd[0], "set_rename" ) != 0 )
     668                                set_setstr( &irc->set, "control_channel", cmd[2] );
     669                }
     670        }
    650671        else if( user_find( irc, cmd[2] ) && ( nick_cmp( cmd[1], cmd[2] ) != 0 ) )
    651672        {
     
    695716       
    696717        return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
     718}
     719
     720char *set_eval_control_channel( set_t *set, char *new_name )
     721{
     722        irc_t *irc = set->data;
     723       
     724        if( strcmp( irc->channel, new_name ) != 0 )
     725        {
     726                char *cmd[] = { "set_rename", irc->channel, new_name, NULL };
     727               
     728                cmd_rename( irc, cmd );
     729        }
     730       
     731        return strcmp( irc->channel, new_name ) == 0 ? new_name : SET_INVALID;
    697732}
    698733
     
    908943                online = 1;
    909944        else
    910                 online =  away = 1;
     945                online = away = 1;
    911946       
    912947        if( strchr( irc->umode, 'b' ) != NULL )
     
    921956                if( online == 1 )
    922957                {
     958                        char st[256] = "Online";
     959                       
     960                        if( u->status_msg )
     961                                g_snprintf( st, sizeof( st ) - 1, "Online (%s)", u->status_msg );
     962                       
    923963                        g_snprintf( s, sizeof( s ) - 1, "%s@%s %s(%s)", u->user, u->host, u->ic->acc->prpl->name, u->ic->acc->user );
    924                         irc_usermsg( irc, format, u->nick, s, "Online" );
     964                        irc_usermsg( irc, format, u->nick, s, st );
    925965                }
    926966               
     
    11151155                irc_usermsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] );
    11161156        }
    1117 
    1118 
    1119 
    1120 #if 0
    1121         account_t *a;
    1122         struct im_connection *ic;
    1123         char *chat, *channel, *nick = NULL, *password = NULL;
    1124         struct groupchat *c;
    1125        
    1126         if( !( a = account_get( irc, cmd[1] ) ) )
    1127         {
    1128                 irc_usermsg( irc, "Invalid account" );
    1129                 return;
    1130         }
    1131         else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) )
    1132         {
    1133                 irc_usermsg( irc, "That account is not on-line" );
    1134                 return;
    1135         }
    1136         else if( a->prpl->chat_join == NULL )
    1137         {
    1138                 irc_usermsg( irc, "Command `%s' not supported by this protocol", cmd[0] );
    1139                 return;
    1140         }
    1141         ic = a->ic;
    1142        
    1143         chat = cmd[2];
    1144         if( cmd[3] )
    1145         {
    1146                 if( strchr( CTYPES, cmd[3][0] ) == NULL )
    1147                         channel = g_strdup_printf( "&%s", cmd[3] );
    1148                 else
    1149                         channel = g_strdup( cmd[3] );
    1150         }
    1151         else
    1152         {
    1153                 char *s;
    1154                
    1155                 channel = g_strdup_printf( "&%s", chat );
    1156                 if( ( s = strchr( channel, '@' ) ) )
    1157                         *s = 0;
    1158         }
    1159         if( cmd[3] && cmd[4] )
    1160                 nick = cmd[4];
    1161         else
    1162                 nick = irc->nick;
    1163         if( cmd[3] && cmd[4] && cmd[5] )
    1164                 password = cmd[5];
    1165        
    1166         if( !nick_ok( channel + 1 ) )
    1167         {
    1168                 irc_usermsg( irc, "Invalid channel name: %s", channel );
    1169                 g_free( channel );
    1170                 return;
    1171         }
    1172         else if( g_strcasecmp( channel, irc->channel ) == 0 || irc_chat_by_channel( irc, channel ) )
    1173         {
    1174                 irc_usermsg( irc, "Channel already exists: %s", channel );
    1175                 g_free( channel );
    1176                 return;
    1177         }
    1178        
    1179         if( ( c = a->prpl->chat_join( ic, chat, nick, password ) ) )
    1180         {
    1181                 g_free( c->channel );
    1182                 c->channel = channel;
    1183         }
    1184         else
    1185         {
    1186                 irc_usermsg( irc, "Tried to join chat, not sure if this was successful" );
    1187                 g_free( channel );
    1188         }
    1189 #endif
    11901157}
    11911158
  • tests/check_jabber_util.c

    r1014cab r123cac7  
    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

    r1014cab r123cac7  
    2525
    2626#include "bitlbee.h"
     27
     28#include "arc.h"
     29#include "base64.h"
    2730#include "commands.h"
    28 #include "crypting.h"
    2931#include "protocols/nogaim.h"
    3032#include "help.h"
    3133#include "ipc.h"
     34#include "md5.h"
     35#include "misc.h"
    3236#include <signal.h>
    3337#include <unistd.h>
     
    4044static void sighandler( int signal );
    4145
     46static int crypt_main( int argc, char *argv[] );
     47
    4248int main( int argc, char *argv[] )
    4349{
     
    4551        char *old_cwd = NULL;
    4652        struct sigaction sig, old;
     53       
     54        if( argc > 1 && strcmp( argv[1], "-x" ) == 0 )
     55                return crypt_main( argc, argv );
    4756       
    4857        log_init();
     
    159168}
    160169
     170static int crypt_main( int argc, char *argv[] )
     171{
     172        int pass_len;
     173        unsigned char *pass_cr, *pass_cl;
     174       
     175        if( argc < 4 || ( strcmp( argv[2], "hash" ) != 0 &&
     176                          strcmp( argv[2], "unhash" ) != 0 && argc < 5 ) )
     177        {
     178                printf( "Supported:\n"
     179                        "  %s -x enc <key> <cleartext password>\n"
     180                        "  %s -x dec <key> <encrypted password>\n"
     181                        "  %s -x hash <cleartext password>\n"
     182                        "  %s -x unhash <hashed password>\n"
     183                        "  %s -x chkhash <hashed password> <cleartext password>\n",
     184                        argv[0], argv[0], argv[0], argv[0], argv[0] );
     185        }
     186        else if( strcmp( argv[2], "enc" ) == 0 )
     187        {
     188                pass_len = arc_encode( argv[4], strlen( argv[4] ), (unsigned char**) &pass_cr, argv[3], 12 );
     189                printf( "%s\n", base64_encode( pass_cr, pass_len ) );
     190        }
     191        else if( strcmp( argv[2], "dec" ) == 0 )
     192        {
     193                pass_len = base64_decode( argv[4], (unsigned char**) &pass_cr );
     194                arc_decode( pass_cr, pass_len, (char**) &pass_cl, argv[3] );
     195                printf( "%s\n", pass_cl );
     196        }
     197        else if( strcmp( argv[2], "hash" ) == 0 )
     198        {
     199                md5_byte_t pass_md5[21];
     200                md5_state_t md5_state;
     201               
     202                random_bytes( pass_md5 + 16, 5 );
     203                md5_init( &md5_state );
     204                md5_append( &md5_state, (md5_byte_t*) argv[3], strlen( argv[3] ) );
     205                md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */
     206                md5_finish( &md5_state, pass_md5 );
     207               
     208                printf( "%s\n", base64_encode( pass_md5, 21 ) );
     209        }
     210        else if( strcmp( argv[2], "unhash" ) == 0 )
     211        {
     212                printf( "Hash %s submitted to a massive Beowulf cluster of\n"
     213                        "overclocked 486s. Expect your answer next year somewhere around this time. :-)\n", argv[3] );
     214        }
     215        else if( strcmp( argv[2], "chkhash" ) == 0 )
     216        {
     217                char *hash = strncmp( argv[3], "md5:", 4 ) == 0 ? argv[3] + 4 : argv[3];
     218                int st = md5_verify_password( argv[4], hash );
     219               
     220                printf( "Hash %s given password.\n", st == 0 ? "matches" : "does not match" );
     221               
     222                return st;
     223        }
     224       
     225        return 0;
     226}
     227
    161228static void sighandler( int signal )
    162229{
     
    214281        return( (double) time->tv_sec + (double) time->tv_usec / 1000000 );
    215282}
    216 
    217 
  • user.h

    r1014cab r123cac7  
    3434       
    3535        char *away;
     36        char *status_msg; /* Non-IRC extension, but nice on IM. */
    3637       
    3738        char is_private;
Note: See TracChangeset for help on using the changeset viewer.