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

📄 oscar.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 5 页
字号:
		g_slist_free(images);	}	return 1;}static int gaim_odc_typing(aim_session_t *sess, aim_frame_t *fr, ...) {	va_list ap;	char *sn;	int typing;	GaimConnection *gc = sess->aux_data;	va_start(ap, fr);	sn = va_arg(ap, char *);	typing = va_arg(ap, int);	va_end(ap);	if (typing == 0x0002) {		/* I had to leave this. It's just too funny. It reminds me of my sister. */		gaim_debug_info("oscar",				   "ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn);		serv_got_typing(gc, sn, 0, GAIM_TYPING);	} else if (typing == 0x0001)		serv_got_typing(gc, sn, 0, GAIM_TYPED);	else		serv_got_typing_stopped(gc, sn);	return 1;}static int gaim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *message, GaimConvImFlags imflags) {	char *buf;	size_t len;	int ret;	GString *msg = g_string_new("<HTML><BODY>");	GString *data = g_string_new("</BODY></HTML><BINARY>");	GData *attribs;	const char *start, *end, *last;	int oscar_id = 0;	last = message;	/* for each valid IMG tag... */	while (last && *last && gaim_markup_find_tag("img", last, &start, &end, &attribs)) {		GaimStoredImage *image = NULL;		const char *id;		if (start - last) {			g_string_append_len(msg, last, start - last);		}		id = g_datalist_get_data(&attribs, "id");		/* ... if it refers to a valid gaim image ... */		if (id && (image = gaim_imgstore_get(atoi(id)))) {			/* ... append the message from start to the tag ... */			unsigned long size = gaim_imgstore_get_size(image);			const char *filename = gaim_imgstore_get_filename(image);			gpointer imgdata = gaim_imgstore_get_data(image);			oscar_id++;			/* ... insert a new img tag with the oscar id ... */			if (filename)				g_string_append_printf(msg,					"<IMG SRC=\"%s\" ID=\"%d\" DATASIZE=\"%lu\">",					filename, oscar_id, size);			else				g_string_append_printf(msg,					"<IMG ID=\"%d\" DATASIZE=\"%lu\">",					oscar_id, size);			/* ... and append the data to the binary section ... */			g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%lu\">",				oscar_id, size);			data = g_string_append_len(data, imgdata, size);			data = g_string_append(data, "</DATA>");		}			/* If the tag is invalid, skip it, thus no else here */		g_datalist_clear(&attribs);		/* continue from the end of the tag */		last = end + 1;	}	/* append any remaining message data (without the > :-) */	if (last && *last)		msg = g_string_append(msg, last);	/* if we inserted any images in the binary section, append it */	if (oscar_id) {		msg = g_string_append_len(msg, data->str, data->len);		msg = g_string_append(msg, "</BINARY>");	}	len = msg->len;	buf = msg->str;	g_string_free(msg, FALSE);	g_string_free(data, TRUE);	/* XXX - The last parameter below is the encoding.  Let Paco-Paco do something with it. */	if (imflags & GAIM_CONV_IM_AUTO_RESP)		ret =  aim_odc_send_im(sess, conn, buf, len, 0, 1);	else		ret =  aim_odc_send_im(sess, conn, buf, len, 0, 0);	g_free(buf);	return ret;}struct ask_do_dir_im {	char *who;	GaimConnection *gc;};static void oscar_cancel_direct_im(struct ask_do_dir_im *data) {	g_free(data->who);	g_free(data);}/* this function is used to initiate a direct im session with someone. * we start listening on a port and send a request. they either connect * or send some kind of reply. If they can't connect, they ask us to * connect to them, and so we do that. * * this function will also get called if the other side initiate's a direct * im and we try to connect and fail. in that case cookie will not be null. * * note that cookie is an 8 byte string that isn't NULL terminated */static void oscar_direct_im_initiate(GaimConnection *gc, const char *who, const char *cookie) {	OscarData *od;	struct oscar_direct_im *dim;	int listenfd;	const char *ip;	od = (OscarData *)gc->proto_data;	dim = oscar_direct_im_find(od, who);	if (dim) {		if (!(dim->connected)) {  /* We'll free the old, unconnected dim, and start over */			oscar_direct_im_disconnect(od, dim);			gaim_debug_info("oscar",					   "Gave up on old direct IM, trying again\n");		} else {			gaim_notify_error(gc, NULL, "DirectIM already open.", NULL);			return;		}	}	dim = g_new0(struct oscar_direct_im, 1);	dim->gc = gc;	g_snprintf(dim->name, sizeof dim->name, "%s", who);	listenfd = gaim_network_listen_range(5190, 5199);	ip = gaim_network_get_my_ip(od->conn ? od->conn->fd : -1);	if (listenfd >= 0)		dim->conn = aim_odc_initiate(od->sess, who, listenfd, gaim_network_ip_atoi(ip), gaim_network_get_port_from_fd(listenfd), cookie);	if (dim->conn != NULL) {		char *tmp;		GaimConversation *conv;		od->direct_ims = g_slist_append(od->direct_ims, dim);		dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,						oscar_callback, dim->conn);		aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIM_ESTABLISHED,					gaim_odc_initiate, 0);		conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, who);		tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for Direct IM."), who, ip,		                      gaim_network_get_port_from_fd(listenfd));		gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));		g_free(tmp);	} else {		gaim_notify_error(gc, NULL, _("Unable to open Direct IM"), NULL);		oscar_direct_im_destroy(od, dim);	}}static void oscar_direct_im(struct ask_do_dir_im *data) {	GaimConnection *gc = data->gc;	if (!g_list_find(gaim_connections_get_all(), gc)) {		g_free(data->who);		g_free(data);		return;	}	oscar_direct_im_initiate(gc, data->who, NULL);	g_free(data->who);	g_free(data);}/* this is the right click menu cb thingy */static void oscar_ask_direct_im(GaimBlistNode *node, gpointer ignored) {	GaimBuddy *buddy;	GaimConnection *gc;	gchar *buf;	struct ask_do_dir_im *data;	g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node));	buddy = (GaimBuddy *) node;	gc = gaim_account_get_connection(buddy->account);	data = g_new0(struct ask_do_dir_im, 1);	data->who = g_strdup(buddy->name);	data->gc = gc;	buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."),			buddy->name);	gaim_request_action(gc, NULL, buf,			_("Because this reveals your IP address, it "			  "may be considered a privacy risk.  Do you "			  "wish to continue?"),			0, data, 2,			_("Connect"), G_CALLBACK(oscar_direct_im),			_("Cancel"), G_CALLBACK(oscar_cancel_direct_im));	g_free(buf);}/***************************************************************************** * End scary direct im stuff *****************************************************************************/static void oscar_callback(gpointer data, gint source, GaimInputCondition condition) {	aim_conn_t *conn = (aim_conn_t *)data;	aim_session_t *sess = aim_conn_getsess(conn);	GaimConnection *gc = sess ? sess->aux_data : NULL;	OscarData *od;	if (!gc) {		gaim_debug_info("oscar",				   "oscar callback for closed connection (1).\n");		return;	}      	od = (OscarData *)gc->proto_data;	if (!g_list_find(gaim_connections_get_all(), gc)) {		/* oh boy. this is probably bad. i guess the only thing we 		 * can really do is return? */		gaim_debug_info("oscar",				   "oscar callback for closed connection (2).\n");		gaim_debug_misc("oscar", "gc = %p\n", gc);		return;	}	if (condition & GAIM_INPUT_READ) {		if (conn->type == AIM_CONN_TYPE_LISTENER) {			gaim_debug_info("oscar",					   "got information on rendezvous listener\n");			if (aim_handlerendconnect(od->sess, conn) < 0) {				gaim_debug_error("oscar",						   "connection error (rendezvous listener)\n");				aim_conn_kill(od->sess, &conn);				/* AAA - Don't we need to gaim_xfer_cancel here? --marv */			}		} else {			if (aim_get_command(od->sess, conn) >= 0) {				aim_rxdispatch(od->sess);				if (od->killme) {					gaim_debug_error("oscar", "Waiting to be destroyed\n");					return;				}			} else {				if ((conn->type == AIM_CONN_TYPE_BOS) ||					   !(aim_getconn_type(od->sess, AIM_CONN_TYPE_BOS))) {					gaim_debug_error("oscar",							   "major connection error\n");					gaim_connection_error(gc, _("Disconnected."));				} else if (conn->type == AIM_CONN_TYPE_CHAT) {					struct chat_connection *c = find_oscar_chat_by_conn(gc, conn);					GaimConversation *conv = gaim_find_chat(gc, c->id);					char *buf;					gaim_debug_info("oscar",							   "disconnected from chat room %s\n", c->name);					c->conn = NULL;					if (c->inpa > 0)						gaim_input_remove(c->inpa);					c->inpa = 0;					c->fd = -1;					aim_conn_kill(od->sess, &conn);					buf = g_strdup_printf(_("You have been disconnected from chat room %s."), c->name);					if (conv) 						gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_ERROR, time(NULL));					else						gaim_notify_error(gc, NULL, buf, NULL);					g_free(buf);				} else if (conn->type == AIM_CONN_TYPE_CHATNAV) {					if (od->cnpa > 0)						gaim_input_remove(od->cnpa);					od->cnpa = 0;					gaim_debug_info("oscar",							   "removing chatnav input watcher\n");					while (od->create_rooms) {						struct create_room *cr = od->create_rooms->data;						g_free(cr->name);						od->create_rooms =							g_slist_remove(od->create_rooms, cr);						g_free(cr);						gaim_notify_error(gc, NULL,										  _("Chat is currently unavailable"),										  NULL);					}					aim_conn_kill(od->sess, &conn);				} else if (conn->type == AIM_CONN_TYPE_AUTH) {					if (od->paspa > 0)						gaim_input_remove(od->paspa);					od->paspa = 0;					gaim_debug_info("oscar",							   "removing authconn input watcher\n");					aim_conn_kill(od->sess, &conn);				} else if (conn->type == AIM_CONN_TYPE_EMAIL) {					if (od->emlpa > 0)						gaim_input_remove(od->emlpa);					od->emlpa = 0;					gaim_debug_info("oscar",							   "removing email input watcher\n");					aim_conn_kill(od->sess, &conn);				} else if (conn->type == AIM_CONN_TYPE_ICON) {					if (od->icopa > 0)						gaim_input_remove(od->icopa);					od->icopa = 0;					gaim_debug_info("oscar",							   "removing icon input watcher\n");					aim_conn_kill(od->sess, &conn);				} else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) {					if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)						gaim_odc_disconnect(od->sess, conn);					aim_conn_kill(od->sess, &conn);				} else {					gaim_debug_error("oscar",							   "holy crap! generic connection error! %hu\n",							   conn->type);					aim_conn_kill(od->sess, &conn);				}			}		}	}}static void oscar_debug(aim_session_t *sess, int level, const char *format, va_list va) {	GaimConnection *gc = sess->aux_data;	gchar *s = g_strdup_vprintf(format, va);	gchar *buf;	buf = g_strdup_printf("%s %d: %s", gaim_account_get_username(gaim_connection_get_account(gc)), level, s);	gaim_debug_info("oscar", buf);	if (buf[strlen(buf)-1] != '\n')		gaim_debug_info(NULL, "\n");	g_free(buf);	g_free(s);}static void oscar_login_connect(gpointer data, gint source, GaimInputCondition cond){	GaimConnection *gc = data;	OscarData *od;	aim_session_t *sess;	aim_conn_t *conn;	if (!g_list_find(gaim_connections_get_all(), gc)) {		close(source);		return;	}	od = gc->proto_data;	sess = od->sess;	conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);	conn->fd = source;	if (source < 0) {		gaim_connection_error(gc, _("Couldn't connect to host"));		return;	}	aim_conn_completeconnect(sess, conn);	gc->inpa = gaim_input_add(conn->fd, GAIM_INPUT_READ, oscar_callback, conn);	aim_request_login(sess, conn, gaim_account_get_username(gaim_connection_get_account(gc)));	gaim_debug_info("oscar",			   "Screen name sent, waiting for response\n");	gaim_connection_update_progress(gc, _("Screen name sent"), 1, OSCAR_CONNECT_STEPS);	ck[1] = 0x65;}static void oscar_login(GaimAccount *account) {	aim_session_t *sess;	aim_conn_t *conn;	GaimConnection *gc = gaim_account_get_connection(account);	OscarData *od = gc->proto_data = g_new0(OscarData, 1);	gaim_debug_misc("oscar", "oscar_login: gc = %p\n", gc);	if (!aim_snvalid(gaim_account_get_username(account))) {		gchar *buf;		buf = g_strdup_printf(_("Unable to login: Could not sign on as %s because the screen name is invalid.  Screen names must either start with a letter and contain only letters, numbers and spaces, or contain only numbers."), gaim_account_get_username(account));		gaim_connection_error(gc, buf);		g_free(buf);	}	if (isdigit(*(gaim_account_get_username(account)))) {		od->icq = TRUE;	} else {		gc->flags |= GAIM_CONNECTION_HTML;		gc->flags |= GAIM_CONNECTION_AUTO_RESP;	}	od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, oscar_free_buddyinfo);	sess = g_new0(aim_session_t, 1);	aim_session_init(sess, TRUE, 0);	aim_setdebuggingcb(sess, oscar_debug);	/*	 * We need an immediate queue because we don't use a while-loop 	 * to see if things need to be sent.	 */	aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);	od->sess = sess;	sess->aux_data = gc;	conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);	if (conn == NULL) {		gaim_debug_error("oscar",				   "internal connection error\n");		gaim_connection_error(gc, _("Unable to login to AIM"));		return;	}

⌨️ 快捷键说明

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