[DiscuzNt]整合DiscuzNt论坛目前所发现的小BUG及个人简单解决办法

     前段时间因为公司项目需要,需要在网站中整合BBS论坛,主要实现会员信息同步,经过目前市面上开源的BBS项目,最终认为还是DiscuzNt比较好,原因有以下几点:

1、符合国人习惯,DiscuzNt是由PHP版的Discuz演化而来,市场占有率比较高,而且比较符合国人的习惯。

2、采用.NET语言编写,源码看起来不会因为跨语言而导致问题。

3、有官方支持,市面上的.NET语言编写BBS论坛能比的上DiscuzNt还真的不多,官方会经常发布维护版及升级版,会根据广大站长的需求进行版本升级,所以这点很重要。

在选择完了需要整合的论坛后,就开始查看其源代码,然后找资料,看看如何进行整合,不过由于本篇文章并不是介绍如何整合DiscuzNt,所以如果想了解整合DiscuzNt的朋友可以去官方论坛:DiscuzNt进行查询。

今天主要介绍的还是在这次的项目整合过程中发现的问题及个人的简单解决办法。

首先声明下,我整合的DiscuzNt是3.1的版本,是2010年3月16号发布的版本,并不一定适用于最新的版本。

 

一、使用第三方加密的后遗症

这次的项目中会员密码加密方式采用的是公司一直沿用的加密方式,和DiscuzNt默认的自带方式不一样,所以第一反应还是修改DiscuzNt中的加密方式,本来以为会很麻烦,后来看了一下DiscuzNt的源码,发现其实很方便,只需要2步:

1、修改Discuz.Plugin.PasswordMode(第三方加密模式)ThirdPartMode.cs,这个类是DiscuzNt为需要扩展开发需求的开发者预留的扩展插件接口,需要实现自定义加密方式的开发者只需修改这个类中的3个与密码相关的方法中的密码加密:CheckPwd、CreateUserInfo、SaveUserInfo

2、修改Discuz.Web项目下Config目录下的general.config配置文件中的Passwordmode2

本来以为修改好了就OK了,心中还在窃喜,真简单,结果没相当问题就来了:

 

在DiscuzNt论坛中,为了方便网友上传文件采用的silverlight进行批量上传附件,但是我修改了加密方式后点击批量上传总是会提示我:“当前用户信息无效,请尝试刷新页面”,于是我就去查看silverlight上传的源码及老代写的这篇文章:DiscuzNT使用Silverlight进行多文件上传,发现报出这个问题是在Discuz.Web.Services.MixObjects.cs中的:

/// <summary>
/// WEB权限认证
/// </summary>
/// <param name="creinfo">认证信息</param>
/// <returns>是否通过验正</returns>
private bool AuthenticateUser(CredentialInfo creinfo)
{
    if (creinfo.ForumID > 0)
    {
        int olid = Discuz.Forum.OnlineUsers.GetOlidByUid(creinfo.UserID);
        if (olid > 0)
        {
            OnlineUserInfo oluserinfo = Discuz.Forum.OnlineUsers.GetOnlineUser(olid);
            if (oluserinfo.Userid == creinfo.UserID && 
                Utils.UrlEncode(Discuz.Forum.ForumUtils.SetCookiePassword(oluserinfo.Password.Trim(), GeneralConfigs.GetConfig().Passwordkey)) == creinfo.Password &&//检测用户id和口令
                creinfo.AuthToken == DES.Encode(string.Format("{0},{1}", oluserinfo.Olid.ToString(), oluserinfo.Username.ToString()), oluserinfo.Password.Substring(0, 10)).Replace("+", "["))//检查认证信息
            {
                return true;
            }
        }
    }
    return false;
}

这段代码主要是对当前要进行上传的用户进行验证,本来如果不对加密方式进行修改是不会进行出现这个问题,所以我单步调试了下代码,果然发现问题:

Utils.UrlEncode(Discuz.Forum.ForumUtils.SetCookiePassword(oluserinfo.Password.Trim(), GeneralConfigs.GetConfig().Passwordkey))

主要还是这句代码中的的oluserinfo.Password,由于我的加密方式生成的字符串长度相比discuznt的长度要短,所以后面会多出许多空格,然后再经过Utils.UrlEncode进行过URL编码后,就会多出许多无用的字符所以导致了用户信息验证失败。

找到问题修改起来就方便许多了,只需加上Trim()方法,将多余的空格清除掉就OK了。

 

二、多次引用导致引用内容被截断

这个问题是在上线后发现的,在会员发帖的时候,如果多次引用了前面的内容会出现内容,如下图:

pic55 

可以看到在引用的内容明显可以发现内容被截断了,而且由于截断了导致后面应该是链接的UBB标签显示了出来,当然如果再次引用这个帖子会导致内容变的更加乱,所以得想办法解决,查看一下源码,在Discuz.Web项目下的Aspx/1目录下的postreply.aspx.cs类中的606行:

message = "[quote] 原帖由 [b]" + postinfo.Poster + "[/b] 于 " + postinfo.Postdatetime + " 发表\r\n" + UBB.ClearAttachUBB(Utils.GetSubString(postinfo.Message, 200, "......")) + " [/quote]";

