📄 sametime.c
字号:
pd = mwSession_getClientData(session); gc = pd->gc; switch(state) { case mwSession_STARTING: msg = _("Sending Handshake"); purple_connection_update_progress(gc, msg, 2, MW_CONNECT_STEPS); break; case mwSession_HANDSHAKE: msg = _("Waiting for Handshake Acknowledgement"); purple_connection_update_progress(gc, msg, 3, MW_CONNECT_STEPS); break; case mwSession_HANDSHAKE_ACK: msg = _("Handshake Acknowledged, Sending Login"); purple_connection_update_progress(gc, msg, 4, MW_CONNECT_STEPS); break; case mwSession_LOGIN: msg = _("Waiting for Login Acknowledgement"); purple_connection_update_progress(gc, msg, 5, MW_CONNECT_STEPS); break; case mwSession_LOGIN_REDIR: msg = _("Login Redirected"); purple_connection_update_progress(gc, msg, 6, MW_CONNECT_STEPS); session_loginRedirect(session, info); break; case mwSession_LOGIN_CONT: msg = _("Forcing Login"); purple_connection_update_progress(gc, msg, 7, MW_CONNECT_STEPS); case mwSession_LOGIN_ACK: msg = _("Login Acknowledged"); purple_connection_update_progress(gc, msg, 8, MW_CONNECT_STEPS); break; case mwSession_STARTED: msg = _("Starting Services"); purple_connection_update_progress(gc, msg, 9, MW_CONNECT_STEPS); session_started(pd); msg = _("Connected"); purple_connection_update_progress(gc, msg, 10, MW_CONNECT_STEPS); purple_connection_set_state(gc, PURPLE_CONNECTED); break; case mwSession_STOPPING: session_stopping(pd); if(GPOINTER_TO_UINT(info) & ERR_FAILURE) { char *err = mwError(GPOINTER_TO_UINT(info)); purple_connection_error(gc, err); g_free(err); } break; case mwSession_STOPPED: break; case mwSession_UNKNOWN: default: DEBUG_WARN("session in unknown state\n"); }}static void mw_session_setPrivacyInfo(struct mwSession *session) { struct mwPurplePluginData *pd; PurpleConnection *gc; PurpleAccount *acct; struct mwPrivacyInfo *privacy; GSList *l, **ll; guint count; DEBUG_INFO("privacy information set from server\n"); g_return_if_fail(session != NULL); pd = mwSession_getClientData(session); g_return_if_fail(pd != NULL); gc = pd->gc; g_return_if_fail(gc != NULL); acct = purple_connection_get_account(gc); g_return_if_fail(acct != NULL); privacy = mwSession_getPrivacyInfo(session); count = privacy->count; ll = (privacy->deny)? &acct->deny: &acct->permit; for(l = *ll; l; l = l->next) g_free(l->data); g_slist_free(*ll); l = *ll = NULL; while(count--) { struct mwUserItem *u = privacy->users + count; l = g_slist_prepend(l, g_strdup(u->id)); } *ll = l;}static void mw_session_setUserStatus(struct mwSession *session) { struct mwPurplePluginData *pd; PurpleConnection *gc; struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL }; struct mwUserStatus *stat; g_return_if_fail(session != NULL); pd = mwSession_getClientData(session); g_return_if_fail(pd != NULL); gc = pd->gc; g_return_if_fail(gc != NULL); idb.user = mwSession_getProperty(session, mwSession_AUTH_USER_ID); stat = mwSession_getUserStatus(session); /* trigger an update of our own status if we're in the buddy list */ mwServiceAware_setStatus(pd->srvc_aware, &idb, stat);}static void mw_session_admin(struct mwSession *session, const char *text) { PurpleConnection *gc; PurpleAccount *acct; const char *host; const char *msg; char *prim; gc = session_to_gc(session); g_return_if_fail(gc != NULL); acct = purple_connection_get_account(gc); g_return_if_fail(acct != NULL); host = purple_account_get_string(acct, MW_KEY_HOST, NULL); msg = _("A Sametime administrator has issued the following announcement" " on server %s"); prim = g_strdup_printf(msg, NSTR(host)); purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO, _("Sametime Administrator Announcement"), prim, text, NULL, NULL); g_free(prim);}/** called from read_cb, attempts to read available data from sock and pass it to the session, passing back the return code from the read call for handling in read_cb */static int read_recv(struct mwSession *session, int sock) { guchar buf[BUF_LEN]; int len; len = read(sock, buf, BUF_LEN); if(len > 0) mwSession_recv(session, buf, len); return len;}/** callback triggered from purple_input_add, watches the socked for available data to be processed by the session */static void read_cb(gpointer data, gint source, PurpleInputCondition cond) { struct mwPurplePluginData *pd = data; int ret = 0, err = 0; g_return_if_fail(pd != NULL); ret = read_recv(pd->session, pd->socket); /* normal operation ends here */ if(ret > 0) return; /* fetch the global error value */ err = errno; /* read problem occurred if we're here, so we'll need to take care of it and clean up internal state */ if(pd->socket) { close(pd->socket); pd->socket = 0; } if(pd->gc->inpa) { purple_input_remove(pd->gc->inpa); pd->gc->inpa = 0; } if(! ret) { DEBUG_INFO("connection reset\n"); purple_connection_error(pd->gc, _("Connection reset")); } else if(ret < 0) { char *msg = strerror(err); DEBUG_INFO("error in read callback: %s\n", msg); msg = g_strdup_printf(_("Error reading from socket: %s"), msg); purple_connection_error(pd->gc, msg); g_free(msg); }}/** Callback passed to purple_proxy_connect when an account is logged in, and if the session logging in receives a redirect message */static void connect_cb(gpointer data, gint source, const gchar *error_message) { struct mwPurplePluginData *pd = data; PurpleConnection *gc = pd->gc; if(source < 0) { /* connection failed */ if(pd->socket) { /* this is a redirect connect, force login on existing socket */ mwSession_forceLogin(pd->session); } else { /* this is a regular connect, error out */ purple_connection_error(pd->gc, _("Unable to connect to host")); } return; } if(pd->socket) { /* stop any existing login attempt */ mwSession_stop(pd->session, ERR_SUCCESS); } pd->socket = source; gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, read_cb, pd); mwSession_start(pd->session);}static void mw_session_announce(struct mwSession *s, struct mwLoginInfo *from, gboolean may_reply, const char *text) { struct mwPurplePluginData *pd; PurpleAccount *acct; PurpleConversation *conv; PurpleBuddy *buddy; char *who = from->user_id; char *msg; pd = mwSession_getClientData(s); acct = purple_connection_get_account(pd->gc); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, acct); if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, who); buddy = purple_find_buddy(acct, who); if(buddy) who = (char *) purple_buddy_get_contact_alias(buddy); who = g_strdup_printf(_("Announcement from %s"), who); msg = purple_markup_linkify(text); purple_conversation_write(conv, who, msg, PURPLE_MESSAGE_RECV, time(NULL)); g_free(who); g_free(msg);}static struct mwSessionHandler mw_session_handler = { mw_session_io_write, mw_session_io_close, mw_session_clear, mw_session_stateChange, mw_session_setPrivacyInfo, mw_session_setUserStatus, mw_session_admin, mw_session_announce,};static void mw_aware_on_attrib(struct mwServiceAware *srvc, struct mwAwareAttribute *attrib) { ; /** @todo handle server attributes. There may be some stuff we actually want to look for, but I'm not aware of anything right now.*/}static void mw_aware_clear(struct mwServiceAware *srvc) { ; /* nothing for now */}static struct mwAwareHandler mw_aware_handler = { mw_aware_on_attrib, mw_aware_clear,};static struct mwServiceAware *mw_srvc_aware_new(struct mwSession *s) { struct mwServiceAware *srvc; srvc = mwServiceAware_new(s, &mw_aware_handler); return srvc;};static void mw_conf_invited(struct mwConference *conf, struct mwLoginInfo *inviter, const char *invitation) { struct mwServiceConference *srvc; struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; char *c_inviter, *c_name, *c_topic, *c_invitation; GHashTable *ht; srvc = mwConference_getService(conf); session = mwService_getSession(MW_SERVICE(srvc)); pd = mwSession_getClientData(session); gc = pd->gc; ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); c_inviter = g_strdup(inviter->user_id); g_hash_table_insert(ht, CHAT_KEY_CREATOR, c_inviter); c_name = g_strdup(mwConference_getName(conf)); g_hash_table_insert(ht, CHAT_KEY_NAME, c_name); c_topic = g_strdup(mwConference_getTitle(conf)); g_hash_table_insert(ht, CHAT_KEY_TOPIC, c_topic); c_invitation = g_strdup(invitation); g_hash_table_insert(ht, CHAT_KEY_INVITE, c_invitation); DEBUG_INFO("received invitation from '%s' to join ('%s','%s'): '%s'\n", NSTR(c_inviter), NSTR(c_name), NSTR(c_topic), NSTR(c_invitation)); if(! c_topic) c_topic = "(no title)"; if(! c_invitation) c_invitation = "(no message)"; serv_got_chat_invite(gc, c_topic, c_inviter, c_invitation, ht);}/* The following mess helps us relate a mwConference to a PurpleConvChat in the various forms by which either may be indicated */#define CONF_TO_ID(conf) (GPOINTER_TO_INT(conf))#define ID_TO_CONF(pd, id) (conf_find_by_id((pd), (id)))#define CHAT_TO_ID(chat) (purple_conv_chat_get_id(chat))#define ID_TO_CHAT(id) (purple_find_chat(id))#define CHAT_TO_CONF(pd, chat) (ID_TO_CONF((pd), CHAT_TO_ID(chat)))#define CONF_TO_CHAT(conf) (ID_TO_CHAT(CONF_TO_ID(conf)))static struct mwConference *conf_find_by_id(struct mwPurplePluginData *pd, int id) { struct mwServiceConference *srvc = pd->srvc_conf; struct mwConference *conf = NULL; GList *l, *ll; ll = mwServiceConference_getConferences(srvc); for(l = ll; l; l = l->next) { struct mwConference *c = l->data; PurpleConvChat *h = mwConference_getClientData(c); if(CHAT_TO_ID(h) == id) { conf = c; break; } } g_list_free(ll); return conf;}static void mw_conf_opened(struct mwConference *conf, GList *members) { struct mwServiceConference *srvc; struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; PurpleConversation *g_conf; const char *n = mwConference_getName(conf); const char *t = mwConference_getTitle(conf); DEBUG_INFO("conf %s opened, %u initial members\n", NSTR(n), g_list_length(members)); srvc = mwConference_getService(conf); session = mwService_getSession(MW_SERVICE(srvc)); pd = mwSession_getClientData(session); gc = pd->gc; if(! t) t = "(no title)"; g_conf = serv_got_joined_chat(gc, CONF_TO_ID(conf), t); mwConference_setClientData(conf, PURPLE_CONV_CHAT(g_conf), NULL); for(; members; members = members->next) { struct mwLoginInfo *peer = members->data; purple_conv_chat_add_user(PURPLE_CONV_CHAT(g_conf), peer->user_id, NULL, PURPLE_CBFLAGS_NONE, FALSE); }}static void mw_conf_closed(struct mwConference *conf, guint32 reason) { struct mwServiceConference *srvc; struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; const char *n = mwConference_getName(conf); char *msg = mwError(reason); DEBUG_INFO("conf %s closed, 0x%08x\n", NSTR(n), reason); srvc = mwConference_getService(conf); session = mwService_getSession(MW_SERVICE(srvc)); pd = mwSession_getClientData(session); gc = pd->gc; serv_got_chat_left(gc, CONF_TO_ID(conf)); purple_notify_error(gc, _("Conference Closed"), NULL, msg); g_free(msg);}static void mw_conf_peer_joined(struct mwConference *conf, struct mwLoginInfo *peer) { struct mwServiceConference *srvc; struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; PurpleConvChat *g_conf; const char *n = mwConference_getName(conf); DEBUG_INFO("%s joined conf %s\n", NSTR(peer->user_id), NSTR(n)); srvc = mwConference_getService(conf); session = mwService_getSession(MW_SERVICE(srvc)); pd = mwSession_getClientData(session); gc = pd->gc; g_conf = mwConference_getClientData(conf); g_return_if_fail(g_conf != NULL); purple_conv_chat_add_user(g_conf, peer->user_id, NULL, PURPLE_CBFLAGS_NONE, TRUE);}static void mw_conf_peer_parted(struct mwConference *conf, struct mwLoginInfo *peer) { struct mwServiceConference *srvc; struct mwSession *session; struct mwPurplePluginData *pd; PurpleConnection *gc; PurpleConvChat *g_conf; const char *n = mwConference_getName(conf); DEBUG_INFO("%s left conf %s\n", NSTR(peer->user_id), NSTR(n)); srvc = mwConference_getService(conf); session = mwService_getSession(MW_SERVICE(srvc)); pd = mwSession_getClientData(session); gc = pd->gc; g_conf = mwConference_getClientData(conf); g_return_if_fail(g_conf != NULL); purple_conv_chat_remove_user(g_conf, peer->user_id, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -