示例#1
0
文件: msn.c 项目: GRMrGecko/bitlbee
static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away )
{
	struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who );
	struct msn_buddy_data *bd = bu ? bu->data : NULL;
	struct msn_switchboard *sb;
	
#ifdef DEBUG
	if( strcmp( who, "raw" ) == 0 )
	{
		msn_ns_write( ic, -1, "%s\r\n", message );
	}
	else
#endif
	if( bd && bd->flags & MSN_BUDDY_FED )
	{
		msn_ns_sendmessage( ic, bu, message );
	}
	else if( ( sb = msn_sb_by_handle( ic, who ) ) )
	{
		return( msn_sb_sendmessage( sb, message ) );
	}
	else
	{
		struct msn_message *m;
		
		/* Create a message. We have to arrange a usable switchboard, and send the message later. */
		m = g_new0( struct msn_message, 1 );
		m->who = g_strdup( who );
		m->text = g_strdup( message );
		
		return msn_sb_write_msg( ic, m );
	}
	
	return( 0 );
}
示例#2
0
int msn_ns_set_display_name( struct im_connection *ic, const char *value )
{
	struct msn_data *md = ic->proto_data;
	char fn[strlen(value)*3+1];
	
	strcpy( fn, value );
	http_encode( 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_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn );
}
示例#3
0
文件: msn.c 项目: GRMrGecko/bitlbee
static void msn_set_away( struct im_connection *ic, char *state, char *message )
{
	char *uux;
	struct msn_data *md = ic->proto_data;
	
	if( state == NULL )
		md->away_state = msn_away_state_list;
	else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL )
		md->away_state = msn_away_state_list + 1;
	
	if( !msn_ns_write( ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2 ) )
		return;
	
	uux = g_markup_printf_escaped( "<EndpointData><Capabilities>%d:%02d"
	                               "</Capabilities></EndpointData>",
	                               MSN_CAP1, MSN_CAP2 );
	msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
	g_free( uux );
	
	uux = g_markup_printf_escaped( "<PrivateEndpointData><EpName>%s</EpName>"
	                               "<Idle>%s</Idle><ClientType>%d</ClientType>"
	                               "<State>%s</State></PrivateEndpointData>",
	                               md->uuid,
	                               strcmp( md->away_state->code, "IDL" ) ? "false" : "true",
	                               1, /* ? */
	                               md->away_state->code );
	msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
	g_free( uux );
	
	uux = g_markup_printf_escaped( "<Data><DDP></DDP><PSM>%s</PSM>"
	                               "<CurrentMedia></CurrentMedia>"
	                               "<MachineGuid>%s</MachineGuid></Data>",
	                               message ? message : "", md->uuid );
	msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux );
	g_free( uux );
}
示例#4
0
文件: ns.c 项目: GRMrGecko/bitlbee
static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
{
	struct msn_handler_data *handler = data;
	struct im_connection *ic = handler->data;
	struct msn_data *md;
	
	if( !g_slist_find( msn_connections, ic ) )
		return FALSE;
	
	md = ic->proto_data;
	
	if( source == -1 )
	{
		imcb_error( ic, "Could not connect to server" );
		imc_logout( ic, TRUE );
		return FALSE;
	}
	
	g_free( handler->rxq );
	handler->rxlen = 0;
	handler->rxq = g_new0( char, 1 );
	
	if( md->uuid == NULL )
	{
		struct utsname name;
		sha1_state_t sha[1];
		
		/* UUID == SHA1("BitlBee" + my hostname + MSN username) */
		sha1_init( sha );
		sha1_append( sha, (void*) "BitlBee", 7 );
		if( uname( &name ) == 0 )
		{
			sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) );
		}
		sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) );
		md->uuid = sha1_random_uuid( sha );
		memcpy( md->uuid, "b171be3e", 8 ); /* :-P */
	}
	
	if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) )
	{
		handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler );
		imcb_log( ic, "Connected to server, waiting for reply" );
	}
	
	return FALSE;
}
示例#5
0
int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group )
{
	struct msn_data *md = ic->proto_data;
	char groupid[8];
	bee_user_t *bu;
	struct msn_buddy_data *bd;
	char *adl;
	
	*groupid = '\0';
#if 0
	if( group )
	{
		int i;
		for( i = 0; i < md->groupcount; i ++ )
			if( g_strcasecmp( md->grouplist[i], group ) == 0 )
			{
				g_snprintf( groupid, sizeof( groupid ), " %d", i );
				break;
			}
	}
#endif
	
	if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
	    !( bd = bu->data ) || !( bd->flags & list ) )
		return 1;
	
	bd->flags &= ~list;
	
	if( list == MSN_BUDDY_FL )
		msn_soap_ab_contact_del( ic, bu );
	else
		msn_soap_memlist_edit( ic, who, FALSE, list );
	
	if( ( adl = adlrml_entry( who, list ) ) )
	{
		int st = msn_ns_write( ic, -1, "RML %d %zd\r\n%s",
		                       ++md->trId, strlen( adl ), adl );
		g_free( adl );
		
		return st;
	}
	
	return 1;
}
示例#6
0
文件: sb.c 项目: shiplu/bitlbee
int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m )
{
    struct msn_data *md = ic->proto_data;
    struct msn_switchboard *sb;

    /* FIXME: *CHECK* the reliability of using spare sb's! */
    if( ( sb = msn_sb_spare( ic ) ) )
    {
        debug( "Trying to use a spare switchboard to message %s", m->who );

        sb->who = g_strdup( m->who );
        if( msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, m->who ) )
        {
            /* He/She should join the switchboard soon, let's queue the message. */
            sb->msgq = g_slist_append( sb->msgq, m );
            return( 1 );
        }
    }

    debug( "Creating a new switchboard to message %s", m->who );

    /* If we reach this line, there was no spare switchboard, so let's make one. */
    if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) )
    {
        g_free( m->who );
        g_free( m->text );
        g_free( m );

        return( 0 );
    }

    /* And queue the message to md. We'll pick it up when the switchboard comes up. */
    md->msgq = g_slist_append( md->msgq, m );

    /* FIXME: If the switchboard creation fails, the message will not be sent. */

    return( 1 );
}
示例#7
0
int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group )
{
	struct msn_data *md = ic->proto_data;
	char groupid[8];
	bee_user_t *bu;
	struct msn_buddy_data *bd;
	char *adl;
	
	*groupid = '\0';
#if 0
	if( group )
	{
		int i;
		for( i = 0; i < md->groupcount; i ++ )
			if( g_strcasecmp( md->grouplist[i], group ) == 0 )
			{
				g_snprintf( groupid, sizeof( groupid ), " %d", i );
				break;
			}
		
		if( *groupid == '\0' )
		{
			/* Have to create this group, it doesn't exist yet. */
			struct msn_groupadd *ga;
			GSList *l;
			
			for( l = md->grpq; l; l = l->next )
			{
				ga = l->data;
				if( g_strcasecmp( ga->group, group ) == 0 )
					break;
			}
			
			ga = g_new0( struct msn_groupadd, 1 );
			ga->who = g_strdup( who );
			ga->group = g_strdup( group );
			md->grpq = g_slist_prepend( md->grpq, ga );
			
			if( l == NULL )
			{
				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 );
				return msn_write( ic, buf, strlen( buf ) );
			}
			else
			{
				/* This can happen if the user's doing lots of adds to a
				   new group at once; we're still waiting for the server
				   to confirm group creation. */
				return 1;
			}
		}
	}
