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

📄 toc.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * purple * * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include "internal.h"#include "account.h"#include "accountopt.h"#include "conversation.h"#include "debug.h"#include "notify.h"#include "privacy.h"#include "proxy.h"#include "prpl.h"#include "request.h"#include "util.h"#include "version.h"static PurplePlugin *my_protocol = NULL;#define REVISION "penguin"#define TYPE_SIGNON    1#define TYPE_DATA      2#define TYPE_ERROR     3#define TYPE_SIGNOFF   4#define TYPE_KEEPALIVE 5#define FLAPON "FLAPON\r\n\r\n"#define ROAST "Tic/Toc"#define TOC_HOST "toc.oscar.aol.com"#define TOC_PORT 9898#define AUTH_HOST "login.oscar.aol.com"#define AUTH_PORT 5190#define LANGUAGE "english"#define STATE_OFFLINE 0#define STATE_FLAPON 1#define STATE_SIGNON_REQUEST 2#define STATE_ONLINE 3#define STATE_PAUSE 4#define VOICE_UID     "09461341-4C7F-11D1-8222-444553540000"#define FILE_SEND_UID "09461343-4C7F-11D1-8222-444553540000"#define IMAGE_UID     "09461345-4C7F-11D1-8222-444553540000"#define B_ICON_UID    "09461346-4C7F-11D1-8222-444553540000"#define STOCKS_UID    "09461347-4C7F-11D1-8222-444553540000"#define FILE_GET_UID  "09461348-4C7F-11D1-8222-444553540000"#define GAMES_UID     "0946134a-4C7F-11D1-8222-444553540000"#define UC_UNAVAILABLE	0x01#define UC_AOL			0x02#define UC_ADMIN		0x04#define UC_UNCONFIRMED	0x08#define UC_NORMAL		0x10#define UC_WIRELESS		0x20struct ft_request {	PurpleConnection *gc;	char *user;	char UID[2048];	char *cookie;	char *ip;	int port;	char *message;	char *filename;	int files;	int size;};struct buddy_icon {	guint32 hash;	guint32 len;	time_t time;	void *data;};struct toc_data {	int toc_fd;	char toc_ip[20];	int seqno;	int state;};struct sflap_hdr {	unsigned char ast;	unsigned char type;	unsigned short seqno;	unsigned short len;};struct signon {	unsigned int ver;	unsigned short tag;	unsigned short namelen;	char username[80];};/* constants to identify proto_opts */#define USEROPT_AUTH      0#define USEROPT_AUTHPORT  1#define TOC_CONNECT_STEPS 3static void toc_login_callback(gpointer, gint, PurpleInputCondition);static void toc_callback(gpointer, gint, PurpleInputCondition);/* ok. this function used to take username/password, and return 0 on success. * now, it takes username/password, and returns NULL on error or a new purple_connection * on success. */static void toc_login(PurpleAccount *account){	PurpleConnection *gc;	struct toc_data *tdt;	char buf[80];	gc = purple_account_get_connection(account);	gc->proto_data = tdt = g_new0(struct toc_data, 1);	gc->flags |= PURPLE_CONNECTION_HTML;	gc->flags |= PURPLE_CONNECTION_AUTO_RESP;	g_snprintf(buf, sizeof buf, _("Looking up %s"),			purple_account_get_string(account, "server", TOC_HOST));	purple_connection_update_progress(gc, buf, 0, TOC_CONNECT_STEPS);	purple_debug(PURPLE_DEBUG_INFO, "toc", "Client connects to TOC\n");	if (purple_proxy_connect(gc, account,				purple_account_get_string(account, "server", TOC_HOST),				purple_account_get_int(account, "port", TOC_PORT),				toc_login_callback, gc) != 0 || !account->gc) {		g_snprintf(buf, sizeof(buf), _("Connect to %s failed"),				purple_account_get_string(account, "server", TOC_HOST));		purple_connection_error(gc, buf);		return;	}}static void toc_login_callback(gpointer data, gint source, PurpleInputCondition cond){	PurpleConnection *gc = data;	struct toc_data *tdt;	char buf[80];	struct sockaddr_in name;	socklen_t namelen;	if (!PURPLE_CONNECTION_IS_VALID(gc)) {		if (source >= 0)			close(source);		return;	}	tdt = gc->proto_data;	if (source == -1) {		/* we didn't successfully connect. tdt->toc_fd is valid here */		purple_connection_error(gc, _("Unable to connect."));		return;	}	tdt->toc_fd = source;	/*	 * Copy the IP that we're connected to.  We need this because "GOTO_URL"'s 	 * should open on the exact server we're connected to.  toc.oscar.aol.com 	 * doesn't work because that hostname resolves to multiple IP addresses.	 */	if (getpeername(tdt->toc_fd, (struct sockaddr *)&name, &namelen) == 0)		strncpy(tdt->toc_ip, inet_ntoa(name.sin_addr), sizeof(tdt->toc_ip));	else		strncpy(tdt->toc_ip, purple_account_get_string(gc->account, "server", TOC_HOST), sizeof(tdt->toc_ip));	purple_debug(PURPLE_DEBUG_INFO, "toc",			   "Client sends \"FLAPON\\r\\n\\r\\n\"\n");	if (write(tdt->toc_fd, FLAPON, strlen(FLAPON)) < 0) {		purple_connection_error(gc, _("Disconnected."));		return;	}	tdt->state = STATE_FLAPON;	/* i know a lot of people like to look at purple to see how TOC works. so i'll comment	 * on what this does. it's really simple. when there's data ready to be read from the	 * toc_fd file descriptor, toc_callback is called, with gc passed as its data arg. */	gc->inpa = purple_input_add(tdt->toc_fd, PURPLE_INPUT_READ, toc_callback, gc);	g_snprintf(buf, sizeof(buf), _("Signon: %s"), purple_account_get_username(gc->account));	purple_connection_update_progress(gc, buf, 1, TOC_CONNECT_STEPS);}static void toc_close(PurpleConnection *gc){	if (gc->inpa > 0)		purple_input_remove(gc->inpa);	gc->inpa = 0;	close(((struct toc_data *)gc->proto_data)->toc_fd);	g_free(gc->proto_data);}static void toc_build_config(PurpleAccount *account, char *s, int len, gboolean show){	PurpleBlistNode *gnode, *cnode, *bnode;	PurpleGroup *g;	PurpleBuddy *b;	GSList *plist = account->permit;	GSList *dlist = account->deny;	int pos = 0;	if (!account->perm_deny)		account->perm_deny = 1;	pos += g_snprintf(&s[pos], len - pos, "m %d\n", account->perm_deny);	for(gnode = purple_get_blist()->root; gnode && len > pos; gnode = gnode->next) {		g = (PurpleGroup *)gnode;		if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))			continue;		if(purple_group_on_account(g, account)) {			pos += g_snprintf(&s[pos], len - pos, "g %s\n", g->name);			for(cnode = gnode->child; cnode; cnode = cnode->next) {				if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode))					continue;				for(bnode = gnode->child; bnode && len > pos; bnode = bnode->next) {					b = (PurpleBuddy *)bnode;					if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode))						continue;					if(b->account == account) {						pos += g_snprintf(&s[pos], len - pos, "b %s%s%s\n",								b->name,								(show && b->alias) ? ":" : "",								(show && b->alias) ? b->alias : "");					}				}			}		}	}	while (len > pos && plist) {		pos += g_snprintf(&s[pos], len - pos, "p %s\n", (char *)plist->data);		plist = plist->next;	}	while (len > pos && dlist) {		pos += g_snprintf(&s[pos], len - pos, "d %s\n", (char *)dlist->data);		dlist = dlist->next;	}}char *escape_message(const char *msg){	char *ret;	int i, j;	if (!msg)		return NULL;	/* Calculate the length after escaping */	for (i=0, j=0; msg[i]; i++)		switch (msg[i]) {			case '$':			case '[':			case ']':			case '(':			case ')':				j++;			default:				j++;		}	/* Allocate a string */	ret = (char *)g_malloc((j+1) * sizeof(char));	/* Copy the string */	for (i=0, j=0; msg[i]; i++)		switch (msg[i]) {			case '$':			case '[':			case ']':			case '(':			case ')':				ret[j++] = '\\';			default:				ret[j++] = msg[i];			}	ret[j] = '\0';	return ret;}/* * Duplicates the input string, replacing each \n with a <BR>, and  * escaping a few other characters. */char *escape_text(const char *msg){	char *ret;	int i, j;	if (!msg)		return NULL;	/* Calculate the length after escaping */	for (i=0, j=0; msg[i]; i++)		switch (msg[i]) {			case '\n':				j += 4;				break;			case '{':			case '}':			case '\\':			case '"':				j += 1;			default:				j += 1;		}	/* Allocate a string */	ret = (char *)malloc((j+1) * sizeof(char));	/* Copy the string */	for (i=0, j=0; msg[i]; i++)		switch (msg[i]) {			case '\n':				ret[j++] = '<';				ret[j++] = 'B';				ret[j++] = 'R';				ret[j++] = '>';				break;			case '{':			case '}':			case '\\':			case '"':				ret[j++] = '\\';			default:				ret[j++] = msg[i];		}	ret[j] = '\0';	return ret;}static int sflap_send(PurpleConnection *gc, const char *buf, int olen, int type){	struct toc_data *tdt = (struct toc_data *)gc->proto_data;	int len;	int slen = 0;	int ret;	struct sflap_hdr hdr;	char *escaped, *obuf;	if (tdt->state == STATE_PAUSE)		/* TOC has given us the PAUSE message; sending could cause a disconnect		 * so we just return here like everything went through fine */		return 0;	if (olen < 0) {		escaped = escape_message(buf);		len = strlen(escaped);	} else {		escaped = g_memdup(buf, olen);		len = olen;	}	/*	 * One _last_ 2048 check here!  This shouldn't ever	 * get hit though, hopefully.  If it gets hit on an IM	 * It'll lose the last " and the message won't go through,	 * but this'll stop a segfault.	 */	if (len > MSG_LEN) {		purple_debug(PURPLE_DEBUG_WARNING, "toc", "message too long, truncating\n");		escaped[MSG_LEN - 1] = '\0';		len = MSG_LEN;	}	if (olen < 0)		purple_debug(PURPLE_DEBUG_INFO, "toc", "C: %s\n", escaped);	hdr.ast = '*';	hdr.type = type;	hdr.seqno = htons(tdt->seqno++ & 0xffff);	hdr.len = htons(len + (type == TYPE_SIGNON ? 0 : 1));	obuf = (char *)malloc((sizeof(hdr)+len+1) * sizeof(char));	memcpy(obuf, &hdr, sizeof(hdr));	slen += sizeof(hdr);	memcpy(&obuf[slen], escaped, len);	slen += len;	if (type != TYPE_SIGNON) {		obuf[slen] = '\0';		slen += 1;	}	ret = write(tdt->toc_fd, obuf, slen);	free(obuf);	g_free(escaped);	return ret;}static int toc_send_raw(PurpleConnection *gc, const char *buf, int len){	return sflap_send(gc, buf, len, 2);}static int wait_reply(PurpleConnection *gc, char *buffer, size_t buflen){	struct toc_data *tdt = (struct toc_data *)gc->proto_data;	struct sflap_hdr *hdr;	int ret;	if (read(tdt->toc_fd, buffer, sizeof(struct sflap_hdr)) < 0) {		purple_debug(PURPLE_DEBUG_ERROR, "toc", "Couldn't read flap header\n");		return -1;	}	hdr = (struct sflap_hdr *)buffer;	if (buflen < ntohs(hdr->len)) {		/* fake like there's a read error */		purple_debug(PURPLE_DEBUG_ERROR, "toc",				   "buffer too small (have %d, need %d)\n",				   buflen, ntohs(hdr->len));		return -1;	}	if (ntohs(hdr->len) > 0) {		int count = 0;		ret = 0;		do {			count += ret;			ret = read(tdt->toc_fd,				   buffer + sizeof(struct sflap_hdr) + count, ntohs(hdr->len) - count);		} while (count + ret < ntohs(hdr->len) && ret > 0);		buffer[sizeof(struct sflap_hdr) + count + ret] = '\0';		return ret;	} else		return 0;}static unsigned char *roast_password(const char *pass){	/* Trivial "encryption" */	static unsigned char rp[256];	static char *roast = ROAST;	int pos = 2;	int x;	strcpy(rp, "0x");	for (x = 0; (x < 150) && pass[x]; x++)		pos += sprintf(&rp[pos], "%02x", pass[x] ^ roast[x % strlen(roast)]);	rp[pos] = '\0';	return rp;

⌨️ 快捷键说明

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