使用libpurple函数库接入服务器

news2025/4/16 7:29:46

代码;

#define CUSTOM_USER_DIRECTORY  "/dev/null"					// 定义用户目录
#define CUSTOM_PLUGIN_PATH ""							// 定义插件目录
#define PLUGIN_SAVE_PREF "/purple/nullclient/plugins/saved"		// 定义插件头目录
#define UI_ID "nullclient"										// 定义用户接口ID
#include <purple.h>											// 包含libpurple库
#include <glib.h>											// 包含GLib库
#include <signal.h>
#include <string.h>
#include <unistd.h>
#define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)		// 定义GLib读成员
#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
														// 定义GLib写成员
typedef struct _PurpleGLibIOClosure {							// 该结构用于作为回调函数参数
   PurpleInputFunction function;								// 函数名
   guint result;												// 返回结果
   gpointer data;											// 数据参数
} PurpleGLibIOClosure;




static void purple_glib_io_destroy(gpointer data)					// 该函数用于清除数据
{
   g_free(data);											// 释放data所指向的内存空间
}

static gboolean purple_glib_io_invoke(GIOChannel *source,
                                   GIOCondition condition,
                                   gpointer data)				// 调用GLib输入输出接口
{
   PurpleGLibIOClosure *closure = data;							// 创建libpurple输入输出终止符
   PurpleInputCondition purple_cond = 0;							// 创建libpurple输入条件对象
   if (condition & PURPLE_GLIB_READ_COND)					// 判断条件是否为读取
      purple_cond |= PURPLE_INPUT_READ;					// 将libpurple输入条件对象设为读取
   if (condition & PURPLE_GLIB_WRITE_COND)					// 判断条件是否为写入
      purple_cond |= PURPLE_INPUT_WRITE;					// 将libpurple输入条件对象设为写入
   closure->function(closure->data, g_io_channel_unix_get_fd(source),
           purple_cond);										// 调用回调函数执行输入输出操作
   return TRUE;
}

static guint glib_input_add(gint fd,
                         PurpleInputCondition condition,
                         PurpleInputFunction function,
                         gpointer data)						// 加入一个GLib输入接口
{
   PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);	// 创建libpurple输入输出终止符
   GIOChannel *channel;										// 声明GLib通道对象
   GIOCondition cond = 0;									// 声明GLib输入输出条件
   closure->function = function;								// 定义回调函数
   closure->data = data;										// 定义数据指针
   if (condition & PURPLE_INPUT_READ)						// 判断条件是否为读取
      cond |= PURPLE_GLIB_READ_COND; 					// 将libpurple输入条件对象设为读取
   if (condition & PURPLE_INPUT_WRITE) 						// 判断条件是否为写入
      cond |= PURPLE_GLIB_WRITE_COND; 					// 将libpurple输入条件对象设为写入
   channel = g_io_channel_unix_new(fd);							// 创建GLib通道
   closure->result = g_io_add_watch_full(channel,
                                      G_PRIORITY_DEFAULT,
                                      cond,
                                      purple_glib_io_invoke,
                                      closure,
                                      purple_glib_io_destroy);		// 设置通道中的回调函数
   g_io_channel_unref(channel);								// 将通道对象托管
   return closure->result;
}

static PurpleEventLoopUiOps glib_eventloops = 					// 定义GLib事件循环
{
   g_timeout_add,											// 超时处理
   g_source_remove,										// 源删除
   glib_input_add,											// 添加输入管道
   g_source_remove,										// 源删除
   NULL,
#if GLIB_CHECK_VERSION(2,14,0)								// 判断GLib版本是否为2.14.0
   g_timeout_add_seconds,									// 超时秒数
#else
   NULL,
#endif
   NULL
};

static void null_write_conv(PurpleConversation *conv,				// 会话标识符
                         const char *who,						// 好友ID
                         const char *alias,						// 昵称
                         const char *message,					// 消息
                         PurpleMessageFlags flags,				// 消息类型
                         time_t mtime)							// 发送时间
{
   const char *name;										// 用于保存好友名称
   if (alias && *alias)										// 判断存在好友昵称
      name = alias;											// 将好友名称设为昵称
   else if (who && *who)										// 判断好友ID存在
      name = who;											// 将好友名称设为好友ID
   else
      name = NULL;
   printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
         purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
         name, message);									// 输出会话
}

