diff options
-rw-r--r-- | lib/xmltree.c | 14 | ||||
-rw-r--r-- | protocols/msn/msn.c | 37 | ||||
-rw-r--r-- | protocols/msn/msn.h | 1 | ||||
-rw-r--r-- | protocols/msn/msn_util.c | 49 | ||||
-rw-r--r-- | protocols/msn/ns.c | 80 | ||||
-rw-r--r-- | protocols/msn/soap.c | 34 | ||||
-rw-r--r-- | protocols/msn/soap.h | 33 | ||||
-rw-r--r-- | protocols/nogaim.h | 2 | ||||
-rw-r--r-- | storage_xml.c | 10 |
9 files changed, 113 insertions, 147 deletions
diff --git a/lib/xmltree.c b/lib/xmltree.c index f413b8f7..5fd43014 100644 --- a/lib/xmltree.c +++ b/lib/xmltree.c @@ -173,20 +173,20 @@ int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) { - for( i = 0; xt->handlers[i].func; i ++ ) + if( xt->handlers ) for( i = 0; xt->handlers[i].func; i ++ ) { /* This one is fun! \o/ */ - /* If handler.name == NULL it means it should always match. */ + /* If handler.name == NULL it means it should always match. */ if( ( xt->handlers[i].name == NULL || - /* If it's not, compare. There should always be a name. */ + /* If it's not, compare. There should always be a name. */ g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && - /* If handler.parent == NULL, it's a match. */ + /* If handler.parent == NULL, it's a match. */ ( xt->handlers[i].parent == NULL || - /* If there's a parent node, see if the name matches. */ + /* If there's a parent node, see if the name matches. */ ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : - /* If there's no parent, the handler should mention <root> as a parent. */ - g_strcasecmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) + /* If there's no parent, the handler should mention <root> as a parent. */ + strcmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) { st = xt->handlers[i].func( node, xt->data ); diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 99db509c..ed0881d1 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -24,6 +24,7 @@ */ #include "nogaim.h" +#include "soap.h" #include "msn.h" int msn_chat_id; @@ -34,8 +35,11 @@ static char *set_eval_display_name( set_t *set, char *value ); static void msn_init( account_t *acc ) { - set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); - set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc ); + set_t *s; + + s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); + s->flags |= ACC_SET_NOSAVE | ACC_SET_ONLINE_ONLY; + set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); @@ -202,11 +206,6 @@ static void msn_set_away( struct im_connection *ic, char *state, char *message ) return; } -static void msn_set_my_name( struct im_connection *ic, char *info ) -{ - msn_set_display_name( ic, info ); -} - static void msn_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ @@ -331,10 +330,9 @@ static char *set_eval_display_name( set_t *set, char *value ) { account_t *acc = set->data; struct im_connection *ic = acc->ic; - - /* Allow any name if we're offline. */ - if( ic == NULL ) - return value; + struct msn_data *md = ic->proto_data; + char buf[512]; + char *fn; if( strlen( value ) > 129 ) { @@ -342,10 +340,18 @@ static char *set_eval_display_name( set_t *set, char *value ) return NULL; } - /* Returning NULL would be better, because the server still has to - confirm the name change. However, it looks a bit confusing to the - user. */ - return msn_set_display_name( ic, value ) ? value : NULL; + msn_soap_addressbook_set_display_name( ic, value ); + + fn = g_malloc( strlen( value ) * 3 + 1 ); + strcpy( fn, value ); + http_encode( fn ); + g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", + ++md->trId, fn ); + g_free( fn ); + + /* Note: We don't actually know if the server accepted the new name, + and won't give proper feedback yet if it doesn't. */ + return msn_write( ic, buf, strlen( buf ) ) ? value : NULL; } static void msn_buddy_data_add( bee_user_t *bu ) @@ -374,7 +380,6 @@ void msn_initmodule() ret->away_states = msn_away_states; ret->set_away = msn_set_away; ret->get_info = msn_get_info; - ret->set_my_name = msn_set_my_name; ret->add_buddy = msn_add_buddy; ret->remove_buddy = msn_remove_buddy; ret->chat_msg = msn_chat_msg; diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 5c7949c9..1828cc8a 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -206,7 +206,6 @@ void msn_buddy_ask( struct im_connection *ic, char *handle, char *realname ); char *msn_findheader( char *text, char *header, int len ); char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); -char *msn_http_encode( const char *input ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ); char *msn_p11_challenge( char *challenge ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 3a19d92f..bd1bea42 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -60,7 +60,7 @@ int msn_logged_in( struct im_connection *ic ) int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ) { struct msn_data *md = ic->proto_data; - char buf[1024], *realname, groupid[8]; + char buf[1024], realname[strlen(realname_)*3+1], groupid[8]; *groupid = '\0'; if( group ) @@ -93,9 +93,10 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * if( l == NULL ) { - char *groupname = msn_http_encode( group ); + char groupname[strlen(group)+1]; + strcpy( groupname, group ); + http_encode( groupname ); g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 ); - g_free( groupname ); return msn_write( ic, buf, strlen( buf ) ); } else @@ -108,9 +109,9 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * } } - realname = msn_http_encode( realname_ ); + strcpy( realname, realname_ ); + http_encode( realname ); g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid ); - g_free( realname ); return msn_write( ic, buf, strlen( buf ) ); } @@ -379,32 +380,6 @@ int msn_handler( struct msn_handler_data *h ) return( 1 ); } -/* The difference between this function and the normal http_encode() function - is that this one escapes every 7-bit ASCII character because this is said - to avoid some lame server-side checks when setting a real-name. Also, - non-ASCII characters are not escaped because MSN servers don't seem to - appreciate that! */ -char *msn_http_encode( const char *input ) -{ - char *ret, *s; - int i; - - ret = s = g_new0( char, strlen( input ) * 3 + 1 ); - for( i = 0; input[i]; i ++ ) - if( input[i] & 128 ) - { - *s = input[i]; - s ++; - } - else - { - g_snprintf( s, 4, "%%%02X", input[i] ); - s += 3; - } - - return ret; -} - void msn_msgq_purge( struct im_connection *ic, GSList **list ) { struct msn_message *m; @@ -445,18 +420,6 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) g_string_free( ret, TRUE ); } -gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ) -{ - char *fn = msn_http_encode( rawname ); - struct msn_data *md = ic->proto_data; - char buf[1024]; - - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); - g_free( fn ); - - return msn_write( ic, buf, strlen( buf ) ) != 0; -} - /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ char *msn_p11_challenge( char *challenge ) { diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 0c067b8c..777a6ebd 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -34,7 +34,6 @@ static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition c static int msn_ns_command( gpointer data, char **cmd, int num_parts ); static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); -static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); static void msn_ns_send_adl( struct im_connection *ic ); gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) @@ -473,40 +472,6 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts ) imc_logout( ic, allow_reconnect ); return( 0 ); } -#if 0 - /* Discard this one completely for now since I don't care about the ack - and since MSN servers can apparently screw up the formatting. */ - else if( strcmp( cmd[0], "REA" ) == 0 ) - { - if( num_parts < 5 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - if( g_strcasecmp( cmd[3], ic->acc->user ) == 0 ) - { - set_t *s; - - http_decode( cmd[4] ); - strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) ); - ic->displayname[sizeof(ic->displayname)-1] = 0; - - if( ( s = set_find( &ic->acc->set, "display_name" ) ) ) - { - g_free( s->value ); - s->value = g_strdup( cmd[4] ); - } - } - else - { - /* This is not supposed to happen, but let's handle it anyway... */ - http_decode( cmd[4] ); - imcb_rename_buddy( ic, cmd[3], cmd[4] ); - } - } -#endif else if( strcmp( cmd[0], "IPG" ) == 0 ) { imcb_error( ic, "Received IPG command, we don't handle them yet." ); @@ -800,48 +765,3 @@ static void msn_ns_send_adl( struct im_connection *ic ) g_free( adls ); xt_free_node( adl ); } - -static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ) -{ - set_t *s; - - if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL ) - return FALSE; /* Shouldn't happen.. */ - - http_decode( name ); - - if( s->value && strcmp( s->value, name ) == 0 ) - { - return TRUE; - /* The names match, nothing to worry about. */ - } - else if( s->value != NULL && - ( strcmp( name, ic->acc->user ) == 0 || - set_getbool( &ic->acc->set, "local_display_name" ) ) ) - { - /* The server thinks our display name is our e-mail address - which is probably wrong, or the user *wants* us to do this: - Always use the locally set display_name. */ - return msn_set_display_name( ic, s->value ); - } - else - { - if( s->value && *s->value ) - imcb_log( ic, "BitlBee thinks your display name is `%s' but " - "the MSN server says it's `%s'. Using the MSN " - "server's name. Set local_display_name to true " - "to use the local name.", s->value, name ); - - if( g_utf8_validate( name, -1, NULL ) ) - { - g_free( s->value ); - s->value = g_strdup( name ); - } - else - { - imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); - } - - return TRUE; - } -} diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 5eae3089..cd54858f 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -608,3 +608,37 @@ int msn_soap_addressbook_request( struct im_connection *ic ) msn_soap_addressbook_handle_response, msn_soap_addressbook_free_data ); } + +/* Variant: Change our display name. */ +static int msn_soap_ab_namechange_build_request( struct msn_soap_req_data *soap_req ) +{ + struct msn_data *md = soap_req->ic->proto_data; + + soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); + soap_req->action = g_strdup( SOAP_AB_NAMECHANGE_ACTION ); + soap_req->payload = g_markup_printf_escaped( SOAP_AB_NAMECHANGE_PAYLOAD, + md->tokens[1], (char *) soap_req->data ); + + return 1; +} + +static int msn_soap_ab_namechange_handle_response( struct msn_soap_req_data *soap_req ) +{ + /* TODO: Ack the change? Not sure what the NAKs look like.. */ + return MSN_SOAP_OK; +} + +static int msn_soap_ab_namechange_free_data( struct msn_soap_req_data *soap_req ) +{ + g_free( soap_req->data ); + return 0; +} + +int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ) +{ + return msn_soap_start( ic, g_strdup( new ), + msn_soap_ab_namechange_build_request, + NULL, + msn_soap_ab_namechange_handle_response, + msn_soap_ab_namechange_free_data ); +} diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 14b0624b..5673583a 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -219,7 +219,40 @@ int msn_soap_memlist_request( struct im_connection *ic ); "</soap:Body>" \ "</soap:Envelope>" +#define SOAP_AB_NAMECHANGE_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" + +#define SOAP_AB_NAMECHANGE_PAYLOAD \ +"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ +"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">" \ + "<soap:Header>" \ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<ApplicationId>CFE80F9D-180F-4399-82AB-413F33A1FA11</ApplicationId>" \ + "<IsMigration>false</IsMigration>" \ + "<PartnerScenario>Initial</PartnerScenario>" \ + "</ABApplicationHeader>" \ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<ManagedGroupRequest>false</ManagedGroupRequest>" \ + "<TicketToken>%s</TicketToken>" \ + "</ABAuthHeader>" \ + "</soap:Header>" \ + "<soap:Body>" \ + "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<abId>00000000-0000-0000-0000-000000000000</abId>" \ + "<contacts>" \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<contactInfo>" \ + "<contactType>Me</contactType>" \ + "<displayName>%s</displayName>" \ + "</contactInfo>" \ + "<propertiesChanged>DisplayName</propertiesChanged>" \ + "</Contact>" \ + "</contacts>" \ + "</ABContactUpdate>" \ + "</soap:Body>" \ +"</soap:Envelope>" + int msn_soap_addressbook_request( struct im_connection *ic ); +int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ); #endif /* __SOAP_H__ */ diff --git a/protocols/nogaim.h b/protocols/nogaim.h index be67bb24..90254508 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -193,6 +193,8 @@ struct prpl { /* Request profile info. Free-formatted stuff, the IM module gives back this info via imcb_log(). Implementing these are optional. */ void (* get_info) (struct im_connection *, char *who); + /* set_my_name is *DEPRECATED*, not used by the UI anymore. Use the + display_name setting instead. */ void (* set_my_name) (struct im_connection *, char *name); void (* set_name) (struct im_connection *, char *who, char *name); diff --git a/storage_xml.c b/storage_xml.c index 1d6757ae..5035e214 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -319,6 +319,16 @@ static void xml_text( GMarkupParseContext *ctx, const gchar *text_orig, gsize te } else if( g_strcasecmp( g_markup_parse_context_get_element( ctx ), "setting" ) == 0 && xd->current_setting ) { + if( xd->current_account ) + { + set_t *s = set_find( xd->current_set_head, xd->current_setting ); + if( s && ( s->flags & ACC_SET_ONLINE_ONLY ) ) + { + g_free( xd->current_setting ); + xd->current_setting = NULL; + return; + } + } set_setstr( xd->current_set_head, xd->current_setting, (char*) text ); g_free( xd->current_setting ); xd->current_setting = NULL; |