标签 x2 下的文章

游客可见游客发布的待审核帖子的bug分析

话说好久没捉虫了,今天突然发现个,哈哈~
此bug在Discuz! x2版本上发现。

具体表现为:
版块开启游客发表权限,发表新主题进入待审核。
在游客下发布帖子,提示进入审核,但游客状态下可以直接浏览。

代码分析:
source\function\function_forum.php文件,有如下代码

if(!$_G['forum_auditstatuson'] && !empty($_G['thread'])
		&& !($_G['thread']['displayorder'] >= 0 || (in_array($_G['thread']['displayorder'], array(-4,-3,-2)) && $_G['thread']['authorid'] == $_G['uid']))) {
	$_G['thread'] = null;
}

这里后面的$_G['thread']['authorid'] == $_G['uid']没有对$_G['uid']是否存在进行判断。

修复方案:
在$_G['thread']['authorid'] == $_G['uid']后面加上下面的代码:

 && $_G['uid']

此bug在Discuz! x25下未发现。

调用远程接口失败报错分析及验证方法

问题描述:
在开通云平台或者开启/关闭某个云平台服务的时候,云平台报下面的错误:
调用远程接口失败。请检查您的服务器是否处于内网以及您服务器的防火墙设置。

出现此类问题的可能原因:
1.没有开放80端口,云平台只允许访问80端口。
非80端口的站点请改为80端口开通。

2.您的网站处于内网。
云平台只能在外网使用,请在外网搭建站点再进行开通。

3.接口文件无法访问或输出不正确。
接口文件为:您的论坛地址/api/manyou/my.php,您可以试着在浏览器里访问接口文件看是否可以正常访问。
类似的输出如下:

4.服务器上有防火墙,拦截了云平台与站点间接口文件的通信。
云平台是通过curl的方式去请求站点的接口文件,有些空间商可能对此做了限制,可咨询空间商。

5.域名还未完全生效。
如果您是使用一个刚申请的域名开通云平台,这种情况下可能是域名还未完全生效,建议您等24小时再进行开通操作。

6.云平台回调论坛方法的操作时间超时。
在开通/关闭的操作中,云平台会回调论坛的方法进行更新缓存等操作,此步操作可能超时,导致云平台没有收到正确的返回值。
此类可参考之前一个的问题分析:http://www.liudon.org/?p=102

如果出现此类报错,站长可以按下面的方法自行进行一下验证,检查问题是出在云平台访问站点接口文件还是云平台回调论坛方法上。

验证方法:
x2版本:
找到api\manyou\my.php文件,搜索代码

$my->run();

这句代码下面添加代码

file_put_contents('./d.txt', '云平台访问接口文件成功!');

修改后,进入站点后台->云平台下进行开通云平台或者开启/关闭某些云平台服务的操作,这个时候仍会报调用远程接口失败的错误。
这个时候进入网站目录/api/manyou目录下,检查是否有d.txt文件,里面的内容应该是“云平台访问接口文件成功!”。

如果存在d.txt,则说明云平台可以正常访问站点的接口文件,问题出在云平台回调论坛方法这里。这种情况大部分都会在更新缓存这里,可以参考这个方法修改试下:http://www.liudon.org/?p=102

如果没有生成d.txt,则说明云平台无法访问站点的接口文件,问题处在云平台访问站点接口文件这里。云平台无法访问站点的接口文件的原因,可能是服务器上有防火墙或者新域名还未完全生效。

建议您按上面的验证方法自行进行一下验证,如果自己解决不了,希望您在官方发帖求助的时候可以贴上您验证的结果,方便我们定位问题。

Discuz! x2更新DIY模板分析

碰到一个DIY模板更新的问题,顺便分析了下更新的机制,整理记录下来了就。

哪些是DIY模板呢?
DIY模板加载的代码比较特殊,具体格式类似下面

include template('diy:***');

***为其他内容,不限。
如加载论坛首页的代码:

include template('diy:forum/discuz:'.$gid);

模板是如何加载的呢?
这里不对x2默认的模板加载方式进行分析,只针对DIY部分的更新加以说明。
找到source/function/function_core.php文件,找到template函数,在函数里可找到如下代码:

if($tpldir == 'data/diy' && ($tplrefresh ==1 || ($tplrefresh > 1 && !($_G['timestamp'] % $tplrefresh))) && filemtime($diypath.$file.'.htm') < filemtime(DISCUZ_ROOT.TPLDIR.'/'.($primaltpl ? $primaltpl : $oldfile).'.htm')) {
	if (!updatediytemplate($file)) {
		unlink($diypath.$file.'.htm');
		$tpldir = '';
	}
}