static PurpleConversationUiOps null_conv_uiops = 					// 定义会话UI选项
{
   NULL,													// 创建会话
   NULL,													// 清除会话
   NULL,													// 输入聊天消息
   NULL,													// 输入通信信息
   null_write_conv,											// 写入会话
   NULL,													// 添加联系人
   NULL,													// 修改联系人名
   NULL,													// 删除联系人
   NULL,													// 更新联系人姓名
   NULL,													// 当前时间
   NULL,													// 获得焦点
   NULL,													// 增加表情
   NULL,													// 输入表情
   NULL,													// 关闭表情
   NULL,													// 发送确认
};

static void null_ui_init(void)									// 初始化用户接口
{
   purple_conversations_set_ui_ops(&null_conv_uiops);				// 使用会话UI选项初始化用户接口
}

static PurpleCoreUiOps null_core_uiops = 						// 定义核心用户接口选项
{
   NULL, NULL, null_ui_init, NULL
};

static void init_libpurple(void)									// 初始化libpurple
{
   purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);			// 设置用户目录
   purple_debug_set_enabled(FALSE);							// 不接受调试信息
   purple_core_set_ui_ops(&null_core_uiops);						// 设置核心用户接口选项
   purple_eventloop_set_ui_ops(&glib_eventloops);					// 设置GLib事件循环
   purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH);		// 添加搜索插件路径
   if (!purple_core_init(UI_ID)) {								// 初始化libpurple环境
      fprintf(stderr,
            "libpurple初始化失败!\n");
      abort();
   }
   purple_set_blist(purple_blist_new());							// 读取联系人列表
   purple_blist_load();
   purple_prefs_load();										// 读取用户配置
   purple_plugins_load_saved(PLUGIN_SAVE_PREF);				// 加载插件
   purple_pounces_load();									// 完成初始化
}

static void signed_on(PurpleConnection *gc, gpointer null)			// 接收libpurple信号
{
   PurpleAccount *account = purple_connection_get_account(gc);		// 读取本地账户信息
   printf("Account connected: %s %s\n", account->username, account->protocol_id);
}

static void connect_to_signals_for_demonstration_purposes_only(void)	// 对信号进行过滤
{
   static int handle;											// 用于保存句柄
   purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
            PURPLE_CALLBACK(signed_on), NULL);				// 设置过滤器和回调函数
}

int main(int argc, char *argv[])
{
   GList *iter;												// 声明GList链表节点
   int i, num;												// 用户循环控制变量
   GList *names = NULL;										// 声明GList链表
   const char *prpl;
   char name[128];											// 用于保存用户名
   char *password;											// 用于保存密码
   GMainLoop *loop = g_main_loop_new(NULL, FALSE);			// 创建一个主循环
   PurpleAccount *account;									// 定义libpurple账户
   PurpleSavedStatus *status;									// 定义libpurple状态
   char *res;												// 用于用户输入交互
   signal(SIGCHLD, SIG_IGN);								// 设置libpurple信号
   init_libpurple();											// 初始化libpurple库
   printf("libpurple初始化成功。\n");
   iter = purple_plugins_get_protocols();							// 通过插件获得即时通信协议
   for (i = 0; iter; iter = iter->next) {								// 遍历GList链表
      PurplePlugin *plugin = iter->data;							// 取得libpurple插件信息
      PurplePluginInfo *info = plugin->info;
      if (info && info->name) {
         printf("\t%d: %s\n", i++, info->name);						// 输出libpurple插件名
         names = g_list_append(names, info->id);					// 将libpurple插件名加入GList链表
      }
   }
   printf("请选择一个协议 [0-%d]: ", i-1);							// 提示用户选择一个IM协议
   res = fgets(name, sizeof(name), stdin);							// 从终端读取用户输入
   if (!res) {
      fprintf(stderr, "协议选择不正确");
      abort();
   }
   sscanf(name, "%d", &num);									// 输入协议编号
   prpl = g_list_nth_data(names, num);							// 在GList链表中读取相关协议信息
   printf("用户名: ");											// 提述输入用户名
   res = fgets(name, sizeof(name), stdin);							// 从终端读取用户输入
   if (!res) {
      fprintf(stderr, "无法读取用户名");
      abort();
   }
   name[strlen(name) - 1] = 0;
   account = purple_account_new(name, prpl);					// 创建账户
   password = getpass("请输入密码: ");
   purple_account_set_password(account, password);				// 获取用户密码
   purple_account_set_enabled(account, UI_ID, TRUE);				// 激活账户
   status = purple_savedstatus_new(NULL, 
                                  PURPLE_STATUS_AVAILABLE);	// 设置当前状态为可用
   purple_savedstatus_activate(status);							// 设置用户状态为“活动”
   connect_to_signals_for_demonstration_purposes_only();			// 接收IM服务器传来的消息
   g_main_loop_run(loop);									// 启动GLib主循环
   return 0;
}

