Discuz! 链接提示插件
第一个插件终于开发完成了。
下载地址:http://addon.discuz.com/?@linktips.plugin
功能:论坛、微博中的链接,当鼠标滑过时进行提示:打开、复制、举报。后台可以看到举报信息哦,管理员可以根据用户举报的地址进行核对,如果是违法地址,既可以放入黑名单,如果确定是合理的地址,即可放入白名单。
javascript 事件绑定(兼容各种浏览器)
IE中的 attachEvent 函数在添加事件绑定的时候不传递this对象。这让开发者很纠结,不过有政策就有对策。使用如下方法代替事件绑定函数,兼容各种浏览器。
<script type="text/javascript"> function addEvent(o,e,f) { if(o.addEventListener) { o.addEventListener(e,f,false) } else { var ctype="_"+e,a,i; if(!o[ctype]){ a=o[ctype]=[]; o.attachEvent("on"+e,function(evt){ evt=event; evt.target=event.srcElement; for(var i=0,l=a.length;i<l;i++) a[i].call(o,evt); }); } a=o[ctype]; i=a.length; while(i--)if(a[i]==f)return; a.push(f); } } function delEvent(o,e,f) { if(o.removeEventListener) { o.removeEventListener(e,f,false); } else { var ctype="_"+e; if(o[ctype]) { var a=o[ctype],i=a.length; while(i--) if(a[i]==f) { a.splice(i,1);break; } } } } </script>
addEventListener-事件流(小插曲,只是提醒注意这个知识点)
说到 addEventListener 不得不说到事件流,先说事件流对后面的解释比较方便。
当一个事件发生时,分为三个阶段:
捕获阶段 从根节点开始顺序而下,检测每个节点是否注册了事件处理程序。如果注册了事件处理程序,并且 useCapture 为 true,则调用该事件处理程序。(IE 中无此阶段。)
目标阶段 触发在目标对象本身注册的事件处理程序,也称正常事件派发阶段。
冒泡阶段 从目标节点到根节点,检测每个节点是否注册了事件处理程序,如果注册了事件处理程序,并且 useCapture 为 false,则调用该事件处理程序。
上面提到的 useCapture 也就是 addEventListener 的第三个参数了。
还要谢谢Ander的帮助:http://user.qzone.qq.com/81839603/infocenter#!app=2&pos=1319529117
js中document.body.scrollTop始终为0
代码改成
document.documentElement.scrollTop这样就没有问题了。
造成这个的原因是html页面声明了:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
当然这一条还是不能删除的。
Discuz! X2.5 添加自定义数据调用模块(简单方法)
Discuz!X系列的diy功能还是相当不错的,在对其进行二次开发的过程中,或许需要加入新的数据调用模块,这样可以使你开发的功能模块也像原来的模块一样,只需要点点鼠标,填写一些简单的信息,就可以在各个页面的各个位置显示你想显示的数据啦。
以下就目前最新版X2.5做一个简答的介绍:
大致可以分为以下三个步骤:
一、添加数据调用程序
二、后台更新diy模块分类缓存
三、添加相应的数据模板
具体操作如下:
一、添加数据调用程序
1> 在 source/class/block/ 目录下新建文件夹如 :news
2>
在news文件夹下,新建 blockclass.php,内容如下:
<?php if(!defined('IN_DISCUZ')) { exit('Access Denied'); } $blockclass = array( 'name' => lang('blockclass', 'blockclass_resource'), ); ?>
再在news文件夹下,新建 block_news.php,内容如下:
<?php if(!defined('IN_DISCUZ')) { exit('Access Denied'); } class block_news extends discuz_block { public $setting = array(); public function block_news() { $this->setting = array(.........); //这儿对setting进行初始化 } public function name() { // 这儿设置数据来源 return lang('blockclass', 'blockclass_news_script_news'); } public function blockclass() { // 这儿设置调用模块类型 return array('news', lang('blockclass', 'blockclass_news')); } public function fields() { $fields = array(.........); //这儿对fields进行设置,除了discuz本身支持的变量外,只有这儿设置的字段才可以在模板中调用。 return $fields; } public function getsetting() { return $this->setting; } public function getdata($style, $parameter) { $list = array(.........); // 这儿根据实际情况从数据库或许相应的数据 return array('html' => '', 'data' => $list); } } ?>
以上代码中 lang(....),均为语言处理,这里略过。还有 $setting,$fields,$list的格式可以参考 source/class/block/member/block_member.php中对应变量的格式。
二、进入后台-工具-更新缓存,一定要勾选“DIY 模块分类缓存”,然后开始更新。
三、进入后台-门户-模块模板,在这个下添加你对应的模板。
以上,只是简单说明,~~,因时间有限,只能到此为止啦。。。。。
preg_replace的/e修饰符妙用与慎用
preg_replace — 执行正则表达式的搜索和替换
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit ] )
在 subject 中搜索 pattern 模式的匹配项并替换为 replacement 。如果指定了 limit ,则仅替换 limit 个匹配,如果省略 limit 或者其值为 -1,则所有的匹配项都会被替换。
特别注意:
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
在Discuz程序中很聪明的利用了这个“e”,比如说在生成模板缓冲的时候,部分php代码执行了,而部分php代码未执行。如下代码:
$template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template); $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template); $template = preg_replace("/\{lang\s+(.+?)\}/ies", "\$this->languagevar('\\1')", $template); $template = preg_replace("/[\n\r\t]*\{block\/(\d+?)\}[\n\r\t]*/ie", "\$this->blocktags('\\1')", $template);
可以看出文字替换就是提前处理了。
上面的这种写法完全可以用下面的方式,显得更加易读易懂
$template = preg_replace("/\{lang\s+(.+?)\}/is", $this->languagevar('\\1'), $template);在有这些好处的同时,这个"e"往往在不注意的情况下很容易产生漏洞,还请慎用。下面举例说明:
比如说某程序文件中有这样的写法
<?php function test($str){ //...... //...... return $str; } echo preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", 'test("\1")', $_GET["h"]); ?>
提交 ?h=[php]phpinfo()[/php],phpinfo()会被执行吗?
肯定不会。
因为经过正则匹配后, replacement 参数变为'test("phpinfo()")',此时phpinfo仅是被当做一个字符串参数了。
有没有办法让它执行呢?
当然有。
在这里我们如果提交?h=[php]{${phpinfo()}}[/php],phpinfo()就会被执行。
为什么呢?
在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;单引号中的变量不会被处理。
注意:双引号中的函数不会被执行和替换。
在这里我们需要通过{${}}构造出了一个特殊的变量,'test("{${phpinfo()}}")',达到让函数被执行的效果 ${phpinfo()} 会被解释执行。
phpinfo() 可以获取到服务器端的各种信息,方便进一步攻击,所以这是每个网站基本应该预防的一点。
如何避免出现上面的漏洞呢?
可以把上面的代码这样写,用户就没有办法攻击了
echo preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", "test('\\1')", $_GET["h"]);
上面的内容仅供学习参考,并无任何恶意。
上面的程序还有一点点小的区别哦,看下面两行代码对比
echo preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", "test('\1')", $_GET["h"]); //下面两行代码替换是等价的,注意单引号与双引号 echo preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", "test('\\1')", $_GET["h"]); echo preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", 'test("\1")', $_GET["h"]);