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

📄 zephyr.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *//* * purple * * Copyright (C) 1998-2001, Mark Spencer <markster@marko.net> * Some code borrowed from GtkZephyr, by * Jag/Sean Dilda <agrajag@linuxpower.org>/<smdilda@unity.ncsu.edu> * http://gtkzephyr.linuxpower.org/ * * Some code borrowed from kzephyr, by * Chris Colohan <colohan+@cs.cmu.edu> *  * 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 "libpurple/internal.h"#include "accountopt.h"#include "debug.h"#include "notify.h"#include "prpl.h"#include "server.h"#include "util.h"#include "cmds.h"#include "privacy.h"#include "version.h"#include "zephyr.h"#include "internal.h"#include <strings.h>#define ZEPHYR_FALLBACK_CHARSET "ISO-8859-1"/* these are deliberately high, since most people don't send multiple "PING"s */#define ZEPHYR_TYPING_SEND_TIMEOUT 15#define ZEPHYR_TYPING_RECV_TIMEOUT 10#define ZEPHYR_FD_READ 0#define ZEPHYR_FD_WRITE 1extern Code_t ZGetLocations(ZLocations_t *, int *);extern Code_t ZSetLocation(char *);extern Code_t ZUnsetLocation();extern Code_t ZGetSubscriptions(ZSubscription_t *, int*);extern char __Zephyr_realm[];typedef struct _zframe zframe;typedef struct _zephyr_triple zephyr_triple;typedef struct _zephyr_account zephyr_account;typedef struct _parse_tree parse_tree;typedef enum {	PURPLE_ZEPHYR_NONE, /* Non-kerberized ZEPH0.2 */	PURPLE_ZEPHYR_KRB4, /* ZEPH0.2 w/ KRB4 support */	PURPLE_ZEPHYR_TZC,  /* tzc executable proxy */	PURPLE_ZEPHYR_INTERGALACTIC_KRB4, /* Kerberized ZEPH0.3 */} zephyr_connection_type;struct _zephyr_account {	PurpleAccount* account;	char *username;	char *realm;	char *encoding;	char* galaxy; /* not yet useful */	char* krbtkfile; /* not yet useful */	guint32 nottimer;	guint32 loctimer;	GList *pending_zloc_names;	GSList *subscrips;	int last_id;	unsigned short port;	char ourhost[HOST_NAME_MAX + 1];	char ourhostcanon[HOST_NAME_MAX + 1];	zephyr_connection_type connection_type;	int totzc[2];	int fromtzc[2];	char *exposure;	pid_t tzc_pid;	gchar *away;};#define MAXCHILDREN 20struct _parse_tree {	gchar* contents;	parse_tree *children[MAXCHILDREN];	int num_children;};parse_tree null_parse_tree = { 	"", 	{NULL}, 	0,};#define use_none(zephyr) ((zephyr->connection_type == PURPLE_ZEPHYR_NONE)?1:0)#define use_krb4(zephyr) ((zephyr->connection_type == PURPLE_ZEPHYR_KRB4)?1:0)#define use_tzc(zephyr) ((zephyr->connection_type == PURPLE_ZEPHYR_TZC)?1:0)#define use_zeph02(zephyr) (  (zephyr->connection_type == PURPLE_ZEPHYR_NONE)?1: ((zephyr->connection_type == PURPLE_ZEPHYR_KRB4)?1:0))/* struct I need for zephyr_to_html */struct _zframe {	/* true for everything but @color, since inside the parens of that one is	 * the color. */	gboolean has_closer;	/* @i, @b, etc. */	const char *env;	/* }=1, ]=2, )=4, >=8 */	int closer_mask;	/* }, ], ), > */	char *closer;	/* </i>, </font>, </b>, etc. */	const char *closing;	/* text including the opening html thingie. */	GString *text;	/* href for links */	gboolean is_href;	GString *href;	struct _zframe *enclosing;};struct _zephyr_triple {	char *class;	char *instance;	char *recipient;	char *name;	gboolean open;	int id;};#define z_call(func)		if (func != ZERR_NONE)\					return;#define z_call_r(func)		if (func != ZERR_NONE)\					return TRUE;#define z_call_s(func, err)	if (func != ZERR_NONE) {\					purple_connection_error(gc, err);\					return;\				}#ifdef WIN32extern const char *username;#endifstatic Code_t zephyr_subscribe_to(zephyr_account* zephyr, char* class, char *instance, char *recipient, char* galaxy) {	if (use_tzc(zephyr)) {		/* ((tzcfodder . subscribe) ("class" "instance" "recipient")) */		gchar *zsubstr = g_strdup_printf("((tzcfodder . subscribe) (\"%s\" \"%s\" \"%s\"))\n",class,instance,recipient);		write(zephyr->totzc[ZEPHYR_FD_WRITE],zsubstr,strlen(zsubstr));		g_free(zsubstr);		return ZERR_NONE;	}	else {		if (use_zeph02(zephyr)) {			ZSubscription_t sub;			sub.zsub_class = class;			sub.zsub_classinst = instance;			sub.zsub_recipient = recipient; 			return ZSubscribeTo(&sub,1,0);		} else {			/* This should not happen */			return -1;		}	}	return -1;}char *local_zephyr_normalize(zephyr_account* zephyr,const char *);static void zephyr_chat_set_topic(PurpleConnection * gc, int id, const char *topic);char* zephyr_tzc_deescape_str(const char *message);static char *zephyr_strip_local_realm(zephyr_account* zephyr,const char* user){	/*	  Takes in a username of the form username or username@realm 	  and returns:	  username, if there is no realm, or the realm is the local realm	  or:	  username@realm if there is a realm and it is foreign	*/	char *tmp = g_strdup(user);	char *at = strchr(tmp,'@');	if (at && !g_ascii_strcasecmp(at+1,zephyr->realm)) {		/* We're passed in a username of the form user@users-realm */		char* tmp2;		*at = '\0';		tmp2 = g_strdup(tmp);		g_free(tmp);		return tmp2;	}	else {		/* We're passed in a username of the form user or user@foreign-realm */		return tmp;	}}/* this is so bad, and if Zephyr weren't so fucked up to begin with I * wouldn't do this. but it is so i will. *//* just for debugging */static void handle_unknown(ZNotice_t notice){	purple_debug_error("zephyr","z_packet: %s\n", notice.z_packet);	purple_debug_error("zephyr","z_version: %s\n", notice.z_version);	purple_debug_error("zephyr","z_kind: %d\n", (int)(notice.z_kind));	purple_debug_error("zephyr","z_class: %s\n", notice.z_class);	purple_debug_error("zephyr","z_class_inst: %s\n", notice.z_class_inst);	purple_debug_error("zephyr","z_opcode: %s\n", notice.z_opcode);	purple_debug_error("zephyr","z_sender: %s\n", notice.z_sender);	purple_debug_error("zephyr","z_recipient: %s\n", notice.z_recipient);	purple_debug_error("zephyr","z_message: %s\n", notice.z_message);	purple_debug_error("zephyr","z_message_len: %d\n", notice.z_message_len);}static zephyr_triple *new_triple(zephyr_account *zephyr,const char *c, const char *i, const char *r){	zephyr_triple *zt;	zt = g_new0(zephyr_triple, 1);	zt->class = g_strdup(c);	zt->instance = g_strdup(i);	zt->recipient = g_strdup(r);	zt->name = g_strdup_printf("%s,%s,%s", c, i?i:"", r?r:"");	zt->id = ++(zephyr->last_id);	zt->open = FALSE;	return zt;}static void free_triple(zephyr_triple * zt){	g_free(zt->class);	g_free(zt->instance);	g_free(zt->recipient);	g_free(zt->name);	g_free(zt);}/* returns true if zt1 is a subset of zt2.  This function is used to   determine whether a zephyr sent to zt1 should be placed in the chat   with triple zt2    zt1 is a subset of zt2    iff. the classnames are identical ignoring case    AND. the instance names are identical (ignoring case), or zt2->instance is *.   AND. the recipient names are identical*/static gboolean triple_subset(zephyr_triple * zt1, zephyr_triple * zt2){	if (!zt2) {		purple_debug_error("zephyr","zt2 doesn't exist\n"); 		return FALSE;	}	if (!zt1) {		purple_debug_error("zephyr","zt1 doesn't exist\n");		return FALSE;	}	if (!(zt1->class)) {		purple_debug_error("zephyr","zt1c doesn't exist\n");		return FALSE;	}	if (!(zt1->instance)) {		purple_debug_error("zephyr","zt1i doesn't exist\n");		return FALSE;	}	if (!(zt1->recipient)) {		purple_debug_error("zephyr","zt1r doesn't exist\n");		return FALSE;	}	if (!(zt2->class)) {		purple_debug_error("zephyr","zt2c doesn't exist\n");		return FALSE;	}	if (!(zt2->recipient)) {		purple_debug_error("zephyr","zt2r doesn't exist\n");		return FALSE;	}	if (!(zt2->instance)) {		purple_debug_error("zephyr","zt2i doesn't exist\n");		return FALSE;	}	if (g_ascii_strcasecmp(zt2->class, zt1->class)) {		return FALSE;	}	if (g_ascii_strcasecmp(zt2->instance, zt1->instance) && g_ascii_strcasecmp(zt2->instance, "*")) {		return FALSE;	}	if (g_ascii_strcasecmp(zt2->recipient, zt1->recipient)) {		return FALSE;	}	purple_debug_info("zephyr","<%s,%s,%s> is in <%s,%s,%s>\n",zt1->class,zt1->instance,zt1->recipient,zt2->class,zt2->instance,zt2->recipient);	return TRUE;}static zephyr_triple *find_sub_by_triple(zephyr_account *zephyr,zephyr_triple * zt){	zephyr_triple *curr_t;	GSList *curr = zephyr->subscrips;	while (curr) {		curr_t = curr->data;		if (triple_subset(zt, curr_t))			return curr_t;		curr = curr->next;	}	return NULL;}static zephyr_triple *find_sub_by_id(zephyr_account *zephyr,int id){	zephyr_triple *zt;	GSList *curr = zephyr->subscrips;	while (curr) {		zt = curr->data;		if (zt->id == id)			return zt;		curr = curr->next;	}	return NULL;}/*    Converts strings to utf-8 if necessary using user specified encoding*/static gchar *zephyr_recv_convert(PurpleConnection *gc,gchar *string, int len){	gchar *utf8;	GError *err = NULL;	zephyr_account *zephyr = gc->proto_data;	if (g_utf8_validate(string, len, NULL)) {		return g_strdup(string);	} else {		utf8 = g_convert(string, len, "UTF-8", zephyr->encoding, NULL, NULL, &err);		if (err) {			purple_debug_error("zephyr", "recv conversion error: %s\n", err->message);			utf8 = g_strdup(_("(There was an error converting this message.	 Check the 'Encoding' option in the Account Editor)"));			g_error_free(err);		}		return utf8;	}}/* This parses HTML formatting (put out by one of the gtkimhtml widgets    And converts it to zephyr formatting.   It currently deals properly with <b>, <br>, <i>, <font face=...>, <font color=...>,   It ignores <font back=...>   It does   <font size = "1 or 2" -> @small   3 or 4  @medium()   5,6, or 7 @large()   <a href is dealt with by outputting "description <link>" or just "description" as appropriate*/static char *html_to_zephyr(const char *message){	zframe *frames, *new_f;	char *ret;	if (*message == '\0')		return g_strdup("");	frames = g_new(zframe, 1);	frames->text = g_string_new("");	frames->href = NULL;	frames->is_href = FALSE;	frames->enclosing = NULL;	frames->closing = NULL;	frames->env = "";	frames->has_closer = FALSE;	frames->closer_mask = 15;	purple_debug_info("zephyr","html received %s\n",message);	while (*message) {		if (frames->closing && !g_ascii_strncasecmp(message, frames->closing, strlen(frames->closing))) {			zframe *popped;			message += strlen(frames->closing);			popped = frames;			frames = frames->enclosing;			if (popped->is_href) {				frames->href = popped->text;			} else {				g_string_append(frames->text, popped->env);				if (popped->has_closer) {					g_string_append_c(frames->text,							  (popped->closer_mask & 1) ? '{' :							  (popped->closer_mask & 2) ? '[' :							  (popped->closer_mask & 4) ? '(' :							  '<');				}				g_string_append(frames->text, popped->text->str);				if (popped->href)				{					int text_len = strlen(popped->text->str), href_len = strlen(popped->href->str);					if (!((text_len == href_len && !strncmp(popped->href->str, popped->text->str, text_len)) ||					      (7 + text_len == href_len && !strncmp(popped->href->str, "http://", 7) &&					       !strncmp(popped->href->str + 7, popped->text->str, text_len)) ||					      (7 + text_len == href_len && !strncmp(popped->href->str, "mailto:", 7) &&					       !strncmp(popped->href->str + 7, popped->text->str, text_len)))) {						g_string_append(frames->text, " <");						g_string_append(frames->text, popped->href->str);						if (popped->closer_mask & ~8) {							g_string_append_c(frames->text, '>');							popped->closer_mask &= ~8;						} else {							g_string_append(frames->text, "@{>}");						}					}					g_string_free(popped->href, TRUE);				}				if (popped->has_closer) {					g_string_append_c(frames->text,							  (popped->closer_mask & 1) ? '}' :							  (popped->closer_mask & 2) ? ']' :							  (popped->closer_mask & 4) ? ')' :							  '>');				}				if (!popped->has_closer)					frames->closer_mask = popped->closer_mask;				g_string_free(popped->text, TRUE);			}			g_free(popped);		} else if (*message == '<') {			if (!g_ascii_strncasecmp(message + 1, "i>", 2)) {				new_f = g_new(zframe, 1);				new_f->enclosing = frames;				new_f->text = g_string_new("");				new_f->href = NULL;				new_f->is_href = FALSE;				new_f->closing = "</i>";

⌨️ 快捷键说明

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