编译;

运行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1826168.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DELL服务器插入新磁盘、创建虚拟磁盘、挂载磁盘步骤

文章目录 一、磁盘清理&#xff08;可选&#xff0c;针对新硬盘是Foreign状态&#xff09;1、进入VD Mgmt2、清理新硬盘配置 二、创建虚拟磁盘1、进入Device Settings2、创建虚拟磁盘 三、挂载磁盘到系统1、分区磁盘&#xff08;注意实际磁盘的名称&#xff09;2、格式化分区3、…

跨境电商中的IP隔离是什么?怎么做?

一、IP地址隔离的概念和原理 当我们谈论 IP 地址隔离时&#xff0c;我们实际上是在讨论一种网络安全策略&#xff0c;旨在通过技术手段将网络划分为不同的区域或子网&#xff0c;每个区域或子网都有自己独特的 IP 地址范围。这种划分使网络管理员可以更精细地控制哪些设备或用…

微服务feign组件学习

手写不易&#xff0c;对您有帮助。麻烦一键三连。也欢饮各位大料指正&#xff0c;交流。 微服务feign组件学习 1.概念1.1 feign 概念1.2 Ribbon概念 2.使用2.1 集成feign2.1.1 maven依赖2.1.2 项目结构 2.2 使用2.2.1 定义feign接口2.2.2 消费端服务调用2.2.3 消费端扫描feig…

Java面试题汇总(持续更新.....)

Java面试题 1. JVM & JDK & JRE Java虚拟机&#xff08;JVM&#xff09;是运行Java字节码的虚拟机&#xff0c;JVM有针对不同系统的特定实现&#xff0c;目的是使用相同的字节码&#xff0c;他们都会给出相同的结果。字节码和不同系统的JVM实现是Java语言“一次编译、…

个人网站制作 Part 25 添加实时聊天功能 | Web开发项目添加页面缓存

文章目录 &#x1f469;‍&#x1f4bb; 基础Web开发练手项目系列&#xff1a;个人网站制作&#x1f680; 添加实时聊天功能&#x1f528;使用聊天服务&#x1f527;步骤 1: 选择聊天服务&#x1f527;步骤 2: 安装Socket.io&#x1f527;步骤 3: 创建Socket.io服务器 &#x1…

抽奖系统源码_微信抽奖系统PHP源码开源

介绍&#xff1a; 微信抽奖系统源码是一个以php MySQL进行开发的手机抽奖系统源码。用途&#xff1a;适合做推广营销、直播、粉丝抽奖。 功能介绍&#xff1a; 1、后台可以设置每个抽奖用户的抽奖次数,后台添加设置奖品,适和企业和商场搞活动,后台添加用户&#xff0c;才能抽…

如何应对缺失值带来的分布变化?探索填充缺失值的最佳插补算法

本文将探讨了缺失值插补的不同方法&#xff0c;并比较了它们在复原数据真实分布方面的效果&#xff0c;处理插补是一个不确定性的问题&#xff0c;尤其是在样本量较小或数据复杂性高时的挑战&#xff0c;应选择能够适应数据分布变化并准确插补缺失值的方法。 我们假设存在一个…

【多线程】Thread类及其基本用法

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. Java中多线程编程1.1 操作系统线程与Java线程1.2 简单使用多线程1.2.1 初步创建新线程代码1.2.2 理解每个…

小功率无变压器电源设计

采用无变压器电源解决方案为低功率电路提供所需电源通常是有利的。 事实上&#xff0c;如果负载电流只有几十毫安&#xff0c;则可以将输入交流电压转换为直流电压&#xff0c;而无需使用大型、昂贵且笨重的变压器。不带变压器的替代方案也更便宜、更轻并且占地面积更小。无变…

深入剖析人才管理的关键要素:“选、用、育、留”四大核心要素