这段就是判断如果是DIY模板,同时满足更新条件,则更新相应的DIY模板。
更新的操作为updatediytemplate($file)。
还是在function_core.php文件里,找到updatediytemplate函数,代码如下:

function updatediytemplate($targettplname = '') {
	global $_G;
	$r = false;
	$where = empty($targettplname) ? '' : " WHERE targettplname='$targettplname'";
	$query = DB::query("SELECT * FROM ".DB::table('common_diy_data')."$where");
	require_once libfile('function/portalcp');
	while($value = DB::fetch($query)) {
		$r = save_diy_data($value['primaltplname'], $value['targettplname'], unserialize($value['diycontent']));
	}
	return $r;
}

common_diy_data表里存放的就是DIY数据,数据格式类似如下:


这里会从common_diy_data中查出更新的源文件和目前文件。

找到source/function/function_portalcp.php,找到save_diy_data函数,有如下代码:

function save_diy_data($primaltplname, $targettplname, $data, $database = false, $optype = '') {
	global $_G;
	if (empty($data) || !is_array($data)) return false;
	checksecurity($data['spacecss']);
	$file = ($_G['cache']['style_default']['tpldir'] ? $_G['cache']['style_default']['tpldir'] : './template/default').'/'.$primaltplname.'.htm';
	if (!file_exists($file)) {
		$file = './template/default/'.$primaltplname.'.htm';
	}
	if(!file_exists($file)) return false;
	......(中间的部分省略)
	return $r;
}

注意里面的这句代码

$file = ($_G['cache']['style_default']['tpldir'] ? $_G['cache']['style_default']['tpldir'] : './template/default').'/'.$primaltplname.'.htm';

这里会以你当前使用的风格路径下的相应文件$primailtplname.htm为源文件进行更新。

云平台报调用远程接口失败的问题分析

最近帮同事排查了一个这样的问题,类似的情况貌似不少,特总结分析一下。

问题描述:
当开通或关闭某个云平台服务的时候,报如下错误信息:
调用远程接口失败。请检查您的服务器是否处于内网以及您服务器的防火墙设置。

云平台测试站点的接口文件正常,于是开始在文件里断点记录,发现程序也执行完了。
咨询了下云平台的同事,说是有可能是超时导致的。

于是进站点后台,进入chrome开发者模式下的网络选项卡,记录所有网络链接。
然后去开通或关闭某个服务,发现需要耗时8s之久,估计确实像同事说的那样是超时导致的。

问题总结:
出现此类问题的站点一般装了很多插件,更新插件缓存时耗时太久导致云平台访问超时没有正确的返回,进而报上面的错误。
解决的方法有两种:
1> 进入后台->插件下,关闭所有的插件,然后再去云平台下开通/关闭某些服务。
2> 找到source\function\function_cloud.php文件,搜索代码

require_once libfile('function/cache');
updatecache(array('plugin', 'setting', 'styles'));

改为

//require_once libfile('function/cache');
//updatecache(array('plugin', 'setting', 'styles'));

此端更改为注释掉更新缓存的代码。
然后去后台->云平台下开通/关闭某些服务,开通或关闭后还需要再到后台->工具下手动更新一下缓存。

有此问题的站长不妨按上面的方法试下。

x2个人资料的隐私更新问题分析及解决方法

问题描述:
后台设置某项用户栏目的默认隐私设为公开,这里以QQ为例。
然后注册一个新会员,设置个人资料里的QQ项。
更改后台此项用户栏目QQ的默认隐私为保密,但是此用户的空间里仍显示QQ项。

 

问题原因:
在source\module\forum\forum_viewthread.php文件判断隐私的地方并未对某项资料的全局隐私做判断,代码如下:

if(!empty($post['privacy']['profile'][$field])) {
	continue;
}

这里仅判断了用户此项资料的隐私设置,如果存在就跳出,不予显示,但是这里并未对这项资料的全局隐私做判断,会导致出现开头提到的问题。

修正方法:
在source\module\forum\forum_viewthread.php文件中,搜索下面代码

if(!empty($post['privacy']['profile'][$field])) {
	continue;
}

改为

if(!empty($post['privacy']['profile'][$field]) || $_G['setting']['privacy']['profile'][$field]) {
	continue;
}

此问题在1010版本下发现,其他版本未验证。