Changes in / [d444c09:eda54e4]


Ignore:
Files:
1 added
24 edited

Legend:

Unmodified
Added
Removed
  • bitlbee.c

    rd444c09 reda54e4  
    7070#ifdef IPV6
    7171        memset( &listen_addr6, 0, sizeof( listen_addr6 ) );
     72        memset( &listen_addr, 0, sizeof( listen_addr ) );
    7273        listen_addr6.sin6_family = AF_INET6;
    7374        listen_addr6.sin6_port = htons( global.conf->port );
     
    7778                use_ipv6 = 0;
    7879#endif
    79                 memset( &listen_addr, 0, sizeof( listen_addr ) );
    8080                listen_addr.sin_family = AF_INET;
    8181                listen_addr.sin_port = htons( global.conf->port );
     
    125125                        exit( 0 );
    126126               
    127                 chdir( "/" );
     127//              chdir( "/" );
    128128               
    129129                /* Sometimes std* are already closed (for example when we're in a RESTARTed
  • doc/user-guide/misc.xml

    rd444c09 reda54e4  
    8181
    8282<para>
     83Some protocols (like Jabber) also support named groupchats. BitlBee now supports these too. You can use the <emphasis>join_chat</emphasis> command to join them. See <emphasis>help join_chat</emphasis> for more information.
     84</para>
     85
     86<para>
    8387This is all you'll probably need to know. If you have any problems, please read <emphasis>help groupchats3</emphasis>.
    8488</para>
  • irc.c

    rd444c09 reda54e4  
    659659                }
    660660        }
    661         else if( ( c = chat_by_channel( channel ) ) )
     661        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    662662        {
    663663                GList *l;
     
    812812        else
    813813        {
    814                 struct groupchat *c = chat_by_channel( channel );
     814                struct groupchat *c = irc_chat_by_channel( irc, channel );
    815815               
    816816                if( c )
     
    950950        if( *nick == '#' || *nick == '&' )
    951951        {
    952                 if( !( c = chat_by_channel( nick ) ) )
     952                if( !( c = irc_chat_by_channel( irc, nick ) ) )
    953953                {
    954954                        irc_reply( irc, 403, "%s :Channel does not exist", nick );
     
    12161216        return TRUE;
    12171217}
     1218
     1219struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel )
     1220{
     1221        struct groupchat *c;
     1222        account_t *a;
     1223       
     1224        /* This finds the connection which has a conversation which belongs to this channel */
     1225        for( a = irc->accounts; a; a = a->next )
     1226        {
     1227                if( a->ic == NULL )
     1228                        continue;
     1229               
     1230                c = a->ic->groupchats;
     1231                while( c )
     1232                {
     1233                        if( c->channel && g_strcasecmp( c->channel, channel ) == 0 )
     1234                                return c;
     1235                       
     1236                        c = c->next;
     1237                }
     1238        }
     1239       
     1240        return NULL;
     1241}
  • irc.h

    rd444c09 reda54e4  
    140140
    141141void buddy_send_handler( irc_t *irc, user_t *u, char *msg, int flags );
     142struct groupchat *irc_chat_by_channel( irc_t *irc, char *channel );
    142143
    143144#endif
  • irc_commands.c

    rd444c09 reda54e4  
    144144                irc_join( irc, u, irc->channel );
    145145        }
    146         else if( ( c = chat_by_channel( cmd[1] ) ) )
     146        else if( ( c = irc_chat_by_channel( irc, cmd[1] ) ) )
    147147        {
    148148                user_t *u = user_find( irc, irc->nick );
     
    201201{
    202202        char *nick = cmd[1], *channel = cmd[2];
    203         struct groupchat *c = chat_by_channel( channel );
     203        struct groupchat *c = irc_chat_by_channel( irc, channel );
    204204        user_t *u = user_find( irc, nick );
    205205       
     
    287287                        u = u->next;
    288288                }
    289         else if( ( c = chat_by_channel( channel ) ) )
     289        else if( ( c = irc_chat_by_channel( irc, channel ) ) )
    290290                for( l = c->in_room; l; l = l->next )
    291291                {
  • nick.c

    rd444c09 reda54e4  
    5757        static char nick[MAX_NICK_LENGTH+1];
    5858        char *store_handle, *found_nick;
    59         int inf_protection = 256;
    6059       
    6160        memset( nick, 0, MAX_NICK_LENGTH + 1 );
     
    8281        }
    8382        g_free( store_handle );
     83       
     84        /* Make sure the nick doesn't collide with an existing one by adding
     85           underscores and that kind of stuff, if necessary. */
     86        nick_dedupe( acc, handle, nick );
     87       
     88        return nick;
     89}
     90
     91void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] )
     92{
     93        int inf_protection = 256;
    8494       
    8595        /* Now, find out if the nick is already in use at the moment, and make
     
    120130                }
    121131        }
    122        
    123         return nick;
    124132}
    125133
  • nick.h

    rd444c09 reda54e4  
    2626void nick_set( account_t *acc, const char *handle, const char *nick );
    2727char *nick_get( account_t *acc, const char *handle );
     28void nick_dedupe( account_t *acc, const char *handle, char nick[MAX_NICK_LENGTH+1] );
    2829int nick_saved( account_t *acc, const char *handle );
    2930void nick_del( account_t *acc, const char *handle );
  • protocols/jabber/Makefile

    rd444c09 reda54e4  
    1010
    1111# [SH] Program variables
    12 objects = io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o
     12objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o sasl.o xmltree.o
    1313
    1414CFLAGS += -Wall
  • protocols/jabber/io.c

    rd444c09 reda54e4  
    4444        struct jabber_data *jd = ic->proto_data;
    4545        gboolean ret;
     46       
     47        if( jd->flags & JFLAG_XMLCONSOLE )
     48        {
     49                char *msg;
     50               
     51                msg = g_strdup_printf( "TX: %s", buf );
     52                imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 );
     53                g_free( msg );
     54        }
    4655       
    4756        if( jd->tx_len == 0 )
     
    427436{
    428437        struct im_connection *ic = data;
    429         struct xt_node *c;
    430         char *s, *type = NULL, *text = NULL;
    431438        int allow_reconnect = TRUE;
    432        
    433         for( c = node->children; c; c = c->next )
    434         {
    435                 if( !( s = xt_find_attr( c, "xmlns" ) ) ||
    436                     strcmp( s, XMLNS_STREAM_ERROR ) != 0 )
    437                         continue;
    438                
    439                 if( strcmp( c->name, "text" ) != 0 )
    440                 {
    441                         type = c->name;
    442                 }
    443                 /* Only use the text if it doesn't have an xml:lang attribute,
    444                    if it's empty or if it's set to something English. */
    445                 else if( !( s = xt_find_attr( c, "xml:lang" ) ) ||
    446                          !*s || strncmp( s, "en", 2 ) == 0 )
    447                 {
    448                         text = c->text;
    449                 }
    450         }
     439        struct jabber_error *err;
     440       
     441        err = jabber_error_parse( node, XMLNS_STREAM_ERROR );
    451442       
    452443        /* Tssk... */
    453         if( type == NULL )
     444        if( err->code == NULL )
    454445        {
    455446                imcb_error( ic, "Unknown stream error reported by server" );
    456447                imc_logout( ic, allow_reconnect );
     448                jabber_error_free( err );
    457449                return XT_ABORT;
    458450        }
     
    461453           should turn off auto-reconnect to make sure we won't get some nasty
    462454           infinite loop! */
    463         if( strcmp( type, "conflict" ) == 0 )
     455        if( strcmp( err->code, "conflict" ) == 0 )
    464456        {
    465457                imcb_error( ic, "Account and resource used from a different location" );
     
    468460        else
    469461        {
    470                 imcb_error( ic, "Stream error: %s%s%s", type, text ? ": " : "", text ? text : "" );
    471         }
    472        
     462                imcb_error( ic, "Stream error: %s%s%s", err->code, err->text ? ": " : "",
     463                            err->text ? err->text : "" );
     464        }
     465       
     466        jabber_error_free( err );
    473467        imc_logout( ic, allow_reconnect );
    474468       
     
    484478}
    485479
     480static xt_status jabber_xmlconsole( struct xt_node *node, gpointer data )
     481{
     482        struct im_connection *ic = data;
     483        struct jabber_data *jd = ic->proto_data;
     484       
     485        if( jd->flags & JFLAG_XMLCONSOLE )
     486        {
     487                char *msg, *pkt;
     488               
     489                pkt = xt_to_string( node );
     490                msg = g_strdup_printf( "RX: %s", pkt );
     491                imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 );
     492                g_free( msg );
     493                g_free( pkt );
     494        }
     495       
     496        return XT_NEXT;
     497}
     498
    486499static const struct xt_handler_entry jabber_handlers[] = {
     500        { NULL,                 "stream:stream",        jabber_xmlconsole },
    487501        { "stream:stream",      "<root>",               jabber_end_of_stream },
    488502        { "message",            "stream:stream",        jabber_pkt_message },
  • protocols/jabber/iq.c

    rd444c09 reda54e4  
    9999                else if( strcmp( s, XMLNS_DISCOVER ) == 0 )
    100100                {
     101                        const char *features[] = { XMLNS_VERSION,
     102                                                   XMLNS_TIME,
     103                                                   XMLNS_CHATSTATES,
     104                                                   XMLNS_MUC,
     105                                                   NULL };
     106                        const char **f;
     107                       
    101108                        c = xt_new_node( "identity", NULL, NULL );
    102109                        xt_add_attr( c, "category", "client" );
     
    105112                        xt_add_child( reply, c );
    106113                       
    107                         c = xt_new_node( "feature", NULL, NULL );
    108                         xt_add_attr( c, "var", XMLNS_VERSION );
    109                         xt_add_child( reply, c );
    110                        
    111                         c = xt_new_node( "feature", NULL, NULL );
    112                         xt_add_attr( c, "var", XMLNS_TIME );
    113                         xt_add_child( reply, c );
    114                        
    115                         c = xt_new_node( "feature", NULL, NULL );
    116                         xt_add_attr( c, "var", XMLNS_CHATSTATES );
    117                         xt_add_child( reply, c );
    118                        
    119                         /* Later this can be useful to announce things like
    120                            MUC support. */
     114                        for( f = features; *f; f ++ )
     115                        {
     116                                c = xt_new_node( "feature", NULL, NULL );
     117                                xt_add_attr( c, "var", *f );
     118                                xt_add_child( reply, c );
     119                        }
    121120                }
    122121                else
     
    373372                                                                   group->text : NULL );
    374373                               
    375                                 imcb_rename_buddy( ic, jid, name );
     374                                if( name )
     375                                        imcb_rename_buddy( ic, jid, name );
    376376                        }
    377377                        else if( strcmp( sub, "remove" ) == 0 )
    378378                        {
    379                                 /* Don't have any API call for this yet! So let's
    380                                    just try to handle this as well as we can. */
    381379                                jabber_buddy_remove_bare( ic, jid );
    382                                 imcb_buddy_status( ic, jid, 0, NULL, NULL );
    383                                 /* FIXME! */
     380                                imcb_remove_buddy( ic, jid, NULL );
    384381                        }
    385382                }
  • protocols/jabber/jabber.c

    rd444c09 reda54e4  
    197197        jabber_end_stream( ic );
    198198       
     199        while( ic->groupchats )
     200                jabber_chat_free( ic->groupchats );
     201       
    199202        if( jd->r_inpa >= 0 )
    200203                b_event_remove( jd->r_inpa );
     
    224227        struct jabber_buddy *bud;
    225228        struct xt_node *node;
     229        char *s;
    226230        int st;
    227231       
    228         bud = jabber_buddy_by_jid( ic, who, 0 );
     232        if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 )
     233                return jabber_write( ic, message, strlen( message ) );
     234       
     235        if( ( s = strchr( who, '=' ) ) && jabber_chat_by_name( ic, s + 1 ) )
     236                bud = jabber_buddy_by_ext_jid( ic, who, 0 );
     237        else
     238                bud = jabber_buddy_by_jid( ic, who, 0 );
    229239       
    230240        node = xt_new_node( "body", message, NULL );
     
    311321static void jabber_add_buddy( struct im_connection *ic, char *who, char *group )
    312322{
     323        struct jabber_data *jd = ic->proto_data;
     324       
     325        if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 )
     326        {
     327                jd->flags |= JFLAG_XMLCONSOLE;
     328                imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL );
     329                return;
     330        }
     331       
    313332        if( jabber_add_to_roster( ic, who, NULL ) )
    314333                presence_send_request( ic, who, "subscribe" );
     
    317336static void jabber_remove_buddy( struct im_connection *ic, char *who, char *group )
    318337{
     338        struct jabber_data *jd = ic->proto_data;
     339       
     340        if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 )
     341        {
     342                jd->flags &= ~JFLAG_XMLCONSOLE;
     343                /* Not necessary for now. And for now the code isn't too
     344                   happy if the buddy is completely gone right after calling
     345                   this function already.
     346                imcb_remove_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL );
     347                */
     348                return;
     349        }
     350       
    319351        /* We should always do this part. Clean up our administration a little bit. */
    320352        jabber_buddy_remove_bare( ic, who );
     
    322354        if( jabber_remove_from_roster( ic, who ) )
    323355                presence_send_request( ic, who, "unsubscribe" );
     356}
     357
     358static struct groupchat *jabber_chat_join_( struct im_connection *ic, char *room, char *nick, char *password )
     359{
     360        if( strchr( room, '@' ) == NULL )
     361                imcb_error( ic, "Invalid room name: %s", room );
     362        else if( jabber_chat_by_name( ic, room ) )
     363                imcb_error( ic, "Already present in chat `%s'", room );
     364        else
     365                return jabber_chat_join( ic, room, nick, password );
     366       
     367        return NULL;
     368}
     369
     370static void jabber_chat_msg_( struct groupchat *c, char *message, int flags )
     371{
     372        if( c && message )
     373                jabber_chat_msg( c, message, flags );
     374}
     375
     376static void jabber_chat_leave_( struct groupchat *c )
     377{
     378        if( c )
     379                jabber_chat_leave( c, NULL );
    324380}
    325381
     
    388444        ret->buddy_msg = jabber_buddy_msg;
    389445        ret->away_states = jabber_away_states;
    390 //      ret->get_status_string = jabber_get_status_string;
    391446        ret->set_away = jabber_set_away;
    392447//      ret->set_info = jabber_set_info;
     
    394449        ret->add_buddy = jabber_add_buddy;
    395450        ret->remove_buddy = jabber_remove_buddy;
    396 //      ret->chat_msg = jabber_chat_msg;
     451        ret->chat_msg = jabber_chat_msg_;
    397452//      ret->chat_invite = jabber_chat_invite;
    398 //      ret->chat_leave = jabber_chat_leave;
    399 //      ret->chat_open = jabber_chat_open;
     453        ret->chat_leave = jabber_chat_leave_;
     454        ret->chat_join = jabber_chat_join_;
    400455        ret->keepalive = jabber_keepalive;
    401456        ret->send_typing = jabber_send_typing;
  • protocols/jabber/jabber.h

    rd444c09 reda54e4  
    3232typedef enum
    3333{
    34         JFLAG_STREAM_STARTED = 1,       /* Set when we detected the beginning of the stream
     34        JFLAG_STREAM_STARTED = 1,       /* Set when we detected the beginning of the stream
    3535                                           and want to do auth. */
    36         JFLAG_AUTHENTICATED = 2,        /* Set when we're successfully authenticatd. */
    37         JFLAG_STREAM_RESTART = 4,       /* Set when we want to restart the stream (after
     36        JFLAG_AUTHENTICATED = 2,        /* Set when we're successfully authenticatd. */
     37        JFLAG_STREAM_RESTART = 4,       /* Set when we want to restart the stream (after
    3838                                           SASL or TLS). */
    39         JFLAG_WAIT_SESSION = 8,         /* Set if we sent a <session> tag and need a reply
     39        JFLAG_WAIT_SESSION = 8,         /* Set if we sent a <session> tag and need a reply
    4040                                           before we continue. */
    41         JFLAG_WAIT_BIND = 16,           /* ... for <bind> tag. */
    42         JFLAG_WANT_TYPING = 32,         /* Set if we ever sent a typing notification, this
     41        JFLAG_WAIT_BIND = 16,           /* ... for <bind> tag. */
     42        JFLAG_WANT_TYPING = 32,         /* Set if we ever sent a typing notification, this
    4343                                           activates all XEP-85 related code. */
     44        JFLAG_XMLCONSOLE = 64,          /* If the user added an xmlconsole buddy. */
    4445} jabber_flags_t;
    4546
     
    5051        JBFLAG_DOES_XEP85 = 2,          /* Set this when the resource seems to support
    5152                                           XEP85 (typing notification shite). */
     53        JBFLAG_IS_CHATROOM = 4,         /* It's convenient to use this JID thingy for
     54                                           groupchat state info too. */
     55        JBFLAG_IS_ANONYMOUS = 8,        /* For anonymous chatrooms, when we don't have
     56                                           have a real JID. */
    5257} jabber_buddy_flags_t;
    53 
    54 #define JABBER_PORT_DEFAULT "5222"
    55 #define JABBER_PORT_MIN 5220
    56 #define JABBER_PORT_MAX 5229
    5758
    5859struct jabber_data
     
    101102        char *resource;
    102103       
     104        char *ext_jid; /* The JID to use in BitlBee. The real JID if possible, */
     105                       /* otherwise something similar to the conference JID. */
     106       
    103107        int priority;
    104108        struct jabber_away_state *away_state;
     
    110114        struct jabber_buddy *next;
    111115};
     116
     117struct jabber_chat
     118{
     119        int flags;
     120        char *name;
     121        char *my_full_jid; /* Separate copy because of case sensitivity. */
     122        struct jabber_buddy *me;
     123};
     124
     125#define JABBER_XMLCONSOLE_HANDLE "xmlconsole"
     126
     127#define JABBER_PORT_DEFAULT "5222"
     128#define JABBER_PORT_MIN 5220
     129#define JABBER_PORT_MAX 5229
    112130
    113131/* Prefixes to use for packet IDs (mainly for IQ packets ATM). Usually the
     
    132150#define XMLNS_TIME         "jabber:iq:time"                     /* XEP-0090 */
    133151#define XMLNS_VCARD        "vcard-temp"                         /* XEP-0054 */
     152#define XMLNS_DELAY        "jabber:x:delay"                     /* XEP-0091 */
    134153#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"  /* 0085 */
    135154#define XMLNS_DISCOVER     "http://jabber.org/protocol/disco#info"  /* 0030 */
     155#define XMLNS_MUC          "http://jabber.org/protocol/muc"     /* XEP-0045 */
     156#define XMLNS_MUC_USER     "http://jabber.org/protocol/muc#user"/* XEP-0045 */
    136157
    137158/* iq.c */
     
    164185const struct jabber_away_state *jabber_away_state_by_name( char *name );
    165186void jabber_buddy_ask( struct im_connection *ic, char *handle );
    166 char *jabber_normalize( char *orig );
     187char *jabber_normalize( const char *orig );
    167188
    168189typedef enum
    169190{
    170191        GET_BUDDY_CREAT = 1,    /* Try to create it, if necessary. */
    171         GET_BUDDY_EXACT = 2,    /* Get an exact message (only makes sense with bare JIDs). */
     192        GET_BUDDY_EXACT = 2,    /* Get an exact match (only makes sense with bare JIDs). */
     193        GET_BUDDY_FIRST = 4,    /* No selection, simply get the first resource for this JID. */
    172194} get_buddy_flags_t;
     195
     196struct jabber_error
     197{
     198        char *code, *text, *type;
     199};
    173200
    174201struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid );
    175202struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags );
     203struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags );
    176204int jabber_buddy_remove( struct im_connection *ic, char *full_jid );
    177205int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid );
     206struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name );
     207time_t jabber_get_timestamp( struct xt_node *xt );
     208struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns );
     209void jabber_error_free( struct jabber_error *err );
    178210
    179211extern const struct jabber_away_state jabber_away_state_list[];
     
    193225gboolean sasl_supported( struct im_connection *ic );
    194226
     227/* conference.c */
     228struct groupchat *jabber_chat_join( struct im_connection *ic, char *room, char *nick, char *password );
     229void jabber_chat_free( struct groupchat *c );
     230int jabber_chat_msg( struct groupchat *ic, char *message, int flags );
     231int jabber_chat_leave( struct groupchat *c, const char *reason );
     232void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );
     233void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node );
     234
    195235#endif
  • protocols/jabber/jabber_util.c

    rd444c09 reda54e4  
    4848                   call p_s_u() now to send the new prio setting, it would
    4949                   send the old setting because the set->value gets changed
    50                    when the eval returns a non-NULL value.
     50                   after the (this) eval returns a non-NULL value.
    5151                   
    5252                   So now I can choose between implementing post-set
     
    129129/* Cache a node/packet for later use. Mainly useful for IQ packets if you need
    130130   them when you receive the response. Use this BEFORE sending the packet so
    131    it'll get a new id= tag, and do NOT free() the packet after writing it! */
     131   it'll get a new id= tag, and do NOT free() the packet after sending it! */
    132132void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func )
    133133{
     
    252252
    253253/* Returns a new string. Don't leak it! */
    254 char *jabber_normalize( char *orig )
     254char *jabber_normalize( const char *orig )
    255255{
    256256        int len, i;
     
    320320        else
    321321        {
     322                /* Keep in mind that full_jid currently isn't really
     323                   a full JID... */
    322324                new->bare_jid = g_strdup( full_jid );
    323325                g_hash_table_insert( jd->buddies, new->bare_jid, new );
     
    333335        {
    334336                /* Let's waste some more bytes of RAM instead of to make
    335                    memory management a total disaster here.. */
     337                   memory management a total disaster here. And it saves
     338                   me one g_free() call in this function. :-P */
    336339                new->full_jid = full_jid;
    337340        }
     
    353356        if( ( s = strchr( jid, '/' ) ) )
    354357        {
     358                int none_found = 0;
     359               
    355360                *s = 0;
    356361                if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) )
     
    370375                        }
    371376                }
    372                
    373                 if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && imcb_find_buddy( ic, jid ) )
     377                else
     378                {
     379                        /* This hack is there to make sure that O_CREAT will
     380                           work if there's already another resouce present
     381                           for this JID, even if it's an unknown buddy. This
     382                           is done to handle conferences properly. */
     383                        none_found = 1;
     384                }
     385               
     386                if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && ( imcb_find_buddy( ic, jid ) || !none_found ) )
    374387                {
    375388                        *s = '/';
     
    418431}
    419432
     433/* I'm keeping a separate ext_jid attribute to save a JID that makes sense
     434   to export to BitlBee. This is mainly for groupchats right now. It's
     435   a bit of a hack, but I just think having the user nickname in the hostname
     436   part of the hostmask doesn't look nice on IRC. Normally you can convert
     437   a normal JID to ext_jid by swapping the part before and after the / and
     438   replacing the / with a =. But there should be some stripping (@s are
     439   allowed in Jabber nicks...). */
     440struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags )
     441{
     442        struct jabber_buddy *bud;
     443        char *s, *jid;
     444       
     445        jid = jabber_normalize( jid_ );
     446       
     447        if( ( s = strchr( jid, '=' ) ) == NULL )
     448                return NULL;
     449       
     450        for( bud = jabber_buddy_by_jid( ic, s + 1, GET_BUDDY_FIRST ); bud; bud = bud->next )
     451        {
     452                /* Hmmm, could happen if not all people in the chat are anonymized? */
     453                if( bud->ext_jid == NULL )
     454                        continue;
     455               
     456                if( strcmp( bud->ext_jid, jid ) == 0 )
     457                        break;
     458        }
     459       
     460        g_free( jid );
     461       
     462        return bud;
     463}
     464
    420465/* Remove one specific full JID from our list. Use this when a buddy goes
    421466   off-line (because (s)he can still be online from a different location.
     
    441486                        g_hash_table_remove( jd->buddies, bud->bare_jid );
    442487                        g_free( bud->bare_jid );
     488                        g_free( bud->ext_jid );
    443489                        g_free( bud->full_jid );
    444490                        g_free( bud->away_message );
     
    473519                                        g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next );
    474520                               
     521                                g_free( bi->ext_jid );
    475522                                g_free( bi->full_jid );
    476523                                g_free( bi->away_message );
     
    495542   specified bare JID. Use this when removing someone from the contact
    496543   list, for example. */
    497 int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid_ )
     544int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid )
    498545{
    499546        struct jabber_data *jd = ic->proto_data;
    500547        struct jabber_buddy *bud, *next;
    501         char *bare_jid;
    502        
    503         if( strchr( bare_jid_, '/' ) )
     548       
     549        if( strchr( bare_jid, '/' ) )
    504550                return 0;
    505551       
    506         bare_jid = jabber_normalize( bare_jid_ );
    507        
    508         if( ( bud = g_hash_table_lookup( jd->buddies, bare_jid ) ) )
     552        if( ( bud = jabber_buddy_by_jid( ic, bare_jid, GET_BUDDY_FIRST ) ) )
    509553        {
    510554                /* Most important: Remove the hash reference. We don't know
    511555                   this buddy anymore. */
    512556                g_hash_table_remove( jd->buddies, bud->bare_jid );
     557                g_free( bud->bare_jid );
    513558               
    514559                /* Deallocate the linked list of resources. */
    515560                while( bud )
    516561                {
     562                        /* ext_jid && anonymous means that this buddy is
     563                           specific to one groupchat (the one we're
     564                           currently cleaning up) so it can be deleted
     565                           completely. */
     566                        if( bud->ext_jid && bud->flags & JBFLAG_IS_ANONYMOUS )
     567                                imcb_remove_buddy( ic, bud->ext_jid, NULL );
     568                       
    517569                        next = bud->next;
     570                        g_free( bud->ext_jid );
    518571                        g_free( bud->full_jid );
    519572                        g_free( bud->away_message );
     
    522575                }
    523576               
    524                 g_free( bare_jid );
    525577                return 1;
    526578        }
    527579        else
    528580        {
    529                 g_free( bare_jid );
    530581                return 0;
    531582        }
    532583}
     584
     585struct groupchat *jabber_chat_by_name( struct im_connection *ic, const char *name )
     586{
     587        char *normalized = jabber_normalize( name );
     588        struct groupchat *ret;
     589        struct jabber_chat *jc;
     590       
     591        for( ret = ic->groupchats; ret; ret = ret->next )
     592        {
     593                jc = ret->data;
     594                if( strcmp( normalized, jc->name ) == 0 )
     595                        break;
     596        }
     597        g_free( normalized );
     598       
     599        return ret;
     600}
     601
     602time_t jabber_get_timestamp( struct xt_node *xt )
     603{
     604        struct tm tp, utc;
     605        struct xt_node *c;
     606        time_t res, tres;
     607        char *s = NULL;
     608       
     609        for( c = xt->children; ( c = xt_find_node( c, "x" ) ); c = c->next )
     610        {
     611                if( ( s = xt_find_attr( c, "xmlns" ) ) && strcmp( s, XMLNS_DELAY ) == 0 )
     612                        break;
     613        }
     614       
     615        if( !c || !( s = xt_find_attr( c, "stamp" ) ) )
     616                return 0;
     617       
     618        memset( &tp, 0, sizeof( tp ) );
     619        if( sscanf( s, "%4d%2d%2dT%2d:%2d:%2d", &tp.tm_year, &tp.tm_mon, &tp.tm_mday,
     620                                                &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) != 6 )
     621                return 0;
     622       
     623        tp.tm_year -= 1900;
     624        tp.tm_mon --;
     625        tp.tm_isdst = -1; /* GRRRRRRRRRRR */
     626       
     627        res = mktime( &tp );
     628        /* Problem is, mktime() just gave us the GMT timestamp for the
     629           given local time... While the given time WAS NOT local. So
     630           we should fix this now.
     631       
     632           Now I could choose between messing with environment variables
     633           (kludgy) or using timegm() (not portable)... Or doing the
     634           following, which I actually prefer... */
     635        gmtime_r( &res, &utc );
     636        utc.tm_isdst = -1; /* Once more: GRRRRRRRRRRRRRRRRRR!!! */
     637        if( utc.tm_hour == tp.tm_hour && utc.tm_min == tp.tm_min )
     638                /* Sweet! We're in UTC right now... */
     639                return res;
     640       
     641        tres = mktime( &utc );
     642        res += res - tres;
     643       
     644        /* Yes, this is a hack. And it will go wrong around DST changes.
     645           BUT this is more likely to be threadsafe than messing with
     646           environment variables, and possibly more portable... */
     647       
     648        return res;
     649}
     650
     651struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns )
     652{
     653        struct jabber_error *err = g_new0( struct jabber_error, 1 );
     654        struct xt_node *c;
     655        char *s;
     656       
     657        err->type = xt_find_attr( node, "type" );
     658       
     659        for( c = node->children; c; c = c->next )
     660        {
     661                if( !( s = xt_find_attr( c, "xmlns" ) ) ||
     662                    strcmp( s, xmlns ) != 0 )
     663                        continue;
     664               
     665                if( strcmp( c->name, "text" ) != 0 )
     666                {
     667                        err->code = c->name;
     668                }
     669                /* Only use the text if it doesn't have an xml:lang attribute,
     670                   if it's empty or if it's set to something English. */
     671                else if( !( s = xt_find_attr( c, "xml:lang" ) ) ||
     672                         !*s || strncmp( s, "en", 2 ) == 0 )
     673                {
     674                        err->text = c->text;
     675                }
     676        }
     677       
     678        return err;
     679}
     680
     681void jabber_error_free( struct jabber_error *err )
     682{
     683        g_free( err );
     684}
  • protocols/jabber/message.c

    rd444c09 reda54e4  
    3030        char *type = xt_find_attr( node, "type" );
    3131        struct xt_node *body = xt_find_node( node->children, "body" ), *c;
     32        struct jabber_buddy *bud = NULL;
    3233        char *s;
     34       
     35        if( !from )
     36                return XT_HANDLED; /* Consider this packet corrupted. */
     37       
     38        bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT );
    3339       
    3440        if( type && strcmp( type, "error" ) == 0 )
     
    3642                /* Handle type=error packet. */
    3743        }
    38         else if( type && strcmp( type, "groupchat" ) == 0 )
     44        else if( type && from && strcmp( type, "groupchat" ) == 0 )
    3945        {
    40                 /* TODO! */
     46                jabber_chat_pkt_message( ic, bud, node );
    4147        }
    4248        else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */
    4349        {
    44                 struct jabber_buddy *bud = NULL;
    4550                GString *fullmsg = g_string_new( "" );
    4651               
    4752                if( ( s = strchr( from, '/' ) ) )
    4853                {
    49                         if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) )
     54                        if( bud )
     55                        {
    5056                                bud->last_act = time( NULL );
     57                                from = bud->ext_jid ? : bud->bare_jid;
     58                        }
    5159                        else
    5260                                *s = 0; /* We need to generate a bare JID now. */
     
    7684               
    7785                if( fullmsg->len > 0 )
    78                         imcb_buddy_msg( ic, bud ? bud->bare_jid : from, fullmsg->str, 0, 0 );
     86                        imcb_buddy_msg( ic, from, fullmsg->str,
     87                                        0, jabber_get_timestamp( node ) );
    7988               
    8089                g_string_free( fullmsg, TRUE );
    8190               
    8291                /* Handling of incoming typing notifications. */
    83                 if( xt_find_node( node->children, "composing" ) )
     92                if( bud == NULL )
     93                {
     94                        /* Can't handle these for unknown buddies. */
     95                }
     96                else if( xt_find_node( node->children, "composing" ) )
    8497                {
    8598                        bud->flags |= JBFLAG_DOES_XEP85;
    86                         imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_TYPING );
     99                        imcb_buddy_typing( ic, from, OPT_TYPING );
    87100                }
    88101                /* No need to send a "stopped typing" signal when there's a message. */
     
    90103                {
    91104                        bud->flags |= JBFLAG_DOES_XEP85;
    92                         imcb_buddy_typing( ic, bud ? bud->bare_jid : from, 0 );
     105                        imcb_buddy_typing( ic, from, 0 );
    93106                }
    94107                else if( xt_find_node( node->children, "paused" ) )
    95108                {
    96109                        bud->flags |= JBFLAG_DOES_XEP85;
    97                         imcb_buddy_typing( ic, bud ? bud->bare_jid : from, OPT_THINKING );
     110                        imcb_buddy_typing( ic, from, OPT_THINKING );
    98111                }
    99112               
  • protocols/jabber/presence.c

    rd444c09 reda54e4  
    3131        struct xt_node *c;
    3232        struct jabber_buddy *bud;
     33        int is_chat = 0, is_away = 0;
    3334        char *s;
    3435       
     
    3637                return XT_HANDLED;
    3738       
     39        if( ( s = strchr( from, '/' ) ) )
     40        {
     41                *s = 0;
     42                if( jabber_chat_by_name( ic, from ) )
     43                        is_chat = 1;
     44                *s = '/';
     45        }
     46       
    3847        if( type == NULL )
    3948        {
    40                 int is_away = 0;
    41                
    4249                if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) )
    4350                {
     
    7279                        bud->priority = 0;
    7380               
    74                 if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) )
     81                if( is_chat )
     82                        jabber_chat_pkt_presence( ic, bud, node );
     83                else if( bud == jabber_buddy_by_jid( ic, bud->bare_jid, 0 ) )
    7584                        imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
    7685                                           ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
     
    7988        else if( strcmp( type, "unavailable" ) == 0 )
    8089        {
    81                 if( jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) == NULL )
     90                if( ( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ) ) == NULL )
    8291                {
    8392                        if( set_getbool( &ic->irc->set, "debug" ) )
     
    8695                }
    8796               
     97                /* Handle this before we delete the JID. */
     98                if( is_chat )
     99                {
     100                        jabber_chat_pkt_presence( ic, bud, node );
     101                }
     102               
    88103                jabber_buddy_remove( ic, from );
    89104               
    90                 if( ( s = strchr( from, '/' ) ) )
     105                if( is_chat )
     106                {
     107                        /* Nothing else to do for now? */
     108                }
     109                else if( ( s = strchr( from, '/' ) ) )
    91110                {
    92111                        *s = 0;
    93112               
    94                         /* Only count this as offline if there's no other resource
    95                            available anymore. */
    96                         if( jabber_buddy_by_jid( ic, from, 0 ) == NULL )
     113                        /* If another resource is still available, send its presence
     114                           information. */
     115                        if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) )
     116                        {
     117                                if( bud->away_state && ( *bud->away_state->code == 0 ||
     118                                    strcmp( bud->away_state->code, "chat" ) == 0 ) )
     119                                        is_away = OPT_AWAY;
     120                               
     121                                imcb_buddy_status( ic, bud->bare_jid, OPT_LOGGED_IN | is_away,
     122                                                   ( is_away && bud->away_state ) ? bud->away_state->full_name : NULL,
     123                                                   bud->away_message );
     124                        }
     125                        else
     126                        {
     127                                /* Otherwise, count him/her as offline now. */
    97128                                imcb_buddy_status( ic, from, 0, NULL, NULL );
     129                        }
    98130                       
    99131                        *s = '/';
     
    126158        else if( strcmp( type, "error" ) == 0 )
    127159        {
    128                 /* What to do with it? */
     160                struct jabber_error *err;
     161               
     162                if( ( c = xt_find_node( node->children, "error" ) ) )
     163                {
     164                        err = jabber_error_parse( c, XMLNS_STANZA_ERROR );
     165                        imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name,
     166                                    err->code, err->text ? ": " : "",
     167                                    err->text ? err->text : "" );
     168                        jabber_error_free( err );
     169                }
     170                /* What else to do with it? */
    129171        }
    130172        else
     
    145187        char *show = jd->away_state->code;
    146188        char *status = jd->away_message;
     189        struct groupchat *c;
    147190        int st;
    148191       
     
    156199        st = jabber_write_packet( ic, node );
    157200       
     201        /* Have to send this update to all groupchats too, the server won't
     202           do this automatically. */
     203        for( c = ic->groupchats; c && st; c = c->next )
     204        {
     205                struct jabber_chat *jc = c->data;
     206               
     207                xt_add_attr( node, "to", jc->my_full_jid );
     208                st = jabber_write_packet( ic, node );
     209        }
     210       
    158211        xt_free_node( node );
    159212        return st;
  • protocols/jabber/xmltree.c

    rd444c09 reda54e4  
    442442   list, not the node itself! The reason you have to do this by hand: So
    443443   that you can also use this function as a find-next. */
    444 struct xt_node *xt_find_node( struct xt_node *node, char *name )
     444struct xt_node *xt_find_node( struct xt_node *node, const char *name )
    445445{
    446446        while( node )
     
    455455}
    456456
    457 char *xt_find_attr( struct xt_node *node, char *key )
     457char *xt_find_attr( struct xt_node *node, const char *key )
    458458{
    459459        int i;
     
    524524}
    525525
    526 void xt_add_attr( struct xt_node *node, char *key, char *value )
     526void xt_add_attr( struct xt_node *node, const char *key, const char *value )
    527527{
    528528        int i;
     
    551551}
    552552
    553 int xt_remove_attr( struct xt_node *node, char *key )
     553int xt_remove_attr( struct xt_node *node, const char *key )
    554554{
    555555        int i, last;
  • protocols/jabber/xmltree.h

    rd444c09 reda54e4  
    8787void xt_free_node( struct xt_node *node );
    8888void xt_free( struct xt_parser *xt );
    89 struct xt_node *xt_find_node( struct xt_node *node, char *name );
    90 char *xt_find_attr( struct xt_node *node, char *key );
     89struct xt_node *xt_find_node( struct xt_node *node, const char *name );
     90char *xt_find_attr( struct xt_node *node, const char *key );
    9191
    9292struct xt_node *xt_new_node( char *name, char *text, struct xt_node *children );
    9393void xt_add_child( struct xt_node *parent, struct xt_node *child );
    94 void xt_add_attr( struct xt_node *node, char *key, char *value );
    95 int xt_remove_attr( struct xt_node *node, char *key );
     94void xt_add_attr( struct xt_node *node, const char *key, const char *value );
     95int xt_remove_attr( struct xt_node *node, const char *key );
    9696
    9797#endif
  • protocols/msn/sb.c

    rd444c09 reda54e4  
    232232        if( sb->chat )
    233233        {
    234                 imcb_chat_removed( sb->chat );
     234                imcb_chat_free( sb->chat );
    235235        }
    236236       
  • protocols/nogaim.c

    rd444c09 reda54e4  
    9999}
    100100
    101  
    102101struct prpl *find_protocol(const char *name)
    103102{
     
    289288{
    290289        irc_t *irc = ic->irc;
    291         user_t *t, *u = irc->users;
     290        user_t *t, *u;
    292291        account_t *a;
    293292       
     
    306305        b_event_remove( ic->inpa );
    307306       
     307        u = irc->users;
    308308        while( u )
    309309        {
     
    428428{
    429429        user_t *u = user_findhandle( ic, handle );
    430         char *s, newnick[MAX_NICK_LENGTH+1];
    431430       
    432431        if( !u || !realname ) return;
     
    440439                if( ( ic->flags & OPT_LOGGED_IN ) && set_getbool( &ic->irc->set, "display_namechanges" ) )
    441440                        imcb_log( ic, "User `%s' changed name to `%s'", u->nick, u->realname );
    442                
    443                 if( !u->online && !nick_saved( ic->acc, handle ) )
    444                 {
    445                         /* Detect numeric handles: */
    446                         for( s = u->user; isdigit( *s ); s++ );
     441        }
     442}
     443
     444void imcb_remove_buddy( struct im_connection *ic, char *handle, char *group )
     445{
     446        user_t *u;
     447       
     448        if( ( u = user_findhandle( ic, handle ) ) )
     449                user_del( ic->irc, u->nick );
     450}
     451
     452/* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM
     453   modules to suggest a nickname for a handle. */
     454void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick )
     455{
     456        user_t *u = user_findhandle( ic, handle );
     457        char newnick[MAX_NICK_LENGTH+1], *orig_nick;
     458       
     459        if( u && !u->online && !nick_saved( ic->acc, handle ) )
     460        {
     461                /* Only do this if the person isn't online yet (which should
     462                   be the case if we just added it) and if the user hasn't
     463                   assigned a nickname to this buddy already. */
     464               
     465                strncpy( newnick, nick, MAX_NICK_LENGTH );
     466                newnick[MAX_NICK_LENGTH] = 0;
     467               
     468                /* Some processing to make sure this string is a valid IRC nickname. */
     469                nick_strip( newnick );
     470                if( set_getbool( &ic->irc->set, "lcnicks" ) )
     471                        nick_lc( newnick );
     472               
     473                if( strcmp( u->nick, newnick ) != 0 )
     474                {
     475                        /* Only do this if newnick is different from the current one.
     476                           If rejoining a channel, maybe we got this nick already
     477                           (and dedupe would only add an underscore. */
     478                        nick_dedupe( ic->acc, handle, newnick );
    447479                       
    448                         if( *s == 0 )
    449                         {
    450                                 /* If we reached the end of the string, it only contained numbers.
    451                                    Seems to be an ICQ# then, so hopefully realname contains
    452                                    something more useful. */
    453                                 strcpy( newnick, realname );
    454                                
    455                                 /* Some processing to make sure this string is a valid IRC nickname. */
    456                                 nick_strip( newnick );
    457                                 if( set_getbool( &ic->irc->set, "lcnicks" ) )
    458                                         nick_lc( newnick );
    459                                
    460                                 u->nick = g_strdup( newnick );
    461                         }
    462                 }
    463         }
    464 }
    465 
     480                        /* u->nick will be freed halfway the process, so it can't be
     481                           passed as an argument. */
     482                        orig_nick = g_strdup( u->nick );
     483                        user_rename( ic->irc, orig_nick, newnick );
     484                        g_free( orig_nick );
     485                }
     486        }
     487}
    466488
    467489/* prpl.c */
     
    554576                u->online = 0;
    555577               
    556                 /* Remove him/her from the conversations to prevent PART messages after he/she QUIT already */
    557                 for( c = ic->conversations; c; c = c->next )
     578                /* Remove him/her from the groupchats to prevent PART messages after he/she QUIT already */
     579                for( c = ic->groupchats; c; c = c->next )
    558580                        remove_chat_buddy_silent( c, (char*) handle );
    559581        }
     
    670692}
    671693
    672 void imcb_chat_removed( struct groupchat *c )
     694void imcb_chat_free( struct groupchat *c )
    673695{
    674696        struct im_connection *ic = c->ic;
    675         struct groupchat *l = NULL;
     697        struct groupchat *l;
    676698        GList *ir;
    677699       
     
    693715                }
    694716               
     717                /* Find the previous chat in the linked list. */
     718                for( l = ic->groupchats; l && l->next != c; l = l->next );
     719               
    695720                if( l )
    696721                        l->next = c->next;
    697722                else
    698                         ic->conversations = c->next;
     723                        ic->groupchats = c->next;
    699724               
    700725                for( ir = c->in_room; ir; ir = ir->next )
     
    741766        /* This one just creates the conversation structure, user won't see anything yet */
    742767       
    743         if( ic->conversations )
    744         {
    745                 for( c = ic->conversations; c->next; c = c->next );
     768        if( ic->groupchats )
     769        {
     770                for( c = ic->groupchats; c->next; c = c->next );
    746771                c = c->next = g_new0( struct groupchat, 1 );
    747772        }
    748773        else
    749                 ic->conversations = c = g_new0( struct groupchat, 1 );
     774                ic->groupchats = c = g_new0( struct groupchat, 1 );
    750775       
    751776        c->ic = ic;
     
    796821}
    797822
     823/* This function is one BIG hack... :-( EREWRITE */
    798824void imcb_chat_remove_buddy( struct groupchat *b, char *handle, char *reason )
    799825{
     
    807833        if( g_strcasecmp( handle, b->ic->acc->user ) == 0 )
    808834        {
     835                if( b->joined == 0 )
     836                        return;
     837               
    809838                u = user_find( b->ic->irc, b->ic->irc->nick );
    810839                b->joined = 0;
     
    816845        }
    817846       
    818         if( remove_chat_buddy_silent( b, handle ) )
    819                 if( ( b->joined || me ) && u )
    820                         irc_part( b->ic->irc, u, b->channel );
     847        if( me || ( remove_chat_buddy_silent( b, handle ) && b->joined && u ) )
     848                irc_part( b->ic->irc, u, b->channel );
    821849}
    822850
     
    844872
    845873/* Misc. BitlBee stuff which shouldn't really be here */
    846 
    847 struct groupchat *chat_by_channel( char *channel )
    848 {
    849         struct im_connection *ic;
    850         struct groupchat *c;
    851         GSList *l;
    852        
    853         /* This finds the connection which has a conversation which belongs to this channel */
    854         for( l = connections; l; l = l->next )
    855         {
    856                 ic = l->data;
    857                 for( c = ic->conversations; c && g_strcasecmp( c->channel, channel ) != 0; c = c->next );
    858                 if( c )
    859                         return c;
    860         }
    861        
    862         return NULL;
    863 }
    864874
    865875char *set_eval_away_devoice( set_t *set, char *value )
     
    10951105        ic->acc->prpl->rem_deny( ic, handle );
    10961106}
     1107
     1108void imcb_clean_handle( struct im_connection *ic, char *handle )
     1109{
     1110        /* Accepts a handle and does whatever is necessary to make it
     1111           BitlBee-friendly. Currently this means removing everything
     1112           outside 33-127 (ASCII printable excl spaces), @ (only one
     1113           is allowed) and ! and : */
     1114        char out[strlen(handle)+1];
     1115        int s, d;
     1116       
     1117        s = d = 0;
     1118        while( handle[s] )
     1119        {
     1120                if( handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' &&
     1121                    ( handle[s] & 0x80 ) == 0 )
     1122                {
     1123                        if( handle[s] == '@' )
     1124                        {
     1125                                /* See if we got an @ already? */
     1126                                out[d] = 0;
     1127                                if( strchr( out, '@' ) )
     1128                                        continue;
     1129                        }
     1130                       
     1131                        out[d++] = handle[s];
     1132                }
     1133                s ++;
     1134        }
     1135        out[d] = handle[s];
     1136       
     1137        strcpy( handle, out );
     1138}
  • protocols/nogaim.h

    rd444c09 reda54e4  
    6161#define OPT_AWAY        0x00000004
    6262#define OPT_DOES_HTML   0x00000010
     63#define OPT_LOCALBUDDY  0x00000020 /* For nicks local to one groupchat */
    6364#define OPT_TYPING      0x00000100 /* Some pieces of code make assumptions */
    6465#define OPT_THINKING    0x00000200 /* about these values... Stupid me! */
     
    9192        irc_t *irc;
    9293       
    93         struct groupchat *conversations;
     94        struct groupchat *groupchats;
    9495};
    9596
     
    104105        GList *ignored;
    105106       
    106         /* BitlBee */
    107107        struct groupchat *next;
    108108        char *channel;
     
    265265G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle );
    266266G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, char *handle, char *realname );
     267G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, char *handle, char *nick );
    267268
    268269/* Buddy activity */
     
    276277G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, char *handle, char *msg, u_int32_t flags, time_t sent_at );
    277278G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, char *handle, u_int32_t flags );
     279G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle );
    278280
    279281/* Groupchats */
     
    291293/* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */
    292294G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, char *who, char *msg, u_int32_t flags, time_t sent_at );
    293 G_MODULE_EXPORT void imcb_chat_removed( struct groupchat *c );
    294 struct groupchat *chat_by_channel( char *channel );
     295G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c );
    295296
    296297/* Actions, or whatever. */
  • protocols/oscar/oscar.c

    rd444c09 reda54e4  
    20222022                                       
    20232023                                        if (realname) {
     2024                                                imcb_buddy_nick_hint(ic, curitem->name, realname);
    20242025                                                imcb_rename_buddy(ic, curitem->name, realname);
    20252026                                                g_free(realname);
     
    25142515
    25152516        /* Notify the conversation window that we've left the chat */
    2516         imcb_chat_removed(cc->cnv);
     2517        imcb_chat_free(cc->cnv);
    25172518
    25182519        /* Destroy the chat_connection */
  • protocols/yahoo/yahoo.c

    rd444c09 reda54e4  
    145145        GSList *l;
    146146       
    147         while( ic->conversations )
    148                 imcb_chat_removed( ic->conversations );
     147        while( ic->groupchats )
     148                imcb_chat_free( ic->groupchats );
    149149       
    150150        for( l = yd->buddygroups; l; l = l->next )
     
    318318       
    319319        yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title );
    320         imcb_chat_removed( c );
     320        imcb_chat_free( c );
    321321}
    322322
     
    798798{
    799799        yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" );
    800         imcb_chat_removed( inv->c );
     800        imcb_chat_free( inv->c );
    801801        g_free( inv->name );
    802802        g_free( inv );
     
    841841        struct groupchat *c;
    842842       
    843         for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next );
     843        for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
    844844       
    845845        if( c )
     
    853853        struct groupchat *c;
    854854       
    855         for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next );
     855        for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
    856856       
    857857        if( c )
     
    865865        struct groupchat *c;
    866866       
    867         for( c = ic->conversations; c && strcmp( c->title, room ) != 0; c = c->next );
     867        for( c = ic->groupchats; c && strcmp( c->title, room ) != 0; c = c->next );
    868868       
    869869        if( c )
  • root_commands.c

    rd444c09 reda54e4  
    912912        if( cmd[3] )
    913913        {
    914                 channel = g_strdup( cmd[3] );
     914                if( cmd[3][0] != '#' && cmd[3][0] != '&' )
     915                        channel = g_strdup_printf( "&%s", cmd[3] );
     916                else
     917                        channel = g_strdup( cmd[3] );
    915918        }
    916919        else
     
    918921                char *s;
    919922               
    920                 channel = g_strdup( chat );
     923                channel = g_strdup_printf( "&%s", chat );
    921924                if( ( s = strchr( channel, '@' ) ) )
    922925                        *s = 0;
     
    924927        if( cmd[3] && cmd[4] )
    925928                nick = cmd[4];
     929        else
     930                nick = irc->nick;
    926931        if( cmd[3] && cmd[4] && cmd[5] )
    927932                password = cmd[5];
    928933       
    929         c = a->prpl->chat_join( ic, chat, nick, password );
    930        
    931         g_free( channel );
     934        if( !nick_ok( channel + 1 ) )
     935        {
     936                irc_usermsg( irc, "Invalid channel name: %s", channel );
     937                g_free( channel );
     938                return;
     939        }
     940        else if( g_strcasecmp( channel, irc->channel ) == 0 || irc_chat_by_channel( irc, channel ) )
     941        {
     942                irc_usermsg( irc, "Channel already exists: %s", channel );
     943                g_free( channel );
     944                return;
     945        }
     946       
     947        if( ( c = a->prpl->chat_join( ic, chat, nick, password ) ) )
     948        {
     949                g_free( c->channel );
     950                c->channel = channel;
     951        }
     952        else
     953        {
     954                irc_usermsg( irc, "Tried to join chat, not sure if this was successful" );
     955                g_free( channel );
     956        }
    932957}
    933958
  • user.c

    rd444c09 reda54e4  
    161161}
    162162
     163/* DO NOT PASS u->nick FOR oldnick !!! */
    163164void user_rename( irc_t *irc, char *oldnick, char *newnick )
    164165{
Note: See TracChangeset for help on using the changeset viewer.