コード例 #1
0
ファイル: skype.c プロジェクト: meh/killerbee-skype
void
Skype_login (account_t* account)
{
    im_connection* connection = imcb_new(account);
    SkypeData*     skype      = g_new0(struct SkypeData, 1);

    connection->proto_data = skype;

    imcb_log(connection, "Connecting");

    skype->ssl = ssl_connect(
        set_getstr(&account->set, "server"),
        set_getint(&account->set, "port"),
        Skype_connected,
        connection
    );

    skype->fd         = skype->ssl ? ssl_getfd(skype->ssl) : -1;
    skype->username   = g_strdup(account->user);
    skype->connection = connection;

    if (set_getbool(&account->set, "skypeconsole")) {
        imcb_add_buddy(connection, "skypeconsole", NULL);
    }
}
コード例 #2
0
ファイル: twitter.c プロジェクト: mrdon/bitlbee
static void twitter_main_loop_start(struct im_connection *ic)
{
	struct twitter_data *td = ic->proto_data;

	/* Create the room now that we "logged in". */
	if (td->flags & TWITTER_MODE_CHAT)
		twitter_groupchat_init(ic);

	imcb_log(ic, "Getting initial statuses");

	// Run this once. After this queue the main loop function (or open the
	// stream if available).
	twitter_main_loop(ic, -1, 0);
	
	if (set_getbool(&ic->acc->set, "stream")) {
		/* That fetch was just to get backlog, the stream will give
		   us the rest. \o/ */
		twitter_open_stream(ic);
		
		/* Stream sends keepalives (empty lines) or actual data at
		   least twice a minute. Disconnect if this stops. */
		ic->flags |= OPT_PONGS;
	} else {
		/* Not using the streaming API, so keep polling the old-
		   fashioned way. :-( */
		td->main_loop_id =
		    b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000,
		                  twitter_main_loop, ic);
	}
}
コード例 #3
0
ファイル: purple.c プロジェクト: AaronVanGeffen/bitlbee
static void purple_login(account_t *acc)
{
	struct im_connection *ic = imcb_new(acc);
	struct purple_data *pd;

	if ((local_bee != NULL && local_bee != acc->bee) ||
	    (global.conf->runmode == RUNMODE_DAEMON && !getenv("BITLBEE_DEBUG"))) {
		imcb_error(ic,  "Daemon mode detected. Do *not* try to use libpurple in daemon mode! "
		           "Please use inetd or ForkDaemon mode instead.");
		imc_logout(ic, FALSE);
		return;
	}
	local_bee = acc->bee;

	/* For now this is needed in the _connected() handlers if using
	   GLib event handling, to make sure we're not handling events
	   on dead connections. */
	purple_connections = g_slist_prepend(purple_connections, ic);

	ic->proto_data = pd = g_new0(struct purple_data, 1);
	pd->account = purple_account_new(acc->user, (char *) acc->prpl->data);
	pd->input_requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
	                                           NULL, g_free);
	pd->next_request_id = 0;
	purple_account_set_password(pd->account, acc->pass);
	purple_sync_settings(acc, pd->account);

	purple_account_set_enabled(pd->account, "BitlBee", TRUE);

	if (set_getbool(&acc->set, "mail_notifications") && set_getstr(&acc->set, "mail_notifications_handle")) {
		imcb_add_buddy(ic, set_getstr(&acc->set, "mail_notifications_handle"), NULL);
	}
}
コード例 #4
0
ファイル: auth.c プロジェクト: Songzhongrang/reposity
/*
 * In AIM 3.5 protocol, the first stage of login is to request login from the
 * Authorizer, passing it the screen name for verification.  If the name is
 * invalid, a 0017/0003 is spit back, with the standard error contents.  If
 * valid, a 0017/0007 comes back, which is the signal to send it the main
 * login command (0017/0002).
 *
 */
