Changeset 5ebff60 for protocols/msn/ns.c
- Timestamp:
- 2015-02-20T22:50:54Z (9 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/msn/ns.c
raf359b4 r5ebff60 1 1 /********************************************************************\ 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * … … 33 33 #include "xmltree.h" 34 34 35 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond);36 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond);37 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts);38 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts);39 40 static void msn_ns_send_adl_start( struct im_connection *ic);41 static void msn_ns_send_adl( struct im_connection *ic);42 43 int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ...)35 static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond); 36 static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond); 37 static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts); 38 static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts); 39 40 static void msn_ns_send_adl_start(struct im_connection *ic); 41 static void msn_ns_send_adl(struct im_connection *ic); 42 43 int msn_ns_write(struct im_connection *ic, int fd, const char *fmt, ...) 44 44 { 45 45 struct msn_data *md = ic->proto_data; … … 48 48 size_t len; 49 49 int st; 50 51 va_start( params, fmt);52 out = g_strdup_vprintf( fmt, params);53 va_end( params);54 55 if ( fd < 0 )50 51 va_start(params, fmt); 52 out = g_strdup_vprintf(fmt, params); 53 va_end(params); 54 55 if (fd < 0) { 56 56 fd = md->ns->fd; 57 58 if( getenv( "BITLBEE_DEBUG" ) ) 59 fprintf( stderr, "->NS%d:%s\n", fd, out ); 60 61 len = strlen( out ); 62 st = write( fd, out, len ); 63 g_free( out ); 64 if( st != len ) 65 { 66 imcb_error( ic, "Short write() to main server" ); 67 imc_logout( ic, TRUE ); 57 } 58 59 if (getenv("BITLBEE_DEBUG")) { 60 fprintf(stderr, "->NS%d:%s\n", fd, out); 61 } 62 63 len = strlen(out); 64 st = write(fd, out, len); 65 g_free(out); 66 if (st != len) { 67 imcb_error(ic, "Short write() to main server"); 68 imc_logout(ic, TRUE); 68 69 return 0; 69 70 } 70 71 71 72 return 1; 72 73 } 73 74 74 gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ) 75 { 76 if( handler->fd >= 0 ) 77 closesocket( handler->fd ); 78 75 gboolean msn_ns_connect(struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port) 76 { 77 if (handler->fd >= 0) { 78 closesocket(handler->fd); 79 } 80 79 81 handler->exec_command = msn_ns_command; 80 82 handler->exec_message = msn_ns_message; 81 83 handler->data = ic; 82 handler->fd = proxy_connect( host, port, msn_ns_connected, handler ); 83 if( handler->fd < 0 ) 84 { 85 imcb_error( ic, "Could not connect to server" ); 86 imc_logout( ic, TRUE ); 84 handler->fd = proxy_connect(host, port, msn_ns_connected, handler); 85 if (handler->fd < 0) { 86 imcb_error(ic, "Could not connect to server"); 87 imc_logout(ic, TRUE); 87 88 return FALSE; 88 89 } 89 90 90 91 return TRUE; 91 92 } 92 93 93 static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond)94 static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond) 94 95 { 95 96 struct msn_handler_data *handler = data; 96 97 struct im_connection *ic = handler->data; 97 98 struct msn_data *md; 98 99 if ( !g_slist_find( msn_connections, ic ) )99 100 if (!g_slist_find(msn_connections, ic)) { 100 101 return FALSE; 101 102 } 103 102 104 md = ic->proto_data; 103 104 if( source == -1 ) 105 { 106 imcb_error( ic, "Could not connect to server" ); 107 imc_logout( ic, TRUE ); 105 106 if (source == -1) { 107 imcb_error(ic, "Could not connect to server"); 108 imc_logout(ic, TRUE); 108 109 return FALSE; 109 110 } 110 111 g_free( handler->rxq);111 112 g_free(handler->rxq); 112 113 handler->rxlen = 0; 113 handler->rxq = g_new0( char, 1 ); 114 115 if( md->uuid == NULL ) 116 { 114 handler->rxq = g_new0(char, 1); 115 116 if (md->uuid == NULL) { 117 117 struct utsname name; 118 118 sha1_state_t sha[1]; 119 119 120 120 /* UUID == SHA1("BitlBee" + my hostname + MSN username) */ 121 sha1_init( sha ); 122 sha1_append( sha, (void*) "BitlBee", 7 ); 123 if( uname( &name ) == 0 ) 124 { 125 sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) ); 126 } 127 sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) ); 128 md->uuid = sha1_random_uuid( sha ); 129 memcpy( md->uuid, "b171be3e", 8 ); /* :-P */ 130 } 131 132 if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) 133 { 134 handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); 135 imcb_log( ic, "Connected to server, waiting for reply" ); 136 } 137 121 sha1_init(sha); 122 sha1_append(sha, (void *) "BitlBee", 7); 123 if (uname(&name) == 0) { 124 sha1_append(sha, (void *) name.nodename, strlen(name.nodename)); 125 } 126 sha1_append(sha, (void *) ic->acc->user, strlen(ic->acc->user)); 127 md->uuid = sha1_random_uuid(sha); 128 memcpy(md->uuid, "b171be3e", 8); /* :-P */ 129 } 130 131 if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER)) { 132 handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler); 133 imcb_log(ic, "Connected to server, waiting for reply"); 134 } 135 138 136 return FALSE; 139 137 } 140 138 141 void msn_ns_close( struct msn_handler_data *handler ) 142 { 143 if( handler->fd >= 0 ) 144 { 145 closesocket( handler->fd ); 146 b_event_remove( handler->inpa ); 147 } 148 139 void msn_ns_close(struct msn_handler_data *handler) 140 { 141 if (handler->fd >= 0) { 142 closesocket(handler->fd); 143 b_event_remove(handler->inpa); 144 } 145 149 146 handler->fd = handler->inpa = -1; 150 g_free( handler->rxq);151 g_free( handler->cmd_text);152 147 g_free(handler->rxq); 148 g_free(handler->cmd_text); 149 153 150 handler->rxlen = 0; 154 151 handler->rxq = NULL; … … 156 153 } 157 154 158 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond)155 static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond) 159 156 { 160 157 struct msn_handler_data *handler = data; 161 158 struct im_connection *ic = handler->data; 162 163 if( msn_handler( handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ 164 { 165 imcb_error( ic, "Error while reading from server" ); 166 imc_logout( ic, TRUE ); 167 159 160 if (msn_handler(handler) == -1) { /* Don't do this on ret == 0, it's already done then. */ 161 imcb_error(ic, "Error while reading from server"); 162 imc_logout(ic, TRUE); 163 168 164 return FALSE; 169 } 170 else 165 } else { 171 166 return TRUE; 172 } 173 174 static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts ) 167 } 168 } 169 170 static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts) 175 171 { 176 172 struct im_connection *ic = handler->data; 177 173 struct msn_data *md = ic->proto_data; 178 179 if( num_parts == 0 ) 180 { 174 175 if (num_parts == 0) { 181 176 /* Hrrm... Empty command...? Ignore? */ 182 return( 1 ); 183 } 184 185 if( strcmp( cmd[0], "VER" ) == 0 ) 186 { 187 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 ) 188 { 189 imcb_error( ic, "Unsupported protocol" ); 190 imc_logout( ic, FALSE ); 191 return( 0 ); 192 } 193 194 return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", 195 ++md->trId, ic->acc->user ) ); 196 } 197 else if( strcmp( cmd[0], "CVR" ) == 0 ) 198 { 177 return(1); 178 } 179 180 if (strcmp(cmd[0], "VER") == 0) { 181 if (cmd[2] && strncmp(cmd[2], MSNP_VER, 5) != 0) { 182 imcb_error(ic, "Unsupported protocol"); 183 imc_logout(ic, FALSE); 184 return(0); 185 } 186 187 return(msn_ns_write(ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", 188 ++md->trId, ic->acc->user)); 189 } else if (strcmp(cmd[0], "CVR") == 0) { 199 190 /* We don't give a damn about the information we just received */ 200 return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); 201 } 202 else if( strcmp( cmd[0], "XFR" ) == 0 ) 203 { 191 return msn_ns_write(ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user); 192 } else if (strcmp(cmd[0], "XFR") == 0) { 204 193 char *server; 205 194 int port; 206 207 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 ) 208 { 209 b_event_remove( handler->inpa ); 195 196 if (num_parts >= 6 && strcmp(cmd[2], "NS") == 0) { 197 b_event_remove(handler->inpa); 210 198 handler->inpa = -1; 211 212 server = strchr( cmd[3], ':' ); 213 if( !server ) 214 { 215 imcb_error( ic, "Syntax error" ); 216 imc_logout( ic, TRUE ); 217 return( 0 ); 199 200 server = strchr(cmd[3], ':'); 201 if (!server) { 202 imcb_error(ic, "Syntax error"); 203 imc_logout(ic, TRUE); 204 return(0); 218 205 } 219 206 *server = 0; 220 port = atoi( server + 1);207 port = atoi(server + 1); 221 208 server = cmd[3]; 222 223 imcb_log( ic, "Transferring to other server" ); 224 return msn_ns_connect( ic, handler, server, port ); 225 } 226 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 ) 227 { 209 210 imcb_log(ic, "Transferring to other server"); 211 return msn_ns_connect(ic, handler, server, port); 212 } else if (num_parts >= 6 && strcmp(cmd[2], "SB") == 0) { 228 213 struct msn_switchboard *sb; 229 230 server = strchr( cmd[3], ':' ); 231 if( !server ) 232 { 233 imcb_error( ic, "Syntax error" ); 234 imc_logout( ic, TRUE ); 235 return( 0 ); 214 215 server = strchr(cmd[3], ':'); 216 if (!server) { 217 imcb_error(ic, "Syntax error"); 218 imc_logout(ic, TRUE); 219 return(0); 236 220 } 237 221 *server = 0; 238 port = atoi( server + 1);222 port = atoi(server + 1); 239 223 server = cmd[3]; 240 241 if( strcmp( cmd[4], "CKI" ) != 0 ) 242 { 243 imcb_error( ic, "Unknown authentication method for switchboard" ); 244 imc_logout( ic, TRUE ); 245 return( 0 ); 246 } 247 248 debug( "Connecting to a new switchboard with key %s", cmd[5] ); 249 250 if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL ) 251 { 224 225 if (strcmp(cmd[4], "CKI") != 0) { 226 imcb_error(ic, "Unknown authentication method for switchboard"); 227 imc_logout(ic, TRUE); 228 return(0); 229 } 230 231 debug("Connecting to a new switchboard with key %s", cmd[5]); 232 233 if ((sb = msn_sb_create(ic, server, port, cmd[5], MSN_SB_NEW)) == NULL) { 252 234 /* Although this isn't strictly fatal for the NS connection, it's 253 235 definitely something serious (we ran out of file descriptors?). */ 254 imcb_error( ic, "Could not create new switchboard" ); 255 imc_logout( ic, TRUE ); 256 return( 0 ); 257 } 258 259 if( md->msgq ) 260 { 236 imcb_error(ic, "Could not create new switchboard"); 237 imc_logout(ic, TRUE); 238 return(0); 239 } 240 241 if (md->msgq) { 261 242 struct msn_message *m = md->msgq->data; 262 243 GSList *l; 263 264 sb->who = g_strdup( m->who);265 244 245 sb->who = g_strdup(m->who); 246 266 247 /* Move all the messages to the first user in the message 267 248 queue to the switchboard message queue. */ 268 249 l = md->msgq; 269 while( l ) 270 { 250 while (l) { 271 251 m = l->data; 272 252 l = l->next; 273 if( strcmp( m->who, sb->who ) == 0 ) 274 { 275 sb->msgq = g_slist_append( sb->msgq, m ); 276 md->msgq = g_slist_remove( md->msgq, m ); 253 if (strcmp(m->who, sb->who) == 0) { 254 sb->msgq = g_slist_append(sb->msgq, m); 255 md->msgq = g_slist_remove(md->msgq, m); 277 256 } 278 257 } 279 258 } 280 } 281 else 282 { 283 imcb_error( ic, "Syntax error" ); 284 imc_logout( ic, TRUE ); 285 return( 0 ); 286 } 287 } 288 else if( strcmp( cmd[0], "USR" ) == 0 ) 289 { 290 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 && 291 strcmp( cmd[3], "S" ) == 0 ) 292 { 293 g_free( md->pp_policy ); 294 md->pp_policy = g_strdup( cmd[4] ); 295 msn_soap_passport_sso_request( ic, cmd[5] ); 296 } 297 else if( strcmp( cmd[2], "OK" ) == 0 ) 298 { 259 } else { 260 imcb_error(ic, "Syntax error"); 261 imc_logout(ic, TRUE); 262 return(0); 263 } 264 } else if (strcmp(cmd[0], "USR") == 0) { 265 if (num_parts >= 6 && strcmp(cmd[2], "SSO") == 0 && 266 strcmp(cmd[3], "S") == 0) { 267 g_free(md->pp_policy); 268 md->pp_policy = g_strdup(cmd[4]); 269 msn_soap_passport_sso_request(ic, cmd[5]); 270 } else if (strcmp(cmd[2], "OK") == 0) { 299 271 /* If the number after the handle is 0, the e-mail 300 272 address is unverified, which means we can't change 301 273 the display name. */ 302 if ( cmd[4][0] == '0' )274 if (cmd[4][0] == '0') { 303 275 md->flags |= MSN_EMAIL_UNVERIFIED; 304 305 imcb_log( ic, "Authenticated, getting buddy list" ); 306 msn_soap_memlist_request( ic ); 307 } 308 else 309 { 310 imcb_error( ic, "Unknown authentication type" ); 311 imc_logout( ic, FALSE ); 312 return( 0 ); 313 } 314 } 315 else if( strcmp( cmd[0], "MSG" ) == 0 ) 316 { 317 if( num_parts < 4 ) 318 { 319 imcb_error( ic, "Syntax error" ); 320 imc_logout( ic, TRUE ); 321 return( 0 ); 322 } 323 324 handler->msglen = atoi( cmd[3] ); 325 326 if( handler->msglen <= 0 ) 327 { 328 imcb_error( ic, "Syntax error" ); 329 imc_logout( ic, TRUE ); 330 return( 0 ); 331 } 332 } 333 else if( strcmp( cmd[0], "BLP" ) == 0 ) 334 { 335 msn_ns_send_adl_start( ic ); 336 return msn_ns_finish_login( ic ); 337 } 338 else if( strcmp( cmd[0], "ADL" ) == 0 ) 339 { 340 if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) 341 { 342 msn_ns_send_adl( ic ); 343 return msn_ns_finish_login( ic ); 344 } 345 else if( num_parts >= 3 ) 346 { 347 handler->msglen = atoi( cmd[2] ); 348 } 349 } 350 else if( strcmp( cmd[0], "PRP" ) == 0 ) 351 { 352 imcb_connected( ic ); 353 } 354 else if( strcmp( cmd[0], "CHL" ) == 0 ) 355 { 276 } 277 278 imcb_log(ic, "Authenticated, getting buddy list"); 279 msn_soap_memlist_request(ic); 280 } else { 281 imcb_error(ic, "Unknown authentication type"); 282 imc_logout(ic, FALSE); 283 return(0); 284 } 285 } else if (strcmp(cmd[0], "MSG") == 0) { 286 if (num_parts < 4) { 287 imcb_error(ic, "Syntax error"); 288 imc_logout(ic, TRUE); 289 return(0); 290 } 291 292 handler->msglen = atoi(cmd[3]); 293 294 if (handler->msglen <= 0) { 295 imcb_error(ic, "Syntax error"); 296 imc_logout(ic, TRUE); 297 return(0); 298 } 299 } else if (strcmp(cmd[0], "BLP") == 0) { 300 msn_ns_send_adl_start(ic); 301 return msn_ns_finish_login(ic); 302 } else if (strcmp(cmd[0], "ADL") == 0) { 303 if (num_parts >= 3 && strcmp(cmd[2], "OK") == 0) { 304 msn_ns_send_adl(ic); 305 return msn_ns_finish_login(ic); 306 } else if (num_parts >= 3) { 307 handler->msglen = atoi(cmd[2]); 308 } 309 } else if (strcmp(cmd[0], "PRP") == 0) { 310 imcb_connected(ic); 311 } else if (strcmp(cmd[0], "CHL") == 0) { 356 312 char *resp; 357 313 int st; 358 359 if( num_parts < 3 ) 360 { 361 imcb_error( ic, "Syntax error" ); 362 imc_logout( ic, TRUE ); 363 return( 0 ); 364 } 365 366 resp = msn_p11_challenge( cmd[2] ); 367 368 st = msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s", 369 ++md->trId, MSNP11_PROD_ID, 370 strlen( resp ), resp ); 371 g_free( resp ); 314 315 if (num_parts < 3) { 316 imcb_error(ic, "Syntax error"); 317 imc_logout(ic, TRUE); 318 return(0); 319 } 320 321 resp = msn_p11_challenge(cmd[2]); 322 323 st = msn_ns_write(ic, -1, "QRY %d %s %zd\r\n%s", 324 ++md->trId, MSNP11_PROD_ID, 325 strlen(resp), resp); 326 g_free(resp); 372 327 return st; 373 } 374 else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 ) 375 { 328 } else if (strcmp(cmd[0], "ILN") == 0 || strcmp(cmd[0], "NLN") == 0) { 376 329 const struct msn_away_state *st; 377 330 const char *handle; 378 331 int cap = 0; 379 380 if( num_parts < 6 ) 381 { 382 imcb_error( ic, "Syntax error" ); 383 imc_logout( ic, TRUE ); 384 return( 0 ); 332 333 if (num_parts < 6) { 334 imcb_error(ic, "Syntax error"); 335 imc_logout(ic, TRUE); 336 return(0); 385 337 } 386 338 /* ILN and NLN are more or less the same, except ILN has a trId 387 at the start, and NLN has a capability field at the end. 339 at the start, and NLN has a capability field at the end. 388 340 Does ILN still exist BTW? */ 389 if( cmd[0][1] == 'I' ) 390 cmd ++; 391 else 392 cap = atoi( cmd[4] ); 393 394 handle = msn_normalize_handle( cmd[2] ); 395 if( strcmp( handle, ic->acc->user ) == 0 ) 341 if (cmd[0][1] == 'I') { 342 cmd++; 343 } else { 344 cap = atoi(cmd[4]); 345 } 346 347 handle = msn_normalize_handle(cmd[2]); 348 if (strcmp(handle, ic->acc->user) == 0) { 396 349 return 1; /* That's me! */ 397 398 http_decode( cmd[3] );399 imcb_rename_buddy( ic, handle, cmd[3]);400 401 st = msn_away_state_by_code( cmd[1] ); 402 if( !st )403 {350 351 } 352 http_decode(cmd[3]); 353 imcb_rename_buddy(ic, handle, cmd[3]); 354 355 st = msn_away_state_by_code(cmd[1]); 356 if (!st) { 404 357 /* FIXME: Warn/Bomb about unknown away state? */ 405 358 st = msn_away_state_list + 1; 406 359 } 407 408 imcb_buddy_status( ic, handle, OPT_LOGGED_IN | 409 ( st != msn_away_state_list ? OPT_AWAY : 0 ) | 410 ( cap & 1 ? OPT_MOBILE : 0 ), 411 st->name, NULL ); 412 413 msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) ); 414 } 415 else if( strcmp( cmd[0], "FLN" ) == 0 ) 416 { 360 361 imcb_buddy_status(ic, handle, OPT_LOGGED_IN | 362 (st != msn_away_state_list ? OPT_AWAY : 0) | 363 (cap & 1 ? OPT_MOBILE : 0), 364 st->name, NULL); 365 366 msn_sb_stop_keepalives(msn_sb_by_handle(ic, handle)); 367 } else if (strcmp(cmd[0], "FLN") == 0) { 417 368 const char *handle; 418 419 if ( cmd[1] == NULL )369 370 if (cmd[1] == NULL) { 420 371 return 1; 421 422 handle = msn_normalize_handle( cmd[1] ); 423 imcb_buddy_status( ic, handle, 0, NULL, NULL ); 424 msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE ); 425 } 426 else if( strcmp( cmd[0], "RNG" ) == 0 ) 427 { 372 } 373 374 handle = msn_normalize_handle(cmd[1]); 375 imcb_buddy_status(ic, handle, 0, NULL, NULL); 376 msn_sb_start_keepalives(msn_sb_by_handle(ic, handle), TRUE); 377 } else if (strcmp(cmd[0], "RNG") == 0) { 428 378 struct msn_switchboard *sb; 429 379 char *server; 430 380 int session, port; 431 432 if( num_parts < 7 ) 433 { 434 imcb_error( ic, "Syntax error" ); 435 imc_logout( ic, TRUE ); 436 return( 0 ); 437 } 438 439 session = atoi( cmd[1] ); 440 441 server = strchr( cmd[2], ':' ); 442 if( !server ) 443 { 444 imcb_error( ic, "Syntax error" ); 445 imc_logout( ic, TRUE ); 446 return( 0 ); 381 382 if (num_parts < 7) { 383 imcb_error(ic, "Syntax error"); 384 imc_logout(ic, TRUE); 385 return(0); 386 } 387 388 session = atoi(cmd[1]); 389 390 server = strchr(cmd[2], ':'); 391 if (!server) { 392 imcb_error(ic, "Syntax error"); 393 imc_logout(ic, TRUE); 394 return(0); 447 395 } 448 396 *server = 0; 449 port = atoi( server + 1);397 port = atoi(server + 1); 450 398 server = cmd[2]; 451 452 if( strcmp( cmd[3], "CKI" ) != 0 ) 453 { 454 imcb_error( ic, "Unknown authentication method for switchboard" ); 455 imc_logout( ic, TRUE ); 456 return( 0 ); 457 } 458 459 debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] ); 460 461 if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL ) 462 { 399 400 if (strcmp(cmd[3], "CKI") != 0) { 401 imcb_error(ic, "Unknown authentication method for switchboard"); 402 imc_logout(ic, TRUE); 403 return(0); 404 } 405 406 debug("Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4]); 407 408 if ((sb = msn_sb_create(ic, server, port, cmd[4], session)) == NULL) { 463 409 /* Although this isn't strictly fatal for the NS connection, it's 464 410 definitely something serious (we ran out of file descriptors?). */ 465 imcb_error( ic, "Could not create new switchboard" ); 466 imc_logout( ic, TRUE ); 467 return( 0 ); 468 } 469 else 470 { 471 sb->who = g_strdup( msn_normalize_handle( cmd[5] ) ); 472 } 473 } 474 else if( strcmp( cmd[0], "OUT" ) == 0 ) 475 { 411 imcb_error(ic, "Could not create new switchboard"); 412 imc_logout(ic, TRUE); 413 return(0); 414 } else { 415 sb->who = g_strdup(msn_normalize_handle(cmd[5])); 416 } 417 } else if (strcmp(cmd[0], "OUT") == 0) { 476 418 int allow_reconnect = TRUE; 477 478 if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 ) 479 { 480 imcb_error( ic, "Someone else logged in with your account" ); 419 420 if (cmd[1] && strcmp(cmd[1], "OTH") == 0) { 421 imcb_error(ic, "Someone else logged in with your account"); 481 422 allow_reconnect = FALSE; 482 } 483 else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 ) 484 { 485 imcb_error( ic, "Terminating session because of server shutdown" ); 486 } 487 else 488 { 489 imcb_error( ic, "Session terminated by remote server (%s)", 490 cmd[1] ? cmd[1] : "reason unknown)" ); 491 } 492 493 imc_logout( ic, allow_reconnect ); 494 return( 0 ); 495 } 496 else if( strcmp( cmd[0], "IPG" ) == 0 ) 497 { 498 imcb_error( ic, "Received IPG command, we don't handle them yet." ); 499 500 handler->msglen = atoi( cmd[1] ); 501 502 if( handler->msglen <= 0 ) 503 { 504 imcb_error( ic, "Syntax error" ); 505 imc_logout( ic, TRUE ); 506 return( 0 ); 423 } else if (cmd[1] && strcmp(cmd[1], "SSD") == 0) { 424 imcb_error(ic, "Terminating session because of server shutdown"); 425 } else { 426 imcb_error(ic, "Session terminated by remote server (%s)", 427 cmd[1] ? cmd[1] : "reason unknown)"); 428 } 429 430 imc_logout(ic, allow_reconnect); 431 return(0); 432 } else if (strcmp(cmd[0], "IPG") == 0) { 433 imcb_error(ic, "Received IPG command, we don't handle them yet."); 434 435 handler->msglen = atoi(cmd[1]); 436 437 if (handler->msglen <= 0) { 438 imcb_error(ic, "Syntax error"); 439 imc_logout(ic, TRUE); 440 return(0); 507 441 } 508 442 } 509 443 #if 0 510 else if( strcmp( cmd[0], "ADG" ) == 0 ) 511 { 512 char *group = g_strdup( cmd[3] ); 444 else if (strcmp(cmd[0], "ADG") == 0) { 445 char *group = g_strdup(cmd[3]); 513 446 int groupnum, i; 514 447 GSList *l, *next; 515 516 http_decode( group ); 517 if( sscanf( cmd[4], "%d", &groupnum ) == 1 ) 518 { 519 if( groupnum >= md->groupcount ) 520 { 521 md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 ); 522 for( i = md->groupcount; i <= groupnum; i ++ ) 448 449 http_decode(group); 450 if (sscanf(cmd[4], "%d", &groupnum) == 1) { 451 if (groupnum >= md->groupcount) { 452 md->grouplist = g_renew(char *, md->grouplist, groupnum + 1); 453 for (i = md->groupcount; i <= groupnum; i++) { 523 454 md->grouplist[i] = NULL; 455 } 524 456 md->groupcount = groupnum + 1; 525 457 } 526 g_free( md->grouplist[groupnum]);458 g_free(md->grouplist[groupnum]); 527 459 md->grouplist[groupnum] = group; 528 } 529 else 530 { 460 } else { 531 461 /* Shouldn't happen, but if it does, give up on the group. */ 532 g_free( group);533 imcb_error( ic, "Syntax error");534 imc_logout( ic, TRUE);462 g_free(group); 463 imcb_error(ic, "Syntax error"); 464 imc_logout(ic, TRUE); 535 465 return 0; 536 466 } 537 538 for( l = md->grpq; l; l = next ) 539 { 467 468 for (l = md->grpq; l; l = next) { 540 469 struct msn_groupadd *ga = l->data; 541 470 next = l->next; 542 if( g_strcasecmp( ga->group, group ) == 0 ) 543 { 544 if( !msn_buddy_list_add( ic, "FL", ga->who, ga->who, group ) ) 471 if (g_strcasecmp(ga->group, group) == 0) { 472 if (!msn_buddy_list_add(ic, "FL", ga->who, ga->who, group)) { 545 473 return 0; 546 547 g_free( ga->group ); 548 g_free( ga->who ); 549 g_free( ga ); 550 md->grpq = g_slist_remove( md->grpq, ga ); 474 } 475 476 g_free(ga->group); 477 g_free(ga->who); 478 g_free(ga); 479 md->grpq = g_slist_remove(md->grpq, ga); 551 480 } 552 481 } 553 482 } 554 483 #endif 555 else if( strcmp( cmd[0], "GCF" ) == 0 ) 556 { 484 else if (strcmp(cmd[0], "GCF") == 0) { 557 485 /* Coming up is cmd[2] bytes of stuff we're supposed to 558 486 censore. Meh. */ 559 handler->msglen = atoi( cmd[2] ); 560 } 561 else if( strcmp( cmd[0], "UBX" ) == 0 ) 562 { 487 handler->msglen = atoi(cmd[2]); 488 } else if (strcmp(cmd[0], "UBX") == 0) { 563 489 /* Status message. */ 564 if( num_parts >= 3 ) 565 handler->msglen = atoi( cmd[2] ); 566 } 567 else if( strcmp( cmd[0], "NOT" ) == 0 ) 568 { 490 if (num_parts >= 3) { 491 handler->msglen = atoi(cmd[2]); 492 } 493 } else if (strcmp(cmd[0], "NOT") == 0) { 569 494 /* Some kind of notification, poorly documented but 570 495 apparently used to announce address book changes. */ 571 if( num_parts >= 2 ) 572 handler->msglen = atoi( cmd[1] ); 573 } 574 else if( strcmp( cmd[0], "UBM" ) == 0 ) 575 { 576 if( num_parts >= 7 ) 577 handler->msglen = atoi( cmd[6] ); 578 } 579 else if( strcmp( cmd[0], "QNG" ) == 0 ) 580 { 496 if (num_parts >= 2) { 497 handler->msglen = atoi(cmd[1]); 498 } 499 } else if (strcmp(cmd[0], "UBM") == 0) { 500 if (num_parts >= 7) { 501 handler->msglen = atoi(cmd[6]); 502 } 503 } else if (strcmp(cmd[0], "QNG") == 0) { 581 504 ic->flags |= OPT_PONGED; 582 } 583 else if( g_ascii_isdigit( cmd[0][0] ) ) 584 { 585 int num = atoi( cmd[0] ); 586 const struct msn_status_code *err = msn_status_by_number( num ); 587 588 imcb_error( ic, "Error reported by MSN server: %s", err->text ); 589 590 if( err->flags & STATUS_FATAL ) 591 { 592 imc_logout( ic, TRUE ); 593 return( 0 ); 594 } 595 505 } else if (g_ascii_isdigit(cmd[0][0])) { 506 int num = atoi(cmd[0]); 507 const struct msn_status_code *err = msn_status_by_number(num); 508 509 imcb_error(ic, "Error reported by MSN server: %s", err->text); 510 511 if (err->flags & STATUS_FATAL) { 512 imc_logout(ic, TRUE); 513 return(0); 514 } 515 596 516 /* Oh yes, errors can have payloads too now. Discard them for now. */ 597 if( num_parts >= 3 ) 598 handler->msglen = atoi( cmd[2] ); 599 } 600 else 601 { 517 if (num_parts >= 3) { 518 handler->msglen = atoi(cmd[2]); 519 } 520 } else { 602 521 /* debug( "Received unknown command from main server: %s", cmd[0] ); */ 603 522 } 604 605 return( 1);606 } 607 608 static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts)523 524 return(1); 525 } 526 527 static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts) 609 528 { 610 529 struct im_connection *ic = handler->data; 611 530 char *body; 612 531 int blen = 0; 613 614 if ( !num_parts )615 return( 1);616 617 if( ( body = strstr( msg, "\r\n\r\n" ) ) ) 618 {532 533 if (!num_parts) { 534 return(1); 535 } 536 537 if ((body = strstr(msg, "\r\n\r\n"))) { 619 538 body += 4; 620 blen = msglen - ( body - msg ); 621 } 622 623 if( strcmp( cmd[0], "MSG" ) == 0 ) 624 { 625 if( g_strcasecmp( cmd[1], "Hotmail" ) == 0 ) 626 { 627 char *ct = get_rfc822_header( msg, "Content-Type:", msglen ); 628 629 if( !ct ) 630 return( 1 ); 631 632 if( g_strncasecmp( ct, "application/x-msmsgssystemmessage", 33 ) == 0 ) 633 { 539 blen = msglen - (body - msg); 540 } 541 542 if (strcmp(cmd[0], "MSG") == 0) { 543 if (g_strcasecmp(cmd[1], "Hotmail") == 0) { 544 char *ct = get_rfc822_header(msg, "Content-Type:", msglen); 545 546 if (!ct) { 547 return(1); 548 } 549 550 if (g_strncasecmp(ct, "application/x-msmsgssystemmessage", 33) == 0) { 634 551 char *mtype; 635 552 char *arg1; 636 637 if ( !body )638 return( 1);639 640 mtype = get_rfc822_header( body, "Type:", blen ); 641 arg1 = get_rfc822_header( body, "Arg1:", blen);642 643 if( mtype && strcmp( mtype, "1" ) == 0 ) 644 {645 if ( arg1 )646 imcb_log( ic, "The server is going down for maintenance in %s minutes.", arg1 );647 }648 649 g_free( arg1 );650 g_free( mtype ); 651 }652 else if( g_strncasecmp( ct, "text/x-msmsgsprofile", 20 ) == 0 )653 {553 554 if (!body) { 555 return(1); 556 } 557 558 mtype = get_rfc822_header(body, "Type:", blen); 559 arg1 = get_rfc822_header(body, "Arg1:", blen); 560 561 if (mtype && strcmp(mtype, "1") == 0) { 562 if (arg1) { 563 imcb_log(ic, "The server is going down for maintenance in %s minutes.", 564 arg1); 565 } 566 } 567 568 g_free(arg1); 569 g_free(mtype); 570 } else if (g_strncasecmp(ct, "text/x-msmsgsprofile", 20) == 0) { 654 571 /* We don't care about this profile for now... */ 655 } 656 else if( g_strncasecmp( ct, "text/x-msmsgsinitialemailnotification", 37 ) == 0 ) 657 { 658 if( set_getbool( &ic->acc->set, "mail_notifications" ) ) 659 { 660 char *inbox = get_rfc822_header( body, "Inbox-Unread:", blen ); 661 char *folders = get_rfc822_header( body, "Folders-Unread:", blen ); 662 663 if( inbox && folders ) 664 imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); 665 666 g_free( inbox ); 667 g_free( folders ); 668 } 669 } 670 else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 ) 671 { 672 if( set_getbool( &ic->acc->set, "mail_notifications" ) ) 673 { 674 char *from = get_rfc822_header( body, "From-Addr:", blen ); 675 char *fromname = get_rfc822_header( body, "From:", blen ); 676 677 if( from && fromname ) 678 imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); 679 680 g_free( from ); 681 g_free( fromname ); 682 } 683 } 684 else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) 685 { 686 } 687 else if( g_strncasecmp( ct, "text/x-msmsgsinitialmdatanotification", 37 ) == 0 || 688 g_strncasecmp( ct, "text/x-msmsgsoimnotification", 28 ) == 0 ) 689 { 572 } else if (g_strncasecmp(ct, "text/x-msmsgsinitialemailnotification", 37) == 0) { 573 if (set_getbool(&ic->acc->set, "mail_notifications")) { 574 char *inbox = get_rfc822_header(body, "Inbox-Unread:", blen); 575 char *folders = get_rfc822_header(body, "Folders-Unread:", blen); 576 577 if (inbox && folders) { 578 imcb_log(ic, 579 "INBOX contains %s new messages, plus %s messages in other folders.", inbox, 580 folders); 581 } 582 583 g_free(inbox); 584 g_free(folders); 585 } 586 } else if (g_strncasecmp(ct, "text/x-msmsgsemailnotification", 30) == 0) { 587 if (set_getbool(&ic->acc->set, "mail_notifications")) { 588 char *from = get_rfc822_header(body, "From-Addr:", blen); 589 char *fromname = get_rfc822_header(body, "From:", blen); 590 591 if (from && fromname) { 592 imcb_log(ic, "Received an e-mail message from %s <%s>.", fromname, 593 from); 594 } 595 596 g_free(from); 597 g_free(fromname); 598 } 599 } else if (g_strncasecmp(ct, "text/x-msmsgsactivemailnotification", 35) == 0) { 600 } else if (g_strncasecmp(ct, "text/x-msmsgsinitialmdatanotification", 37) == 0 || 601 g_strncasecmp(ct, "text/x-msmsgsoimnotification", 28) == 0) { 690 602 /* We received an offline message. Or at least notification 691 603 that there is one waiting for us. Fetching the message(s) … … 694 606 have the notification server send them directly, I was 695 607 pretty sure I saw Pidgin do it.. 696 608 697 609 At least give a notification for now, seems like a 698 610 reasonable thing to do. Only problem is, they'll keep 699 611 coming back at login time until you read them using a 700 612 different client. :-( */ 701 702 char *xml = get_rfc822_header( body, "Mail-Data:", blen);613 614 char *xml = get_rfc822_header(body, "Mail-Data:", blen); 703 615 struct xt_node *md, *m; 704 705 if ( !xml )616 617 if (!xml) { 706 618 return 1; 707 md = xt_from_string( xml, 0 ); 708 if( !md ) 619 } 620 md = xt_from_string(xml, 0); 621 if (!md) { 709 622 return 1; 710 711 for( m = md->children; ( m = xt_find_node( m, "M" ) ); m = m->next ) 712 {713 struct xt_node *e = xt_find_node( m->children, "E");714 struct xt_node *rt = xt_find_node( m->children, "RT");623 } 624 625 for (m = md->children; (m = xt_find_node(m, "M")); m = m->next) { 626 struct xt_node *e = xt_find_node(m->children, "E"); 627 struct xt_node *rt = xt_find_node(m->children, "RT"); 715 628 struct tm tp; 716 629 time_t msgtime = 0; 717 718 if ( !e || !e->text )630 631 if (!e || !e->text) { 719 632 continue; 720 721 memset( &tp, 0, sizeof( tp ) ); 722 if( rt && rt->text &&723 sscanf( rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.",724 &tp.tm_year, &tp.tm_mon, &tp.tm_mday,725 &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) == 6 )726 {633 } 634 635 memset(&tp, 0, sizeof(tp)); 636 if (rt && rt->text && 637 sscanf(rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.", 638 &tp.tm_year, &tp.tm_mon, &tp.tm_mday, 639 &tp.tm_hour, &tp.tm_min, &tp.tm_sec) == 6) { 727 640 tp.tm_year -= 1900; 728 tp.tm_mon 729 msgtime = mktime_utc( &tp);730 641 tp.tm_mon--; 642 msgtime = mktime_utc(&tp); 643 731 644 } 732 imcb_buddy_msg( ic, e->text, "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, msgtime ); 733 } 734 735 g_free( xml ); 736 xt_free_node( md ); 737 } 738 else 739 { 740 debug( "Can't handle %s packet from notification server", ct ); 741 } 742 743 g_free( ct ); 744 } 745 } 746 else if( strcmp( cmd[0], "UBX" ) == 0 ) 747 { 645 imcb_buddy_msg(ic, e->text, 646 "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, 647 msgtime); 648 } 649 650 g_free(xml); 651 xt_free_node(md); 652 } else { 653 debug("Can't handle %s packet from notification server", ct); 654 } 655 656 g_free(ct); 657 } 658 } else if (strcmp(cmd[0], "UBX") == 0) { 748 659 struct xt_node *ubx, *psm; 749 660 char *psm_text = NULL; 750 751 ubx = xt_from_string( msg, msglen);752 if ( ubx && strcmp( ubx->name, "Data") == 0 &&753 ( psm = xt_find_node( ubx->children, "PSM" ) ) )661 662 ubx = xt_from_string(msg, msglen); 663 if (ubx && strcmp(ubx->name, "Data") == 0 && 664 (psm = xt_find_node(ubx->children, "PSM"))) { 754 665 psm_text = psm->text; 755 756 imcb_buddy_status_msg( ic, msn_normalize_handle( cmd[1] ), psm_text ); 757 xt_free_node( ubx ); 758 } 759 else if( strcmp( cmd[0], "ADL" ) == 0 ) 760 { 666 } 667 668 imcb_buddy_status_msg(ic, msn_normalize_handle(cmd[1]), psm_text); 669 xt_free_node(ubx); 670 } else if (strcmp(cmd[0], "ADL") == 0) { 761 671 struct xt_node *adl, *d, *c; 762 763 if ( !( adl = xt_from_string( msg, msglen ) ) )672 673 if (!(adl = xt_from_string(msg, msglen))) { 764 674 return 1; 765 766 for( d = adl->children; d; d = d->next ) 767 {675 } 676 677 for (d = adl->children; d; d = d->next) { 768 678 char *dn; 769 if ( strcmp( d->name, "d") != 0 ||770 ( dn = xt_find_attr( d, "n" ) ) == NULL )679 if (strcmp(d->name, "d") != 0 || 680 (dn = xt_find_attr(d, "n")) == NULL) { 771 681 continue; 772 for( c = d->children; c; c = c->next )773 {682 } 683 for (c = d->children; c; c = c->next) { 774 684 bee_user_t *bu; 775 685 struct msn_buddy_data *bd; 776 686 char *cn, *handle, *f, *l; 777 687 int flags; 778 779 if ( strcmp( c->name, "c") != 0 ||780 ( l = xt_find_attr( c, "l" )) == NULL ||781 ( cn = xt_find_attr( c, "n" ) ) == NULL )688 689 if (strcmp(c->name, "c") != 0 || 690 (l = xt_find_attr(c, "l")) == NULL || 691 (cn = xt_find_attr(c, "n")) == NULL) { 782 692 continue; 783 693 } 694 784 695 /* FIXME: Use "t" here, guess I should just add it 785 696 as a prefix like elsewhere in the protocol. */ 786 handle = g_strdup_printf( "%s@%s", cn, dn ); 787 if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || 788 ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) 789 { 790 g_free( handle ); 697 handle = g_strdup_printf("%s@%s", cn, dn); 698 if (!((bu = bee_user_by_handle(ic->bee, ic, handle)) || 699 (bu = bee_user_new(ic->bee, ic, handle, 0)))) { 700 g_free(handle); 791 701 continue; 792 702 } 793 g_free( handle);703 g_free(handle); 794 704 bd = bu->data; 795 796 if( ( f = xt_find_attr( c, "f" ) ) ) 797 { 798 http_decode( f ); 799 imcb_rename_buddy( ic, bu->handle, f ); 800 } 801 802 flags = atoi( l ) & 15; 803 if( bd->flags != flags ) 804 { 705 706 if ((f = xt_find_attr(c, "f"))) { 707 http_decode(f); 708 imcb_rename_buddy(ic, bu->handle, f); 709 } 710 711 flags = atoi(l) & 15; 712 if (bd->flags != flags) { 805 713 bd->flags = flags; 806 msn_buddy_ask( bu ); 807 } 808 } 809 } 810 } 811 else if( strcmp( cmd[0], "UBM" ) == 0 ) 812 { 714 msn_buddy_ask(bu); 715 } 716 } 717 } 718 } else if (strcmp(cmd[0], "UBM") == 0) { 813 719 /* This one will give us msgs from federated networks. Technically 814 720 it should also get us offline messages, but I don't know how 815 721 I can signal MSN servers to use it. */ 816 722 char *ct, *handle; 817 818 if( strcmp( cmd[1], ic->acc->user ) == 0 ) 819 { 723 724 if (strcmp(cmd[1], ic->acc->user) == 0) { 820 725 /* With MPOP, you'll get copies of your own msgs from other 821 726 sessions. Discard those at least for now. */ 822 727 return 1; 823 728 } 824 825 ct = get_rfc822_header( msg, "Content-Type", msglen ); 826 if( strncmp( ct, "text/plain", 10 ) != 0 ) 827 { 729 730 ct = get_rfc822_header(msg, "Content-Type", msglen); 731 if (strncmp(ct, "text/plain", 10) != 0) { 828 732 /* Typing notification or something? */ 829 g_free( ct);733 g_free(ct); 830 734 return 1; 831 735 } 832 if( strcmp( cmd[2], "1" ) != 0 ) 833 handle = g_strdup_printf( "%s:%s", cmd[2], cmd[1] ); 834 else 835 handle = g_strdup( cmd[1] ); 836 837 imcb_buddy_msg( ic, handle, body, 0, 0 ); 838 g_free( handle ); 839 } 840 736 if (strcmp(cmd[2], "1") != 0) { 737 handle = g_strdup_printf("%s:%s", cmd[2], cmd[1]); 738 } else { 739 handle = g_strdup(cmd[1]); 740 } 741 742 imcb_buddy_msg(ic, handle, body, 0, 0); 743 g_free(handle); 744 } 745 841 746 return 1; 842 747 } 843 748 844 void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error)749 void msn_auth_got_passport_token(struct im_connection *ic, const char *token, const char *error) 845 750 { 846 751 struct msn_data *md; 847 752 848 753 /* Dead connection? */ 849 if ( g_slist_find( msn_connections, ic ) == NULL )754 if (g_slist_find(msn_connections, ic) == NULL) { 850 755 return; 851 756 } 757 852 758 md = ic->proto_data; 853 854 if( token ) 855 { 856 msn_ns_write( ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid ); 857 } 858 else 859 { 860 imcb_error( ic, "Error during Passport authentication: %s", error ); 861 imc_logout( ic, TRUE ); 862 } 863 } 864 865 void msn_auth_got_contact_list( struct im_connection *ic ) 759 760 if (token) { 761 msn_ns_write(ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid); 762 } else { 763 imcb_error(ic, "Error during Passport authentication: %s", error); 764 imc_logout(ic, TRUE); 765 } 766 } 767 768 void msn_auth_got_contact_list(struct im_connection *ic) 866 769 { 867 770 struct msn_data *md; 868 771 869 772 /* Dead connection? */ 870 if ( g_slist_find( msn_connections, ic ) == NULL )773 if (g_slist_find(msn_connections, ic) == NULL) { 871 774 return; 872 775 } 776 873 777 md = ic->proto_data; 874 msn_ns_write( ic, -1, "BLP %d %s\r\n", ++md->trId, "BL");875 } 876 877 static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data)778 msn_ns_write(ic, -1, "BLP %d %s\r\n", ++md->trId, "BL"); 779 } 780 781 static gboolean msn_ns_send_adl_1(gpointer key, gpointer value, gpointer data) 878 782 { 879 783 struct xt_node *adl = data, *d, *c; … … 884 788 char *domain; 885 789 char l[4]; 886 887 if ( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) )790 791 if ((bd->flags & 7) == 0 || (bd->flags & MSN_BUDDY_ADL_SYNCED)) { 888 792 return FALSE; 889 890 strcpy( handle, bu->handle ); 891 if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */ 892 return FALSE; 793 } 794 795 strcpy(handle, bu->handle); 796 if ((domain = strchr(handle, '@')) == NULL) { /* WTF */ 797 return FALSE; 798 } 893 799 *domain = '\0'; 894 domain ++; 895 896 if( ( d = adl->children ) == NULL || 897 g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 ) 898 { 899 d = xt_new_node( "d", NULL, NULL ); 900 xt_add_attr( d, "n", domain ); 901 xt_insert_child( adl, d ); 902 } 903 904 g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 ); 905 c = xt_new_node( "c", NULL, NULL ); 906 xt_add_attr( c, "n", handle ); 907 xt_add_attr( c, "l", l ); 908 xt_add_attr( c, "t", "1" ); /* FIXME: Network type, i.e. 32 for Y!MSG */ 909 xt_insert_child( d, c ); 910 800 domain++; 801 802 if ((d = adl->children) == NULL || 803 g_strcasecmp(xt_find_attr(d, "n"), domain) != 0) { 804 d = xt_new_node("d", NULL, NULL); 805 xt_add_attr(d, "n", domain); 806 xt_insert_child(adl, d); 807 } 808 809 g_snprintf(l, sizeof(l), "%d", bd->flags & 7); 810 c = xt_new_node("c", NULL, NULL); 811 xt_add_attr(c, "n", handle); 812 xt_add_attr(c, "l", l); 813 xt_add_attr(c, "t", "1"); /* FIXME: Network type, i.e. 32 for Y!MSG */ 814 xt_insert_child(d, c); 815 911 816 /* Do this in batches of 100. */ 912 817 bd->flags |= MSN_BUDDY_ADL_SYNCED; … … 914 819 } 915 820 916 static void msn_ns_send_adl( struct im_connection *ic)821 static void msn_ns_send_adl(struct im_connection *ic) 917 822 { 918 823 struct xt_node *adl; 919 824 struct msn_data *md = ic->proto_data; 920 825 char *adls; 921 922 adl = xt_new_node( "ml", NULL, NULL ); 923 xt_add_attr( adl, "l", "1" ); 924 g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl ); 925 if( adl->children == NULL ) 926 { 826 827 adl = xt_new_node("ml", NULL, NULL); 828 xt_add_attr(adl, "l", "1"); 829 g_tree_foreach(md->domaintree, msn_ns_send_adl_1, adl); 830 if (adl->children == NULL) { 927 831 /* This tells the caller that we're done now. */ 928 832 md->adl_todo = -1; 929 xt_free_node( adl);833 xt_free_node(adl); 930 834 return; 931 835 } 932 933 adls = xt_to_string( adl);934 xt_free_node( adl);935 msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen( adls ), adls);936 g_free( adls);937 } 938 939 static void msn_ns_send_adl_start( struct im_connection *ic)836 837 adls = xt_to_string(adl); 838 xt_free_node(adl); 839 msn_ns_write(ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen(adls), adls); 840 g_free(adls); 841 } 842 843 static void msn_ns_send_adl_start(struct im_connection *ic) 940 844 { 941 845 struct msn_data *md; 942 846 GSList *l; 943 847 944 848 /* Dead connection? */ 945 if ( g_slist_find( msn_connections, ic ) == NULL )849 if (g_slist_find(msn_connections, ic) == NULL) { 946 850 return; 947 851 } 852 948 853 md = ic->proto_data; 949 854 md->adl_todo = 0; 950 for( l = ic->bee->users; l; l = l->next ) 951 { 855 for (l = ic->bee->users; l; l = l->next) { 952 856 bee_user_t *bu = l->data; 953 857 struct msn_buddy_data *bd = bu->data; 954 955 if ( bu->ic != ic || ( bd->flags & 7 ) == 0 )858 859 if (bu->ic != ic || (bd->flags & 7) == 0) { 956 860 continue; 957 861 } 862 958 863 bd->flags &= ~MSN_BUDDY_ADL_SYNCED; 959 864 md->adl_todo++; 960 865 } 961 962 msn_ns_send_adl( ic);963 } 964 965 int msn_ns_finish_login( struct im_connection *ic)866 867 msn_ns_send_adl(ic); 868 } 869 870 int msn_ns_finish_login(struct im_connection *ic) 966 871 { 967 872 struct msn_data *md = ic->proto_data; 968 969 if ( ic->flags & OPT_LOGGED_IN )873 874 if (ic->flags & OPT_LOGGED_IN) { 970 875 return 1; 971 972 if( md->adl_todo < 0 ) 876 } 877 878 if (md->adl_todo < 0) { 973 879 md->flags |= MSN_DONE_ADL; 974 975 if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) ) 976 { 977 if( md->flags & MSN_EMAIL_UNVERIFIED ) 978 imcb_connected( ic ); 979 else 980 return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); 981 } 982 880 } 881 882 if ((md->flags & MSN_DONE_ADL) && (md->flags & MSN_GOT_PROFILE)) { 883 if (md->flags & MSN_EMAIL_UNVERIFIED) { 884 imcb_connected(ic); 885 } else { 886 return msn_ns_set_display_name(ic, set_getstr(&ic->acc->set, "display_name")); 887 } 888 } 889 983 890 return 1; 984 891 } 985 892 986 int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text)893 int msn_ns_sendmessage(struct im_connection *ic, bee_user_t *bu, const char *text) 987 894 { 988 895 struct msn_data *md = ic->proto_data; 989 896 int type = 0; 990 897 char *buf, *handle; 991 992 if ( strncmp( text, "\r\r\r", 3 ) == 0 )898 899 if (strncmp(text, "\r\r\r", 3) == 0) { 993 900 /* Err. Shouldn't happen but I guess it can. Don't send others 994 901 any of the "SHAKE THAT THING" messages. :-D */ 995 902 return 1; 996 903 } 904 997 905 /* This might be a federated contact. Get its network number, 998 906 prefixed to bu->handle with a colon. Default is 1. */ 999 for ( handle = bu->handle; g_ascii_isdigit( *handle ); handle ++ )907 for (handle = bu->handle; g_ascii_isdigit(*handle); handle++) { 1000 908 type = type * 10 + *handle - '0'; 1001 if( *handle == ':' ) 1002 handle ++; 1003 else 909 } 910 if (*handle == ':') { 911 handle++; 912 } else { 1004 913 type = 1; 1005 1006 buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text ); 1007 1008 if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", 1009 ++md->trId, handle, type, 1010 1, /* type == IM (not nudge/typing) */ 1011 strlen( buf ), buf ) ) 914 } 915 916 buf = g_strdup_printf("%s%s", MSN_MESSAGE_HEADERS, text); 917 918 if (msn_ns_write(ic, -1, "UUM %d %s %d %d %zd\r\n%s", 919 ++md->trId, handle, type, 920 1, /* type == IM (not nudge/typing) */ 921 strlen(buf), buf)) { 1012 922 return 1; 1013 else923 } else { 1014 924 return 0; 1015 } 1016 1017 void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ) 925 } 926 } 927 928 void msn_ns_oim_send_queue(struct im_connection *ic, GSList **msgq) 1018 929 { 1019 930 GSList *l; 1020 1021 for( l = *msgq; l; l = l->next ) 1022 { 931 932 for (l = *msgq; l; l = l->next) { 1023 933 struct msn_message *m = l->data; 1024 bee_user_t *bu = bee_user_by_handle( ic->bee, ic, m->who);1025 1026 if ( bu )1027 if ( !msn_ns_sendmessage( ic, bu, m->text ) )934 bee_user_t *bu = bee_user_by_handle(ic->bee, ic, m->who); 935 936 if (bu) { 937 if (!msn_ns_sendmessage(ic, bu, m->text)) { 1028 938 return; 1029 } 1030 1031 while( *msgq != NULL ) 1032 { 939 } 940 } 941 } 942 943 while (*msgq != NULL) { 1033 944 struct msn_message *m = (*msgq)->data; 1034 1035 g_free( m->who);1036 g_free( m->text);1037 g_free( m);1038 1039 *msgq = g_slist_remove( *msgq, m);1040 } 1041 } 945 946 g_free(m->who); 947 g_free(m->text); 948 g_free(m); 949 950 *msgq = g_slist_remove(*msgq, m); 951 } 952 }
Note: See TracChangeset
for help on using the changeset viewer.