@ -25,6 +25,7 @@
void connection__init ( )
void connection__init ( )
{
{
srand ( time ( NULL ) ) ;
xmpp_initialize ( ) ;
xmpp_initialize ( ) ;
}
}
@ -87,10 +88,11 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
struct t_user * user ;
struct t_user * user ;
struct t_channel * channel ;
struct t_channel * channel ;
xmpp_stanza_t * pres__x_signed , * pres__x_muc_user , * show , * idle , * pres__x__item , * pres__c , * pres__status ;
xmpp_stanza_t * pres__x_signed , * pres__x_muc_user , * show , * idle , * pres__x__item , * pres__c , * pres__status ;
const char * from, * from_bare , * from_res , * type , * role = NULL , * affiliation = NULL , * jid = NULL ;
const char * to, * from, * from_bare , * from_res , * type , * role = NULL , * affiliation = NULL , * jid = NULL ;
const char * show__text = NULL , * idle__since = NULL , * certificate = NULL , * node = NULL , * ver = NULL ;
const char * show__text = NULL , * idle__since = NULL , * certificate = NULL , * node = NULL , * ver = NULL ;
char * clientid = NULL , * status ;
char * clientid = NULL , * status ;
to = xmpp_stanza_get_to ( stanza ) ;
from = xmpp_stanza_get_from ( stanza ) ;
from = xmpp_stanza_get_from ( stanza ) ;
if ( from = = NULL )
if ( from = = NULL )
return 1 ;
return 1 ;
@ -115,9 +117,20 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
ver = xmpp_stanza_get_attribute ( pres__c , " ver " ) ;
ver = xmpp_stanza_get_attribute ( pres__c , " ver " ) ;
if ( node & & ver )
if ( node & & ver )
{
{
int len = strlen ( node ) + 1 + strlen ( ver ) ;
int len = strlen ( node ) + 1 + strlen ( ver ) + 1 ;
clientid = malloc ( sizeof ( char ) * len ) ;
clientid = malloc ( sizeof ( char ) * len ) ;
snprintf ( clientid , len , " %s#%s " , node , ver ) ;
snprintf ( clientid , len , " %s#%s " , node , ver ) ;
xmpp_stanza_t * children [ 2 ] = { NULL } ;
children [ 0 ] = stanza__iq_pubsub_items ( account - > context , NULL ,
" eu.siacs.conversations.axolotl.devicelist " ) ;
children [ 0 ] = stanza__iq_pubsub ( account - > context , NULL ,
children , with_noop ( " http://jabber.org/protocol/pubsub " ) ) ;
children [ 0 ] = stanza__iq ( account - > context , NULL , children , NULL ,
strdup ( " fetch2 " ) , to ? strdup ( to ) : NULL , strdup ( from_bare ) ,
strdup ( " get " ) ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
}
}
}
}
pres__status = xmpp_stanza_get_child_by_name ( stanza , " status " ) ;
pres__status = xmpp_stanza_get_child_by_name ( stanza , " status " ) ;
@ -133,8 +146,60 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
for ( pres__x__item = xmpp_stanza_get_children ( pres__x_muc_user ) ;
for ( pres__x__item = xmpp_stanza_get_children ( pres__x_muc_user ) ;
pres__x__item ; pres__x__item = xmpp_stanza_get_next ( pres__x__item ) )
pres__x__item ; pres__x__item = xmpp_stanza_get_next ( pres__x__item ) )
{
{
if ( weechat_strcasecmp ( xmpp_stanza_get_name ( pres__x__item ) , " item " ) ! = 0 )
const char * pres__x__item__name = xmpp_stanza_get_name ( pres__x__item ) ;
if ( weechat_strcasecmp ( pres__x__item__name , " item " ) ! = 0 )
{
if ( weechat_strcasecmp ( pres__x__item__name , " status " ) = = 0 )
{
const char * pres__x__status__code = xmpp_stanza_get_attribute (
pres__x__item , " code " ) ;
switch ( strtol ( pres__x__status__code , NULL , 10 ) )
{
case 100 : // Non-Anonymous: [message | Entering a room]: Inform user that any occupant is allowed to see the user's full JID
weechat_buffer_set ( channel - > buffer , " notify " , " 2 " ) ;
break ;
case 101 : // : [message (out of band) | Affiliation change]: Inform user that his or her affiliation changed while not in the room
break ;
case 102 : // : [message | Configuration change]: Inform occupants that room now shows unavailable members
break ;
case 103 : // : [message | Configuration change]: Inform occupants that room now does not show unavailable members
break ;
case 104 : // : [message | Configuration change]: Inform occupants that a non-privacy-related room configuration change has occurred
break ;
case 110 : // Self-Presence: [presence | Any room presence]: Inform user that presence refers to one of its own room occupants
break ;
case 170 : // Logging Active: [message or initial presence | Configuration change]: Inform occupants that room logging is now enabled
break ;
case 171 : // : [message | Configuration change]: Inform occupants that room logging is now disabled
break ;
case 172 : // : [message | Configuration change]: Inform occupants that the room is now non-anonymous
break ;
case 173 : // : [message | Configuration change]: Inform occupants that the room is now semi-anonymous
break ;
case 174 : // : [message | Configuration change]: Inform occupants that the room is now fully-anonymous
break ;
case 201 : // : [presence | Entering a room]: Inform user that a new room has been created
break ;
case 210 : // Nick Modified: [presence | Entering a room]: Inform user that the service has assigned or modified the occupant's roomnick
break ;
case 301 : // : [presence | Removal from room]: Inform user that he or she has been banned from the room
break ;
case 303 : // : [presence | Exiting a room]: Inform all occupants of new room nickname
break ;
case 307 : // : [presence | Removal from room]: Inform user that he or she has been kicked from the room
break ;
case 321 : // : [presence | Removal from room]: Inform user that he or she is being removed from the room because of an affiliation change
break ;
case 322 : // : [presence | Removal from room]: Inform user that he or she is being removed from the room because the room has been changed to members-only and the user is not a member
break ;
case 332 : // : [presence | Removal from room]: Inform user that he or she is being removed from the room because of a system shutdown
break ;
default :
break ;
}
}
continue ;
continue ;
}
role = xmpp_stanza_get_attribute ( pres__x__item , " role " ) ;
role = xmpp_stanza_get_attribute ( pres__x__item , " role " ) ;
affiliation = xmpp_stanza_get_attribute ( pres__x__item , " affiliation " ) ;
affiliation = xmpp_stanza_get_attribute ( pres__x__item , " affiliation " ) ;
@ -156,7 +221,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
{
{
user - > profile . pgp_id = pgp__verify ( channel - > buffer , account - > pgp , certificate ) ;
user - > profile . pgp_id = pgp__verify ( channel - > buffer , account - > pgp , certificate ) ;
if ( channel - > type ! = CHANNEL_TYPE_MUC )
if ( channel - > type ! = CHANNEL_TYPE_MUC )
channel - > pgp _ id = user - > profile . pgp_id ;
channel - > pgp . id = user - > profile . pgp_id ;
}
}
if ( channel )
if ( channel )
@ -185,7 +250,7 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
{
{
user - > profile . pgp_id = pgp__verify ( channel - > buffer , account - > pgp , certificate ) ;
user - > profile . pgp_id = pgp__verify ( channel - > buffer , account - > pgp , certificate ) ;
if ( channel - > type ! = CHANNEL_TYPE_MUC )
if ( channel - > type ! = CHANNEL_TYPE_MUC )
channel - > pgp _ id = user - > profile . pgp_id ;
channel - > pgp . id = user - > profile . pgp_id ;
}
}
if ( channel )
if ( channel )
@ -328,8 +393,8 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
{
{
if ( account - > omemo )
if ( account - > omemo )
{
{
omemo__handle_devicelist ( account - > omemo , from ,
omemo__handle_devicelist ( account - > omemo ,
items ) ;
from ? from : account_jid ( account ) , items ) ;
}
}
children = malloc ( sizeof ( * children ) * ( 3 + 1 ) ) ;
children = malloc ( sizeof ( * children ) * ( 3 + 1 ) ) ;
@ -355,9 +420,11 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
children [ 0 ] =
children [ 0 ] =
stanza__iq_pubsub ( account - > context , NULL , children ,
stanza__iq_pubsub ( account - > context , NULL , children ,
with_noop ( " http://jabber.org/protocol/pubsub " ) ) ;
with_noop ( " http://jabber.org/protocol/pubsub " ) ) ;
char * uuid = xmpp_uuid_gen ( account - > context ) ;
children [ 0 ] =
children [ 0 ] =
stanza__iq ( account - > context , NULL , children , NULL , strdup ( " fetch1 " ) ,
stanza__iq ( account - > context , NULL , children , NULL , uuid ,
strdup ( to ) , strdup ( from ) , strdup ( " get " ) ) ;
strdup ( to ) , strdup ( from ) , strdup ( " get " ) ) ;
xmpp_free ( account - > context , uuid ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
@ -457,7 +524,7 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
" eu.siacs.conversations.axolotl " ) ;
" eu.siacs.conversations.axolotl " ) ;
if ( encrypted & & account - > omemo )
if ( encrypted & & account - > omemo )
{
{
omemo__decode ( account - > omemo , from_bare , encrypted ) ;
cleartext = omemo__decode ( account , from_bare , encrypted ) ;
}
}
x = xmpp_stanza_get_child_by_name_and_ns ( stanza , " x " , " jabber:x:encrypted " ) ;
x = xmpp_stanza_get_child_by_name_and_ns ( stanza , " x " , " jabber:x:encrypted " ) ;
intext = xmpp_stanza_get_text ( body ) ;
intext = xmpp_stanza_get_text ( body ) ;
@ -650,9 +717,9 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
weechat_prefix ( " network " ) , weechat_color ( " gray " ) ,
weechat_prefix ( " network " ) , weechat_color ( " gray " ) ,
channel__transport_name ( channel - > transport ) ) ;
channel__transport_name ( channel - > transport ) ) ;
}
}
else if ( ! x & & text = = intext & & channel - > transport ! = CHANNEL_TRANSPORT_PLAIN TEXT )
else if ( ! x & & text = = intext & & channel - > transport ! = CHANNEL_TRANSPORT_PLAIN )
{
{
channel - > transport = CHANNEL_TRANSPORT_PLAIN TEXT ;
channel - > transport = CHANNEL_TRANSPORT_PLAIN ;
weechat_printf_date_tags ( channel - > buffer , date , NULL , " %s%sTransport: %s " ,
weechat_printf_date_tags ( channel - > buffer , date , NULL , " %s%sTransport: %s " ,
weechat_prefix ( " network " ) , weechat_color ( " gray " ) ,
weechat_prefix ( " network " ) , weechat_color ( " gray " ) ,
channel__transport_name ( channel - > transport ) ) ;
channel__transport_name ( channel - > transport ) ) ;
@ -682,43 +749,38 @@ int connection__message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *
return 1 ;
return 1 ;
}
}
int connection__iq_handler ( xmpp_conn_t * conn , xmpp_stanza_t * stanza , void * userdata )
xmpp_stanza_t * connection__get_caps ( xmpp_stanza_t * reply , struct t_account * account , char * * hash )
{
{
struct t_account * account = ( struct t_account * ) userdata ;
xmpp_stanza_t * query = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_t * reply , * query , * identity , * feature , * x , * field , * value , * text , * fin ;
xmpp_stanza_set_name ( query , " query " ) ;
xmpp_stanza_t * pubsub , * items , * item , * list , * bundle , * device ;
xmpp_stanza_set_ns ( query , " http://jabber.org/protocol/disco#info " ) ;
xmpp_stanza_t * storage , * conference , * nick ;
static struct utsname osinfo ;
const char * id = xmpp_stanza_get_id ( stanza ) ;
const char * from = xmpp_stanza_get_from ( stanza ) ;
query = xmpp_stanza_get_child_by_name_and_ns (
stanza , " query " , " http://jabber.org/protocol/disco#info " ) ;
const char * type = xmpp_stanza_get_attribute ( stanza , " type " ) ;
if ( query & & type & & weechat_strcasecmp ( type , " get " ) = = 0 )
{
char * client_name ;
reply = xmpp_stanza_reply ( stanza ) ;
xmpp_stanza_set_type ( reply , " result " ) ;
client_name = weechat_string_eval_expression ( " weechat ${info:version} " ,
char * client_name = weechat_string_eval_expression (
NULL , NULL , NULL ) ;
" weechat ${info:version} " , NULL , NULL , NULL ) ;
char * * serial = weechat_string_dyn_alloc ( 256 ) ;
weechat_string_dyn_concat ( serial , " client/pc// " , - 1 ) ;
weechat_string_dyn_concat ( serial , client_name , - 1 ) ;
weechat_string_dyn_concat ( serial , " < " , - 1 ) ;
identity = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_t * identity = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( identity , " identity " ) ;
xmpp_stanza_set_name ( identity , " identity " ) ;
xmpp_stanza_set_attribute ( identity , " category " , " client " ) ;
xmpp_stanza_set_attribute ( identity , " category " , " client " ) ;
xmpp_stanza_set_attribute ( identity , " name " , client_name ) ;
xmpp_stanza_set_attribute ( identity , " name " , client_name ) ;
free ( client_name ) ;
xmpp_stanza_set_attribute ( identity , " type " , " pc " ) ;
xmpp_stanza_set_attribute ( identity , " type " , " pc " ) ;
xmpp_stanza_add_child ( query , identity ) ;
xmpp_stanza_add_child ( query , identity ) ;
xmpp_stanza_release ( identity ) ;
xmpp_stanza_release ( identity ) ;
# define FEATURE(ns) \
xmpp_stanza_t * feature = NULL ;
# define FEATURE(NS) \
feature = xmpp_stanza_new ( account - > context ) ; \
feature = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_name ( feature , " feature " ) ; \
xmpp_stanza_set_name ( feature , " feature " ) ; \
xmpp_stanza_set_attribute ( feature , " var " , ns ) ; \
xmpp_stanza_set_attribute ( feature , " var " , NS ) ; \
xmpp_stanza_add_child ( query , feature ) ; \
xmpp_stanza_add_child ( query , feature ) ; \
xmpp_stanza_release ( feature ) ;
xmpp_stanza_release ( feature ) ; \
weechat_string_dyn_concat ( serial , NS , - 1 ) ; \
weechat_string_dyn_concat ( serial , " < " , - 1 ) ;
FEATURE ( " eu.siacs.conversations.axolotl.devicelist+notify " ) ;
FEATURE ( " eu.siacs.conversations.axolotl.devicelist+notify " ) ;
FEATURE ( " http://jabber.org/protocol/caps " ) ;
FEATURE ( " http://jabber.org/protocol/caps " ) ;
@ -754,160 +816,132 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
FEATURE ( " urn:xmpp:time " ) ;
FEATURE ( " urn:xmpp:time " ) ;
# undef FEATURE
# undef FEATURE
x = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_t * x = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( x , " x " ) ;
xmpp_stanza_set_name ( x , " x " ) ;
xmpp_stanza_set_ns ( x , " jabber:x:data " ) ;
xmpp_stanza_set_ns ( x , " jabber:x:data " ) ;
xmpp_stanza_set_attribute ( x , " type " , " result " ) ;
xmpp_stanza_set_attribute ( x , " type " , " result " ) ;
static struct utsname osinfo ;
if ( uname ( & osinfo ) < 0 )
if ( uname ( & osinfo ) < 0 )
{
{
* osinfo . sysname = 0 ;
* osinfo . sysname = 0 ;
* osinfo . release = 0 ;
* osinfo . release = 0 ;
}
}
xmpp_stanza_t * field , * value , * text ;
// This is utter bullshit, TODO: anything but this.
// This is utter bullshit, TODO: anything but this.
{
# define FEATURE1(VAR, TYPE, VALUE) \
field = xmpp_stanza_new ( account - > context ) ;
field = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_name ( field , " field " ) ;
xmpp_stanza_set_name ( field , " field " ) ; \
xmpp_stanza_set_attribute ( field , " var " , " FORM_TYPE " ) ;
xmpp_stanza_set_attribute ( field , " var " , VAR ) ; \
xmpp_stanza_set_attribute ( field , " type " , " hidden " ) ;
if ( TYPE ) xmpp_stanza_set_attribute ( field , " type " , TYPE ) ; \
value = xmpp_stanza_new ( account - > context ) ; \
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ; \
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_text ( text , VALUE ) ; \
xmpp_stanza_add_child ( value , text ) ; \
xmpp_stanza_release ( text ) ; \
xmpp_stanza_add_child ( field , value ) ; \
xmpp_stanza_release ( value ) ; \
xmpp_stanza_add_child ( x , field ) ; \
xmpp_stanza_release ( field ) ; \
if ( strcmp ( VAR , " FORM_TYPE " ) = = 0 ) { \
weechat_string_dyn_concat ( serial , VAR , - 1 ) ; \
weechat_string_dyn_concat ( serial , " < " , - 1 ) ; \
} \
weechat_string_dyn_concat ( serial , VALUE , - 1 ) ; \
weechat_string_dyn_concat ( serial , " < " , - 1 ) ;
# define FEATURE2(VAR, TYPE, VALUE1, VALUE2) \
field = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_name ( field , " field " ) ; \
xmpp_stanza_set_attribute ( field , " var " , VAR ) ; \
xmpp_stanza_set_attribute ( field , " type " , TYPE ) ; \
value = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_name ( value , " value " ) ; \
text = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_text ( text , VALUE1 ) ; \
xmpp_stanza_add_child ( value , text ) ; \
xmpp_stanza_release ( text ) ; \
xmpp_stanza_add_child ( field , value ) ; \
xmpp_stanza_release ( value ) ; \
value = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_name ( value , " value " ) ; \
text = xmpp_stanza_new ( account - > context ) ; \
xmpp_stanza_set_text ( text , VALUE2 ) ; \
xmpp_stanza_add_child ( value , text ) ; \
xmpp_stanza_release ( text ) ; \
xmpp_stanza_add_child ( field , value ) ; \
xmpp_stanza_release ( value ) ; \
xmpp_stanza_add_child ( x , field ) ; \
xmpp_stanza_release ( field ) ; \
weechat_string_dyn_concat ( serial , VAR , - 1 ) ; \
weechat_string_dyn_concat ( serial , " < " , - 1 ) ; \
weechat_string_dyn_concat ( serial , VALUE1 , - 1 ) ; \
weechat_string_dyn_concat ( serial , " < " , - 1 ) ; \
weechat_string_dyn_concat ( serial , VALUE2 , - 1 ) ; \
weechat_string_dyn_concat ( serial , " < " , - 1 ) ;
FEATURE1 ( " FORM_TYPE " , " hidden " , " urn:xmpp:dataforms:softwareinfo " ) ;
FEATURE2 ( " ip_version " , " text-multi " , " ipv4 " , " ipv6 " ) ;
FEATURE1 ( " os " , NULL , osinfo . sysname ) ;
FEATURE1 ( " os_version " , NULL , osinfo . release ) ;
FEATURE1 ( " software " , NULL , " weechat " ) ;
FEATURE1 ( " software_version " , NULL , weechat_info_get ( " version " , NULL ) ) ;
# undef FEATURE1
# undef FEATURE2
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_add_child ( query , x ) ;
xmpp_stanza_set_text ( text , " urn:xmpp:dataforms:softwareinfo " ) ;
xmpp_stanza_release ( x ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_set_type ( reply , " result " ) ;
xmpp_stanza_release ( value ) ;
xmpp_stanza_add_child ( reply , query ) ;
xmpp_stanza_add_child ( x , field ) ;
weechat_printf ( NULL , " verstr: %s " , * serial ) ;
xmpp_stanza_release ( field ) ;
unsigned char digest [ 20 ] ;
}
xmpp_sha1_t * sha1 = xmpp_sha1_new ( account - > context ) ;
xmpp_sha1_update ( sha1 , ( unsigned char * ) * serial , strlen ( * serial ) ) ;
xmpp_sha1_final ( sha1 ) ;
weechat_string_dyn_free ( serial , 1 ) ;
xmpp_sha1_to_digest ( sha1 , digest ) ;
xmpp_sha1_free ( sha1 ) ;
if ( hash )
{
{
field = xmpp_stanza_new ( account - > context ) ;
char * cap_hash = xmpp_base64_encode ( account - > context , digest , 20 ) ;
xmpp_stanza_set_name ( field , " field " ) ;
* hash = strdup ( cap_hash ) ;
xmpp_stanza_set_attribute ( field , " var " , " ip_version " ) ;
xmpp_free ( account - > context , cap_hash ) ;
xmpp_stanza_set_attribute ( field , " type " , " text-multi " ) ;
weechat_printf ( NULL , " verhash: %s " , * hash ) ;
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_text ( text , " ipv4 " ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_release ( value ) ;
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_text ( text , " ipv6 " ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_release ( value ) ;
xmpp_stanza_add_child ( x , field ) ;
xmpp_stanza_release ( field ) ;
}
}
{
return reply ;
field = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( field , " field " ) ;
xmpp_stanza_set_attribute ( field , " var " , " os " ) ;
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_text ( text , osinfo . sysname ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_release ( value ) ;
xmpp_stanza_add_child ( x , field ) ;
xmpp_stanza_release ( field ) ;
}
}
int connection__iq_handler ( xmpp_conn_t * conn , xmpp_stanza_t * stanza , void * userdata )
{
{
field = xmpp_stanza_new ( account - > context ) ;
struct t_account * account = ( struct t_account * ) userdata ;
xmpp_stanza_set_name ( field , " field " ) ;
xmpp_stanza_t * reply , * query , * text , * fin ;
xmpp_stanza_set_attribute ( field , " var " , " os_version " ) ;
xmpp_stanza_t * pubsub , * items , * item , * list , * bundle , * device ;
xmpp_stanza_t * storage , * conference , * nick ;
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_text ( text , osinfo . release ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_release ( value ) ;
xmpp_stanza_add_child ( x , field ) ;
xmpp_stanza_release ( field ) ;
}
const char * id = xmpp_stanza_get_id ( stanza ) ;
const char * from = xmpp_stanza_get_from ( stanza ) ;
const char * to = xmpp_stanza_get_to ( stanza ) ;
query = xmpp_stanza_get_child_by_name_and_ns (
stanza , " query " , " http://jabber.org/protocol/disco#info " ) ;
const char * type = xmpp_stanza_get_attribute ( stanza , " type " ) ;
if ( query & & type )
{
{
field = xmpp_stanza_new ( account - > context ) ;
if ( weechat_strcasecmp ( type , " get " ) = = 0 )
xmpp_stanza_set_name ( field , " field " ) ;
xmpp_stanza_set_attribute ( field , " var " , " software " ) ;
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_text ( text , " weechat " ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_release ( value ) ;
xmpp_stanza_add_child ( x , field ) ;
xmpp_stanza_release ( field ) ;
}
{
{
field = xmpp_stanza_new ( account - > context ) ;
reply = connection__get_caps ( xmpp_stanza_reply ( stanza ) , account , NULL ) ;
xmpp_stanza_set_name ( field , " field " ) ;
xmpp_stanza_set_attribute ( field , " var " , " software_version " ) ;
value = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( value , " value " ) ;
text = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_text ( text , weechat_info_get ( " version " , NULL ) ) ;
xmpp_stanza_add_child ( value , text ) ;
xmpp_stanza_release ( text ) ;
xmpp_stanza_add_child ( field , value ) ;
xmpp_stanza_release ( value ) ;
xmpp_stanza_add_child ( x , field ) ;
xmpp_stanza_release ( field ) ;
}
xmpp_stanza_add_child ( query , x ) ;
xmpp_stanza_release ( x ) ;
xmpp_stanza_add_child ( reply , query ) ;
xmpp_send ( conn , reply ) ;
xmpp_send ( conn , reply ) ;
xmpp_stanza_release ( reply ) ;
xmpp_stanza_release ( reply ) ;
}
free ( client_name ) ;
if ( weechat_strcasecmp ( type , " result " ) = = 0 )
{
}
}
}
pubsub = xmpp_stanza_get_child_by_name_and_ns (
pubsub = xmpp_stanza_get_child_by_name_and_ns (
@ -926,14 +960,47 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
{
{
item = xmpp_stanza_get_child_by_name ( items , " item " ) ;
item = xmpp_stanza_get_child_by_name ( items , " item " ) ;
if ( item )
if ( item )
item_id = xmpp_stanza_get_id ( item ) ;
if ( item & & item_id & & weechat_strcasecmp ( item_id , " current " ) = = 0 )
{
{
item_id = xmpp_stanza_get_id ( item ) ;
list = xmpp_stanza_get_child_by_name_and_ns (
list = xmpp_stanza_get_child_by_name_and_ns (
item , " list " , " eu.siacs.conversations.axolotl " ) ;
item , " list " , " eu.siacs.conversations.axolotl " ) ;
if ( list & & account - > omemo )
if ( list & & account - > omemo )
{
{
omemo__handle_devicelist ( account - > omemo , from , items ) ;
omemo__handle_devicelist ( account - > omemo ,
from ? from : account_jid ( account ) , items ) ;
xmpp_stanza_t * children [ 2 ] = { NULL } ;
for ( device = xmpp_stanza_get_children ( list ) ;
device ; device = xmpp_stanza_get_next ( device ) )
{
const char * name = xmpp_stanza_get_name ( device ) ;
if ( weechat_strcasecmp ( name , " device " ) ! = 0 )
continue ;
const char * device_id = xmpp_stanza_get_id ( device ) ;
char bundle_node [ 128 ] = { 0 } ;
snprintf ( bundle_node , sizeof ( bundle_node ) ,
" eu.siacs.conversations.axolotl.bundles:%s " ,
device_id ) ;
children [ 1 ] = NULL ;
children [ 0 ] =
stanza__iq_pubsub_items ( account - > context , NULL ,
strdup ( bundle_node ) ) ;
children [ 0 ] =
stanza__iq_pubsub ( account - > context , NULL , children ,
with_noop ( " http://jabber.org/protocol/pubsub " ) ) ;
char * uuid = xmpp_uuid_gen ( account - > context ) ;
children [ 0 ] =
stanza__iq ( account - > context , NULL , children , NULL , uuid ,
to ? strdup ( to ) : NULL , from ? strdup ( from ) : NULL ,
strdup ( " get " ) ) ;
xmpp_free ( account - > context , uuid ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
}
if ( weechat_strcasecmp ( account_jid ( account ) , from ) = = 0 )
if ( weechat_strcasecmp ( account_jid ( account ) , from ) = = 0 )
{
{
@ -975,6 +1042,11 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
}
}
reply = account__get_devicelist ( account ) ;
reply = account__get_devicelist ( account ) ;
char * uuid = xmpp_uuid_gen ( account - > context ) ;
xmpp_stanza_set_id ( reply , uuid ) ;
xmpp_free ( account - > context , uuid ) ;
xmpp_stanza_set_attribute ( reply , " to " , from ) ;
xmpp_stanza_set_attribute ( reply , " from " , to ) ;
xmpp_send ( conn , reply ) ;
xmpp_send ( conn , reply ) ;
xmpp_stanza_release ( reply ) ;
xmpp_stanza_release ( reply ) ;
}
}
@ -997,7 +1069,8 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
strlen ( " eu.siacs.conversations.axolotl.bundles: " ) ;
strlen ( " eu.siacs.conversations.axolotl.bundles: " ) ;
if ( account - > omemo & & strlen ( items_node ) > node_prefix )
if ( account - > omemo & & strlen ( items_node ) > node_prefix )
{
{
omemo__handle_bundle ( account - > omemo , from ,
omemo__handle_bundle ( account - > omemo ,
from ? from : account_jid ( account ) ,
strtol ( items_node + node_prefix ,
strtol ( items_node + node_prefix ,
NULL , 10 ) ,
NULL , 10 ) ,
items ) ;
items ) ;
@ -1046,6 +1119,12 @@ int connection__iq_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userd
weechat_string_dyn_concat ( command , intext , - 1 ) ;
weechat_string_dyn_concat ( command , intext , - 1 ) ;
}
}
weechat_command ( account - > buffer , * command ) ;
weechat_command ( account - > buffer , * command ) ;
struct t_channel * ptr_channel =
channel__search ( account , jid ) ;
struct t_gui_buffer * ptr_buffer =
ptr_channel ? ptr_channel - > buffer : NULL ;
if ( ptr_buffer )
weechat_buffer_set ( ptr_buffer , " short_name " , name ) ;
weechat_string_dyn_free ( command , 1 ) ;
weechat_string_dyn_free ( command , 1 ) ;
}
}
@ -1108,7 +1187,6 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
xmpp_stanza_t * pres , * pres__c , * pres__status , * pres__status__text ,
xmpp_stanza_t * pres , * pres__c , * pres__status , * pres__status__text ,
* pres__x , * pres__x__text , * * children ;
* pres__x , * pres__x__text , * * children ;
char cap_hash [ 28 + 1 ] = { 0 } ;
xmpp_handler_add ( conn , & connection__version_handler ,
xmpp_handler_add ( conn , & connection__version_handler ,
" jabber:iq:version " , " iq " , NULL , account ) ;
" jabber:iq:version " , " iq " , NULL , account ) ;
@ -1135,8 +1213,15 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
xmpp_stanza_set_ns ( pres__c , " http://jabber.org/protocol/caps " ) ;
xmpp_stanza_set_ns ( pres__c , " http://jabber.org/protocol/caps " ) ;
xmpp_stanza_set_attribute ( pres__c , " hash " , " sha-1 " ) ;
xmpp_stanza_set_attribute ( pres__c , " hash " , " sha-1 " ) ;
xmpp_stanza_set_attribute ( pres__c , " node " , " http://weechat.org " ) ;
xmpp_stanza_set_attribute ( pres__c , " node " , " http://weechat.org " ) ;
snprintf ( cap_hash , sizeof ( cap_hash ) , " %027ld= " , time ( NULL ) ) ;
xmpp_stanza_t * caps = xmpp_stanza_new ( account - > context ) ;
xmpp_stanza_set_name ( caps , " caps " ) ;
char * cap_hash ;
caps = connection__get_caps ( caps , account , & cap_hash ) ;
xmpp_stanza_release ( caps ) ;
xmpp_stanza_set_attribute ( pres__c , " ver " , cap_hash ) ;
xmpp_stanza_set_attribute ( pres__c , " ver " , cap_hash ) ;
free ( cap_hash ) ;
children [ 0 ] = pres__c ;
children [ 0 ] = pres__c ;
pres__status = xmpp_stanza_new ( account - > context ) ;
pres__status = xmpp_stanza_new ( account - > context ) ;
@ -1206,21 +1291,26 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
children [ 0 ] =
children [ 0 ] =
stanza__iq_pubsub ( account - > context , NULL , children ,
stanza__iq_pubsub ( account - > context , NULL , children ,
with_noop ( " http://jabber.org/protocol/pubsub " ) ) ;
with_noop ( " http://jabber.org/protocol/pubsub " ) ) ;
char * uuid = xmpp_uuid_gen ( account - > context ) ;
children [ 0 ] =
children [ 0 ] =
stanza__iq ( account - > context , NULL , children , NULL , strdup ( " fetch1 " ) ,
stanza__iq ( account - > context , NULL , children , NULL , uuid ,
strdup ( account_jid ( account ) ) , strdup ( account_jid ( account ) ) ,
strdup ( account_jid ( account ) ) , strdup ( account_jid ( account ) ) ,
strdup ( " get " ) ) ;
strdup ( " get " ) ) ;
xmpp_free ( account - > context , uuid ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
omemo__init ( account - > buffer , & account - > omemo , account - > name ) ;
omemo__init ( account - > buffer , & account - > omemo , account - > name ) ;
if ( account - > omemo )
{
children [ 0 ] =
children [ 0 ] =
omemo__get_bundle ( account - > context ,
omemo__get_bundle ( account - > context ,
strdup ( account_jid ( account ) ) , NULL , account - > omemo ) ;
strdup ( account_jid ( account ) ) , NULL , account - > omemo ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_send ( conn , children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
xmpp_stanza_release ( children [ 0 ] ) ;
}
( void ) weechat_hook_signal_send ( " xmpp_account_connected " ,
( void ) weechat_hook_signal_send ( " xmpp_account_connected " ,
WEECHAT_HOOK_SIGNAL_STRING , account - > name ) ;
WEECHAT_HOOK_SIGNAL_STRING , account - > name ) ;
@ -1235,7 +1325,6 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
char * connection__rand_string ( int length )
char * connection__rand_string ( int length )
{
{
char * string = malloc ( length ) ;
char * string = malloc ( length ) ;
srand ( time ( NULL ) ) ;
for ( int i = 0 ; i < length ; + + i ) {
for ( int i = 0 ; i < length ; + + i ) {
string [ i ] = ' 0 ' + rand ( ) % 72 ; // starting on '0', ending on '}'
string [ i ] = ' 0 ' + rand ( ) % 72 ; // starting on '0', ending on '}'
if ( ! ( ( string [ i ] > = ' 0 ' & & string [ i ] < = ' 9 ' ) | |
if ( ! ( ( string [ i ] > = ' 0 ' & & string [ i ] < = ' 9 ' ) | |