📄 irc.c
字号:
/** * @file irc.c * * gaim * * Copyright (C) 2003, Robbert Haarman <gaim@inglorion.net> * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu> * Copyright (C) 2000-2003, Rob Flynn <rob@tgflinux.com> * 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 "accountopt.h"#include "blist.h"#include "conversation.h"#include "debug.h"#include "notify.h"#include "prpl.h"#include "plugin.h"#include "util.h"#include "version.h"#include "irc.h"static void irc_buddy_append(char *name, struct irc_buddy *ib, GString *string);static const char *irc_blist_icon(GaimAccount *a, GaimBuddy *b);static void irc_blist_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne);static GList *irc_away_states(GaimConnection *gc);static GList *irc_actions(GaimPlugin *plugin, gpointer context);/* static GList *irc_chat_info(GaimConnection *gc); */static void irc_login(GaimAccount *account);static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond);static void irc_close(GaimConnection *gc);static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimConvImFlags flags);static int irc_chat_send(GaimConnection *gc, int id, const char *what);static void irc_chat_join (GaimConnection *gc, GHashTable *data);static void irc_input_cb(gpointer data, gint source, GaimInputCondition cond);static guint irc_nick_hash(const char *nick);static gboolean irc_nick_equal(const char *nick1, const char *nick2);static void irc_buddy_free(struct irc_buddy *ib);static GaimPlugin *_irc_plugin = NULL;static const char *status_chars = "@+%&";static void irc_view_motd(GaimPluginAction *action){ GaimConnection *gc = (GaimConnection *) action->context; struct irc_conn *irc; char *title; if (gc == NULL || gc->proto_data == NULL) { gaim_debug(GAIM_DEBUG_ERROR, "irc", "got MOTD request for NULL gc\n"); return; } irc = gc->proto_data; if (irc->motd == NULL) { gaim_notify_error(gc, _("Error displaying MOTD"), _("No MOTD available"), _("There is no MOTD associated with this connection.")); return; } title = g_strdup_printf(_("MOTD for %s"), irc->server); gaim_notify_formatted(gc, title, title, NULL, irc->motd->str, NULL, NULL);}int irc_send(struct irc_conn *irc, const char *buf){ int ret; if (irc->fd < 0) return -1; /* gaim_debug(GAIM_DEBUG_MISC, "irc", "sent: %s", buf); */ if ((ret = write(irc->fd, buf, strlen(buf))) < 0) gaim_connection_error(gaim_account_get_connection(irc->account), _("Server has disconnected")); return ret;}/* XXX I don't like messing directly with these buddies */gboolean irc_blist_timeout(struct irc_conn *irc){ GString *string = g_string_sized_new(512); char *list, *buf; g_hash_table_foreach(irc->buddies, (GHFunc)irc_buddy_append, (gpointer)string); list = g_string_free(string, FALSE); if (!list || !strlen(list)) { g_free(list); return TRUE; } buf = irc_format(irc, "vn", "ISON", list); g_free(list); irc_send(irc, buf); g_free(buf); return TRUE;}static void irc_buddy_append(char *name, struct irc_buddy *ib, GString *string){ ib->flag = FALSE; g_string_append_printf(string, "%s ", name);}static void irc_ison_one(struct irc_conn *irc, struct irc_buddy *ib){ char *buf; ib->flag = FALSE; buf = irc_format(irc, "vn", "ISON", ib->name); irc_send(irc, buf); g_free(buf);}static const char *irc_blist_icon(GaimAccount *a, GaimBuddy *b){ return "irc";}static void irc_blist_emblems(GaimBuddy *b, char **se, char **sw, char **nw, char **ne){ if (b->present == GAIM_BUDDY_OFFLINE) *se = "offline";}static GList *irc_away_states(GaimConnection *gc){ return g_list_append(NULL, (gpointer)GAIM_AWAY_CUSTOM);}static GList *irc_actions(GaimPlugin *plugin, gpointer context){ GList *list = NULL; GaimPluginAction *act = NULL; act = gaim_plugin_action_new(_("View MOTD"), irc_view_motd); list = g_list_append(list, act); return list;}#if 0static GList *irc_blist_node_menu(GaimBlistNode *node){ GList *m = NULL; GaimBlistNodeAction *act; return m;}#endifstatic GList *irc_chat_join_info(GaimConnection *gc){ GList *m = NULL; struct proto_chat_entry *pce; pce = g_new0(struct proto_chat_entry, 1); pce->label = _("_Channel:"); pce->identifier = "channel"; m = g_list_append(m, pce); pce = g_new0(struct proto_chat_entry, 1); pce->label = _("_Password:"); pce->identifier = "password"; pce->secret = TRUE; m = g_list_append(m, pce); return m;}GHashTable *irc_chat_info_defaults(GaimConnection *gc, const char *chat_name){ GHashTable *defaults; defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); if (chat_name != NULL) g_hash_table_insert(defaults, "channel", g_strdup(chat_name)); return defaults;}static void irc_login(GaimAccount *account){ GaimConnection *gc; struct irc_conn *irc; char *buf, **userparts; const char *username = gaim_account_get_username(account); int err; gc = gaim_account_get_connection(account); gc->flags |= GAIM_CONNECTION_NO_NEWLINES; if (strpbrk(username, " \t\v\r\n") != NULL) { gaim_connection_error(gc, _("IRC nicks may not contain whitespace")); return; } gc->proto_data = irc = g_new0(struct irc_conn, 1); irc->account = account; userparts = g_strsplit(username, "@", 2); gaim_connection_set_display_name(gc, userparts[0]); irc->server = g_strdup(userparts[1]); g_strfreev(userparts); irc->buddies = g_hash_table_new_full((GHashFunc)irc_nick_hash, (GEqualFunc)irc_nick_equal, NULL, (GDestroyNotify)irc_buddy_free); irc->cmds = g_hash_table_new(g_str_hash, g_str_equal); irc_cmd_table_build(irc); irc->msgs = g_hash_table_new(g_str_hash, g_str_equal); irc_msg_table_build(irc); buf = g_strdup_printf(_("Signon: %s"), username); gaim_connection_update_progress(gc, buf, 1, 2); g_free(buf); err = gaim_proxy_connect(account, irc->server, gaim_account_get_int(account, "port", IRC_DEFAULT_PORT), irc_login_cb, gc); if (err || !account->gc) { gaim_connection_error(gc, _("Couldn't create socket")); return; }}static void irc_login_cb(gpointer data, gint source, GaimInputCondition cond){ GaimConnection *gc = data; struct irc_conn *irc = gc->proto_data; char hostname[256]; char *buf; const char *username, *realname; GList *connections = gaim_connections_get_all(); if (source < 0) { gaim_connection_error(gc, _("Couldn't connect to host")); return; } if (!g_list_find(connections, gc)) { close(source); return; } irc->fd = source; if (gc->account->password && *gc->account->password) { buf = irc_format(irc, "vv", "PASS", gc->account->password); if (irc_send(irc, buf) < 0) { gaim_connection_error(gc, "Error sending password"); return; } g_free(buf); } gethostname(hostname, sizeof(hostname)); hostname[sizeof(hostname) - 1] = '\0'; username = gaim_account_get_string(irc->account, "username", ""); realname = gaim_account_get_string(irc->account, "realname", ""); buf = irc_format(irc, "vvvv:", "USER", strlen(username) ? username : g_get_user_name(), hostname, irc->server, strlen(realname) ? realname : IRC_DEFAULT_ALIAS); if (irc_send(irc, buf) < 0) { gaim_connection_error(gc, "Error registering with server"); return; } g_free(buf); buf = irc_format(irc, "vn", "NICK", gaim_connection_get_display_name(gc)); if (irc_send(irc, buf) < 0) { gaim_connection_error(gc, "Error sending nickname"); return; } g_free(buf); gc->inpa = gaim_input_add(irc->fd, GAIM_INPUT_READ, irc_input_cb, gc);}static void irc_close(GaimConnection *gc){ struct irc_conn *irc = gc->proto_data; if (irc == NULL) return; irc_cmd_quit(irc, "quit", NULL, NULL); if (gc->inpa) gaim_input_remove(gc->inpa); g_free(irc->inbuf); close(irc->fd); if (irc->timer) gaim_timeout_remove(irc->timer); g_hash_table_destroy(irc->cmds); g_hash_table_destroy(irc->msgs); if (irc->motd) g_string_free(irc->motd, TRUE); g_free(irc->server); g_free(irc);}static int irc_im_send(GaimConnection *gc, const char *who, const char *what, GaimConvImFlags flags){ struct irc_conn *irc = gc->proto_data; const char *args[2]; if (strchr(status_chars, *who) != NULL) args[0] = who + 1; else args[0] = who; args[1] = what; irc_cmd_privmsg(irc, "msg", NULL, args); return 1;}static void irc_get_info(GaimConnection *gc, const char *who){ struct irc_conn *irc = gc->proto_data; const char *args[1]; args[0] = who; irc_cmd_whois(irc, "whois", NULL, args);}static void irc_set_away(GaimConnection *gc, const char *state, const char *msg){ struct irc_conn *irc = gc->proto_data; const char *args[1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -