Jump to navigation

You are currently browsing the monthly archives for February 2010

discuz7.2勋章模块中的bug

  • Posted on February 28, 2010 at 7:06 pm

discuz 7.2 gbk版

/medal.php中,

}elseif($action == 'apply' && submitcheck('medalsubmit')) {

里面

if($medalpermission[0]) {

里面:

$db->query("INSERT INTO {$tablepre}medallog (uid, medalid, type, dateline, expiration, status) VALUES ('$discuz_uid', '$medalid', '1', '$timestamp', '$expiration', '0')");

$expiration的值永远为0.

所带来的影响就是: 如果用户符合领取某勋章的要求, 点击“领取”之后,领取到的勋章永远都不会到期。

解决办法:

可以继续往下看代码:

} else {
  $expiration = empty($medal['expiration'])? 0 : $timestamp + $medal['expiration'] * 86400;

这个else是处理”申请“勋章的情况。这里就很好地处理了$expiration。

所以把这一行加到

$db->query("INSERT INTO {$tablepre}medallog (uid, medalid, type, dateline, expiration, status) VALUES ('$discuz_uid', '$medalid', '1', '$timestamp', '$expiration', '0')");

前面就可以了。

把新短消息加入到discuz的提醒里面

  • Posted on February 28, 2010 at 5:03 pm

discuz 7.2 gbk版

discuz的默认情况:
接收到新短消息之后,会发出声音;有了新的提醒之后,“提醒”二个字前面会出现红色信封。 新短消息和提醒之间没有任何的联系。
如果用户的电脑没有打开声音,就无法知道是否有了新的短消息。因此,需要把新短消息加入到提醒里面。

在forumdata/cache/cache_settings.php中,我们可以看到
632   ‘promptkeys’ =>
633   array (
634     1 => ‘pm’,
635     2 => ‘announcepm’,
636     3 => ‘task’,
637     4 => ‘systempm’,
638     5 => ‘friend’,
639     6 => ‘threads’,
640   ),
641   ‘prompts’ =>
642   array (
643     ‘pm’ =>
644     array (
645       ‘name’ => ‘私人消息’,
646       ‘script’ => ‘pm.php?filter=newpm’,
647       ‘id’ => ’1′,
648       ‘new’ => 0,
649     ),
650     ‘announcepm’ =>
651     array (
652       ‘name’ => ‘公共消息’,
653       ‘script’ => ‘pm.php?filter=announcepm’,
654       ‘id’ => ’2′,
655       ‘new’ => 0,
656     ),
657     ‘task’ =>
658     array (
659       ‘name’ => ‘论坛任务’,
660       ‘script’ => ‘task.php?item=doing’,
661       ‘id’ => ’3′,
662       ‘new’ => 0,
663     ),
664     ‘systempm’ =>
665     array (
666       ‘name’ => ‘系统消息’,
667       ‘script’ => ”,
668       ‘id’ => ’4′,
669       ‘new’ => 0,
670     ),
671     ‘friend’ =>
672     array (
673       ‘name’ => ‘好友消息’,
674       ‘script’ => ”,
675       ‘id’ => ’5′,
676       ‘new’ => 0,
677     ),
678     ‘threads’ =>
679     array (
680       ‘name’ => ‘帖子消息’,
681       ‘script’ => ”,
682       ‘id’ => ’6′,
683       ‘new’ => 0,
684     ),
685   ),

dz已经预留了pm与announcepm 专门给新短消息来用。
我们需要做的就是 在用户发送完短消息后,插入一条提醒就可以了。
修改uc_client/control/pm.php   function onsendpm()
加入一行

require_once $_SERVER['DOCUMENT_ROOT']."/include/global.func.php";

然后在本函数中搜索

$lastpmid = $_ENV['pm']->sendpm(

在这一行之后,加入:

if ($fromuid)
$notice_message = "<div>收到新的短消息  来自:<a target=_blank href=\"{boardurl}space-uid-".$this->user['uid'].".html\">".$this->user['username']."</a><BR>".htmlspecialchars($message)."<BR><a href=\"{boardurl}pm.php?filter=newpm&uid=".$this->user['uid']."#new\" target=_blank>查看消息</a></div>";
else
$notice_message = "<div>收到新的短消息  <BR>".htmlspecialchars($message)."<BR><a href=\"{boardurl}pm.php?filter=newpm\" target=_blank>查看消息</a></div>";
sendnotice($uid, $notice_message, $notice_typeid);

等等,还没完,还有其它文件要改。
修改 /notice.php

$typeadd = $filter ? "AND typeid='".$prompts[$filter]['id']."'" : "AND typeid IN (".implodeids($promptpmids).")";

之前,加一行:

array_push($promptpmids, 1);

从promptkeys数组中可以看到,1对应的是”pm”.

还要改一下模板:
templates/default/notice.htm
在 <!–{loop $prompts $promptkey $promptdata}–> 里面,把下面的if改成:

<!--{if $promptkey!='announcepm'}-->

即可。

discuz7.2数据调用之主题附件(图片附件)存在的问题

  • Posted on February 26, 2010 at 10:30 am

discuz 7.2 GBK版

工具->数据调用->主题附件->图片附件

经过测试发现,

附件排序方式选择’按最后更新日期排序’或者是’按下载次数倒序排序’的时候,只能取到最近30天内的图片附件列表。

文件include/request.func.php 中:

在function updaterequest中

466                 $orderbysql = $historytime = '';
467                 switch($orderby) {
468                         case 'dateline':
469                                 $orderbysql = "ORDER BY `attach`.`dateline` DESC";
470                         break;
471                         case 'downloads':
472                                 $orderbysql = "ORDER BY `attach`.`downloads` DESC";
473                         break;
474                         case 'hourdownloads';
475                                 $historytime = $timestamp - 3600 * intval($hours);
476                                 $orderbysql = "ORDER BY `attach`.`downloads` DESC";

493                  $historytime = !$historytime ? $timestamp - 2592000 : $historytime;
494 $htsql = "`attach`.`dateline`>=$historytime";

493行改为

$historytime = !$historytime ? 0: $historytime;

即可。

原因我也不想讲了。 2592000秒 = 30天

nginx的client_max_body_size 以及 413 Request Entity Too Large

  • Posted on February 24, 2010 at 9:45 pm

利用nginx做了bbs的web服务器,应用一切正常。后来发现上传文件的时候,对于比较大的文件,在IE中上传30秒左右即失败,这个时候首先怀疑是php.ini中upload_max_filesize 或者 max_execution_time设置得太小了。检查了一下,发现没问题。

然后使用FF上传,直接就提示:内部服务器错误。用firebug跟了一下,发现nginx的真实回应是:413 Request Entity Too Large. 

解决办法: 在nginx.conf中添加 

client_max_body_size 20m;

这下够大了吧. 据说它的默认值是1m……

spawn-fcgi has been removed after lighttpd 1.4.21

  • Posted on February 24, 2010 at 10:04 am

Four and a half months after the release of 1.4.20 comes a new version in the stable branch of lighty: 1.4.21 is here.


spawn-fcgi warning

We decided to remove spawn-fcgi after this release from the lighttpd source, there is now a separate project for it:
http://redmine.lighttpd.net/projects/spawn-fcgi

这样也好。

使用js自动调整iframe高度

  • Posted on February 24, 2010 at 9:12 am

百度了一下,发现了最简单的方法:

在被iframe的页面最后,加一行JS:

window.parent.document.getElementById("fang_list_iframe").style.height=document.body.scrollHeight;

经过测试,发现在主页面含有

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

时,IE可以,FF无效。

这个时候人都变得傻X了,竟然想去修改这个DOCTYPE…

虽说把DOCTYPE改成

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

之后,IE和FF都生效了,但是在IE下面,页面布局都变了。。

最后发现,竟然,要这样写才可以:

window.parent.document.getElementById("fang_list_iframe").style.height=document.body.scrollHeight+"px";

看来还是由于自己的JS写得不够规范。。

好了,下面贴出完整代码:

<script>
 window.parent.scrollTo(0,0);
var mainIFrame = window.parent.document.getElementById("fang_list_iframe");
var scrollHeight = parseInt(document.body.scrollHeight);
var offsetHeight = parseInt(document.body.offsetHeight);
var hight;
var isIE = document.all && window.external;
if( isIE )
 hight = scrollHeight;
else
 hight = scrollHeight < offsetHeight?scrollHeight:offsetHeight;

var sUserAgent = navigator.userAgent;
var isChrome = sUserAgent.indexOf("Safari") > -1 ;
if( isChrome)
 hight = hight + 80;
mainIFrame.style.height=hight+"px";
</script>

无奈的google map

  • Posted on February 23, 2010 at 12:12 pm
	gm = new GMarker(new GLatLng(y,x));
	map.addOverlay(gm);
	gm.bindInfoWindowHtml((msg_bind));
        //错误:
        GEvent.addListener(gm, "mouseover", alert("ft"));
        //正确:
	GEvent.addListener(gm, "mouseover", function (){alert("ft");});

mysql配置中的concurrent_insert与low-priority-updates

  • Posted on February 23, 2010 at 9:49 am

MyISAM在读操作占主导的情况下是很高效的。特别是count(*)操作,简直无敌了。 可一旦出现大量的读写并发,由于table lock的原因,同InnoDB相比,MyISAM的效率就会直线下降. 关于myisam 的table lock ,可以参照我的另外一篇日志: http://www.masalife.com/index.php/archives/184

而且,MyISAM和InnoDB的数据存储方式也有显著不同: 通常,在MyISAM里,新数据会被附加到数据文件的结尾,可是做了一些DELETE操作之后,数据文件就不再是连续的,形象一点来说,就是数据文件里出现了很多hole,此时再插入新数据时,按缺省设置会先看这些hole的大小是否可以容纳下新数据,如果可以,则直接把新数据保存到hole里,反之,则把新数据保存到数据文件的结尾。之所以这样做是为了减少数据文件的大小,降低文件碎片的产生。

但InnoDB里则不是这样,在InnoDB里,由于主键是cluster的,所以,数据文件始终是按照主键排序的,如果使用自增ID做主键,则新数据始终是位于数据文件的结尾。 了解了这些基础知识,下面说说MyISAM几个容易忽视的配置选项:

concurrent_insert:

通常来说,在MyISAM里读写操作是串行的,但当对同一个表进行查询和插入操作时,为了降低锁竞争的频率,根据concurrent_insert的设置,MyISAM是可以并行处理查询和插入的:

mysql_version() > 5.0.6 :

当concurrent_insert=0时,不允许在SELECT操作的时候,并发执行INSERT。

当concurrent_insert=1时,如果表里面没有hole(可能性不大吧),SELECT操作的时候,可以并发执行INSERT,新数据位于数据文件结尾(缺省)。如果同时有多个INSERT操作,这些INSERT是串行执行的。

当concurrent_insert=2时,不管表有没有hole,在select操作的时候,都允许在数据文件结尾并发执行INSERT。如果同时有多个INSERT操作,这些INSERT是串行的。而且一旦select释放了lock之后,INSERT还是会首先尝试插入数据到hole里面。 For a table with a hole, new rows are inserted at the end of the table if it is in use by another thread. Otherwise, MySQL acquires a normal write lock and inserts the row into the hole.

这样看来,把concurrent_insert设置为2是很划算的,至于由此产生的文件碎片,可以定期使用OPTIMIZE TABLE语法优化。

max_write_lock_count:

缺省情况下,写操作的优先级要高于读操作的优先级,即便是先发送的读请求,后发送的写请求,此时也会优先处理写请求,然后再处理读请求。这就造成一个问题:一旦我发出若干个写请求,就会堵塞所有的读请求,直到写请求全都处理完,才有机会处理读请求。此时可以考虑使用max_write_lock_count: max_write_lock_count=2 有了这样的设置,当系统处理2个写操作后,就会暂停写操作,给读操作执行的机会。

low-priority-updates:

我们还可以更干脆点,直接降低写操作的优先级,给读操作更高的优先级。 low-priority-updates=1

综合来看,concurrent_insert=2是绝对推荐的,但是要定期optimize table. 至于max_write_lock_count=1和low-priority-updates=1,则视情况而定,如果可以降低写操作的优先级,则使用low-priority-updates=1,否则使用max_write_lock_count=2。

discuz中添加好友动态

  • Posted on February 22, 2010 at 7:23 pm

discuz 7.2 gbk版

原理:从index_feed里面过滤出好友的feed

修改模板目录里面的 index_navbar.htm
添加一行
<li{if $indexfile == ‘feeds’ && !$type && isset($_GET['modify_buddy']) }{/if}><a href=”$indexname?op=feeds&modify_buddy=1″><span>好友动态</span></a></li>

修改include/index_feeds.inc.php
62 if(!$type) {
63         $view = empty($view) ? 0 : 1;
64         $conf = array(
65                 ‘num’ => 50,
66                 ‘cachelife’ => 300,
67                 ‘multipage’ => $view,
68                 ‘page_url’ => $indexname.(!empty($view) ? ‘?view=all&op=feeds’ : ”)
69         );
70         if (isset($_GET['modify_buddy']))
71         {
72                 include_once DISCUZ_ROOT.’./uc_client/client.php’;
73                 $modify_buddy_list = array();
74                 $modify_buddy_list = uc_friend_ls($discuz_uid, 1, 100, 100, 0);
75                 foreach ($modify_buddy_list as $modify_k=>$modify_v)
76                 {
77                         $conf['uid'][] = $modify_v['friendid'];
78                 }
79         }

限制discuz贴子标题的最小字数

  • Posted on February 19, 2010 at 6:48 pm

discuz 7.2 gbk版

disucz帖子的标题是长度极限是80个字(节),中文和英文都是一样的。
要控制发帖的最小标题长度,只能修改程序。
打开include/post.func.php文件:搜索80 会看到
global $subject, $message, $disablepostctrl, $minpostsize, $maxpostsize;
if(strlen($subject) > 80 ) {

加一行  global  $action;
然后改一下第二行为:
if(strlen($subject)>80 || ($action==’newthread’ && strlen($subject)<6) ){

可能有的同学想偷懒,干脆直接写成 if(strlen($subject)>80 || $strlen($subject) < 6 ) {

这样修改的话,如果原来已经有标题长度<6的贴子,在回贴操作的时候,会进入这个if, 就无法回贴了!  所以一定要检测一下$action,只有在发新贴的时候,才进行长度检测。

除此之外,还要修改语言包的提示:
打开templates/default/messages.lang.php,找到post_subject_toolong
将后面的提示修改为:标题字数应在 6-80 之间,请返回修改标题长度
注意:不要改变这个文件的字符编码(GBK,UTF8)。

Top