在当今这个日新月异的商业时代&#xff0c;企业的成功不再仅仅取决于资金、技术或市场策略&#xff0c;而更多地依赖于企业所拥有的人才资源。有效的人才管理策略&#xff0c;尤其是“选、用、育、留”四大核心要素&#xff0c;已成为推动企业持续发展的关键。 一、选&#xff…

28.启动与暂停程序

上一个内容&#xff1a;27.设计注入功能界面 以它 27.设计注入功能界面 的代码为基础进行修改 点击添加游戏按钮之后就把游戏启动了 CWndINJ.cpp文件中修改&#xff1a; void CWndINJ::OnBnClickedButton1() {// TODO: 在此添加控件通知处理程序代码/*ExeLst.InsertItem(0, L…

虚函数机制-动态绑定的应用

虚函数使得程序在运行的时候根据指针指向对象的类型来确定调用哪个函数。 下图中&#xff1a;都为静态绑定。因为在编译器就确定了可以调用的函数 此时当基类指针指向派生类对象时&#xff0c;因为没有virtual关键字&#xff0c;所以在编译阶段就根据指针类型确定了要指向的函…

博客论坛系统java博客管理系统基于springboot+vue的前后端分离博客论坛系统

文章目录 博客论坛系统一、项目演示二、项目介绍三、部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 博客论坛系统 一、项目演示 博客论坛系统 二、项目介绍 基于springbootvue的前后端分离博客论坛系统 系统角色&#xff1a…

创业者的孤独之旅:马云视角下的战略定位与自我激励

一、引言 在创业的道路上&#xff0c;每一位创业者都如同孤独的旅人&#xff0c;背负着梦想与希望&#xff0c;踏上了充满未知与挑战的征途。马云&#xff0c;这位中国电子商务的巨擘&#xff0c;以其独特的视角和坚韧不拔的精神&#xff0c;为我们揭示了创业者所面临的孤独与…

js注册popstate事件并阻止浏览器返回

提示&#xff1a;记录工作中遇到的需求及解决办法 文章目录 前言一、第一步二、第二步三、第三步四、最后 前言 在做一些重要资料填写的时候, 我们基本都会阻止一下浏览器的回退, 刷新等等, 今天我们主要针对回退, 做一次讲解。 提示&#xff1a;以下是本篇文章正文内容&#…

HCIP认证笔记(填空)

1、为防止攻击者伪造BGP报文对设备进行攻击,可以通过配置GTSM功能检测IP报文中的TTL值的范围来对设备进行保护。如果某台设备配置了“peer x.x.x.x valid-ttl-hops 100",则被检测的报文的TTL值的有效范围为【(156),255】; 解析: peer {group-name | ipv4-address…

2024年7款硬盘恢复软件:即刻恢复硬盘删除的文件!

当文件被删除后&#xff0c;它并不是立即从硬盘中消失&#xff0c;而是被标记为“已删除”&#xff0c;等待垃圾回收处理。因此&#xff0c;在文件被删除后&#xff0c;有几种方法可以尝试恢复删除的数据。 以下是7款常用的数据恢复软件&#xff0c;以及它们的详细介绍&#xf…

IDEA创建SpringBoot项目教程,讲解超详细!!!(2024)

前言 在创建Spring Boot项目时&#xff0c;为了确保项目的顺利构建和运行&#xff0c;我们依赖于JDK&#xff08;Java开发工具包&#xff09;和Maven仓库。 JDK作为Java编程的基础&#xff0c;提供了编译和运行Java应用程序所需的核心类库和工具。 JDK安装配置教程&#xff1…

相对与绝对布局:悬浮的提示框页面

目录 任务描述 相关知识 HTML和CSS基础: 盒子模型: 定位: 伪类: 编程要求 任务描述 在本关中&#xff0c;你需要创建一个简单的HTML页面&#xff0c;其中包括一个按钮。当鼠标悬停在按钮上时&#xff0c;会显示一个浮动的提示框&#xff08;tooltip&#xff09;&#xf…

【SpringBoot】SpringBoot:构建实时聊天应用

文章目录 引言项目初始化添加依赖 配置WebSocket创建WebSocket配置类创建WebSocket处理器 创建前端页面创建聊天页面 测试与部署示例&#xff1a;编写单元测试 部署扩展功能用户身份验证消息持久化群组聊天 结论 引言 随着实时通信技术的快速发展&#xff0c;聊天应用在现代We…