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

📄 oscar.c

📁 oscar message protocol stack
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (dim->watcher)	gaim_input_remove(dim->watcher);	if (dim->conn) {		aim_conn_close(dim->conn);		aim_conn_kill(od->sess, &dim->conn);	}	g_free(dim);}/* the only difference between this and destroy is this writes a conv message */static void oscar_direct_im_disconnect(OscarData *od, struct oscar_direct_im *dim){	GaimConversation *conv;	char buf[256];	gaim_debug_info("oscar",			   "%s disconnected Direct IM.\n", dim->name);	if (dim->connected)		g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), dim->name);	else		g_snprintf(buf, sizeof buf, _("Direct IM with %s failed"), dim->name);	conv = gaim_find_conversation_with_account(dim->name, gaim_connection_get_account(dim->gc));	if (conv) {		gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL));		gaim_conversation_update_progress(conv, 0);	} else {		gaim_notify_error(dim->gc, NULL, _("Direct Connect failed"), buf);	}	oscar_direct_im_destroy(od, dim);	return;}/* oops i made two of these. this one just calls the other one. */static void gaim_odc_disconnect(aim_session_t *sess, aim_conn_t *conn){	GaimConnection *gc = sess->aux_data;	OscarData *od = (OscarData *)gc->proto_data;	struct oscar_direct_im *dim;	char *sn;	sn = g_strdup(aim_odc_getsn(conn));	dim = oscar_direct_im_find(od, sn);	oscar_direct_im_disconnect(od, dim);	g_free(sn);}static void destroy_direct_im_request(struct ask_direct *d) {	gaim_debug_info("oscar", "Freeing DirectIM prompts.\n");	g_free(d->sn);	g_free(d);}/* this is just a gaim_proxy_connect cb that sets up the rest of the cbs */static void oscar_odc_callback(gpointer data, gint source, GaimInputCondition condition) {	struct oscar_direct_im *dim = data;	GaimConnection *gc = dim->gc;	OscarData *od = gc->proto_data;	GaimConversation *conv;	char buf[256];	struct sockaddr name;	socklen_t name_len = 1;	g_return_if_fail(gc != NULL);	dim->gpc_pend = FALSE;	if (dim->killme) {		oscar_direct_im_destroy(od, dim);		return;	}	if (!g_list_find(gaim_connections_get_all(), gc)) {		oscar_direct_im_destroy(od, dim);		return;	}	if (source < 0) {		if (dim->donttryagain) {			oscar_direct_im_disconnect(od, dim);			return;		} else {			fu8_t cookie[8];			char *who = g_strdup(dim->name);			const char *tmp = aim_odc_getcookie(dim->conn);			memcpy(cookie, tmp, 8);			oscar_direct_im_destroy(od, dim);			oscar_direct_im_initiate(gc, who, cookie);			gaim_debug_info("oscar", "asking direct im initiator to connect to us\n");			g_free(who);			return;		}	}	dim->conn->fd = source;	aim_conn_completeconnect(od->sess, dim->conn);	conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, dim->name);	/* This is the best way to see if we're connected or not */	/* Is this really needed? */	if (getpeername(source, &name, &name_len) == 0) {		g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), dim->name);		dim->connected = TRUE;		gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL));		dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn);	} else {		if (dim->donttryagain) {			oscar_direct_im_disconnect(od, dim);			return;		} else {			fu8_t cookie[8];			char *who = g_strdup(dim->name);			const char *tmp = aim_odc_getcookie(dim->conn);			memcpy(cookie, tmp, 8);			oscar_direct_im_destroy(od, dim);			oscar_direct_im_initiate(gc, who, cookie);			gaim_debug_info("oscar", "asking direct im initiator to connect to us\n");			g_free(who);			return;		}	}}static void accept_direct_im_request(struct ask_direct *d) {	GaimConnection *gc = d->gc;	OscarData *od;	struct oscar_direct_im *dim;	char *host; int port = 5190;	int i, rc;	char *tmp;	GaimConversation *conv;	if (!g_list_find(gaim_connections_get_all(), gc)) {		destroy_direct_im_request(d);		return;	}	od = (OscarData *)gc->proto_data;	gaim_debug_info("oscar", "Accepted DirectIM.\n");	dim = oscar_direct_im_find(od, d->sn);	if (dim && dim->connected) {		destroy_direct_im_request(d); /* 40 */ /* what does that 40 mean? */		gaim_debug_info("oscar", "Wait, we're already connected, ignoring DirectIM.\n");		return;	}	dim = g_new0(struct oscar_direct_im, 1);	dim->gc = d->gc;	dim->donttryagain = d->donttryagain;	g_snprintf(dim->name, sizeof dim->name, "%s", d->sn);	dim->conn = aim_odc_connect(od->sess, d->sn, NULL, d->cookie);	od->direct_ims = g_slist_append(od->direct_ims, dim);	if (!dim->conn) {		oscar_direct_im_disconnect(od, dim);		destroy_direct_im_request(d);		return;	}	aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING,				gaim_odc_incoming, 0);	aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING,				gaim_odc_typing, 0);	aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER,			        gaim_odc_update_ui, 0);	gaim_debug_info("oscar", "ip is %s.\n", d->ip);	for (i = 0; i < (int)strlen(d->ip); i++) {		if (d->ip[i] == ':') {			port = atoi(&(d->ip[i+1]));			break;		}	}	host = g_strndup(d->ip, i);	dim->conn->status |= AIM_CONN_STATUS_INPROGRESS;	dim->gpc_pend = TRUE;	rc = gaim_proxy_connect(gc->account, host, port, oscar_odc_callback, dim);	conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, d->sn);	tmp = g_strdup_printf(_("Attempting to connect to %s at %s:%hu for Direct IM."), d->sn, host,	                      port);	gaim_conversation_write(conv, NULL, tmp, GAIM_MESSAGE_SYSTEM, time(NULL));	g_free(tmp);	g_free(host);	if (rc < 0) {		dim->gpc_pend = FALSE;		oscar_direct_im_disconnect(od, dim);		destroy_direct_im_request(d);		return;	}	destroy_direct_im_request(d);	return;}/* * We have just established a socket with the other dude, so set up some handlers. */static int gaim_odc_initiate(aim_session_t *sess, aim_frame_t *fr, ...) {	GaimConnection *gc = sess->aux_data;	OscarData *od = (OscarData *)gc->proto_data;	GaimConversation *conv;	struct oscar_direct_im *dim;	char buf[256];	char *sn;	va_list ap;	aim_conn_t *newconn, *listenerconn;	va_start(ap, fr);	newconn = va_arg(ap, aim_conn_t *);	listenerconn = va_arg(ap, aim_conn_t *);	va_end(ap);	aim_conn_close(listenerconn);	aim_conn_kill(sess, &listenerconn);	sn = g_strdup(aim_odc_getsn(newconn));	gaim_debug_info("oscar",			   "DirectIM: initiate success to %s\n", sn);	dim = oscar_direct_im_find(od, sn);	conv = gaim_conversation_new(GAIM_CONV_IM, dim->gc->account, sn);	gaim_input_remove(dim->watcher);	dim->conn = newconn;	dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, oscar_callback, dim->conn);	dim->connected = TRUE;	g_snprintf(buf, sizeof buf, _("Direct IM with %s established"), sn);	g_free(sn);	gaim_conversation_write(conv, NULL, buf, GAIM_MESSAGE_SYSTEM, time(NULL));	aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING, gaim_odc_incoming, 0);	aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_odc_typing, 0);	aim_conn_addhandler(sess, newconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER, gaim_odc_update_ui, 0);	return 1;}/* * This is called when each chunk of an image is received.  It can be used to * update a progress bar, or to eat lots of dry cat food.  Wet cat food is * nasty, you sicko. */static int gaim_odc_update_ui(aim_session_t *sess, aim_frame_t *fr, ...) {	va_list ap;	char *sn;	double percent;	GaimConnection *gc = sess->aux_data;	OscarData *od = (OscarData *)gc->proto_data;	GaimConversation *c;	struct oscar_direct_im *dim;	va_start(ap, fr);	sn = va_arg(ap, char *);	percent = va_arg(ap, double);	va_end(ap);	if (!sn || !(dim = oscar_direct_im_find(od, sn)))		return 1;	if (dim->watcher) {		gaim_input_remove(dim->watcher);   /* Otherwise, the callback will callback */		/* The callback will callback? I don't get how that would happen here. */		dim->watcher = 0;	}	c = gaim_find_conversation_with_account(sn, gaim_connection_get_account(gc));	if (c != NULL)		gaim_conversation_update_progress(c, percent);	dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ,				      oscar_callback, dim->conn);	return 1;}/* * This is called after a direct IM has been received in its entirety.  This * function is passed a long chunk of data which contains the IM with any * data chunks (images) appended to it. * * This function rips out all the data chunks and creates an imgstore for * each one.  In order to do this, it first goes through the IM and takes * out all the IMG tags.  When doing so, it rewrites the original IMG tag * with one compatible with the imgstore Gaim core code. For each one, we * then read in chunks of data from the end of the message and actually * create the img store using the given data. * * For somewhat easy reference, here's a sample message * (without the whitespace and asterisks): * * <HTML><BODY BGCOLOR="#ffffff"> *     <FONT LANG="0"> *     This is a really stupid picture:<BR> *     <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR> *     Yeah it is<BR> *     Here is another one:<BR> *     <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978"> *     </FONT> * </BODY></HTML> * <BINARY> *     <DATA ID="1" SIZE="9894">datadatadatadata</DATA> *     <DATA ID="2" SIZE="65978">datadatadatadata</DATA> * </BINARY> */static int gaim_odc_incoming(aim_session_t *sess, aim_frame_t *fr, ...) {	GaimConnection *gc = sess->aux_data;	GaimConvImFlags imflags = 0;	gchar *utf8;	GString *newmsg = g_string_new("");	GSList *images = NULL;	va_list ap;	const char *sn, *msg, *msgend, *binary;	size_t len;	int encoding, isawaymsg;	va_start(ap, fr);	sn = va_arg(ap, const char *);	msg = va_arg(ap, const char *);	len = va_arg(ap, size_t);	encoding = va_arg(ap, int);	isawaymsg = va_arg(ap, int);	va_end(ap);	msgend = msg + len;	gaim_debug_info("oscar",			   "Got DirectIM message from %s\n", sn);	if (isawaymsg)		imflags |= GAIM_CONV_IM_AUTO_RESP;	/* message has a binary trailer */	if ((binary = gaim_strcasestr(msg, "<binary>"))) {		GData *attribs;		const char *tmp, *start, *end, *last = NULL;		tmp = msg;		/* for each valid image tag... */		while (gaim_markup_find_tag("img", tmp, &start, &end, &attribs)) {			const char *id, *src, *datasize;			const char *tag = NULL, *data = NULL;			size_t size;			int imgid = 0;			/* update the location of the last img tag */			last = end;			/* grab attributes */			id       = g_datalist_get_data(&attribs, "id");			src      = g_datalist_get_data(&attribs, "src");			datasize = g_datalist_get_data(&attribs, "datasize");			/* if we have id & datasize, build the data tag */			if (id && datasize)				tag = g_strdup_printf("<data id=\"%s\" size=\"%s\">", id, datasize);			/* if we have a tag, find the start of the data */			if (tag && (data = gaim_strcasestr(binary, tag)))				data += strlen(tag);			/* check the data is here and store it */			if (data + (size = atoi(datasize)) <= msgend)				imgid = gaim_imgstore_add(data, size, src);			/*			 * XXX - The code below contains some calls to oscar_encoding_to_utf8			 * The hardcoded "us-ascii" value REALLY needs to be removed.			 */			/* if we have a stored image... */			if (imgid) {				/* append the message up to the tag */				utf8 = oscar_encoding_to_utf8("us-ascii", tmp, start - tmp);				if (utf8 != NULL) {					newmsg = g_string_append(newmsg, utf8);					g_free(utf8);				}				/* write the new image tag */				g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid);				/* and record the image number */				images = g_slist_append(images, GINT_TO_POINTER(imgid));			} else {				/* otherwise, copy up to the end of the tag */				utf8 = oscar_encoding_to_utf8("us-ascii", tmp, (end + 1) - tmp);				if (utf8 != NULL) {					newmsg = g_string_append(newmsg, utf8);					g_free(utf8);				}			}			/* clear the attribute list */			g_datalist_clear(&attribs);			/* continue from the end of the tag */			tmp = end + 1;		}		/* append any remaining message data (without the > :-) */		if (last++ && (last < binary))			newmsg = g_string_append_len(newmsg, last, binary - last);		/* set the flag if we caught any images */		if (images)			imflags |= GAIM_CONV_IM_IMAGES;	} else {		g_string_append_len(newmsg, msg, len);	}	/* XXX - I imagine Paco-Paco will want to do some voodoo with the encoding here */	serv_got_im(gc, sn, newmsg->str, imflags, time(NULL));	/* free up the message */	g_string_free(newmsg, TRUE);	/* unref any images we allocated */	if (images) {		GSList *tmp;		int id;		for (tmp = images; tmp != NULL; tmp = tmp->next) {			id = GPOINTER_TO_INT(tmp->data);			gaim_imgstore_unref(id);		}

⌨️ 快捷键说明

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