#endif
	
	if( !( ( bu = bee_user_by_handle( ic->bee, ic, who ) ) ||
	       ( bu = bee_user_new( ic->bee, ic, who, 0 ) ) ) ||
	    !( bd = bu->data ) || bd->flags & list )
		return 1;
	
	bd->flags |= list;
	
	if( list == MSN_BUDDY_FL )
		msn_soap_ab_contact_add( ic, bu );
	else
		msn_soap_memlist_edit( ic, who, TRUE, list );
	
	if( ( adl = adlrml_entry( who, list ) ) )
	{
		int st = msn_ns_write( ic, -1, "ADL %d %zd\r\n%s",
		                       ++md->trId, strlen( adl ), adl );
		g_free( adl );
		
		return st;
	}
	
	return 1;
}
示例#8
0
文件: ns.c 项目: GRMrGecko/bitlbee
static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts )
{
	struct im_connection *ic = handler->data;
	struct msn_data *md = ic->proto_data;
	
	if( num_parts == 0 )
	{
		/* Hrrm... Empty command...? Ignore? */
		return( 1 );
	}
	
	if( strcmp( cmd[0], "VER" ) == 0 )
	{
		if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
		{
			imcb_error( ic, "Unsupported protocol" );
			imc_logout( ic, FALSE );
			return( 0 );
		}
		
		return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
		                      ++md->trId, ic->acc->user ) );
	}
	else if( strcmp( cmd[0], "CVR" ) == 0 )
	{
		/* We don't give a damn about the information we just received */
		return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user );
	}
	else if( strcmp( cmd[0], "XFR" ) == 0 )
	{
		char *server;
		int port;
		
		if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
		{
			b_event_remove( handler->inpa );
			handler->inpa = -1;
			
			server = strchr( cmd[3], ':' );
			if( !server )
			{
				imcb_error( ic, "Syntax error" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			*server = 0;
			port = atoi( server + 1 );
			server = cmd[3];
			
			imcb_log( ic, "Transferring to other server" );
			return msn_ns_connect( ic, handler, server, port );
		}
		else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
		{
			struct msn_switchboard *sb;
			
			server = strchr( cmd[3], ':' );
			if( !server )
			{
				imcb_error( ic, "Syntax error" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			*server = 0;
			port = atoi( server + 1 );
			server = cmd[3];
			
			if( strcmp( cmd[4], "CKI" ) != 0 )
			{
				imcb_error( ic, "Unknown authentication method for switchboard" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			
			debug( "Connecting to a new switchboard with key %s", cmd[5] );

			if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL )
			{
				/* Although this isn't strictly fatal for the NS connection, it's
				   definitely something serious (we ran out of file descriptors?). */
				imcb_error( ic, "Could not create new switchboard" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			
			if( md->msgq )
			{
				struct msn_message *m = md->msgq->data;
				GSList *l;
				
				sb->who = g_strdup( m->who );
				
				/* Move all the messages to the first user in the message
				   queue to the switchboard message queue. */
				l = md->msgq;
				while( l )
				{
					m = l->data;
					l = l->next;
					if( strcmp( m->who, sb->who ) == 0 )
					{
						sb->msgq = g_slist_append( sb->msgq, m );
						md->msgq = g_slist_remove( md->msgq, m );
					}
				}
			}
		}
		else
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
	}
	else if( strcmp( cmd[0], "USR" ) == 0 )
	{
		if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
		    strcmp( cmd[3], "S" ) == 0 )
		{
			g_free( md->pp_policy );
			md->pp_policy = g_strdup( cmd[4] );
			msn_soap_passport_sso_request( ic, cmd[5] );
		}
		else if( strcmp( cmd[2], "OK" ) == 0 )
		{
			/* If the number after the handle is 0, the e-mail
			   address is unverified, which means we can't change
			   the display name. */
			if( cmd[4][0] == '0' )
				md->flags |= MSN_EMAIL_UNVERIFIED;
			
			imcb_log( ic, "Authenticated, getting buddy list" );
			msn_soap_memlist_request( ic );
		}
		else
		{
			imcb_error( ic, "Unknown authentication type" );
			imc_logout( ic, FALSE );
			return( 0 );
		}
	}
	else if( strcmp( cmd[0], "MSG" ) == 0 )
	{
		if( num_parts < 4 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		handler->msglen = atoi( cmd[3] );
		
		if( handler->msglen <= 0 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
	}
	else if( strcmp( cmd[0], "BLP" ) == 0 )
	{
		msn_ns_send_adl_start( ic );
		return msn_ns_finish_login( ic );
	}
	else if( strcmp( cmd[0], "ADL" ) == 0 )
	{
		if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
		{
			msn_ns_send_adl( ic );
			return msn_ns_finish_login( ic );
		}
		else if( num_parts >= 3 )
		{
			handler->msglen = atoi( cmd[2] );
		}
	}
	else if( strcmp( cmd[0], "PRP" ) == 0 )
	{
		imcb_connected( ic );
	}
	else if( strcmp( cmd[0], "CHL" ) == 0 )
	{
		char *resp;
		int st;
		
		if( num_parts < 3 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		resp = msn_p11_challenge( cmd[2] );
		
		st =  msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s",
		                    ++md->trId, MSNP11_PROD_ID,
		                    strlen( resp ), resp );
		g_free( resp );
		return st;
	}
	else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 )
	{
		const struct msn_away_state *st;
		const char *handle;
		int cap = 0;
		
		if( num_parts < 6 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		/* ILN and NLN are more or less the same, except ILN has a trId
		   at the start, and NLN has a capability field at the end. 
		   Does ILN still exist BTW? */
		if( cmd[0][1] == 'I' )
			cmd ++;
		else
			cap = atoi( cmd[4] );

		handle = msn_normalize_handle( cmd[2] );
		if( strcmp( handle, ic->acc->user ) == 0 )
			return 1; /* That's me! */
		
		http_decode( cmd[3] );
		imcb_rename_buddy( ic, handle, cmd[3] );
		
		st = msn_away_state_by_code( cmd[1] );
		if( !st )
		{
			/* FIXME: Warn/Bomb about unknown away state? */
			st = msn_away_state_list + 1;
		}
		
		imcb_buddy_status( ic, handle, OPT_LOGGED_IN | 
		                   ( st != msn_away_state_list ? OPT_AWAY : 0 ) |
		                   ( cap & 1 ? OPT_MOBILE : 0 ),
		                   st->name, NULL );
		
		msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) );
	}
	else if( strcmp( cmd[0], "FLN" ) == 0 )
	{
		const char *handle;
		
		if( cmd[1] == NULL )
			return 1;
		
		handle = msn_normalize_handle( cmd[1] );
		imcb_buddy_status( ic, handle, 0, NULL, NULL );
		msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE );
	}
	else if( strcmp( cmd[0], "RNG" ) == 0 )
	{
		struct msn_switchboard *sb;
		char *server;
		int session, port;
		
		if( num_parts < 7 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		session = atoi( cmd[1] );
		
		server = strchr( cmd[2], ':' );
		if( !server )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		*server = 0;
		port = atoi( server + 1 );
		server = cmd[2];
		
		if( strcmp( cmd[3], "CKI" ) != 0 )
		{
			imcb_error( ic, "Unknown authentication method for switchboard" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] );
		
		if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL )
		{
			/* Although this isn't strictly fatal for the NS connection, it's
			   definitely something serious (we ran out of file descriptors?). */
			imcb_error( ic, "Could not create new switchboard" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		else
		{
			sb->who = g_strdup( msn_normalize_handle( cmd[5] ) );
		}
	}
	else if( strcmp( cmd[0], "OUT" ) == 0 )
	{
		int allow_reconnect = TRUE;
		
		if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 )
		{
			imcb_error( ic, "Someone else logged in with your account" );
			allow_reconnect = FALSE;
		}
		else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 )
		{
			imcb_error( ic, "Terminating session because of server shutdown" );
		}
		else
		{
			imcb_error( ic, "Session terminated by remote server (%s)",
			            cmd[1] ? cmd[1] : "reason unknown)" );
		}
		
		imc_logout( ic, allow_reconnect );
		return( 0 );
	}
	else if( strcmp( cmd[0], "IPG" ) == 0 )
	{
		imcb_error( ic, "Received IPG command, we don't handle them yet." );
		
		handler->msglen = atoi( cmd[1] );
		
		if( handler->msglen <= 0 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
	}
#if 0
	else if( strcmp( cmd[0], "ADG" ) == 0 )
	{
		char *group = g_strdup( cmd[3] );
		int groupnum, i;
		GSList *l, *next;
		
		http_decode( group );
		if( sscanf( cmd[4], "%d", &groupnum ) == 1 )
		{
			if( groupnum >= md->groupcount )
			{
				md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 );
				for( i = md->groupcount; i <= groupnum; i ++ )
					md->grouplist[i] = NULL;
				md->groupcount = groupnum + 1;
			}
			g_free( md->grouplist[groupnum] );
			md->grouplist[groupnum] = group;
		}
示例#9
0
文件: msn.c 项目: GRMrGecko/bitlbee
static void msn_keepalive( struct im_connection *ic )
{
	msn_ns_write( ic, -1, "PNG\r\n" );
}