static void _elim_chat_add_users ( PurpleConversation *conv , GList *cbuddies , gboolean new_arrivals ) { char *ID = new_elim_id(); xmlnode *args = xnode_new( "alist" ); xmlnode *list = xnode_new( "list" ); xmlnode *mcall = func_call( "elim-chat-add-users", ID, args ); g_free( ID ); fprintf( stderr, "(_elim_chat_add_users)\n" ); _elim_conv_args( args, conv ); AL_BOOL( args, "new-arrivals" , new_arrivals ); AL_NODE( args, "participants" , list ); fprintf( stderr, "(_elim_chat_add_users)\n" ); for( ; cbuddies; cbuddies = cbuddies->next ) { xmlnode *cbuddy = xnode_new( "alist" ); PurpleConvChatBuddy *pccb = cbuddies->data; AL_STR ( cbuddy, "name" , pccb->name ? pccb->name : "" ); AL_STR ( cbuddy, "alias" , pccb->alias ? pccb->alias : "" ); AL_STR ( cbuddy, "alias-key", pccb->alias_key ? pccb->alias_key : "" ); AL_ENUM( cbuddy, "flags" , pccb->flags , ":conv-chat-buddy-flags" ); AL_BOOL( cbuddy, "on-blist" , pccb->buddy ); xnode_insert_child( list, cbuddy ); } add_outbound_sexp( mcall ); fprintf( stderr, "(_elim_chat_add_users:DONE)\n" ); }
xmlnode * _h_elim_set_prefs ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); elim_ping(); xmlnode *rval = xnode_new( "alist" ); xmlnode *set = xnode_new( "alist" ); GHashTable *prefs = ALIST_VAL_ALIST( args, "prefs" ); SEXP_VALUE *PREFS = ALIST_VAL ( args, "prefs" ); AL_NODE( rval, "prefs", set ); fprintf( stderr, "hash: %p; sexp: %p\n", prefs, PREFS ); if( prefs ) { GList *key = NULL; GList *keys = g_hash_table_get_keys( prefs ); fprintf( stderr, "keys: %p", keys ); for( key = keys; key; key = key->next ) { gboolean done = TRUE; const char *pref = key->data; PurplePrefType type = purple_prefs_get_type( pref ); switch( type ) { case PURPLE_PREF_BOOLEAN: purple_prefs_set_bool ( pref, ALIST_VAL_BOOL( PREFS, pref ) ); break; case PURPLE_PREF_INT: purple_prefs_set_int ( pref, ALIST_VAL_INT ( PREFS, pref ) ); break; case PURPLE_PREF_STRING: purple_prefs_set_string( pref, ALIST_VAL_STR ( PREFS, pref ) ); break; case PURPLE_PREF_PATH: purple_prefs_set_path ( pref, ALIST_VAL_STR ( PREFS, pref ) ); break; default: done = FALSE; } AL_BOOL( set, pref, done ); } g_list_free( keys ); } sexp_val_free( args ); return response_value( 0, id, name, rval ); }
xmlnode * _h_elim_init ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); char *dir = ALIST_VAL_STRING( args, "dot-dir" ); char *ui = ALIST_VAL_STRING( args, "ui-id" ); gboolean dbg = ALIST_VAL_BOOL ( args, "debug" ); if( !ui ) { ui = "elim"; } // libpurple initialisation: purple_util_set_user_dir ( dir ); purple_util_init (); purple_core_set_ui_ops ( &elim_core_ui_ops ); purple_eventloop_set_ui_ops ( &elim_eventloop_ui_ops ); purple_blist_set_ui_ops ( &elim_blist_ui_ops ); purple_accounts_set_ui_ops ( &elim_account_ui_ops ); purple_request_set_ui_ops ( &elim_request_ui_ops ); purple_idle_set_ui_ops ( &elim_idle_ui_ops ); purple_connections_set_ui_ops ( &elim_connections_ui_ops ); purple_conversations_set_ui_ops( &elim_conversation_ui_ops ); purple_notify_set_ui_ops ( &elim_notify_ui_ops ); // load any data for init: if( purple_get_core() == NULL ) { // purple debug goes to stdout if we don't divert it here: g_set_print_handler( (GPrintFunc)_h_elim_warning ); // look for plugins in user specified directory tree: char *ppath = g_build_filename( purple_user_dir(), "plugins", NULL ); purple_plugins_add_search_path ( ppath ); purple_debug_set_enabled( dbg ); purple_core_init ( ui ); purple_set_blist ( purple_blist_new() ); purple_prefs_load(); purple_blist_load(); // glib signal initialisation: elim_ft_signals_init(); // tidy up: g_free( ppath ); } else { const char *cur_ui = purple_core_get_ui(); if( strcmp( cur_ui, name ) ) { sexp_val_free( args ); return response_error( EINVAL, id, name, "purple has already been initialised" ); } } sexp_val_free( args ); xmlnode *rval = xnode_new( "alist" ); AL_STR( rval, "ui-id", purple_core_get_ui() ); return response_value( 0, id, name, rval ); }
static void _elim_write_conv ( PurpleConversation *conv , const char *name , const char *alias , const char *message , PurpleMessageFlags flags , time_t mtime ) { char *msg = NULL; char *ID = new_elim_id(); xmlnode *args = xnode_new( "alist" ); xmlnode *mcall = func_call( "elim-conv-write-sys", ID, args ); g_free( ID ); fprintf( stderr, "(_elim_write_conv)\n" ); if( _elim_strippable( conv, flags ) ) msg = purple_markup_strip_html( message ); _elim_conv_args( args, conv ); AL_STR ( args, "who" , (name ? name : (alias ? alias : "")) ); AL_STR ( args, "alias", (alias ? alias : (name ? name : "")) ); AL_STR ( args, "text" , msg ? msg : message ); AL_ENUM( args, "flags", flags , ":message-flags" ); AL_INT ( args, "time" , mtime ); if( msg ) g_free( msg ); fprintf( stderr, "(elim-debug _elim_write_conv:DONE)\n" ); add_outbound_sexp( mcall ); }
static void *_elim_request_authorise ( PurpleAccount *account , const char *remote_user , const char *id , const char *alias , const char *message , gboolean on_list , PARA_CB authorize_cb , PARA_CB deny_cb , void *user_data ) { CB_HANDLER *cbh = g_new0( CB_HANDLER, 1 ); AUI_RESP *resp = g_new0( AUI_RESP , 1 ); xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); fprintf( stderr, "(_elim_request_authorise)\n" ); AL_STR ( alist, "user" , remote_user ); AL_STR ( alist, "id" , id ); AL_STR ( alist, "alias" , alias ); AL_BOOL( alist, "on-list" , on_list ); AL_STR ( alist, "message" , message ); AL_PTR ( alist, "account-uid" , account ); AL_STR ( alist, "account-name", purple_account_get_username ( account ) ); AL_STR ( alist, "im-protocol" , purple_account_get_protocol_id( account ) ); resp->ok = authorize_cb; resp->nok = deny_cb; resp->id = ID; resp->data = user_data; cbh ->func = _elim_request_authorise_cb; cbh ->data = resp; store_cb_data( ID, cbh ); xmlnode *mcall = func_call( "elim-account-request-auth", ID, alist ); add_outbound_sexp( mcall ); return cbh; }
xmlnode * response_error( int code , const char *id , const char *name , const char *message ) { GString *status = g_string_new ( "" ); xmlnode *error = xnode_new ( "function-response" ); xmlnode *meth = xnode_new_child ( error, name ); xmlnode *value = xnode_new_child ( error, "alist" ); xmlnode *stat = xnode_new_child ( value, "int" ); xmlnode *mesg = xnode_new_child ( value, "string" ); // set the id attribute on the method and the // status and message alist key name attributes: xnode_set_attrib ( meth , "id" , id ); xnode_set_attrib ( stat , "name", "status" ); xnode_set_attrib ( mesg , "name", "message" ); // insert the data for the status and message: g_string_append_printf( status, "%d" , code ); xnode_insert_data ( stat , status->str, -1 ); xnode_insert_data ( mesg , message , -1 ); g_string_free ( status, TRUE ); return error; }
static void _elim_connect_progress ( PurpleConnection *gc , const char *text , size_t step , size_t step_count ) { PurpleAccount *acct = purple_connection_get_account( gc ); fprintf( stderr, "(_elim_connect_progress)\n" ); if( acct ) { char *ID = new_elim_id(); xmlnode *alist = xnode_new( "alist" ); xmlnode *mcall = func_call( "elim-connection-progress", ID, alist ); const char *aname = purple_account_get_username ( acct ); const char *proto = purple_account_get_protocol_id( acct ); int state = purple_connection_get_state ( gc ); g_free( ID ); AL_PTR ( alist, "account-uid" , acct ); AL_STR ( alist, "account-name", aname ); AL_STR ( alist, "im-protocol" , proto ); AL_INT ( alist, "step" , step ); AL_INT ( alist, "step-count" , step_count ); AL_STR ( alist, "message" , text ); AL_ENUM( alist, "state" , state , ":connection-state" ); add_outbound_sexp( mcall ); } }
static void _elim_report_disconnect_reason( PurpleConnection *conn , PurpleConnectionError reason , const char *text ) { PurpleAccount *acct = purple_connection_get_account( conn ); if( acct ) { char *ID = new_elim_id(); xmlnode *alist = xnode_new( "alist" ); fprintf( stderr, "(_elim_report_disconnect_reason)\n" ); xmlnode *mcall = func_call( "elim-disconnect-reason", ID, alist ); const char *aname = purple_account_get_username ( acct ); const char *proto = purple_account_get_protocol_id( acct ); int state = purple_connection_get_state ( conn ); g_free( ID ); AL_PTR ( alist, "account-uid" , acct ); AL_STR ( alist, "account-name", aname ); AL_STR ( alist, "im-protocol" , proto ); AL_STR ( alist, "message" , text ); AL_ENUM( alist, "reason-code" , reason, ":connection-error" ); AL_ENUM( alist, "state" , state , ":connection-state" ); add_outbound_sexp( mcall ); } }
xmlnode * _h_elim_image ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); xmlnode *rval = xnode_new( "alist" ); int image_id = (int)ALIST_VAL_INT( args, "image-id" ); if( image_id <= 0 ) { sexp_val_free( args ); return response_error( EINVAL, id, name, "bad image ID" ); } fprintf( stderr, "searching for image id %d\n", image_id ); PurpleStoredImage *image = purple_imgstore_find_by_id( image_id ); if( !image ) { sexp_val_free( args ); return response_error( ENOENT, id, name, "image ID not found" ); } size_t size = IGET( image , size ); AL_INT ( rval, "image-id" , image_id ); AL_INT ( rval, "image-size", size ); AL_STR ( rval, "image-file", IGET( image, filename ) ); AL_STR ( rval, "image-type", IGET( image, extension ) ); AL_DATA( rval, "image-data", IGET( image, data ) , size ); sexp_val_free( args ); return response_value( 0, id, name, rval ); }
xmlnode * func_call ( const char *name, const char *id, xmlnode *args ) { xmlnode *mcall = xnode_new ( "function-call" ); xmlnode *meth = xnode_new_child( mcall , name ); xnode_set_attrib( meth, "id", id ); if( args ) xnode_insert_child( mcall, args ); return mcall; }
static void _elim_destroy_conversation ( PurpleConversation *conv ) { char *ID = new_elim_id(); xmlnode *args = xnode_new( "alist" ); xmlnode *mcall = func_call( "elim-conv-destroy", ID, args ); g_free( ID ); fprintf( stderr, "(_elim_destroy_conversation)\n" ); _elim_conv_args( args, conv ); add_outbound_sexp( mcall ); }
static void _elim_chat_remove_users ( PurpleConversation *conv , GList *users ) { char *ID = new_elim_id(); xmlnode *args = xnode_new( "alist" ); xmlnode *mcall = func_call( "elim-chat-remove-users", ID, args ); xmlnode *list = xnode_new( "list" ); g_free( ID ); fprintf( stderr, "(_elim_chat_remove_users)\n" ); _elim_conv_args( args, conv ); for( ; users; users = users->next ) { xmlnode *user = xnode_new_child( list, "string" ); xnode_insert_data( user, users->data ? users->data : "", -1 ); } AL_NODE( args, "participants", list ); fprintf( stderr, "(_elim_chat_remove_users:DONE)\n" ); add_outbound_sexp( mcall ); }
xmlnode * _h_elim_status ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { fprintf(stderr, "(elim-debug entered _h_elim_status)"); ASSERT_ALISTP( args, id, name ); elim_ping(); const char *sid = ALIST_VAL_STR( args, "status-id" ); const char *mesg = ALIST_VAL_STR( args, "status-message" ); signed int _stype = ALIST_VAL_INT( args, "status-type" ); PurpleSavedStatus *status = purple_savedstatus_find( sid ); PurpleStatusPrimitive stype = PURPLE_STATUS_UNSET; // create a new status: if( !status ) { CHECK_STATUS ( args, id, name, stype, _stype ); status = purple_savedstatus_new( sid, stype ); if( status ) { if ( mesg ) purple_savedstatus_set_message( status, mesg ); else if( sid ) purple_savedstatus_set_message( status, sid ); } } else { if( mesg ) purple_savedstatus_set_message( status, mesg ); } if( !status ) { sexp_val_free( args ); return response_error( EINVAL, id, name, "Could not create status" ); } purple_savedstatus_activate( status ); xmlnode *rval = xnode_new( "alist" ); AL_STR ( rval, "status-id" , purple_savedstatus_get_title (status) ); AL_STR ( rval, "status-message", purple_savedstatus_get_message(status) ); AL_ENUM( rval, "status-type" , purple_savedstatus_get_type (status) , ":status-primitive" ); sexp_val_free( args ); fprintf(stderr, "(elim-debug leaving _h_elim_status)"); return response_value( 0, id, name, rval ); }
static void _elim_roomlist_add ( PurpleRoomlist *list , PurpleRoomlistRoom *room ) { g_return_if_fail( list && room ); xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); __roomlist_insert_account( list->account, alist ); AL_PTR ( alist , "roomlist-id" , list ); AL_STR ( alist , "room-name" , room->name ); AL_ENUM( alist , "room-type" , room->type , ":roomlist-room-type" ); AL_PTR ( alist , "room-parent" , room->parent ); AL_BOOL( alist , "room-expanded-once", room->expanded_once ); xmlnode *fields = xnode_new_child( alist, "alist" ); xnode_set_attrib( fields, "name", "fields" ); GList *listf = g_list_first( list->fields ); GList *roomf = g_list_first( room->fields ); #define NNEXTT( a, b ) a = g_list_next( a ), b = g_list_next( b ) #define PTR_TO_BOOL(_p) (_p != NULL) for( ; listf && roomf ; NNEXTT( listf, roomf ) ) { PurpleRoomlistField *f = (PurpleRoomlistField*) listf->data; switch( f->type ) { case PURPLE_ROOMLIST_FIELD_BOOL: AL_BOOL( fields, f->name, PTR_TO_BOOL( roomf->data ) ); break; case PURPLE_ROOMLIST_FIELD_INT: AL_INT ( fields, f->name, roomf->data ); break; case PURPLE_ROOMLIST_FIELD_STRING: AL_STR ( fields, f->name, roomf->data ); break; default: fprintf( stderr, "unsupported room list field type.\n" ); break; } } xmlnode *mcall = func_call( "elim-roomlist-add", ID, alist ); g_free( ID ); add_outbound_sexp( mcall ); }
static void _elim_roomlist_destroy ( PurpleRoomlist *list ) { g_return_if_fail( list ); xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); __roomlist_insert_account( list->account, alist ); AL_PTR ( alist , "roomlist-id", list ); xmlnode *mcall = func_call( "elim-roomlist-destroy", ID, alist ); g_free( ID ); add_outbound_sexp( mcall ); }
/** * Create a new comment node, inserted under parent node as the last child. * * @param parent the parent node (NULL creates a standalone node * @param text the comment text, copied ("--" will be emitted as "- -") */ xnode_t * xnode_new_comment(xnode_t *parent, const char *text) { xnode_t *xn; g_assert(text != NULL); xn = xnode_new(XNODE_T_COMMENT); xn->u.c.text = h_strdup(text); if (parent != NULL) xnode_add_child(parent, xn); return xn; }
void __roomlist_add_list_field( gpointer _field, gpointer _parent ) { g_return_if_fail( _field && _parent ); PurpleRoomlistField *field = _field; xmlnode *parent = _parent; xmlnode *node = xnode_new( "alist" ); AL_ENUM( node , "field-type" , field->type , ":roomlist-field-type" ); AL_STR ( node , "field-label" , field->label ); AL_STR ( node , "field-name" , field->name ); AL_BOOL( node , "field-hidden", field->hidden ); xnode_insert_child( parent, node ); }
xmlnode * _h_elim_set_icon ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); elim_ping(); const char *aname = ALIST_VAL_STR ( args, "account-name" ); const char *proto = ALIST_VAL_STR ( args, "im-protocol" ); gpointer auid = ALIST_VAL_PTR ( args, "account-uid" ); const char *file = ALIST_VAL_STR ( args, "icon-file" ); GString *img = ALIST_VAL_DATA( args, "icon-data" ); gchar *bytes = NULL; gsize len = 0; gpointer set = NULL; PurpleAccount *acct = auid ? find_acct_by_uid( auid ) : purple_accounts_find( aname, proto ); if( !acct ) { sexp_val_free( args ); return response_error( ENXIO, id, name, "unknown account" ); } if( !img && file && *file ) { g_file_get_contents( file, &bytes, &len, NULL ); } else if( img ) { bytes = g_memdup( img->str, img->len ); len = img->len; } // the imgstore owns `bytes' after this, don't free it: set = purple_buddy_icons_set_account_icon( acct, (guchar *)bytes, len ); xmlnode *rval = xnode_new( "alist" ); AL_PTR ( rval, "account-uid" , acct ); AL_STR ( rval, "account-name", purple_account_get_username ( acct ) ); AL_STR ( rval, "im-protocol" , purple_account_get_protocol_id( acct ) ); AL_BOOL( rval, "has-icon" , set ? TRUE : FALSE ); sexp_val_free( args ); return response_value( 0, id, name, rval ); }
xmlnode * _h_elim_send_file ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); elim_ping(); const char *aname = ALIST_VAL_STR( args, "account-name" ); const char *proto = ALIST_VAL_STR( args, "im-protocol" ); gpointer auid = ALIST_VAL_PTR( args, "account-uid" ); PurpleAccount *acct = auid ? find_acct_by_uid( auid ) : purple_accounts_find( aname, proto ); if( !acct ) { sexp_val_free( args ); return response_error( ENXIO, id, name, "unknown account" ); } PurpleConnection *conn = purple_account_get_connection( acct ); if( !conn ) { sexp_val_free( args ); return response_error( ENXIO, id, name, "account not online" ); } // file can be NULL, but that's Ok, it just triggers a req to the user: const char *b_arg = ALIST_VAL_STRING( args, "recipient" ); const char *file = ALIST_VAL_STRING( args, "filename" ); serv_send_file( conn, b_arg, file ); // bname is a static buf allocated in purple_normalize: don't free it! // also, this means that bname is volatile, so use it immediately after // acquiring it, if you make any calls into libpurple they might invalidate // its state: const char *bname = purple_normalize( acct, b_arg ); xmlnode *rval = xnode_new( "alist" ); AL_PTR( rval, "account-uid" , acct ); AL_STR( rval, "recipient" , bname ); sexp_val_free( args ); return response_value( 0, id, name, rval ); }
/** * Create a new text node, inserted under parent node as the last child.. * * When created as verbatim, any '&' character is left as-is, otherwise they * are escaped. All '<' and '>' are escaped regardless. * * @param parent the parent node (NULL creates a standalone node * @param text the text * @param verbatim whether text is to be emitted verbatim or escaped */ xnode_t * xnode_new_text(xnode_t *parent, const char *text, bool verbatim) { xnode_t *xn; g_assert(text != NULL); xn = xnode_new(XNODE_T_TEXT); xn->u.t.text = h_strdup(text); xn->u.t.asis = booleanize(verbatim); if (parent != NULL) xnode_add_child(parent, xn); return xn; }
static void _elim_roomlist_in_progress ( PurpleRoomlist *list , gboolean flag ) { g_return_if_fail( list ); xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); __roomlist_insert_account( list->account, alist ); AL_PTR ( alist , "roomlist-id", list ); AL_BOOL( alist , "in-progress", flag ); xmlnode *mcall = func_call( "elim-roomlist-in-progress", ID, alist ); g_free( ID ); add_outbound_sexp( mcall ); }
/** * Create a new element tag node, inserted under parent node as the last child. * * @param parent the parent node (NULL creates a standalone node) * @param ns the namespace URI (NULL if none) * @param name the element's name (copied) */ xnode_t * xnode_new_element(xnode_t *parent, const char *ns, const char *name) { xnode_t *xn; g_assert(name != NULL); xn = xnode_new(XNODE_T_ELEMENT); xn->u.e.name = atom_str_get(name); xn->u.e.ns_uri = NULL == ns ? NULL : atom_str_get(ns); if (parent != NULL) xnode_add_child(parent, xn); return xn; }
xmlnode * _h_elim_buddy_info ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); PurpleAccount *acct = NULL; PurpleConnection *conn = NULL; gpointer a_uid = NULL; gpointer b_uid = ALIST_VAL_PTR( args, "bnode-uid" ); PurpleBlistNode *bnode = find_blist_node_by_uid( b_uid, TRUE ); PurpleBlistNodeType bt = PURPLE_BLIST_OTHER_NODE; if( !bnode ) HANDLER_FAIL( args, id, name, ENOENT, "no such buddy" ); bt = purple_blist_node_get_type( bnode ); switch( bt ) { case PURPLE_BLIST_BUDDY_NODE: a_uid = purple_buddy_get_account( (PurpleBuddy *)bnode ); break; default: HANDLER_FAIL( args, id, name, EINVAL, "unsupported buddy type" ); break; } FETCH_ACCOUNT( args, id, name, acct, a_uid ); conn = purple_account_get_connection( acct ); if( !conn ) HANDLER_FAIL( args, id, name, ENXIO, "account disconnected" ); xmlnode *rval = xnode_new( "alist" ); AL_PTR ( rval, "bnode-uid" , bnode ); AL_PTR ( rval, "account-uid" , acct ); AL_STR ( rval, "account-name", purple_account_get_username ( acct ) ); AL_STR ( rval, "im-protocol" , purple_account_get_protocol_id( acct ) ); serv_get_info( conn, purple_buddy_get_name( (PurpleBuddy *)bnode ) ); sexp_val_free( args ); return response_value( 0, id, name, rval ); }
static void _elim_roomlist_create ( PurpleRoomlist *list ) { g_return_if_fail( list ); xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); __roomlist_insert_account( list->account, alist ); AL_PTR ( alist, "roomlist-id", list ); xmlnode *flist = xnode_new_child( alist, "alist" ); xnode_set_attrib( flist, "name", "fields" ); g_list_foreach( list->fields, __roomlist_add_list_field, flist ); xmlnode *mcall = func_call( "elim-roomlist-create", ID, alist ); g_free( ID ); add_outbound_sexp( mcall ); }
static void _elim_chat_rename_user ( PurpleConversation *conv , const char *old_name , const char *new_name , const char *new_alias ) { char *ID = new_elim_id(); xmlnode *args = xnode_new( "alist" ); xmlnode *mcall = func_call( "elim-chat-rename-user", ID, args ); g_free( ID ); fprintf( stderr, "(_elim_chat_rename_user)\n" ); _elim_conv_args( args, conv ); AL_STR( args, "old-name" , old_name ); AL_STR( args, "new-name" , new_name ); AL_STR( args, "new-alias", new_alias ); add_outbound_sexp( mcall ); }
static void _elim_notify_added ( PurpleAccount *account , const char *remote_user, const char *id , const char *alias , const char *message ) { xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); fprintf( stderr, "(_elim_notify_added)\n" ); AL_STR( alist, "user" , remote_user ); AL_STR( alist, "alias" , alias ); AL_STR( alist, "message" , message ); AL_PTR( alist, "account-uid" , account ); AL_STR( alist, "account-name" , purple_account_get_username ( account ) ); AL_STR( alist, "im-protocol" , purple_account_get_protocol_id( account ) ); xmlnode *mcall = func_call( "elim-account-notify-added", ID, alist ); g_free( ID ); add_outbound_sexp( mcall ); }
static void _elim_status_changed ( PurpleAccount *account , PurpleStatus *status ) { xmlnode *alist = xnode_new( "alist" ); char *ID = new_elim_id(); fprintf( stderr, "(_elim_status_changed)\n" ); PurpleStatusType *type = purple_status_get_type( status ); PurpleStatusPrimitive statp = purple_status_type_get_primitive( type ); AL_PTR ( alist, "account-uid" , account ); AL_STR ( alist, "account-name", purple_account_get_username ( account ) ); AL_STR ( alist, "im-protocol" , purple_account_get_protocol_id( account ) ); AL_STR ( alist, "status-name" , purple_status_get_name ( status ) ); AL_ENUM( alist, "status-type" , statp, ":status-primitive" ); AL_BOOL( alist, "connected" , purple_account_is_connected ( account ) ); xmlnode *mcall = func_call( "elim-account-status-changed", ID, alist ); g_free( ID ); add_outbound_sexp( mcall ); }
static void _elim_notice ( PurpleConnection *conn, const char *msg ) { PurpleAccount *acct = purple_connection_get_account( conn ); if( acct ) { char *ID = new_elim_id(); xmlnode *alist = xnode_new( "alist" ); xmlnode *mcall = func_call( "elim-connection-state", ID, alist ); const char *aname = purple_account_get_username ( acct ); const char *proto = purple_account_get_protocol_id( acct ); int state = purple_connection_get_state ( conn ); g_free( ID ); AL_PTR ( alist, "account-uid" , acct ); AL_STR ( alist, "account-name", aname ); AL_STR ( alist, "im-protocol" , proto ); AL_STR ( alist, "message" , msg ); AL_ENUM( alist, "state" , state , ":connection-state" ); add_outbound_sexp( mcall ); } }
xmlnode * response_value( int code , const char *id , const char *name , xmlnode *val ) { GString *status = g_string_new ( "" ); xmlnode *mresp = xnode_new ( "function-response" ); xmlnode *meth = xnode_new_child ( mresp, name ); xmlnode *value = xnode_new_child ( mresp, "alist" ); xmlnode *stat = xnode_new_child ( value, "int" ); xnode_set_attrib ( meth , "id" , id ); xnode_set_attrib ( stat , "name", "status" ); xnode_set_attrib ( val , "name", "value" ); g_string_append_printf( status, "%d" , code ); xnode_insert_data ( stat , status->str, -1 ); g_string_free ( status, TRUE ); xnode_insert_child ( value , val ); return mresp; }
xmlnode * _h_elim_add_buddy ( const char *name , const char *id , SEXP_VALUE *args , gpointer data ) { ASSERT_ALISTP( args, id, name ); elim_ping(); int loopc = 0; const char *aname = ALIST_VAL_STR( args, "account-name" ); const char *proto = ALIST_VAL_STR( args, "im-protocol" ); gpointer auid = ALIST_VAL_PTR( args, "account-uid" ); PurpleAccount *acct = auid ? find_acct_by_uid( auid ) : purple_accounts_find( aname, proto ); if( !acct ) { sexp_val_free( args ); return response_error( ENXIO, id, name, "unknown account" ); } const char *b_arg = ALIST_VAL_STRING( args, "bnode-name" ); const char *bname = purple_normalize( acct, b_arg ); const char *gname = ALIST_VAL_STRING( args, "group" ); if( !gname || !*gname ) gname = "Buddies"; PurpleGroup *group = purple_group_new( gname ); PurpleBuddy *buddy = purple_buddy_new( acct, bname, b_arg ); PurpleBuddy *clone = NULL; //fprintf( stderr, "add-buddy( b: %p, g: %p )\n", buddy, group ); // remove other references to this buddy purple_blist_add_buddy ( buddy, NULL, group, NULL ); purple_account_add_buddy( acct , buddy ); while( ( clone = (PurpleBuddy*)find_blist_node_clone( buddy ) ) ) { if( loopc++ > 99 ) { fprintf( stderr, "ARGH! clone reaping looped: %d\n", loopc ); break; } if( clone == buddy ) { fprintf( stderr, "ARGH! %p not a clone of %p\n", buddy, clone ); break; } fprintf( stderr, "(removing clone %p %ld (of buddy: %p)\n", clone, (long)clone, buddy ); fprintf( stderr, " name : %s\n", purple_buddy_get_name(clone) ); fprintf( stderr, " group: %s)\n", purple_group_get_name( purple_buddy_get_group(clone) ) ); purple_blist_remove_buddy( clone ); } xmlnode *rval = xnode_new( "alist" ); AL_PTR( rval, "account-uid" , acct ); AL_PTR( rval, "bnode-uid" , buddy ); AL_PTR( rval, "group-uid" , group ); AL_STR( rval, "bnode-name" , purple_buddy_get_name ( buddy ) ); AL_STR( rval, "bnode-alias" , purple_buddy_get_alias ( buddy ) ); AL_STR( rval, "account-name", purple_account_get_username ( acct ) ); AL_STR( rval, "im-protocol" , purple_account_get_protocol_id( acct ) ); AL_STR( rval, "group-name" , purple_group_get_name ( group ) ); sexp_val_free( args ); return response_value( 0, id, name, rval ); }