Ignore:
Timestamp:
2007-11-19T23:16:18Z (16 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
7df5a08
Parents:
cd428e4 (diff), ef5c185 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merging Jabber groupchat support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/jabber/jabber_util.c

    rcd428e4 r256899f  
    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}
Note: See TracChangeset for help on using the changeset viewer.