⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yahoochat.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
{	struct yahoo_data *yd;	char *room, *topic, *members, *type;	int id;	PurpleConversation *c;	yd = (struct yahoo_data *) gc->proto_data;	if (!yd)		return;	room = g_hash_table_lookup(data, "room");	if (!room)		return;	topic = g_hash_table_lookup(data, "topic");	if (!topic)		topic = "";	members = g_hash_table_lookup(data, "members");	if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) {		id = yd->conf_id++;		c = serv_got_joined_chat(gc, id, room);		yd->confs = g_slist_prepend(yd->confs, c);		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), purple_connection_get_display_name(gc), topic);		yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members);		return;	} else {		if (yd->in_chat)			yahoo_chat_leave(gc, room,					purple_connection_get_display_name(gc),					FALSE);		if (!yd->chat_online)			yahoo_chat_online(gc);		yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic);		return;	}}void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name){	PurpleConversation *c;	c = purple_find_chat(gc, id);	if (!c || !c->name)		return;	if (id != YAHOO_CHAT_ID) {		yahoo_conf_invite(gc, c, purple_connection_get_display_name(gc), name,							purple_conversation_get_name(c), msg);	} else {		yahoo_chat_invite(gc, purple_connection_get_display_name(gc), name,							purple_conversation_get_name(c), msg);	}}struct yahoo_roomlist {	int fd;	int inpa;	gchar *txbuf;	gsize tx_written;	guchar *rxqueue;	int rxlen;	gboolean started;	char *path;	char *host;	PurpleRoomlist *list;	PurpleRoomlistRoom *cat;	PurpleRoomlistRoom *ucat;	GMarkupParseContext *parse;};static void yahoo_roomlist_destroy(struct yahoo_roomlist *yrl){	if (yrl->inpa)		purple_input_remove(yrl->inpa);	g_free(yrl->txbuf);	g_free(yrl->rxqueue);	g_free(yrl->path);	g_free(yrl->host);	if (yrl->parse)		g_markup_parse_context_free(yrl->parse);	g_free(yrl);}enum yahoo_room_type {	yrt_yahoo,	yrt_user,};struct yahoo_chatxml_state {	PurpleRoomlist *list;	struct yahoo_roomlist *yrl;	GQueue *q;	struct {		enum yahoo_room_type type;		char *name;		char *topic;		char *id;		int users, voices, webcams;	} room;};struct yahoo_lobby {	int count, users, voices, webcams;};static struct yahoo_chatxml_state *yahoo_chatxml_state_new(PurpleRoomlist *list, struct yahoo_roomlist *yrl){	struct yahoo_chatxml_state *s;	s = g_new0(struct yahoo_chatxml_state, 1);	s->list = list;	s->yrl = yrl;	s->q = g_queue_new();	return s;}static void yahoo_chatxml_state_destroy(struct yahoo_chatxml_state *s){	g_queue_free(s->q);	g_free(s->room.name);	g_free(s->room.topic);	g_free(s->room.id);	g_free(s);}static void yahoo_chatlist_start_element(GMarkupParseContext *context,                                  const gchar *ename, const gchar **anames,                                  const gchar **avalues, gpointer user_data,                                  GError **error){	struct yahoo_chatxml_state *s = user_data;	PurpleRoomlist *list = s->list;	PurpleRoomlistRoom *r;	PurpleRoomlistRoom *parent;	int i;	if (!strcmp(ename, "category")) {		const gchar *name = NULL, *id = NULL;		for (i = 0; anames[i]; i++) {			if (!strcmp(anames[i], "id"))				id = avalues[i];			if (!strcmp(anames[i], "name"))				name = avalues[i];		}		if (!name || !id)			return;		parent = g_queue_peek_head(s->q);		r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, name, parent);		purple_roomlist_room_add_field(list, r, (gpointer)name);		purple_roomlist_room_add_field(list, r, (gpointer)id);		purple_roomlist_room_add(list, r);		g_queue_push_head(s->q, r);	} else if (!strcmp(ename, "room")) {		s->room.users = s->room.voices = s->room.webcams = 0;		for (i = 0; anames[i]; i++) {			if (!strcmp(anames[i], "id")) {				if (s->room.id)					g_free(s->room.id);				s->room.id = g_strdup(avalues[i]);			} else if (!strcmp(anames[i], "name")) {				if (s->room.name)					g_free(s->room.name);				s->room.name = g_strdup(avalues[i]);			} else if (!strcmp(anames[i], "topic")) {				if (s->room.topic)					g_free(s->room.topic);				s->room.topic = g_strdup(avalues[i]);			} else if (!strcmp(anames[i], "type")) {				if (!strcmp("yahoo", avalues[i]))					s->room.type = yrt_yahoo;				else					s->room.type = yrt_user;			}		}	} else if (!strcmp(ename, "lobby")) {		struct yahoo_lobby *lob = g_new0(struct yahoo_lobby, 1);		for (i = 0; anames[i]; i++) {			if (!strcmp(anames[i], "count")) {				lob->count = strtol(avalues[i], NULL, 10);			} else if (!strcmp(anames[i], "users")) {				s->room.users += lob->users = strtol(avalues[i], NULL, 10);			} else if (!strcmp(anames[i], "voices")) {				s->room.voices += lob->voices = strtol(avalues[i], NULL, 10);			} else if (!strcmp(anames[i], "webcams")) {				s->room.webcams += lob->webcams = strtol(avalues[i], NULL, 10);			}		}		g_queue_push_head(s->q, lob);	}}static void yahoo_chatlist_end_element(GMarkupParseContext *context, const gchar *ename,                                       gpointer user_data, GError **error){	struct yahoo_chatxml_state *s = user_data;	if (!strcmp(ename, "category")) {		g_queue_pop_head(s->q);	} else if (!strcmp(ename, "room")) {		struct yahoo_lobby *lob;		PurpleRoomlistRoom *r, *l;		if (s->room.type == yrt_yahoo)			r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,		                                   s->room.name, s->yrl->cat);		else			r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,		                                   s->room.name, s->yrl->ucat);		purple_roomlist_room_add_field(s->list, r, s->room.name);		purple_roomlist_room_add_field(s->list, r, s->room.id);		purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.users));		purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.voices));		purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.webcams));		purple_roomlist_room_add_field(s->list, r, s->room.topic);		purple_roomlist_room_add(s->list, r);		while ((lob = g_queue_pop_head(s->q))) {			char *name = g_strdup_printf("%s:%d", s->room.name, lob->count);			l = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, r);			purple_roomlist_room_add_field(s->list, l, name);			purple_roomlist_room_add_field(s->list, l, s->room.id);			purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->users));			purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->voices));			purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->webcams));			purple_roomlist_room_add_field(s->list, l, s->room.topic);			purple_roomlist_room_add(s->list, l);			g_free(name);			g_free(lob);		}	}}static GMarkupParser parser = {	yahoo_chatlist_start_element,	yahoo_chatlist_end_element,	NULL,	NULL,	NULL};static void yahoo_roomlist_cleanup(PurpleRoomlist *list, struct yahoo_roomlist *yrl){	purple_roomlist_set_in_progress(list, FALSE);	if (yrl) {		list->proto_data = g_list_remove(list->proto_data, yrl);		yahoo_roomlist_destroy(yrl);	}	purple_roomlist_unref(list);}static void yahoo_roomlist_pending(gpointer data, gint source, PurpleInputCondition cond){	struct yahoo_roomlist *yrl = data;	PurpleRoomlist *list = yrl->list;	char buf[1024];	int len;	guchar *start;	struct yahoo_chatxml_state *s;	len = read(yrl->fd, buf, sizeof(buf));	if (len < 0 && errno == EAGAIN)		return;	if (len <= 0) {		if (yrl->parse)			g_markup_parse_context_end_parse(yrl->parse, NULL);		yahoo_roomlist_cleanup(list, yrl);		return;	}	yrl->rxqueue = g_realloc(yrl->rxqueue, len + yrl->rxlen);	memcpy(yrl->rxqueue + yrl->rxlen, buf, len);	yrl->rxlen += len;	if (!yrl->started) {		yrl->started = TRUE;		start = (guchar *)g_strstr_len((char *)yrl->rxqueue, yrl->rxlen, "\r\n\r\n");		if (!start || (start - yrl->rxqueue + 4) >= yrl->rxlen)			return;		start += 4;	} else {		start = yrl->rxqueue;	}	if (yrl->parse == NULL) {		s = yahoo_chatxml_state_new(list, yrl);		yrl->parse = g_markup_parse_context_new(&parser, 0, s,		             (GDestroyNotify)yahoo_chatxml_state_destroy);	}	if (!g_markup_parse_context_parse(yrl->parse, (char *)start, (yrl->rxlen - (start - yrl->rxqueue)), NULL)) {		yahoo_roomlist_cleanup(list, yrl);		return;	}	yrl->rxlen = 0;}static void yahoo_roomlist_send_cb(gpointer data, gint source, PurpleInputCondition cond){	struct yahoo_roomlist *yrl;	PurpleRoomlist *list;	int written, remaining;	yrl = data;	list = yrl->list;	remaining = strlen(yrl->txbuf) - yrl->tx_written;	written = write(yrl->fd, yrl->txbuf + yrl->tx_written, remaining);	if (written < 0 && errno == EAGAIN)		written = 0;	else if (written <= 0) {		purple_input_remove(yrl->inpa);		yrl->inpa = 0;		g_free(yrl->txbuf);		yrl->txbuf = NULL;		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));		yahoo_roomlist_cleanup(list, yrl);		return;	}	if (written < remaining) {		yrl->tx_written += written;		return;	}	g_free(yrl->txbuf);	yrl->txbuf = NULL;	purple_input_remove(yrl->inpa);	yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_READ,							   yahoo_roomlist_pending, yrl);}static void yahoo_roomlist_got_connected(gpointer data, gint source, const gchar *error_message){	struct yahoo_roomlist *yrl = data;	PurpleRoomlist *list = yrl->list;	struct yahoo_data *yd = purple_account_get_connection(list->account)->proto_data;	if (source < 0) {		purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));		yahoo_roomlist_cleanup(list, yrl);		return;	}	yrl->fd = source;	yrl->txbuf = g_strdup_printf(		"GET http://%s/%s HTTP/1.0\r\n"		"Host: %s\r\n"		"Cookie: Y=%s; T=%s\r\n\r\n",		yrl->host, yrl->path, yrl->host, yd->cookie_y,		yd->cookie_t);	yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_WRITE,							   yahoo_roomlist_send_cb, yrl);	yahoo_roomlist_send_cb(yrl, yrl->fd, PURPLE_INPUT_WRITE);}PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc){	struct yahoo_roomlist *yrl;	PurpleRoomlist *rl;	const char *rll;	char *url;	GList *fields = NULL;	PurpleRoomlistField *f;	rll = purple_account_get_string(purple_connection_get_account(gc),								  "room_list_locale", YAHOO_ROOMLIST_LOCALE);	if (rll != NULL && *rll != '\0') {		url = g_strdup_printf("%s?chatcat=0&intl=%s",	        purple_account_get_string(purple_connection_get_account(gc),	        "room_list", YAHOO_ROOMLIST_URL), rll);	} else {		url = g_strdup_printf("%s?chatcat=0",	        purple_account_get_string(purple_connection_get_account(gc),	        "room_list", YAHOO_ROOMLIST_URL));	}	yrl = g_new0(struct yahoo_roomlist, 1);	rl = purple_roomlist_new(purple_connection_get_account(gc));	yrl->list = rl;	purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);	g_free(url);	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "room", TRUE);	fields = g_list_append(fields, f);	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "id", TRUE);	fields = g_list_append(fields, f);	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Users"), "users", FALSE);	fields = g_list_append(fields, f);	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Voices"), "voices", FALSE);	fields = g_list_append(fields, f);	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Webcams"), "webcams", FALSE);	fields = g_list_append(fields, f);	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Topic"), "topic", FALSE);	fields = g_list_append(fields, f);	purple_roomlist_set_fields(rl, fields);	if (purple_proxy_connect(NULL, purple_connection_get_account(gc), yrl->host, 80,	                       yahoo_roomlist_got_connected, yrl) == NULL)	{		purple_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list."));		yahoo_roomlist_cleanup(rl, yrl);		return NULL;	}	rl->proto_data = g_list_append(rl->proto_data, yrl);	purple_roomlist_set_in_progress(rl, TRUE);	return rl;}void yahoo_roomlist_cancel(PurpleRoomlist *list){	GList *l, *k;	k = l = list->proto_data;	list->proto_data = NULL;	purple_roomlist_set_in_progress(list, FALSE);	for (; l; l = l->next) {		yahoo_roomlist_destroy(l->data);		purple_roomlist_unref(list);	}	g_list_free(k);}void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category){	struct yahoo_roomlist *yrl;	char *url;	char *id;	const char *rll;	if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)		return;	if (!(id = g_list_nth_data(category->fields, 1))) {		purple_roomlist_set_in_progress(list, FALSE);		return;	}	rll = purple_account_get_string(list->account, "room_list_locale",								  YAHOO_ROOMLIST_LOCALE);	if (rll != NULL && *rll != '\0') {		url = g_strdup_printf("%s?chatroom_%s=0&intl=%s",	       purple_account_get_string(list->account,"room_list",	       YAHOO_ROOMLIST_URL), id, rll);	} else {		url = g_strdup_printf("%s?chatroom_%s=0",	       purple_account_get_string(list->account,"room_list",	       YAHOO_ROOMLIST_URL), id);	}	yrl = g_new0(struct yahoo_roomlist, 1);	yrl->list = list;	yrl->cat = category;	list->proto_data = g_list_append(list->proto_data, yrl);	purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);	g_free(url);	yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat);	purple_roomlist_room_add(list, yrl->ucat);	if (purple_proxy_connect(NULL, list->account, yrl->host, 80,	                       yahoo_roomlist_got_connected, yrl) == NULL)	{		purple_notify_error(purple_account_get_connection(list->account),		                  NULL, _("Connection problem"), _("Unable to fetch room list."));		purple_roomlist_ref(list);		yahoo_roomlist_cleanup(list, yrl);		return;	}	purple_roomlist_set_in_progress(list, TRUE);	purple_roomlist_ref(list);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -