第18行: 第18行:
 
* 对于普通类型,例如int,直接在对应位置写'i'就可以。
 
* 对于普通类型,例如int,直接在对应位置写'i'就可以。
 
* 对于需要再次parse的类型,这里只要取出一个字符串就完了,一般是'9s'这样的形式。
 
* 对于需要再次parse的类型,这里只要取出一个字符串就完了,一般是'9s'这样的形式。
 +
 +
样例:
 +
 +
来自UserInfo类
 +
<source lang="python">
 +
_fields = ['active', 'uid', 'pid', 'invisible', 'sockactive', 'sockaddr', 'destuid', 'mode', 'pager', 'in_chat', ['chatid', 1], ['from', 1], 'logintime', 'fill', 'freshtime', 'utmpkey', 'mailbox_prop', ['userid', 1], ['realname', 1], ['username', 1], 'friendsnum', ['friends_uid', 2, '=%di' % Config.MAXFRIENDS ], 'currentboard', 'mailcheck']
 +
    _parser = struct.Struct('=iiiiiiiiii16s%dsi36siiI20s20s40si%dsiI' % (Config.IPLEN + 4, Config.MAXFRIENDS * 4))
 +
</source>
 +
对应c结构:
 +
<source lang="c">
 +
struct user_info {              /* Structure used in UTMP file */
 +
    int active;                /* When allocated this field is true */
 +
    int uid;                    /* Used to find user name in passwd file */
 +
    int pid;                    /* kill() to notify user of talk request */
 +
    int invisible;              /* Used by cloaking function in Xyz menu */
 +
    int sockactive;            /* Used to coordinate talk requests */
 +
    int sockaddr;              /* ... */
 +
    int destuid;                /* talk uses this to identify who called */
 +
    int mode;                  /* UL/DL, Talk Mode, Chat Mode, ... */
 +
    int pager;                  /* pager toggle, true, or false */
 +
    int in_chat;                /* for in_chat commands  */
 +
    char chatid[16];            /* chat id, if in chat mode */
 +
    char from[IPLEN + 4];      /* machine name the user called in from */
 +
    time_t logintime;
 +
#ifdef HAVE_WFORUM
 +
char fill[35];
 +
unsigned char yank;
 +
#else
 +
    char fill[36];
 +
#endif
 +
    time_t freshtime;
 +
    int utmpkey;
 +
    unsigned int mailbox_prop;  /* properties of currentuser's mailbox */
 +
    char userid[20];
 +
    char realname[20];
 +
    char username[40];
 +
    int friendsnum;
 +
    int friends_uid[MAXFRIENDS];
 +
#ifdef FRIEND_MULTI_GROUP
 +
    unsigned int friends_p[MAXFRIENDS];
 +
#endif
 +
    int currentboard;
 +
unsigned int mailcheck; /* if have new mail or new msg, stiger */
 +
};
 +
</source>
  
 
== 数据接口实现 ==
 
== 数据接口实现 ==

2012年7月2日 (一) 16:14的版本

基于Python的BBS实现,提供BBS数据接口

基础结构

C结构的存取

初版实现

需要在对应的类定义域:_fields与_parser。

_fields:

  • _fields为一个list,其中每项对应一个C结构里的域。
  • 每项可以是一个字符串(域名),或者是一个list。
  • 如果是一个list,那第一个必须是个字符串(域名),第二个是类型,之后是类型参数。
    • 类型1: C字符串。从内存中读取之后,会自动截断到第一个\0
    • 类型2: 需要再次parse的域。目前主要用来实现数组。类型参数是再次parse的格式字符串。
      • 例如,对于一个int数组,['friends_uid', 2, '=%di' % Config.MAXFRIENDS ],会再次用后面那个格式进行parse,得到一个list。

_parser:

  • 定义为struct.Struct(格式字符串)
  • 格式字符串里,每项对应了_fields里的一个域。
  • 对于普通类型,例如int,直接在对应位置写'i'就可以。
  • 对于需要再次parse的类型,这里只要取出一个字符串就完了,一般是'9s'这样的形式。

样例:

来自UserInfo类

 _fields = ['active', 'uid', 'pid', 'invisible', 'sockactive', 'sockaddr', 'destuid', 'mode', 'pager', 'in_chat', ['chatid', 1], ['from', 1], 'logintime', 'fill', 'freshtime', 'utmpkey', 'mailbox_prop', ['userid', 1], ['realname', 1], ['username', 1], 'friendsnum', ['friends_uid', 2, '=%di' % Config.MAXFRIENDS ], 'currentboard', 'mailcheck']
    _parser = struct.Struct('=iiiiiiiiii16s%dsi36siiI20s20s40si%dsiI' % (Config.IPLEN + 4, Config.MAXFRIENDS * 4))

对应c结构:

struct user_info {              /* Structure used in UTMP file */
    int active;                 /* When allocated this field is true */
    int uid;                    /* Used to find user name in passwd file */
    int pid;                    /* kill() to notify user of talk request */
    int invisible;              /* Used by cloaking function in Xyz menu */
    int sockactive;             /* Used to coordinate talk requests */
    int sockaddr;               /* ... */
    int destuid;                /* talk uses this to identify who called */
    int mode;                   /* UL/DL, Talk Mode, Chat Mode, ... */
    int pager;                  /* pager toggle, true, or false */
    int in_chat;                /* for in_chat commands   */
    char chatid[16];            /* chat id, if in chat mode */
    char from[IPLEN + 4];       /* machine name the user called in from */
    time_t logintime;
#ifdef HAVE_WFORUM
	char fill[35];
	unsigned char yank;
#else 
    char fill[36];
#endif
    time_t freshtime;
    int utmpkey;
    unsigned int mailbox_prop;  /* properties of currentuser's mailbox */
    char userid[20];
    char realname[20];
    char username[40];
    int friendsnum;
    int friends_uid[MAXFRIENDS];
#ifdef FRIEND_MULTI_GROUP
    unsigned int friends_p[MAXFRIENDS];
#endif
    int currentboard;
	unsigned int mailcheck;				/* if have new mail or new msg, stiger */
};

数据接口实现

  • 登录
    • 用户名/密码登录
已实现,考虑安全原因禁用
    • OAuth登录
部分实现,只是能用而已……
  • 帖子
    • 获取帖子
已实现
    • 发帖
    • 同主题上一帖/下一贴
已实现
  • 版面
    • 获取所有版面列表
已实现
  • 精华区
  • 收藏夹
    • 获取收藏夹列表
已实现
  • 消息
在XMPP接口中实现
  • 好友列表
在XMPP接口中实现
  • 邮箱

XMPP实现

XMPP阶段:

  • 认证
    • 基于外部OAuth
    • 基于明文
TLS层已经加密了,所以无所谓。
已实现,见xmppauth.XMPPAuth类
  • 登录
    • 更新用户信息
    • 增加session
已实现。在xmppserver.XMPPServer类中__init__部分。调用Session.Register()进行注册。
  • 好友列表
    • 获取好友列表(roaster)
已实现。在roster.Roster类中。
    • 跟踪好友状态并更新好友列表
已实现。在rosters.Rosters类中,包括update_sessions()等
    • 隐身功能
已实现,看不见的人,就是看不见……
但是在消息方面有个问题。原来是允许给隐身的人回复消息的,但现在不好判断是否回复,干脆统统不许。
    • 增加好友
    • 删除好友
    • 修改好友昵称
  • 消息
    • 发送消息
已实现。参见rosters.Rosters.send_msg()
    • 消息通知
已实现
目前设计为,当收到SIGUSR2,让所有登录用户检查是否有新消息。
    • 接收消息
已实现。保存内部已读索引,每次检查消息,如果有新消息,则发送给用户。
  • 修改状态
  • 扩展

很多成本不大…… 有空搞搞就好了

    • jabber:iq:last
上次活动时间(在线)/上次上线时间(下线)/uptime(服务器)
    • jabber:iq:version
软件版本/系统信息
    • vcard-temp
用户信息,例如名字、全名、……
初步实现,返回用户名……
用户本地时间……
    • disco#info
查询支持的扩展列表。已实现
  • 注销
    • 更新用户信息
    • 移除session
已实现。用Session.Unregister()。