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

📄 parse.c

📁 irc message protocol stack
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file parse.c * * gaim * * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.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 "internal.h"#include "accountopt.h"#include "conversation.h"#include "notify.h"#include "debug.h"#include "cmds.h"#include "irc.h"#include <stdio.h>#include <stdlib.h>#include <ctype.h>static char *irc_send_convert(struct irc_conn *irc, const char *string);static char *irc_recv_convert(struct irc_conn *irc, const char *string);static void irc_parse_error_cb(struct irc_conn *irc, char *input);static char *irc_mirc_colors[16] = {	"white", "black", "blue", "dark green", "red", "brown", "purple",		"orange", "yellow", "green", "teal", "cyan", "light blue",		"pink", "grey", "light grey" };/*typedef void (*IRCMsgCallback)(struct irc_conn *irc, char *from, char *name, char **args);*/static struct _irc_msg {	char *name;	char *format;	void (*cb)(struct irc_conn *irc, const char *name, const char *from, char **args);} _irc_msgs[] = {	{ "301", "nn:", irc_msg_away },		/* User is away			*/	{ "303", "n:", irc_msg_ison },		/* ISON reply			*/	{ "311", "nnvvv:", irc_msg_whois },	/* Whois user			*/	{ "312", "nnv:", irc_msg_whois },	/* Whois server			*/	{ "313", "nn:", irc_msg_whois },	/* Whois ircop			*/	{ "317", "nnvv", irc_msg_whois },	/* Whois idle			*/	{ "318", "nt:", irc_msg_endwhois },	/* End of WHOIS			*/	{ "319", "nn:", irc_msg_whois },	/* Whois channels		*/	{ "320", "nn:", irc_msg_whois },	/* Whois (fn ident)		*/	{ "321", "*", irc_msg_list },		/* Start of list		*/	{ "322", "ncv:", irc_msg_list },	/* List.			*/	{ "323", ":", irc_msg_list },		/* End of list.			*/	{ "324", "ncv:", irc_msg_chanmode },	/* Channel modes		*/	{ "331", "nc:",	irc_msg_topic },	/* No channel topic		*/	{ "332", "nc:", irc_msg_topic },	/* Channel topic		*/	{ "333", "*", irc_msg_ignore },		/* Topic setter stuff		*/	{ "353", "nvc:", irc_msg_names },	/* Names list			*/	{ "366", "nc:", irc_msg_names },	/* End of names			*/	{ "372", "n:", irc_msg_motd },		/* MOTD				*/	{ "375", "n:", irc_msg_motd },		/* Start MOTD			*/	{ "376", "n:", irc_msg_endmotd },	/* End of MOTD			*/	{ "401", "nt:", irc_msg_nonick },	/* No such nick/chan		*/	{ "403", "nc:", irc_msg_nochan },	/* No such channel		*/	{ "404", "nt:", irc_msg_nosend },	/* Cannot send to chan		*/	{ "421", "nv:", irc_msg_unknown },	/* Unknown command		*/	{ "422", "nv:", irc_msg_endmotd },	/* No MOTD available		*/	{ "433", "vn:", irc_msg_nickused },	/* Nickname already in use	*/	{ "438", "nn:", irc_msg_nochangenick },	/* Nick may not change		*/	{ "442", "nc:", irc_msg_notinchan },	/* Not in channel		*/	{ "473", "nc:", irc_msg_inviteonly },	/* Tried to join invite-only	*/	{ "474", "nc:", irc_msg_banned },	/* Banned from channel		*/	{ "482", "nc:", irc_msg_notop },	/* Need to be op to do that	*/	{ "501", "n:", irc_msg_badmode },	/* Unknown mode flag		*/	{ "506", "nc:", irc_msg_nosend },	/* Must identify to send	*/	{ "515", "nc:", irc_msg_regonly },	/* Registration required	*/	{ "invite", "n:", irc_msg_invite },	/* Invited			*/	{ "join", ":", irc_msg_join },		/* Joined a channel		*/	{ "kick", "cn:", irc_msg_kick },	/* KICK				*/	{ "mode", "tv:", irc_msg_mode },	/* MODE for channel		*/	{ "nick", ":", irc_msg_nick },		/* Nick change			*/	{ "notice", "t:", irc_msg_notice },	/* NOTICE recv			*/	{ "part", "c:", irc_msg_part },		/* Parted a channel		*/	{ "ping", ":", irc_msg_ping },		/* Received PING from server	*/	{ "pong", "v:", irc_msg_pong },		/* Received PONG from server	*/	{ "privmsg", "t:", irc_msg_privmsg },	/* Received private message	*/	{ "topic", "c:", irc_msg_topic },	/* TOPIC command		*/	{ "quit", ":", irc_msg_quit },		/* QUIT notice			*/	{ "wallops", ":", irc_msg_wallops },	/* WALLOPS command		*/	{ NULL, NULL, NULL }};static struct _irc_user_cmd {	char *name;	char *format;	IRCCmdCallback cb;	char *help;} _irc_cmds[] = {	{ "action", ":", irc_cmd_ctcp_action, N_("action &lt;action to perform&gt;:  Perform an action.") },	{ "away", ":", irc_cmd_away, N_("away [message]:  Set an away message, or use no message to return from being away.") },	{ "deop", ":", irc_cmd_op, N_("deop &lt;nick1&gt; [nick2] ...:  Remove channel operator status from someone. You must be a channel operator to do this.") },	{ "devoice", ":", irc_cmd_op, N_("devoice &lt;nick1&gt; [nick2] ...:  Remove channel voice status from someone, preventing them from speaking if the channel is moderated (+m). You must be a channel operator to do this.") },	{ "invite", ":", irc_cmd_invite, N_("invite &lt;nick&gt; [room]:  Invite someone to join you in the specified channel, or the current channel.") },	{ "j", "cv", irc_cmd_join, N_("j &lt;room1&gt;[,room2][,...] [key1[,key2][,...]]:  Enter one or more channels, optionally providing a channel key for each if needed.") },	{ "join", "cv", irc_cmd_join, N_("join &lt;room1&gt;[,room2][,...] [key1[,key2][,...]]:  Enter one or more channels, optionally providing a channel key for each if needed.") },	{ "kick", "n:", irc_cmd_kick, N_("kick &lt;nick&gt; [message]:  Remove someone from a channel. You must be a channel operator to do this.") },	{ "list", ":", irc_cmd_list, N_("list:  Display a list of chat rooms on the network. <i>Warning, some servers may disconnect you upon doing this.</i>") },	{ "me", ":", irc_cmd_ctcp_action, N_("me &lt;action to perform&gt;:  Perform an action.") },	{ "mode", ":", irc_cmd_mode, N_("mode &lt;nick|channel&gt; &lt;+|-&gt;&lt;A-Za-z&gt;:  Set or unset a channel or user mode.") },	{ "msg", "t:", irc_cmd_privmsg, N_("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user (as opposed to a channel).") },	{ "names", "c", irc_cmd_names, N_("names [channel]:  List the users currently in a channel.") },	{ "nick", "n", irc_cmd_nick, N_("nick &lt;new nickname&gt;:  Change your nickname.") },	{ "op", ":", irc_cmd_op, N_("op &lt;nick1&gt; [nick2] ...:  Grant channel operator status to someone. You must be a channel operator to do this.") },	{ "operwall", ":", irc_cmd_wallops, N_("operwall &lt;message&gt;:  If you don't know what this is, you probably can't use it.") },	{ "part", "c:", irc_cmd_part, N_("part [room] [message]:  Leave the current channel, or a specified channel, with an optional message.") },	{ "ping", "n", irc_cmd_ping, N_("ping [nick]:  Asks how much lag a user (or the server if no user specified) has.") },	{ "query", "n:", irc_cmd_query, N_("query &lt;nick&gt; &lt;message&gt;:  Send a private message to a user (as opposed to a channel).") },	{ "quit", ":", irc_cmd_quit, N_("quit [message]:  Disconnect from the server, with an optional message.") },	{ "quote", "*", irc_cmd_quote, N_("quote [...]:  Send a raw command to the server.") },	{ "remove", "n:", irc_cmd_remove, N_("remove &lt;nick&gt; [message]:  Remove someone from a room. You must be a channel operator to do this.") },	{ "topic", ":", irc_cmd_topic, N_("topic [new topic]:  View or change the channel topic.") },	{ "umode", ":", irc_cmd_mode, N_("umode &lt;+|-&gt;&lt;A-Za-z&gt;:  Set or unset a user mode.") },	{ "voice", ":", irc_cmd_op, N_("voice &lt;nick1&gt; [nick2] ...:  Grant channel voice status to someone. You must be a channel operator to do this.") },	{ "wallops", ":", irc_cmd_wallops, N_("wallops &lt;message&gt;:  If you don't know what this is, you probably can't use it.") },	{ "whois", "n", irc_cmd_whois, N_("whois &lt;nick&gt;:  Get information on a user.") },	{ NULL, NULL, NULL }};static GaimCmdRet irc_parse_gaim_cmd(GaimConversation *conv, const gchar *cmd,                                        gchar **args, gchar **error, void *data){	GaimConnection *gc;	struct irc_conn *irc;	struct _irc_user_cmd *cmdent;	gc = gaim_conversation_get_gc(conv);	if (!gc)		return GAIM_CMD_RET_FAILED;	irc = gc->proto_data;	if ((cmdent = g_hash_table_lookup(irc->cmds, cmd)) == NULL)		return GAIM_CMD_RET_FAILED;	(cmdent->cb)(irc, cmd, gaim_conversation_get_name(conv), (const char **)args);	return GAIM_CMD_RET_OK;}static void irc_register_command(struct _irc_user_cmd *c){	GaimCmdFlag f;	char args[10];	char *format;	int i;	f = GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_PRPL_ONLY	    | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS;	format = c->format;	for (i = 0; (i < (sizeof(args) - 1)) && *format; i++, format++)		switch (*format) {		case 'v':		case 'n':		case 'c':		case 't':			args[i] = 'w';			break;		case ':':		case '*':			args[i] = 's';			break;		}	args[i] = '\0';	gaim_cmd_register(c->name, args, GAIM_CMD_P_PRPL, f, "prpl-irc",	                  irc_parse_gaim_cmd, _(c->help), NULL);}void irc_register_commands(void){	struct _irc_user_cmd *c;	for (c = _irc_cmds; c && c->name; c++)		irc_register_command(c);}static char *irc_send_convert(struct irc_conn *irc, const char *string){	char *utf8;	GError *err = NULL;	const gchar *charset;	charset = gaim_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);	if (!strcasecmp("UTF-8", charset))		return g_strdup(string);	utf8 = g_convert(string, strlen(string), charset, "UTF-8", NULL, NULL, &err);	if (err) {		gaim_debug(GAIM_DEBUG_ERROR, "irc", "Send conversion error: %s\n", err->message);		gaim_debug(GAIM_DEBUG_ERROR, "irc", "Sending as UTF-8 instead of %s\n", charset);		utf8 = g_strdup(string);		g_error_free(err);	}		return utf8;}static char *irc_recv_convert(struct irc_conn *irc, const char *string){	char *utf8 = NULL;	GError *err = NULL;	const gchar *charset;	charset = gaim_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET);	if (!strcasecmp("UTF-8", charset)) {		if (g_utf8_validate(string, strlen(string), NULL))			utf8 = g_strdup(string);	} else {		utf8 = g_convert(string, strlen(string), "UTF-8", charset, NULL, NULL, &err);	}	if (err) {		gaim_debug(GAIM_DEBUG_ERROR, "irc", "recv conversion error: %s\n", err->message);		g_error_free(err);	}	if (utf8 == NULL)		utf8 = g_strdup(_("(There was an error converting this message.  Check the 'Encoding' option in the Account Editor)"));	return utf8;}/* XXX tag closings are not necessarily correctly nested here!  If we *     get a ^O or reach the end of the string and there are open *     tags, they are closed in a fixed order ... this means, for *     example, you might see <FONT COLOR="blue">some text <B>with *     various attributes</FONT></B> (notice that B and FONT overlap *     and are not cleanly nested).  This is imminently fixable but *     I am not fixing it right now. */char *irc_mirc2html(const char *string){	const char *cur, *end;	char fg[3] = "\0\0", bg[3] = "\0\0";	int fgnum, bgnum;	int font = 0, bold = 0, underline = 0;	GString *decoded = g_string_sized_new(strlen(string));	cur = string;	do {		end = strpbrk(cur, "\002\003\007\017\026\037");		decoded = g_string_append_len(decoded, cur, end ? end - cur : strlen(cur));		cur = end ? end : cur + strlen(cur);		switch (*cur) {		case '\002':			cur++;			if (!bold) {				decoded = g_string_append(decoded, "<B>");				bold = TRUE;			} else {				decoded = g_string_append(decoded, "</B>");				bold = FALSE;			}			break;		case '\003':			cur++;			fg[0] = fg[1] = bg[0] = bg[1] = '\0';			if (isdigit(*cur))				fg[0] = *cur++;

⌨️ 快捷键说明

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