这句代码是用来拼接引用的内容,但是由于页面整体的考虑采用了截取:Utils.GetSubString(postinfo.Message, 200,”……”),截取前200个字符的内容,这样就导致了截取的过程中把UBB标签也一起给截断了。

所以解决方法也很简单,只要把这个截断去除就OK了:

message = "[quote]" + postinfo.Message + "\r\n [color=#999999]" + postinfo.Poster + " 发表于 " + postinfo.Postdatetime + "[/color][url=" + DNTRequest.GetUrlReferrer() + "#" + postid + "][img]" + Utils.GetRootUrl(forumpath) + "images/common/back.gif[/img][/url][/size][/quote]";

 

三、帖子名称修改后,在论坛首页的最新帖子名称未修改

这个问题也是在使用中发生的,原因就是帖子名起错了,后来修改了,但是回到论坛首页看发现板块中最新的帖子还是原来的名字,本来以为是缓存的,可是等了1天名字竟然还是原来的,所以继续查源码

在Discuz.Web项目的Aspx/1目录下的forumindex.aspx,可以看到每个板块下的最新帖子标题lasttitle及所链接的帖子ID都是从板块的实体信息中获取,到数据库中对应的表dnt_forums中可以找个字段lasttitle和,所以可以认定论坛首页的板块列表的所有信息都来自于dnt_forums。

接着查看编辑帖子页面EditPost.aspx的源码,找到编辑帖子按钮的操作,可以发现其最终是调用数据库中的存储过程:dnt_updatepost1:

CREATE PROCEDURE dnt_updatepost1
	@pid int,
	@title nvarchar(160),
	@message ntext,
	@lastedit nvarchar(50),
	@invisible int,
	@usesig int,
	@htmlon int,
	@smileyoff int,
	@bbcodeoff int,
	@parseurloff int
AS
UPDATE dnt_posts1 SET 
	[title]=@title,
	[message]=@message,
	[lastedit]=@lastedit,
	[invisible]=@invisible,
	[usesig]=@usesig,
	[htmlon]=@htmlon,
	[smileyoff]=@smileyoff,
	[bbcodeoff]=@bbcodeoff,
	[parseurloff]=@parseurloff WHERE [pid]=@pid

可以看到,这个存储过程仅仅是更新了帖子信息,并没有更新帖子所属板块的信息,所以我们只需要在这边进行简单修改既可:

declare @fid int,@tid int,@topictitle nvarchar(60)
--查询帖子所在板块及帖子的标题
select @fid=a.fid,@tid=a.tid,@topictitle=b.title from dnt_posts1 a
inner join dnt_topics b on b.tid=a.tid
where [pid]=@pid
--若最后回复的帖子是当前编辑的帖子则更新其最后回复帖子的标题
UPDATE dnt_forums set [lasttitle]=@topictitle where fid=@fid and lasttid=@tid

在这个存储过程的后面继续添加上面一段代码既可。

不过其实还有个不是办法的办法,就是在这个帖子名字改过后,再回个帖,这样帖子的名字就会更新成最新的了。

 

四、后台帮助管理列表的除数据后未重新绑定

这个问题是在维护论坛帮助的时候发现的,由于discuzNT默认已经帮我们维护好了许多常见的帮助,但是有些帮助在实际运用的过程中并没有用,所以就想在后台删除掉,于是后台人员就将无用的帮助删除了,但是删除后列表里还是原来那么多条数据,刚刚删除的竟然还在列表中,于是我去数据库查看了一下帮助表,发现数据库中数据已经被删除了,说明删除功能没问题,问题出在了删除后的重新绑定上,我看了一下源码在Discuz.Web.Admin项目下的global目录下的global_helplist.aspx页面中绑定列表的代码如下:

helpInfoList = Helps.GetHelpList();

可以看出列表数据是通过调用Helps类下的GetHelpList方法,看下具体的代码:

/// <summary>
/// 帮助信息树形列表
/// </summary>
private static List<HelpInfo> helpListTree = null;       

/// <summary>
/// 获取帮助列表
/// </summary>
/// <returns>帮助列表</returns>
public static List<HelpInfo> GetHelpList()
{
    //if (helpListTree == null)
    //{
        helpListTree = new List<HelpInfo>();
        List<HelpInfo> helpList = Discuz.Data.Help.GetHelpList();

        CreateHelpTree(helpList, 0);
   // }
    return helpListTree;
}

这个GetHelpList方法是静态的,并且其返回列表树helpListTree也是静态的,在方法体内判断helpListTree是否为空,则进行创建,不为空就直接返回列表,但是由于这个列表是静态的,所以在实际运行过程中,这个helpListTree一直不为空,所以我这边将判断是否为空给注释掉了,表示每次都重新获取,这样列表数据就更新了

 

以上就是本篇文章的全部内容了,这些都是我在整合过程中发现的问题,不过都是些小BUG,自己花了点时间就能解决。

PS:1、本文并没有说DiscuzNT不好,只是将现有的DiscuzNt的小BUG提出来,所以请勿以此为由进行评论。

2、可能这些解决方法不是最好的,也可能还有问题,不过目前没发现,如果你有更好的建议欢迎评论,谢谢!

posted @ 2010-09-08 10:02  kyo-yo  阅读(4849)  评论(27编辑  收藏  举报