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

📄 nullprpl.c

📁 Linux下的多协议即时通讯程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/** * purple * * Purple is the legal property of its developers, whose names are too numerous * to list here.  Please refer to the COPYRIGHT file distributed with this * source distribution. * * Nullprpl is a mock protocol plugin for Pidgin and libpurple. You can create * accounts with it, sign on and off, add buddies, and send and receive IMs, * all without connecting to a server! *  * Beyond that basic functionality, nullprpl supports presence and * away/available messages, offline messages, user info, typing notification, * privacy allow/block lists, chat rooms, whispering, room lists, and protocol * icons and emblems. Notable missing features are file transfer and account * registration and authentication. *  * Nullprpl is intended as an example of how to write a libpurple protocol * plugin. It doesn't contain networking code or an event loop, but it does * demonstrate how to use the libpurple API to do pretty much everything a prpl * might need to do. *  * Nullprpl is also a useful tool for hacking on Pidgin, Finch, and other * libpurple clients. It's a full-featured protocol plugin, but doesn't depend * on an external server, so it's a quick and easy way to exercise test new * code. It also allows you to work while you're disconnected. * * 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 <stdarg.h>#include <string.h>#include <time.h>#include <glib.h>#include "internal.h"#include "config.h"#include "account.h"#include "accountopt.h"#include "blist.h"#include "cmds.h"#include "conversation.h"#include "connection.h"#include "debug.h"#include "notify.h"#include "privacy.h"#include "prpl.h"#include "roomlist.h"#include "status.h"#include "util.h"#include "version.h"#define NULLPRPL_ID "prpl-null"static PurplePlugin *_null_protocol = NULL;#define NULL_STATUS_ONLINE   "online"#define NULL_STATUS_AWAY     "away"#define NULL_STATUS_OFFLINE  "offline"typedef void (*GcFunc)(PurpleConnection *from,                       PurpleConnection *to,                       gpointer userdata);typedef struct {  GcFunc fn;  PurpleConnection *from;  gpointer userdata;} GcFuncData;/* * stores offline messages that haven't been delivered yet. maps username * (char *) to GList * of GOfflineMessages. initialized in nullprpl_init. */GHashTable* goffline_messages = NULL;typedef struct {  char *from;  char *message;  time_t mtime;  PurpleMessageFlags flags;} GOfflineMessage;/* * helpers */static PurpleConnection *get_nullprpl_gc(const char *username) {  PurpleAccount *acct = purple_accounts_find(username, NULLPRPL_ID);  if (acct && purple_account_is_connected(acct))    return acct->gc;  else    return NULL;}static void call_if_nullprpl(gpointer data, gpointer userdata) {  PurpleConnection *gc = (PurpleConnection *)(data);  GcFuncData *gcfdata = (GcFuncData *)userdata;  if (!strcmp(gc->account->protocol_id, NULLPRPL_ID))    gcfdata->fn(gcfdata->from, gc, gcfdata->userdata);}static void foreach_nullprpl_gc(GcFunc fn, PurpleConnection *from,                                gpointer userdata) {  GcFuncData gcfdata = { fn, from, userdata };  g_list_foreach(purple_connections_get_all(), call_if_nullprpl,                 &gcfdata);}typedef void(*ChatFunc)(PurpleConvChat *from, PurpleConvChat *to,                        int id, const char *room, gpointer userdata);typedef struct {  ChatFunc fn;  PurpleConvChat *from_chat;  gpointer userdata;} ChatFuncData;static void call_chat_func(gpointer data, gpointer userdata) {  PurpleConnection *to = (PurpleConnection *)data;  ChatFuncData *cfdata = (ChatFuncData *)userdata;  int id = cfdata->from_chat->id;  PurpleConversation *conv = purple_find_chat(to, id);  if (conv) {    PurpleConvChat *chat = purple_conversation_get_chat_data(conv);    cfdata->fn(cfdata->from_chat, chat, id, conv->name, cfdata->userdata);  }}static void foreach_gc_in_chat(ChatFunc fn, PurpleConnection *from,                               int id, gpointer userdata) {  PurpleConversation *conv = purple_find_chat(from, id);  ChatFuncData cfdata = { fn,                          purple_conversation_get_chat_data(conv),                          userdata };  g_list_foreach(purple_connections_get_all(), call_chat_func,                 &cfdata);}static void discover_status(PurpleConnection *from, PurpleConnection *to,                            gpointer userdata) {  char *from_username = from->account->username;  char *to_username = to->account->username;  if (purple_find_buddy(from->account, to_username)) {    PurpleStatus *status = purple_account_get_active_status(to->account);    const char *status_id = purple_status_get_id(status);    const char *message = purple_status_get_attr_string(status, "message");    if (!strcmp(status_id, NULL_STATUS_ONLINE) ||        !strcmp(status_id, NULL_STATUS_AWAY) ||        !strcmp(status_id, NULL_STATUS_OFFLINE)) {      purple_debug_info("nullprpl", "%s sees that %s is %s: %s\n",                        from_username, to_username, status_id, message);      purple_prpl_got_user_status(from->account, to_username, status_id,                                  (message) ? "message" : NULL, message, NULL);    } else {      purple_debug_error("nullprpl",                         "%s's buddy %s has an unknown status: %s, %s",                         from_username, to_username, status_id, message);    }  }}static void report_status_change(PurpleConnection *from, PurpleConnection *to,                                 gpointer userdata) {  purple_debug_info("nullprpl", "notifying %s that %s changed status\n",                    to->account->username, from->account->username);  discover_status(to, from, NULL);}/*  * UI callbacks */static void nullprpl_input_user_info(PurplePluginAction *action){  PurpleConnection *gc = (PurpleConnection *)action->context;  PurpleAccount *acct = purple_connection_get_account(gc);  purple_debug_info("nullprpl", "showing 'Set User Info' dialog for %s\n",                    acct->username);  purple_account_request_change_user_info(acct);}/* this is set to the actions member of the PurplePluginInfo struct at the * bottom. */static GList *nullprpl_actions(PurplePlugin *plugin, gpointer context){  PurplePluginAction *action = purple_plugin_action_new(    _("Set User Info..."), nullprpl_input_user_info);  return g_list_append(NULL, action);}/* * prpl functions */static const char *nullprpl_list_icon(PurpleAccount *acct, PurpleBuddy *buddy){  /* shamelessly steal (er, borrow) the meanwhile protocol icon. it's cute! */  return "meanwhile";}static const char *nullprpl_list_emblem(PurpleBuddy *buddy){  const char* emblem;  if (get_nullprpl_gc(buddy->name)) {    PurplePresence *presence = purple_buddy_get_presence(buddy);    PurpleStatus *status = purple_presence_get_active_status(presence);    emblem = purple_status_get_name(status);  } else {    emblem = "offline";  }  purple_debug_info("nullprpl", "using emblem %s for %s's buddy %s\n",                    emblem, buddy->account->username, buddy->name);  return emblem;}static char *nullprpl_status_text(PurpleBuddy *buddy) {  purple_debug_info("nullprpl", "getting %s's status text for %s\n",                    buddy->name, buddy->account->username);  if (purple_find_buddy(buddy->account, buddy->name)) {    PurplePresence *presence = purple_buddy_get_presence(buddy);    PurpleStatus *status = purple_presence_get_active_status(presence);    const char *name = purple_status_get_name(status);    const char *message = purple_status_get_attr_string(status, "message");    char *text;    if (message && strlen(message) > 0)      text = g_strdup_printf("%s: %s", name, message);    else      text = g_strdup(name);    purple_debug_info("nullprpl", "%s's status text is %s\n", buddy->name, text);    return text;  } else {    purple_debug_info("nullprpl", "...but %s is not logged in\n", buddy->name);    return "Not logged in";  }}static void nullprpl_tooltip_text(PurpleBuddy *buddy,                                  PurpleNotifyUserInfo *info,                                  gboolean full) {  PurpleConnection *gc = get_nullprpl_gc(buddy->name);  if (gc) {    /* they're logged in */    PurplePresence *presence = purple_buddy_get_presence(buddy);    PurpleStatus *status = purple_presence_get_active_status(presence);    const char *msg = nullprpl_status_text(buddy);    purple_notify_user_info_add_pair(info, purple_status_get_name(status),                                     msg);    if (full) {      const char *user_info = purple_account_get_user_info(gc->account);      if (user_info)        purple_notify_user_info_add_pair(info, _("User info"), user_info);    }  } else {    /* they're not logged in */    purple_notify_user_info_add_pair(info, _("User info"), _("not logged in"));  }      purple_debug_info("nullprpl", "showing %s tooltip for %s\n",                    (full) ? "full" : "short", buddy->name);}static GList *nullprpl_status_types(PurpleAccount *acct){  GList *types = NULL;  PurpleStatusType *type;  purple_debug_info("nullprpl", "returning status types for %s: %s, %s, %s\n",                    acct->username,                    NULL_STATUS_ONLINE, NULL_STATUS_AWAY, NULL_STATUS_OFFLINE);

⌨️ 快捷键说明

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