int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
{
	aim_frame_t *fr;
	aim_snacid_t snacid;
	aim_tlvlist_t *tl = NULL;
	struct im_connection *ic = sess->aux_data;

	if (!sess || !conn || !sn) {
		return -EINVAL;
	}

	if (g_ascii_isdigit(sn[0]) && set_getbool(&ic->acc->set, "old_icq_auth")) {
		return goddamnicq(sess, conn, sn);
	}

	sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;

	aim_sendflapver(sess, conn);

	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(sn)))) {
		return -ENOMEM;
	}

	snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
	aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);

	aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *) sn);
	aim_writetlvchain(&fr->data, &tl);
	aim_freetlvchain(&tl);

	aim_tx_enqueue(sess, fr);

	return 0;
}
コード例 #5
0
ファイル: bee_user.c プロジェクト: AaronVanGeffen/bitlbee
void imcb_notify_email(struct im_connection *ic, char *format, ...)
{
	const char *handle;
	va_list params;
	char *msg;

	if (!set_getbool(&ic->acc->set, "mail_notifications")) {
		return;
	}

	va_start(params, format);
	msg = g_strdup_vprintf(format, params);
	va_end(params);

	/* up to the protocol to set_add this if they want to use this */
	handle = set_getstr(&ic->acc->set, "mail_notifications_handle");

	if (handle != NULL) {
		imcb_buddy_msg(ic, handle, msg, 0, 0);
	} else {
		imcb_log(ic, "%s", msg);
	}

	g_free(msg);
}
コード例 #6
0
ファイル: twitter.c プロジェクト: mrdon/bitlbee
static int twitter_buddy_msg(struct im_connection *ic, char *who, char *message, int away)
{
	struct twitter_data *td = ic->proto_data;
	int plen = strlen(td->prefix);

	if (g_strncasecmp(who, td->prefix, plen) == 0 && who[plen] == '_' &&
	    g_strcasecmp(who + plen + 1, ic->acc->user) == 0) {
		if (set_getbool(&ic->acc->set, "oauth") &&
		    td->oauth_info && td->oauth_info->token == NULL) {
			char pin[strlen(message) + 1], *s;

			strcpy(pin, message);
			for (s = pin + sizeof(pin) - 2; s > pin && isspace(*s); s--)
				*s = '\0';
			for (s = pin; *s && isspace(*s); s++) {
			}

			if (!oauth_access_token(s, td->oauth_info)) {
				imcb_error(ic, "OAuth error: %s",
					   "Failed to send access token request");
				imc_logout(ic, TRUE);
				return FALSE;
			}
		} else
			twitter_handle_command(ic, message);
	} else {
		twitter_direct_messages_new(ic, who, message);
	}
	return (0);
}
コード例 #7
0
ファイル: skype.c プロジェクト: meh/killerbee-skype
gboolean
Skype_begin (im_connection* connection)
{
    SkypeData* skype = connection->proto_data;
    int        result;

    if (!skype) {
        return FALSE;
    }

    skype->bfd = b_input_add(skype->fd, B_EV_IO_READ, Skype_loop, connection);

    /* Identifying */
    Skype_printf(connection, "USERNAME %s\n", connection->acc->user);
    Skype_printf(connection, "PASSWORD %s\n", connection->acc->pass);

    result = Skype_printf(connection, "SEARCH FRIENDS\n");

    Skype_printf(connection, "SET USERSTATUS ONLINE\n");

    if (set_getbool(&connection->acc->set, "auto_join")) {
        Skype_printf(connection, "SEARCH BOOKMRKEDCHATS\n");
    }

    return result;
}
コード例 #8
0
ファイル: irc_im.c プロジェクト: wingo/bitlbee
static gboolean bee_irc_user_new(bee_t *bee, bee_user_t *bu)
{
	irc_user_t *iu;
	irc_t *irc = (irc_t *) bee->ui_data;
	char nick[MAX_NICK_LENGTH + 1], *s;

	memset(nick, 0, MAX_NICK_LENGTH + 1);
	strncpy(nick, nick_get(bu), MAX_NICK_LENGTH);

	bu->ui_data = iu = irc_user_new(irc, nick);
	iu->bu = bu;

	if (set_getbool(&irc->b->set, "private")) {
		iu->last_channel = NULL;
	} else {
		iu->last_channel = irc_channel_with_user(irc, iu);
	}

	if ((s = strchr(bu->handle, '@'))) {
		iu->host = g_strdup(s + 1);
		iu->user = g_strndup(bu->handle, s - bu->handle);
	} else {
		iu->user = g_strdup(bu->handle);
		if (bu->ic->acc->server) {
			iu->host = g_strdup(bu->ic->acc->server);
		} else {
			char *s;
			for (s = bu->ic->acc->tag; g_ascii_isalnum(*s); s++) {
				;
			}
			/* Only use the tag if we got to the end of the string.
			   (So allow alphanumerics only. Hopefully not too
			   restrictive.) */
			if (*s) {
				iu->host = g_strdup(bu->ic->acc->prpl->name);
			} else {
				iu->host = g_strdup(bu->ic->acc->tag);
			}
		}
	}

	while ((s = strchr(iu->user, ' '))) {
		*s = '_';
	}

	if (bu->flags & BEE_USER_LOCAL) {
		char *s = set_getstr(&bee->set, "handle_unknown");

		if (strcmp(s, "add_private") == 0) {
			iu->last_channel = NULL;
		} else if (strcmp(s, "add_channel") == 0) {
			iu->last_channel = irc->default_channel;
		}
	}

	iu->f = &irc_user_im_funcs;

	return TRUE;
}
コード例 #9
0
ファイル: irc_im.c プロジェクト: wingo/bitlbee
static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, guint32 flags, time_t sent_at)
{
	irc_t *irc = bee->ui_data;
	irc_user_t *iu = (irc_user_t *) bu->ui_data;
	irc_user_t *src_iu = iu;
	irc_user_t *dst_iu = irc->user;
	const char *dst;
	char *prefix = NULL;
	char *wrapped, *ts = NULL;
	char *msg = g_strdup(msg_);
	char *message_type = "PRIVMSG";
	GSList *l;

	if (sent_at > 0 && set_getbool(&irc->b->set, "display_timestamps")) {
		ts = irc_format_timestamp(irc, sent_at);
	}

	dst = irc_user_msgdest(iu);

	if (flags & OPT_SELFMESSAGE) {
		char *setting = set_getstr(&irc->b->set, "self_messages");

		if (is_bool(setting)) {
			if (bool2int(setting)) {
				/* set to true, send it with src/dst flipped */
				
				dst_iu = iu;
				src_iu = irc->user;

				if (dst == irc->user->nick) {
					dst = dst_iu->nick;
				}
			} else {
				/* set to false, skip the message completely */
				goto cleanup;
			}
		} else if (g_strncasecmp(setting, "prefix", 6) == 0) {
			/* third state, prefix, loosely imitates the znc privmsg_prefix module */

			g_free(msg);
			if (g_strncasecmp(msg_, "/me ", 4) == 0) {
				msg = g_strdup_printf("/me -> %s", msg_ + 4);
			} else {
				msg = g_strdup_printf("-> %s", msg_);
			}

			if (g_strcasecmp(setting, "prefix_notice") == 0) {
				message_type = "NOTICE";
			}
		}

	}

	if (dst != dst_iu->nick) {
		/* if not messaging directly (control channel), call user by name */
		prefix = g_strdup_printf("%s%s%s", dst_iu->nick, set_getstr(&bee->set, "to_char"), ts ? : "");
	} else {
コード例 #10
0
ファイル: irc_user.c プロジェクト: AlD/bitlbee
int irc_user_free( irc_t *irc, irc_user_t *iu )
{
	static struct im_connection *last_ic;
	static char *msg;
	
	if( !iu )
		return 0;
	
	if( iu->bu &&
	    ( iu->bu->ic->flags & OPT_LOGGING_OUT ) &&
	    iu->bu->ic != last_ic )
	{
		char host_prefix[] = "bitlbee.";
		char *s;
		
		/* Irssi recognises netsplits by quitmsgs with two
		   hostnames, where a hostname is a "word" with one
		   of more dots. Mangle no-dot hostnames a bit. */
		if( strchr( irc->root->host, '.' ) )
			*host_prefix = '\0';
		
		last_ic = iu->bu->ic;
		g_free( msg );
		if( !set_getbool( &irc->b->set, "simulate_netsplit" ) )
			msg = g_strdup( "Account off-line" );
		else if( ( s = strchr( iu->bu->ic->acc->user, '@' ) ) )
			msg = g_strdup_printf( "%s%s %s", host_prefix,
			        irc->root->host, s + 1 );
		else
			msg = g_strdup_printf( "%s%s %s.%s",
				host_prefix, irc->root->host,
				iu->bu->ic->acc->prpl->name, irc->root->host );
	}
	else if( !iu->bu || !( iu->bu->ic->flags & OPT_LOGGING_OUT ) )
	{
		g_free( msg );
		msg = g_strdup( "Removed" );
		last_ic = NULL;
	}
	irc_user_quit( iu, msg );
	
	irc->users = g_slist_remove( irc->users, iu );
	g_hash_table_remove( irc->nick_user_hash, iu->key );
	
	g_free( iu->nick );
	if( iu->nick != iu->user ) g_free( iu->user );
	if( iu->nick != iu->host ) g_free( iu->host );
	if( iu->nick != iu->fullname ) g_free( iu->fullname );
	g_free( iu->pastebuf );
	if( iu->pastebuf_timer ) b_event_remove( iu->pastebuf_timer );
	g_free( iu->key );
	g_free( iu );
	
	return 1;
}
コード例 #11
0
ファイル: irc_im.c プロジェクト: meh/bitlbee
static gboolean bee_irc_user_status(bee_t *bee, bee_user_t *bu, bee_user_t *old)
{
	irc_t *irc = bee->ui_data;
	irc_user_t *iu = bu->ui_data;

	/* Do this outside the if below since away state can change without
	   the online state changing. */
	iu->flags &= ~IRC_USER_AWAY;
	if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) {
		iu->flags |= IRC_USER_AWAY;
	}

	if ((bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE)) {
		if (bu->flags & BEE_USER_ONLINE) {
			if (g_hash_table_lookup(irc->watches, iu->key)) {
				irc_send_num(irc, 600, "%s %s %s %d :%s", iu->nick, iu->user,
				             iu->host, (int) time(NULL), "logged online");
			}
		} else {
			if (g_hash_table_lookup(irc->watches, iu->key)) {
				irc_send_num(irc, 601, "%s %s %s %d :%s", iu->nick, iu->user,
				             iu->host, (int) time(NULL), "logged offline");
			}

			/* Send a QUIT since those will also show up in any
			   query windows the user may have, plus it's only
			   one QUIT instead of possibly many (in case of
			   multiple control chans). If there's a channel that
			   shows offline people, a JOIN will follow. */
			if (set_getbool(&bee->set, "offline_user_quits")) {
				irc_user_quit(iu, "Leaving...");
			}
		}
	}

	/* Reset this one since the info may have changed. */
	iu->away_reply_timeout = 0;

	bee_irc_channel_update(irc, NULL, iu);

	/* If away-notify enabled, send status updates when:
	 * Away or Online state changes
	 * Status changes (e.g. "Away" to "Mobile")
	 * Status message changes
	 */
	if ((irc->caps & CAP_AWAY_NOTIFY) &&
	    ((bu->flags & BEE_USER_AWAY) != (old->flags & BEE_USER_AWAY) ||
	     (bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE) ||
	     (g_strcmp0(bu->status, old->status) != 0) ||
	     (g_strcmp0(bu->status_msg, old->status_msg) != 0))) {
		irc_send_away_notify(iu);
	}

	return TRUE;
}
コード例 #12
0
ファイル: ipc.c プロジェクト: dequis/bitlbee-old
gboolean ipc_child_identify( irc_t *irc )
{
	if( global.conf->runmode == RUNMODE_FORKDAEMON )
	{
#ifndef NO_FD_PASSING
		if( !ipc_send_fd( global.listen_socket, irc->fd ) )
			ipc_child_disable();
	
		ipc_to_master_str( "IDENTIFY %s :%s\r\n", irc->user->nick, irc->password );
#endif
		
		return TRUE;
	}
	else if( global.conf->runmode == RUNMODE_DAEMON )
	{
		GSList *l;
		irc_t *old = NULL;
		char *to_init[] = { "TAKEOVER", "INIT", NULL };
		
		for( l = irc_connection_list; l; l = l->next )
		{
			old = l->data;
			
			if( irc != old &&
			    irc->user->nick && old->user->nick &&
			    irc->password && old->password &&
			    strcmp( irc->user->nick, old->user->nick ) == 0 &&
			    strcmp( irc->password, old->password ) == 0 )
				break;
		}
		if( l == NULL || old == NULL ||
		    !set_getbool( &irc->b->set, "allow_takeover" ) ||
		    !set_getbool( &old->b->set, "allow_takeover" ) )
			return FALSE;
		
		ipc_child_cmd_takeover( irc, to_init );
		
		return TRUE;
	}
	else
		return FALSE;
}
コード例 #13
0
ファイル: purple.c プロジェクト: GRMrGecko/bitlbee
static void purple_sync_settings( account_t *acc, PurpleAccount *pa )
{
	PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id );
	PurplePluginProtocolInfo *pi = prpl->info->extra_info;
	GList *i;
	
	for( i = pi->protocol_options; i; i = i->next )
	{
		PurpleAccountOption *o = i->data;
		const char *name;
		set_t *s;
		
		name = purple_account_option_get_setting( o );
		s = set_find( &acc->set, name );
		if( s->value == NULL )
			continue;
		
		switch( purple_account_option_get_type( o ) )
		{
		case PURPLE_PREF_STRING:
		case PURPLE_PREF_STRING_LIST:
			purple_account_set_string( pa, name, set_getstr( &acc->set, name ) );
			break;
		
		case PURPLE_PREF_INT:
			purple_account_set_int( pa, name, set_getint( &acc->set, name ) );
			break;
		
		case PURPLE_PREF_BOOLEAN:
			purple_account_set_bool( pa, name, set_getbool( &acc->set, name ) );
			break;
		
		default:
			break;
		}
	}
	
	if( pi->options & OPT_PROTO_MAIL_CHECK )
		purple_account_set_check_mail( pa, set_getbool( &acc->set, "mail_notifications" ) );
}
コード例 #14
0
ファイル: root_commands.c プロジェクト: EionRobb/bitlbee
gboolean cmd_identify_finish(gpointer data, gint fd, b_input_condition cond)
{
	char *account_on[] = { "account", "on", NULL };
	irc_t *irc = data;

	if (set_getbool(&irc->b->set, "auto_connect")) {
		cmd_account(irc, account_on);
	}

	b_event_remove(irc->login_source_id);
	irc->login_source_id = -1;
	return FALSE;
}
コード例 #15
0
ファイル: twitter.c プロジェクト: mrdon/bitlbee
void twitter_login_finish(struct im_connection *ic)
{
	struct twitter_data *td = ic->proto_data;

	td->flags &= ~TWITTER_DOING_TIMELINE;

	if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info)
		twitter_oauth_start(ic);
	else if (!(td->flags & TWITTER_MODE_ONE) &&
	         !(td->flags & TWITTER_HAVE_FRIENDS)) {
		imcb_log(ic, "Getting contact list");
		twitter_get_friends_ids(ic, -1);
	} else
		twitter_main_loop_start(ic);
}
コード例 #16
0
ファイル: irc_im.c プロジェクト: AlD/bitlbee
static gboolean bee_irc_user_new( bee_t *bee, bee_user_t *bu )
{
	irc_user_t *iu;
	irc_t *irc = (irc_t*) bee->ui_data;
	char nick[MAX_NICK_LENGTH+1], *s;
	
	memset( nick, 0, MAX_NICK_LENGTH + 1 );
	strcpy( nick, nick_get( bu ) );
	
	bu->ui_data = iu = irc_user_new( irc, nick );
	iu->bu = bu;
	
	if( set_getbool( &irc->b->set, "private" ) )
		iu->last_channel = NULL;
	else
		iu->last_channel = irc_channel_with_user( irc, iu );
	
	if( ( s = strchr( bu->handle, '@' ) ) )
	{
		iu->host = g_strdup( s + 1 );
		iu->user = g_strndup( bu->handle, s - bu->handle );
	}
	else
	{
		iu->user = g_strdup( bu->handle );
		if( bu->ic->acc->server )
			iu->host = g_strdup( bu->ic->acc->server );
		else
			iu->host = g_strdup( bu->ic->acc->prpl->name );
	}
	
	while( ( s = strchr( iu->user, ' ' ) ) )
		*s = '_';
	
	if( bu->flags & BEE_USER_LOCAL )
	{
		char *s = set_getstr( &bee->set, "handle_unknown" );
		
		if( strcmp( s, "add_private" ) == 0 )
			iu->last_channel = NULL;
		else if( strcmp( s, "add_channel" ) == 0 )
			iu->last_channel = irc->default_channel;
	}
	
	iu->f = &irc_user_im_funcs;
	
	return TRUE;
}
コード例 #17
0
ファイル: bee_user.c プロジェクト: Songzhongrang/reposity
/* IM->UI callbacks */
void imcb_buddy_status(struct im_connection *ic, const char *handle, int flags, const char *state, const char *message)
{
	bee_t *bee = ic->bee;
	bee_user_t *bu, *old;

	if (!(bu = bee_user_by_handle(bee, ic, handle))) {
		if (g_strcasecmp(set_getstr(&ic->bee->set, "handle_unknown"), "add") == 0) {
			bu = bee_user_new(bee, ic, handle, BEE_USER_LOCAL);
		} else {
			if (g_strcasecmp(set_getstr(&ic->bee->set, "handle_unknown"), "ignore") != 0) {
				imcb_log(ic, "imcb_buddy_status() for unknown handle %s:\n"
				         "flags = %d, state = %s, message = %s", handle, flags,
				         state ? state : "NULL", message ? message : "NULL");
			}

			return;
		}
	}

	/* May be nice to give the UI something to compare against. */
	old = g_memdup(bu, sizeof(bee_user_t));

	/* TODO(wilmer): OPT_AWAY, or just state == NULL ? */
	bu->flags = flags;
	bu->status_msg = g_strdup(message);
	if (state && *state) {
		bu->status = g_strdup(state);
	} else if (flags & OPT_AWAY) {
		bu->status = g_strdup("Away");
	} else {
		bu->status = NULL;
	}

	if (bu->status == NULL && (flags & OPT_MOBILE) &&
	    set_getbool(&bee->set, "mobile_is_away")) {
		bu->flags |= BEE_USER_AWAY;
		bu->status = g_strdup("Mobile");
	}

	if (bee->ui->user_status) {
		bee->ui->user_status(bee, bu, old);
	}

	g_free(old->status_msg);
	g_free(old->status);
	g_free(old);
}
コード例 #18
0
ファイル: irc_im.c プロジェクト: dequis/bitlbee-old
static gboolean bee_irc_user_msg( bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at )
{
	irc_t *irc = bee->ui_data;
	irc_user_t *iu = (irc_user_t *) bu->ui_data;
	const char *dst;
	char *prefix = NULL;
	char *wrapped, *ts = NULL;
	char *msg = g_strdup( msg_ );
	GSList *l;
	
	if( sent_at > 0 && set_getbool( &irc->b->set, "display_timestamps" ) )
		ts = irc_format_timestamp( irc, sent_at );
	
	dst = irc_user_msgdest( iu );
	if( dst != irc->user->nick )
	{
		/* if not messaging directly, call user by name */
		prefix = g_strdup_printf( "%s%s%s", irc->user->nick, set_getstr( &bee->set, "to_char" ), ts ? : "" );
	}
コード例 #19
0
ファイル: irc_im.c プロジェクト: dequis/bitlbee-old
static gboolean bee_irc_user_status( bee_t *bee, bee_user_t *bu, bee_user_t *old )
{
	irc_t *irc = bee->ui_data;
	irc_user_t *iu = bu->ui_data;
	
	/* Do this outside the if below since away state can change without
	   the online state changing. */
	iu->flags &= ~IRC_USER_AWAY;
	if( bu->flags & BEE_USER_AWAY || !( bu->flags & BEE_USER_ONLINE ) )
		iu->flags |= IRC_USER_AWAY;
	
	if( ( bu->flags & BEE_USER_ONLINE ) != ( old->flags & BEE_USER_ONLINE ) )
	{
		if( bu->flags & BEE_USER_ONLINE )
		{
			if( g_hash_table_lookup( irc->watches, iu->key ) )
				irc_send_num( irc, 600, "%s %s %s %d :%s", iu->nick, iu->user,
				              iu->host, (int) time( NULL ), "logged online" );
		}
		else
		{
			if( g_hash_table_lookup( irc->watches, iu->key ) )
				irc_send_num( irc, 601, "%s %s %s %d :%s", iu->nick, iu->user,
				              iu->host, (int) time( NULL ), "logged offline" );
			
			/* Send a QUIT since those will also show up in any
			   query windows the user may have, plus it's only
			   one QUIT instead of possibly many (in case of
			   multiple control chans). If there's a channel that
			   shows offline people, a JOIN will follow. */
			if( set_getbool( &bee->set, "offline_user_quits" ) )
				irc_user_quit( iu, "Leaving..." );
		}
	}
	
	/* Reset this one since the info may have changed. */
	iu->away_reply_timeout = 0;
	
	bee_irc_channel_update( irc, NULL, iu );
	
	return TRUE;
}
コード例 #20
0
ファイル: steam.c プロジェクト: roughnecks/bitlbee-steam
/**
 * Creates a new #SteamData with an #account_t. The returned #SteamData
 * should be freed with #steam_data_free() when no longer needed.
 *
 * @param acc The #account_t.
 *
 * @return The #SteamData or NULL on error.
 **/
SteamData *steam_data_new(account_t *acc)
{
    SteamData *sata;

    g_return_val_if_fail(acc != NULL, NULL);

    sata = g_new0(SteamData, 1);
    sata->api = steam_api_new();
    sata->ic  = imcb_new(acc);
    sata->ic->proto_data = sata;

    sata->api->umqid  = g_strdup(set_getstr(&acc->set, "umqid"));
    sata->api->token  = g_strdup(set_getstr(&acc->set, "token"));
    sata->api->sessid = g_strdup(set_getstr(&acc->set, "sessid"));
    sata->game_status = set_getbool(&acc->set, "game_status");

    steam_api_rehash(sata->api);

    return sata;
}
コード例 #21
0
ファイル: nick.c プロジェクト: malinkb/bitlbee
char *nick_get(bee_user_t *bu)
{
	static char nick[MAX_NICK_LENGTH + 1];
	char *store_handle, *found_nick;
	irc_t *irc = (irc_t *) bu->bee->ui_data;

	memset(nick, 0, MAX_NICK_LENGTH + 1);

	store_handle = clean_handle(bu->handle);
	/* Find out if we stored a nick for this person already. If not, try
	   to generate a sane nick automatically. */
	if ((found_nick = g_hash_table_lookup(bu->ic->acc->nicks, store_handle))) {
		strncpy(nick, found_nick, MAX_NICK_LENGTH);
	} else if ((found_nick = nick_gen(bu))) {
		strncpy(nick, found_nick, MAX_NICK_LENGTH);
		g_free(found_nick);
	} else {
		/* Keep this fallback since nick_gen() can return NULL in some cases. */
		char *s;

		g_snprintf(nick, MAX_NICK_LENGTH, "%s", bu->handle);
		if ((s = strchr(nick, '@'))) {
			while (*s) {
				*(s++) = 0;
			}
		}

		nick_strip(irc, nick);
		if (set_getbool(&bu->bee->set, "lcnicks")) {
			nick_lc(irc, nick);
		}
	}
	g_free(store_handle);

	/* Make sure the nick doesn't collide with an existing one by adding
	   underscores and that kind of stuff, if necessary. */
	nick_dedupe(bu, nick);

	return nick;
}
コード例 #22
0
ファイル: jabber.c プロジェクト: AlD/bitlbee
/* Separate this from jabber_login() so we can do OAuth first if necessary.
   Putting this in io.c would probably be more correct. */
void jabber_connect( struct im_connection *ic )
{
	account_t *acc = ic->acc;
	struct jabber_data *jd = ic->proto_data;
	int i;
	char *connect_to;
	struct ns_srv_reply **srvl = NULL, *srv = NULL;
	
	/* Figure out the hostname to connect to. */
	if( acc->server && *acc->server )
		connect_to = acc->server;
	else if( ( srvl = srv_lookup( "xmpp-client", "tcp", jd->server ) ) ||
	         ( srvl = srv_lookup( "jabber-client", "tcp", jd->server ) ) )
	{
		/* Find the lowest-priority one. These usually come
		   back in random/shuffled order. Not looking at
		   weights etc for now. */
		srv = *srvl;
		for( i = 1; srvl[i]; i ++ )
			if( srvl[i]->prio < srv->prio )
				srv = srvl[i];
		
		connect_to = srv->name;
	}
	else
		connect_to = jd->server;
	
	imcb_log( ic, "Connecting" );
	
	for( i = 0; jabber_port_list[i] > 0; i ++ )
		if( set_getint( &acc->set, "port" ) == jabber_port_list[i] )
			break;

	if( jabber_port_list[i] == 0 )
	{
		imcb_log( ic, "Illegal port number" );
		imc_logout( ic, FALSE );
		return;
	}
	
	/* For non-SSL connections we can try to use the port # from the SRV
	   reply, but let's not do that when using SSL, SSL usually runs on
	   non-standard ports... */
	if( set_getbool( &acc->set, "ssl" ) )
	{
		jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), FALSE, jabber_connected_ssl, ic );
		jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1;
	}
	else
	{
		jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, ic );
	}
	srv_free( srvl );
	
	if( jd->fd == -1 )
	{
		imcb_error( ic, "Could not connect to server" );
		imc_logout( ic, TRUE );
		
		return;
	}
	
	if( set_getbool( &acc->set, "xmlconsole" ) )
	{
		jd->flags |= JFLAG_XMLCONSOLE;
		/* Shouldn't really do this at this stage already, maybe. But
		   I think this shouldn't break anything. */
		imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL );
	}
	
	jabber_generate_id_hash( jd );
}
コード例 #23
0
ファイル: root_commands.c プロジェクト: EionRobb/bitlbee
static void cmd_identify(irc_t *irc, char **cmd)
{
	storage_status_t status;
	gboolean load = TRUE;
	char *password = cmd[1];

	if (irc->status & USTATUS_IDENTIFIED) {
		irc_rootmsg(irc, "You're already logged in.");
		return;
	}

	if (cmd[1] == NULL) {
	} else if (strncmp(cmd[1], "-no", 3) == 0) {
		load = FALSE;
		password = cmd[2];
		if (password == NULL) {
			irc->status |= OPER_HACK_IDENTIFY_NOLOAD;
		}
	} else if (strncmp(cmd[1], "-force", 6) == 0) {
		password = cmd[2];
		if (password == NULL) {
			irc->status |= OPER_HACK_IDENTIFY_FORCE;
		}
	} else if (irc->b->accounts != NULL) {
		irc_rootmsg(irc,
		            "You're trying to identify yourself, but already have "
		            "at least one IM account set up. "
		            "Use \x02identify -noload\x02 or \x02identify -force\x02 "
		            "instead (see \x02help identify\x02).");
		return;
	}

	if (password == NULL) {
		irc_rootmsg(irc, "About to identify, use /OPER to enter the password");
		irc->status |= OPER_HACK_IDENTIFY;
		return;
	}

	status = auth_check_pass(irc, irc->user->nick, password);
	if (load && (status == STORAGE_OK)) {
		status = storage_load(irc, password);
	}

	switch (status) {
	case STORAGE_INVALID_PASSWORD:
		irc_rootmsg(irc, "Incorrect password");
		break;
	case STORAGE_NO_SUCH_USER:
		irc_rootmsg(irc, "The nick is (probably) not registered");
		break;
	case STORAGE_OK:
		irc_rootmsg(irc, "Password accepted%s",
		            load ? ", settings and accounts loaded" : "");
		irc->status |= USTATUS_IDENTIFIED;
		irc_umode_set(irc, "+R", 1);

		if (irc->caps & CAP_SASL) {
			irc_user_t *iu = irc->user;
			irc_send_num(irc, 900, "%s!%s@%s %s :You are now logged in as %s",
				iu->nick, iu->user, iu->host, iu->nick, iu->nick);
		}

		bitlbee_whatsnew(irc);

		/* The following code is a bit hairy now. With takeover
		   support, we shouldn't immediately auto_connect in case
		   we're going to offer taking over an existing session.
		   Do it in 200ms since that should give the parent process
		   enough time to come back to us. */
		if (load) {
			irc_channel_auto_joins(irc, NULL);
			if (!set_getbool(&irc->default_channel->set, "auto_join")) {
				irc_channel_del_user(irc->default_channel, irc->user,
				                     IRC_CDU_PART, "auto_join disabled "
				                     "for this channel.");
			}
			if (set_getbool(&irc->b->set, "auto_connect")) {
				irc->login_source_id = b_timeout_add(200,
				                                     cmd_identify_finish, irc);
			}
		}

		/* If ipc_child_identify() returns FALSE, it means we're
		   already sure that there's no takeover target (only
		   possible in 1-process daemon mode). Start auto_connect
		   immediately. */
		if (!ipc_child_identify(irc) && load) {
			cmd_identify_finish(irc, 0, 0);
		}

		break;
	case STORAGE_OTHER_ERROR:
	default:
		irc_rootmsg(irc, "Unknown error while loading configuration");
		break;
	}
}
コード例 #24
0
ファイル: io.c プロジェクト: jianingy/bitlbee-clone
static xt_status jabber_pkt_features( struct xt_node *node, gpointer data )
{
	struct im_connection *ic = data;
	struct jabber_data *jd = ic->proto_data;
	struct xt_node *c, *reply;
	int trytls;
	
	trytls = g_strcasecmp( set_getstr( &ic->acc->set, "tls" ), "try" ) == 0;
	c = xt_find_node( node->children, "starttls" );
	if( c && !jd->ssl )
	{
		/* If the server advertises the STARTTLS feature and if we're
		   not in a secure connection already: */
		
		c = xt_find_node( c->children, "required" );
		
		if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) )
		{
			imcb_error( ic, "Server requires TLS connections, but TLS is turned off for this account" );
			imc_logout( ic, FALSE );
			
			return XT_ABORT;
		}
		
		/* Only run this if the tls setting is set to true or try: */
		if( ( trytls || set_getbool( &ic->acc->set, "tls" ) ) )
		{
			reply = xt_new_node( "starttls", NULL, NULL );
			xt_add_attr( reply, "xmlns", XMLNS_TLS );
			if( !jabber_write_packet( ic, reply ) )
			{
				xt_free_node( reply );
				return XT_ABORT;
			}
			xt_free_node( reply );
			
			return XT_HANDLED;
		}
	}
	else if( !c && !jd->ssl )
	{
		/* If the server does not advertise the STARTTLS feature and
		   we're not in a secure connection already: (Servers have a
		   habit of not advertising <starttls/> anymore when already
		   using SSL/TLS. */
		
		if( !trytls && set_getbool( &ic->acc->set, "tls" ) )
		{
			imcb_error( ic, "TLS is turned on for this account, but is not supported by this server" );
			imc_logout( ic, FALSE );
			
			return XT_ABORT;
		}
	}
	
	/* This one used to be in jabber_handlers[], but it has to be done
	   from here to make sure the TLS session will be initialized
	   properly before we attempt SASL authentication. */
	if( ( c = xt_find_node( node->children, "mechanisms" ) ) )
	{
		if( sasl_pkt_mechanisms( c, data ) == XT_ABORT )
			return XT_ABORT;
	}
	/* If the server *SEEMS* to support SASL authentication but doesn't
	   support it after all, we should try to do authentication the
	   other way. jabber.com doesn't seem to do SASL while it pretends
	   to be XMPP 1.0 compliant! */
	else if( !( jd->flags & JFLAG_AUTHENTICATED ) && sasl_supported( ic ) )
	{
		if( !jabber_init_iq_auth( ic ) )
			return XT_ABORT;
	}
	
	if( ( c = xt_find_node( node->children, "bind" ) ) )
	{
		reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) );
		xt_add_attr( reply, "xmlns", XMLNS_BIND );
		reply = jabber_make_packet( "iq", "set", NULL, reply );
		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
		
		if( !jabber_write_packet( ic, reply ) )
			return XT_ABORT;
		
		jd->flags |= JFLAG_WAIT_BIND;
	}
	
	if( ( c = xt_find_node( node->children, "session" ) ) )
	{
		reply = xt_new_node( "session", NULL, NULL );
		xt_add_attr( reply, "xmlns", XMLNS_SESSION );
		reply = jabber_make_packet( "iq", "set", NULL, reply );
		jabber_cache_add( ic, reply, jabber_pkt_bind_sess );
		
		if( !jabber_write_packet( ic, reply ) )
			return XT_ABORT;
		
		jd->flags |= JFLAG_WAIT_SESSION;
	}
	
	/* This flag is already set if we authenticated via SASL, so now
	   we can resume the session in the new stream, if we don't have
	   to bind/initialize the session. */
	if( jd->flags & JFLAG_AUTHENTICATED && ( jd->flags & ( JFLAG_WAIT_BIND | JFLAG_WAIT_SESSION ) ) == 0 )
	{
		if( !jabber_get_roster( ic ) )
			return XT_ABORT;
	}
	
	return XT_HANDLED;
}
コード例 #25
0
ファイル: io.c プロジェクト: jianingy/bitlbee-clone
static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond )
{
	struct im_connection *ic = data;
	struct jabber_data *jd = ic->proto_data;
	char buf[512];
	int st;
	
	if( jd->fd == -1 )
		return FALSE;
	
	if( jd->ssl )
		st = ssl_read( jd->ssl, buf, sizeof( buf ) );
	else
		st = read( jd->fd, buf, sizeof( buf ) );
	
	if( st > 0 )
	{
		/* Parse. */
		if( xt_feed( jd->xt, buf, st ) < 0 )
		{
			imcb_error( ic, "XML stream error" );
			imc_logout( ic, TRUE );
			return FALSE;
		}
		
		/* Execute all handlers. */
		if( !xt_handle( jd->xt, NULL, 1 ) )
		{
			/* Don't do anything, the handlers should have
			   aborted the connection already. */
			return FALSE;
		}
		
		if( jd->flags & JFLAG_STREAM_RESTART )
		{
			jd->flags &= ~JFLAG_STREAM_RESTART;
			jabber_start_stream( ic );
		}
		
		/* Garbage collection. */
		xt_cleanup( jd->xt, NULL, 1 );
		
		/* This is a bit hackish, unfortunately. Although xmltree
		   has nifty event handler stuff, it only calls handlers
		   when nodes are complete. Since the server should only
		   send an opening <stream:stream> tag, we have to check
		   this by hand. :-( */
		if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root )
		{
			if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 )
			{
				jd->flags |= JFLAG_STREAM_STARTED;
				
				/* If there's no version attribute, assume
				   this is an old server that can't do SASL
				   authentication. */
				if( !sasl_supported( ic ) )
				{
					/* If there's no version= tag, we suppose
					   this server does NOT implement: XMPP 1.0,
					   SASL and TLS. */
					if( set_getbool( &ic->acc->set, "tls" ) )
					{
						imcb_error( ic, "TLS is turned on for this "
						          "account, but is not supported by this server" );
						imc_logout( ic, FALSE );
						return FALSE;
					}
					else
					{
						return jabber_init_iq_auth( ic );
					}
				}
			}
			else
			{
				imcb_error( ic, "XML stream error" );
				imc_logout( ic, TRUE );
				return FALSE;
			}
		}
	}
	else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) )
	{
		closesocket( jd->fd );
		jd->fd = -1;
		
		imcb_error( ic, "Error while reading from server" );
		imc_logout( ic, TRUE );
		return FALSE;
	}
	
	if( ssl_pending( jd->ssl ) )
		/* OpenSSL empties the TCP buffers completely but may keep some
		   data in its internap buffers. select() won't see that, but
		   ssl_pending() does. */
		return jabber_read_callback( data, fd, cond );
	else
		return TRUE;
}
コード例 #26
0
ファイル: skype.c プロジェクト: GRMrGecko/bitlbee
static void skype_parse_user(struct im_connection *ic, char *line)
{
	int flags = 0;
	char *ptr;
	struct skype_data *sd = ic->proto_data;
	char *user = strchr(line, ' ');
	char *status = strrchr(line, ' ');

	status++;
	ptr = strchr(++user, ' ');
	if (!ptr)
		return;
	*ptr = '\0';
	ptr++;
	if (!strncmp(ptr, "ONLINESTATUS ", 13)) {
		if (!strlen(user) || !strcmp(user, sd->username))
			return;
		if (!set_getbool(&ic->acc->set, "test_join")
				&& !strcmp(user, "echo123"))
			return;
		ptr = g_strdup_printf("*****@*****.**", user);
		imcb_add_buddy(ic, ptr, skype_group_by_username(ic, user));
		if (strcmp(status, "OFFLINE") && (strcmp(status, "SKYPEOUT") ||
			!set_getbool(&ic->acc->set, "skypeout_offline")))
			flags |= OPT_LOGGED_IN;
		if (strcmp(status, "ONLINE") && strcmp(status, "SKYPEME"))
			flags |= OPT_AWAY;
		imcb_buddy_status(ic, ptr, flags, NULL, NULL);
		g_free(ptr);
	} else if (!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20)) {
		char *message = ptr + 20;
		if (strlen(message))
			skype_buddy_ask(ic, user, message);
	} else if (!strncmp(ptr, "BUDDYSTATUS ", 12)) {
		char *st = ptr + 12;
		if (!strcmp(st, "3")) {
			char *buf = g_strdup_printf("*****@*****.**", user);
			imcb_add_buddy(ic, buf, skype_group_by_username(ic, user));
			g_free(buf);
		}
	} else if (!strncmp(ptr, "MOOD_TEXT ", 10)) {
		char *buf = g_strdup_printf("*****@*****.**", user);
		bee_user_t *bu = bee_user_by_handle(ic->bee, ic, buf);
		g_free(buf);
		buf = ptr + 10;
		if (bu)
			imcb_buddy_status(ic, bu->handle, bu->flags, NULL,
					*buf ? buf : NULL);
		if (set_getbool(&ic->acc->set, "show_moods"))
			imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf);
	} else if (!strncmp(ptr, "FULLNAME ", 9)) {
		char *name = ptr + 9;
		if (sd->is_info) {
			sd->is_info = FALSE;
			sd->info_fullname = g_strdup(name);
		} else {
			char *buf = g_strdup_printf("*****@*****.**", user);
			imcb_rename_buddy(ic, buf, name);
			g_free(buf);
		}
	} else if (!strncmp(ptr, "PHONE_HOME ", 11))
		sd->info_phonehome = g_strdup(ptr + 11);
	else if (!strncmp(ptr, "PHONE_OFFICE ", 13))
		sd->info_phoneoffice = g_strdup(ptr + 13);
	else if (!strncmp(ptr, "PHONE_MOBILE ", 13))
		sd->info_phonemobile = g_strdup(ptr + 13);
	else if (!strncmp(ptr, "NROF_AUTHED_BUDDIES ", 20))
		sd->info_nrbuddies = g_strdup(ptr + 20);
	else if (!strncmp(ptr, "TIMEZONE ", 9))
		sd->info_tz = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "LASTONLINETIMESTAMP ", 20))
		sd->info_seen = g_strdup(ptr + 20);
	else if (!strncmp(ptr, "SEX ", 4))
		sd->info_sex = g_strdup(ptr + 4);
	else if (!strncmp(ptr, "LANGUAGE ", 9))
		sd->info_language = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "COUNTRY ", 8))
		sd->info_country = g_strdup(ptr + 8);
	else if (!strncmp(ptr, "PROVINCE ", 9))
		sd->info_province = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "CITY ", 5))
		sd->info_city = g_strdup(ptr + 5);
	else if (!strncmp(ptr, "HOMEPAGE ", 9))
		sd->info_homepage = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "ABOUT ", 6)) {
		/* Support multiple about lines. */
		if (!sd->info_about)
			sd->info_about = g_strdup(ptr + 6);
		else {
			GString *st = g_string_new(sd->info_about);
			g_string_append_printf(st, "\n%s", ptr + 6);
			g_free(sd->info_about);
			sd->info_about = g_strdup(st->str);
			g_string_free(st, TRUE);
		}
	} else if (!strncmp(ptr, "BIRTHDAY ", 9)) {
		sd->info_birthday = g_strdup(ptr + 9);

		GString *st = g_string_new("Contact Information\n");
		g_string_append_printf(st, "Skype Name: %s\n", user);
		if (sd->info_fullname) {
			if (strlen(sd->info_fullname))
				g_string_append_printf(st, "Full Name: %s\n",
					sd->info_fullname);
			g_free(sd->info_fullname);
			sd->info_fullname = NULL;
		}
		if (sd->info_phonehome) {
			if (strlen(sd->info_phonehome))
				g_string_append_printf(st, "Home Phone: %s\n",
					sd->info_phonehome);
			g_free(sd->info_phonehome);
			sd->info_phonehome = NULL;
		}
		if (sd->info_phoneoffice) {
			if (strlen(sd->info_phoneoffice))
				g_string_append_printf(st, "Office Phone: %s\n",
					sd->info_phoneoffice);
			g_free(sd->info_phoneoffice);
			sd->info_phoneoffice = NULL;
		}
		if (sd->info_phonemobile) {
			if (strlen(sd->info_phonemobile))
				g_string_append_printf(st, "Mobile Phone: %s\n",
					sd->info_phonemobile);
			g_free(sd->info_phonemobile);
			sd->info_phonemobile = NULL;
		}
		g_string_append_printf(st, "Personal Information\n");
		if (sd->info_nrbuddies) {
			if (strlen(sd->info_nrbuddies))
				g_string_append_printf(st,
					"Contacts: %s\n", sd->info_nrbuddies);
			g_free(sd->info_nrbuddies);
			sd->info_nrbuddies = NULL;
		}
		if (sd->info_tz) {
			if (strlen(sd->info_tz)) {
				char ib[256];
				time_t t = time(NULL);
				t += atoi(sd->info_tz)-(60*60*24);
				struct tm *gt = gmtime(&t);
				strftime(ib, 256, "%H:%M:%S", gt);
				g_string_append_printf(st,
					"Local Time: %s\n", ib);
			}
			g_free(sd->info_tz);
			sd->info_tz = NULL;
		}
		if (sd->info_seen) {
			if (strlen(sd->info_seen)) {
				char ib[256];
				time_t it = atoi(sd->info_seen);
				struct tm *tm = localtime(&it);
				strftime(ib, 256, ("%Y. %m. %d. %H:%M"), tm);
				g_string_append_printf(st,
					"Last Seen: %s\n", ib);
			}
			g_free(sd->info_seen);
			sd->info_seen = NULL;
		}
		if (sd->info_birthday) {
			if (strlen(sd->info_birthday) &&
				strcmp(sd->info_birthday, "0")) {
				char ib[256];
				struct tm tm;
				strptime(sd->info_birthday, "%Y%m%d", &tm);
				strftime(ib, 256, "%B %d, %Y", &tm);
				g_string_append_printf(st,
					"Birthday: %s\n", ib);

				strftime(ib, 256, "%Y", &tm);
				int year = atoi(ib);
				time_t t = time(NULL);
				struct tm *lt = localtime(&t);
				g_string_append_printf(st,
					"Age: %d\n", lt->tm_year+1900-year);
			}
			g_free(sd->info_birthday);
			sd->info_birthday = NULL;
		}
		if (sd->info_sex) {
			if (strlen(sd->info_sex)) {
				char *iptr = sd->info_sex;
				while (*iptr++)
					*iptr = tolower(*iptr);
				g_string_append_printf(st,
					"Gender: %s\n", sd->info_sex);
			}
			g_free(sd->info_sex);
			sd->info_sex = NULL;
		}
		if (sd->info_language) {
			if (strlen(sd->info_language)) {
				char *iptr = strchr(sd->info_language, ' ');
				if (iptr)
					iptr++;
				else
					iptr = sd->info_language;
				g_string_append_printf(st,
					"Language: %s\n", iptr);
			}
			g_free(sd->info_language);
			sd->info_language = NULL;
		}
		if (sd->info_country) {
			if (strlen(sd->info_country)) {
				char *iptr = strchr(sd->info_country, ' ');
				if (iptr)
					iptr++;
				else
					iptr = sd->info_country;
				g_string_append_printf(st,
					"Country: %s\n", iptr);
			}
			g_free(sd->info_country);
			sd->info_country = NULL;
		}
		if (sd->info_province) {
			if (strlen(sd->info_province))
				g_string_append_printf(st,
					"Region: %s\n", sd->info_province);
			g_free(sd->info_province);
			sd->info_province = NULL;
		}
		if (sd->info_city) {
			if (strlen(sd->info_city))
				g_string_append_printf(st,
					"City: %s\n", sd->info_city);
			g_free(sd->info_city);
			sd->info_city = NULL;
		}
		if (sd->info_homepage) {
			if (strlen(sd->info_homepage))
				g_string_append_printf(st,
					"Homepage: %s\n", sd->info_homepage);
			g_free(sd->info_homepage);
			sd->info_homepage = NULL;
		}
		if (sd->info_about) {
			if (strlen(sd->info_about))
				g_string_append_printf(st, "%s\n",
					sd->info_about);
			g_free(sd->info_about);
			sd->info_about = NULL;
		}
		imcb_log(ic, "%s", st->str);
		g_string_free(st, TRUE);
	}
}
コード例 #27
0
ファイル: ipc.c プロジェクト: dequis/bitlbee-old
static void ipc_child_cmd_takeover( irc_t *irc, char **cmd )
{
	if( strcmp( cmd[1], "NO" ) == 0 )
	{
		/* Master->New connection */
		/* No takeover, finish the login. */
	}
	else if( strcmp( cmd[1], "INIT" ) == 0 )
	{
		/* Master->New connection */
		if( !set_getbool( &irc->b->set, "allow_takeover" ) )
		{
			ipc_child_cmd_takeover_no( irc );
			return;
		}
		
		/* Offer to take over the old session, unless for some reason
		   we're already logging into IM connections. */
		if( irc->login_source_id != -1 )
			query_add( irc, NULL,
			           "You're already connected to this server. "
			           "Would you like to take over this session?",
			           ipc_child_cmd_takeover_yes,
		        	   ipc_child_cmd_takeover_no, NULL, irc );
		
		/* This one's going to connect to accounts, avoid that. */
		b_event_remove( irc->login_source_id );
		irc->login_source_id = -1;
	}
	else if( strcmp( cmd[1], "AUTH" ) == 0 )
	{
		/* Master->Old connection */
		if( irc->password && cmd[2] && cmd[3] &&
		    ipc_child_recv_fd != -1 &&
		    strcmp( irc->user->nick, cmd[2] ) == 0 &&
		    strcmp( irc->password, cmd[3] ) == 0 &&
		    set_getbool( &irc->b->set, "allow_takeover" ) )
		{
			irc_switch_fd( irc, ipc_child_recv_fd );
			irc_sync( irc );
			irc_rootmsg( irc, "You've successfully taken over your old session" );
			ipc_child_recv_fd = -1;
			
			ipc_to_master_str( "TAKEOVER DONE\r\n" );
		}
		else
		{
			ipc_to_master_str( "TAKEOVER FAIL\r\n" );
		}
	}
	else if( strcmp( cmd[1], "DONE" ) == 0 ) 
	{
		/* Master->New connection (now taken over by old process) */
		irc_free( irc );
	}
	else if( strcmp( cmd[1], "FAIL" ) == 0 ) 
	{
		/* Master->New connection */
		irc_rootmsg( irc, "Could not take over old session" );
	}
}
コード例 #28
0
ファイル: sasl.c プロジェクト: mrdon/bitlbee
xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data )
{
	struct im_connection *ic = data;
	struct jabber_data *jd = ic->proto_data;
	struct xt_node *c, *reply;
	char *s;
	int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0;
	int want_oauth = FALSE;
	GString *mechs;
	
	if( !sasl_supported( ic ) )
	{
		/* Should abort this now, since we should already be doing
		   IQ authentication. Strange things happen when you try
		   to do both... */
		imcb_log( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" );
		return XT_HANDLED;
	}
	
	s = xt_find_attr( node, "xmlns" );
	if( !s || strcmp( s, XMLNS_SASL ) != 0 )
	{
		imcb_log( ic, "Stream error while authenticating" );
		imc_logout( ic, FALSE );
		return XT_ABORT;
	}
	
	want_oauth = set_getbool( &ic->acc->set, "oauth" );
	
	mechs = g_string_new( "" );
	c = node->children;
	while( ( c = xt_find_node( c, "mechanism" ) ) )
	{
		if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 )
			sup_plain = 1;
		else if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 )
			sup_digest = 1;
		else if( c->text && g_strcasecmp( c->text, "X-OAUTH2" ) == 0 )
			sup_gtalk = 1;
		else if( c->text && g_strcasecmp( c->text, "X-FACEBOOK-PLATFORM" ) == 0 )
			sup_fb = 1;
		
		if( c->text )
			g_string_append_printf( mechs, " %s", c->text );
		
		c = c->next;
	}
	
	if( !want_oauth && !sup_plain && !sup_digest )
	{
		if( !sup_gtalk && !sup_fb )
			imcb_error( ic, "This server requires OAuth "
			                "(supported schemes:%s)", mechs->str );
		else
			imcb_error( ic, "BitlBee does not support any of the offered SASL "
			                "authentication schemes:%s", mechs->str );
		imc_logout( ic, FALSE );
		g_string_free( mechs, TRUE );
		return XT_ABORT;
	}
	g_string_free( mechs, TRUE );
	
	reply = xt_new_node( "auth", NULL, NULL );
	xt_add_attr( reply, "xmlns", XMLNS_SASL );
	
	if( sup_gtalk && want_oauth )
	{
		int len;
		
		/* X-OAUTH2 is, not *the* standard OAuth2 SASL/XMPP implementation.
		   It's currently used by GTalk and vaguely documented on
		   http://code.google.com/apis/cloudprint/docs/rawxmpp.html . */
		xt_add_attr( reply, "mechanism", "X-OAUTH2" );
		
		len = strlen( jd->username ) + strlen( jd->oauth2_access_token ) + 2;
		s = g_malloc( len + 1 );
		s[0] = 0;
		strcpy( s + 1, jd->username );
		strcpy( s + 2 + strlen( jd->username ), jd->oauth2_access_token );
		reply->text = base64_encode( (unsigned char *)s, len );
		reply->text_len = strlen( reply->text );
		g_free( s );
	}
	else if( sup_fb && want_oauth )
	{
		xt_add_attr( reply, "mechanism", "X-FACEBOOK-PLATFORM" );
		jd->flags |= JFLAG_SASL_FB;
	}
	else if( want_oauth )
	{
		imcb_error( ic, "OAuth requested, but not supported by server" );
		imc_logout( ic, FALSE );
		xt_free_node( reply );
		return XT_ABORT;
	}
	else if( sup_digest )
	{
		xt_add_attr( reply, "mechanism", "DIGEST-MD5" );
		
		/* The rest will be done later, when we receive a <challenge/>. */
	}
	else if( sup_plain )
	{
		int len;
		
		xt_add_attr( reply, "mechanism", "PLAIN" );
		
		/* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */
		len = strlen( jd->username ) + strlen( ic->acc->pass ) + 2;
		s = g_malloc( len + 1 );
		s[0] = 0;
		strcpy( s + 1, jd->username );
		strcpy( s + 2 + strlen( jd->username ), ic->acc->pass );
		reply->text = base64_encode( (unsigned char *)s, len );
		reply->text_len = strlen( reply->text );
		g_free( s );
	}
	
	if( reply && !jabber_write_packet( ic, reply ) )
	{
		xt_free_node( reply );
		return XT_ABORT;
	}
	xt_free_node( reply );
	
	/* To prevent classic authentication from happening. */
	jd->flags |= JFLAG_STREAM_STARTED;
	
	return XT_HANDLED;
}
コード例 #29
0
ファイル: jabber.c プロジェクト: AlD/bitlbee
static void jabber_login( account_t *acc )
{
	struct im_connection *ic = imcb_new( acc );
	struct jabber_data *jd = g_new0( struct jabber_data, 1 );
	char *s;
	
	/* For now this is needed in the _connected() handlers if using
	   GLib event handling, to make sure we're not handling events
	   on dead connections. */
	jabber_connections = g_slist_prepend( jabber_connections, ic );
	
	jd->ic = ic;
	ic->proto_data = jd;
	
	jabber_set_me( ic, acc->user );
	
	jd->fd = jd->r_inpa = jd->w_inpa = -1;
	
	if( jd->server == NULL )
	{
		imcb_error( ic, "Incomplete account name (format it like <*****@*****.**>)" );
		imc_logout( ic, FALSE );
		return;
	}
	
	if( ( s = strchr( jd->server, '/' ) ) )
	{
		*s = 0;
		set_setstr( &acc->set, "resource", s + 1 );
		
		/* Also remove the /resource from the original variable so we
		   won't have to do this again every time. */
		s = strchr( acc->user, '/' );
		*s = 0;
	}
	
	jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free );
	jd->buddies = g_hash_table_new( g_str_hash, g_str_equal );
	
	if( set_getbool( &acc->set, "oauth" ) )
	{
		GSList *p_in = NULL;
		const char *tok;
		
		jd->fd = jd->r_inpa = jd->w_inpa = -1;
		
		if( strstr( jd->server, ".live.com" ) )
			jd->oauth2_service = &oauth2_service_mslive;
		else if( strstr( jd->server, ".facebook.com" ) )
			jd->oauth2_service = &oauth2_service_facebook;
		else
			jd->oauth2_service = &oauth2_service_google;
		
		oauth_params_parse( &p_in, ic->acc->pass );
		
		/* First see if we have a refresh token, in which case any
		   access token we *might* have has probably expired already
		   anyway. */
		if( ( tok = oauth_params_get( &p_in, "refresh_token" ) ) )
		{
			sasl_oauth2_refresh( ic, tok );
		}
		/* If we don't have a refresh token, let's hope the access
		   token is still usable. */
		else if( ( tok = oauth_params_get( &p_in, "access_token" ) ) )
		{
			jd->oauth2_access_token = g_strdup( tok );
			jabber_connect( ic );
		}
		/* If we don't have any, start the OAuth process now. Don't
		   even open an XMPP connection yet. */
		else
		{
			sasl_oauth2_init( ic );
			ic->flags |= OPT_SLOW_LOGIN;
		}
		
		oauth_params_free( &p_in );
	}
	else
		jabber_connect( ic );
}
コード例 #30
0
ファイル: irc.c プロジェクト: dgruss/bitlbee
void irc_free(irc_t * irc)
{
	GSList *l;

	irc->status |= USTATUS_SHUTDOWN;

	log_message(LOGLVL_INFO, "Destroying connection with fd %d", irc->fd);

	if (irc->status & USTATUS_IDENTIFIED && set_getbool(&irc->b->set, "save_on_quit")) {
		if (storage_save(irc, NULL, TRUE) != STORAGE_OK) {
			log_message(LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick);
		}
	}

	for (l = irc_plugins; l; l = l->next) {
		irc_plugin_t *p = l->data;
		if (p->irc_free) {
			p->irc_free(irc);
		}
	}

	irc_connection_list = g_slist_remove(irc_connection_list, irc);

	while (irc->queries != NULL) {
		query_del(irc, irc->queries);
	}

	/* This is a little bit messy: bee_free() frees all b->users which
	   calls us back to free the corresponding irc->users. So do this
	   before we clear the remaining ones ourselves. */
	bee_free(irc->b);

	while (irc->users) {
		irc_user_free(irc, (irc_user_t *) irc->users->data);
	}

	while (irc->channels) {
		irc_channel_free(irc->channels->data);
	}

	if (irc->ping_source_id > 0) {
		b_event_remove(irc->ping_source_id);
	}
	if (irc->r_watch_source_id > 0) {
		b_event_remove(irc->r_watch_source_id);
	}
	if (irc->w_watch_source_id > 0) {
		b_event_remove(irc->w_watch_source_id);
	}

	closesocket(irc->fd);
	irc->fd = -1;

	g_hash_table_foreach_remove(irc->nick_user_hash, irc_free_hashkey, NULL);
	g_hash_table_destroy(irc->nick_user_hash);

	g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL);
	g_hash_table_destroy(irc->watches);

	if (irc->iconv != (GIConv) - 1) {
		g_iconv_close(irc->iconv);
	}
	if (irc->oconv != (GIConv) - 1) {
		g_iconv_close(irc->oconv);
	}

	g_free(irc->sendbuffer);
	g_free(irc->readbuffer);
	g_free(irc->password);

	g_free(irc);

	if (global.conf->runmode == RUNMODE_INETD ||
	    global.conf->runmode == RUNMODE_FORKDAEMON ||
	    (global.conf->runmode == RUNMODE_DAEMON &&
	     global.listen_socket == -1 &&
	     irc_connection_list == NULL)) {
		b_main_quit();
	}
}