aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2010-08-14 14:06:11 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2010-08-14 14:06:11 +0100
commit4452e69ab1f01793a37205db8227a2de2f211d3e (patch)
tree56a9a4bf6b4c41531ddcd225f8415024638b38a3
parentd93c0eb9f3f5d2d2cd78f02422d0c0ed25743e3a (diff)
Allow changing the display_name, now permanently!
-rw-r--r--lib/xmltree.c14
-rw-r--r--protocols/msn/msn.c37
-rw-r--r--protocols/msn/msn.h1
-rw-r--r--protocols/msn/msn_util.c49
-rw-r--r--protocols/msn/ns.c80
-rw-r--r--protocols/msn/soap.c34
-rw-r--r--protocols/msn/soap.h33
-rw-r--r--protocols/nogaim.h2
-rw-r--r--storage_xml.c10
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;