目录

PHP是最好的Web开发语言

PHP 5.4升级实战

切记要根据业务需求,适当考虑php升级及扩展模块的兼容性,盲目升级无意义

软件版本选择

软件名版本号理由
gearmand0.18再往上的版本,对c++ boost库要求>1.39,Centos 5.7不支持
memcached1.4.13可以使用最新版本
libmemcached0.530.53 release from the 1.0 series released
scws1.2.0最新版本
xcache2.0.0最新版本
gearman0.8.1php扩展,只能用此系列的最后版本号,否则libgearman>0.21
memcached2.0.1php扩展,只能上最新版本,否则不兼容php5.4
memcache3.0.6php扩展,只能用最新的beta版本,否则不兼容php5.4

php 5.4.x编译选项

#!/bin/sh
_server_root="/opt/php"
 
PEAR_INSTALLDIR=/usr/share/pear
export PEAR_INSTALLDIR
 
phpconfig="--prefix=$_server_root \
        --with-layout=GNU \
        --disable-debug \
        --enable-ftp \
        --enable-inline-optimization \
        --enable-magic-quotes \
        --enable-mbstring \
        --enable-mm=shared \
        --enable-safe-mode \
        --enable-trans-sid \
        --enable-xml \
        --with-dom \
        --with-curl \
        --with-xsl \
        --with-jpeg-dir \
        --with-png-dir \
        --with-tiff-dir \
        --with-zlib-dir \
        --with-gettext \
        --with-regex=system \
        --with-xml \
        --enable-bcmath \
        --with-gd=shared \
        --with-freetype-dir \
        --enable-gd-native-ttf \
        --without-pdo-sqlite \
        --without-sqlite \
        --without-ldap \
        --without-ldap-sasl \
        --enable-pcntl \
        --enable-sockets \
        --with-mcrypt \
        --enable-soap \
        --enable-libxml \
        --with-mysql=mysqlnd \
        --with-mysqli=mysqlnd \
        --with-pdo-mysql=mysqlnd \
        --enable-zip \
        --enable-fastcgi \
        --enable-cgi \
        --enable-discard-path \
        --enable-force-cgi-redirect \
        --enable-cli \
        --enable-fpm \
        --with-fpm-user=nobody \
        --with-fpm-group=nobody \
        --with-libevent \
        "
 
./configure $phpconfig

php-fpm配置

变化不大,格式从xml转变成ini格式

php.ini配置

short_open_tag = On
max_execution_time = 90
max_input_time = 120
max_input_vars = 300
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
post_max_size = 8M
 
extension_dir = "/opt/php/lib/"
extension="gd.so"
extension="xcache.so"
extension="scws.so"
extension="gearman.so"
extension="memcache.so"
extension="memcached.so"
;extension="zip.so"
;extension="pdo_mysql.so"
;extension="geoip.so"
;extension="mongo.so"
;zend_extension="/opt/php/lib/ZendOptimizer.so"
 
cgi.force_redirect = 0
cgi.fix_pathinfo = 0
file_uploads = On
upload_max_filesize = 8M
max_file_uploads = 5
allow_url_fopen = Off
allow_url_include = Off
 
date.timezone = Asia/Shanghai
session.name = YGXSID
 
[xcache.admin]
xcache.admin.enable_auth = On
xcache.admin.user = "admin"
; Change xcache.admin.pass to the MD5 fingerprint of your password
; Use md5 -s "your_secret_password" to find the fingerprint
xcache.admin.pass = "0d6790ac6338e89139ff37a1ef3bc97a"
 
[xcache]
xcache.shm_scheme =        "mmap"
xcache.size  =               32M
xcache.count =               8
xcache.slots =                8K
xcache.ttl   =                 0
xcache.gc_interval =           0
xcache.var_size  =           32M
xcache.var_count =             1
xcache.var_slots =            8K
xcache.var_ttl   =             0
xcache.var_maxttl   =          0
xcache.var_gc_interval =       0
xcache.test =                Off
xcache.readonly_protection = Off
xcache.mmap_path =    "zero"
xcache.coredump_directory =   ""
xcache.cacher =              Off
xcache.stat   =              Off
xcache.optimizer =           Off
 
[xcache.coverager]
xcache.coverager =          Off
xcache.coveragedump_directory = ""
include_path = ".:/home/html/publiclib"

因为使用include_path和相对路径的情况下, 性能会和寻找的次数有关,所以, 在能使用绝对路径的情况下最好使用绝对路径.

在模块化的系统设计中, 一般应该在模块内, 通过获取模块的部署路径(dirname(FILE), php5.3以后更是提供了DIR常量)从而使用绝对路径.

php-fpm启动脚本

#php_fpm_BIN=/opt/php/bin/php-cgi
php_fpm_BIN=/opt/php/sbin/php-fpm
php_fpm_CONF=/opt/php/etc/php-fpm.conf
 
php_opts="--fpm-config $php_fpm_CONF"
 
#$php_fpm_BIN --fpm $php_opts
$php_fpm_BIN $php_opts

PHP 5.4不兼容问题列举

参考文档

mysqlnd接口不兼容旧密码

mysqlnd接口性能提高

my.cnf

old_passwords=0
 
mysql>update user set Password=PASSWORD('secret');
mysql>flush privileges;

PHP5.4 Fatal error: Call-time pass-by-reference

PHP 5.4 Call-time pass-by-reference

// Right way!
function myFunc(&$arg) { }
myFunc($var);
 
// Wrong way!
function myFunc($arg) { }
myFunc(&$arg);

getaddrinfo failed: Name or service not known

php_network_getaddresses: getaddrinfo failed: Name or service not known in 
 
/hom/html/publiclib/Library/class/memcache.class.php on line 22

ereg和ereg_replace函数不提供支持

if ($noreplace == ""){
	//while (ereg ('{([a-zA-Z0-9_-]+)}', $sql, $regs)) {
	while (preg_match ('/{([a-zA-Z0-9_-]+)}/', $sql, $regs)) {
	$found = $regs[1];
	//$sql = ereg_replace("\{".$found."\}",$this->db_prefix.$found, $sql);
	$sql = preg_replace("/\{".$found."\}/",$this->db_prefix.$found, $sql);
	}
}

session_register不再提供兼容支持

PHP4.2以上版本不需要用session_register()注册,直接可以使用$_SESSION变量
 
//session_register("valicode"); 

foreach用法修改

foreach($records->records as $q)
==》
foreach ($records->records as $k => $q)

PHP 8.3 心血来潮之实践

作为一个充满激情的开发人员,我很高兴地见证了PHP这个广受赞誉的服务器端脚本语言在过去二十年中的发展。

PHP 8.x简介

PHP 8.x系列始于2020年11月26日发布的PHP 8.0,随后是2021年11月25日发布的PHP 8.1。这些版本引入了几个突破性的功能,以及实质性的性能改进,对Web开发环境产生了积极的影响。

PHP 8.0中值得注意的特性包括

  1. 即时(JIT)查询器
  2. 属性(也称为注释)
  3. 命名参数
  4. nullsafe运算符
  5. 匹配表达式

PHP 8.1继续构建在PHP 8.0奠定的坚实基础上,引入了新的特性,如

  1. 枚举
  2. 只读属性
  3. 协程(为了更好的并发支持)
  4. 新的语法改进,如使用字符串键和第一类可调用的数组解包。

PHP 8.2引入了许多新特性,包括:

  1. Co-routines:Co-routines是一个新特性,它允许PHP开发人员编写并发代码,而不需要线程。
  2. 联合类型:联合类型是一个新特性,允许PHP开发人员定义一个变量来保存一组类型中的任何一个。
  3. 改进的错误处理:PHP 8.2对错误处理进行了许多改进,包括更好的错误消息和更优雅地处理错误的能力。

尝鲜源码编译

./configure --prefix=/opt/php8310 --enable-mbstring=shared --enable-fpm --with-fpm-systemd \
--with-openssl --with-zlib --with-bz2 --enable-gd --with-jpeg --enable-intl

PHP防止SQL注入攻击的方法

参考资料: http://php.net/manual/en/security.database.sql-injection.php

<?php
class secure
{
    function secureSuperGlobalGET(&$value, $key)
    {
        $_GET[$key] = htmlspecialchars(stripslashes($_GET[$key]));
        $_GET[$key] = str_ireplace("script", "blocked", $_GET[$key]);
        $_GET[$key] = mysql_escape_string($_GET[$key]);
        return $_GET[$key];
    }
 
    function secureSuperGlobalPOST(&$value, $key)
    {
        $_POST[$key] = htmlspecialchars(stripslashes($_POST[$key]));
        $_POST[$key] = str_ireplace("script", "blocked", $_POST[$key]);
        $_POST[$key] = mysql_escape_string($_POST[$key]);
        return $_POST[$key];
    }
 
    function secureGlobals()
    {
        array_walk($_GET, array($this, 'secureSuperGlobalGET'));
        array_walk($_POST, array($this, 'secureSuperGlobalPOST'));
    }
}
?>

用php从yahoo网页获取股票数据

过下准备写个股票机械交易系统,先搞掂数据采集这部分先,做了个用php从yahoo获取股票数据的例子, 运行在shell下,其实php做shell几好用的.

以下为源代码:

gupiao.php , 获取600808马钢股份的数据.

<?php
include “Snoopy.class.inc”;
 
$url=”http://finance.cn.yahoo.com/q?s=600808.ss”;
 
$snoopy = new Snoopy;
$snoopy->agent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1);
$snoopy->fetch($url);
$getstr=$snoopy->results;
$getstr=trim($getstr);
 
if($getstr==")
{
print “No Data”;
print “\n”;
exit;
}
 
$str=mycut(”<span id=\”top_date\”>”,”<div class=\”ft\”>”,$getstr);
$pieces = explode(”</span>”, $str);
$ftime=$pieces[0];
$ftime=trim($ftime);
print “时间: “.$ftime;
print “\n”;
 
$stra=mycut(”最新价:”,”</”,$str);
$stra=$stra.”</”;
//print $stra;
$stra=mycut(”>”,”</”,$stra);
print “最新价: “.$stra;
print “\n”;
 
$strb=mycut(”今开盘:”,”</”,$str);
$strb=$strb.”</”;
$strb=mycut(”>”,”</”,$strb);
print “开盘价: “.$strb;
print “\n”;
 
$strc=mycut(”最高价:”,”</”,$str);
$strc=$strc.”</”;
$strc=mycut(”>”,”</”,$strc);
print “最高价: “.$strc;
print “\n”;
 
$strd=mycut(”最低价:”,”</li>”,$str);
$strd=mycut(”>”,”</”,$strd);
print “最低价: “.$strd;
print “\n”;
 
$stre=mycut(”前收盘:”,”</”,$str);
$stre=$stre.”</”;
$stre=mycut(”>”,”</”,$stre);
print “前收盘: “.$stre;
print “\n”;
function mycut($firststr,$laststr,$srcstr)
{
// $findstr=”";
 
$pos1 = strpos($srcstr, $firststr);
 
if ($pos1 === false)
{
return “”;
}
 
//print “pos1: “.$pos1.”\n”;
$pos2 = strpos($srcstr, $laststr, $pos1);
 
if ($pos2 === false)
{
return “”;
}
 
if ($pos2<$pos1)
{
return “”;
}
 
//print “pos2: “.$pos2.”\n”;
// $num=1;
$message=explode($firststr,$srcstr);
$message=explode($laststr,$message[1]);
 
return $message[0];
}
 
?>

还是用到php的Snoopy类, 在shell状态下输入php -q gupiao.php就可以执行,当然也可以运行在web下.

ShareTronix

sharetronix是一个开源的php微博系统,其功能之完善令人叫绝,最基本的发微博、转发、评论、好友关注、微博内嵌图片、视频、音乐等自 然不在话下,甚至群组、权限管理、多语言,移动设备访问都一应俱全,而且部署安装过程非常简单,即使不做任何修改,安装之后即刻就能上线一个“五脏俱全” 的微博平台。

server {
        listen 80;
        server_name weibo.152153.com;
        root /usr/yupoo/app/sharetronix.3.1.1;
        if ( -d $request_filename ){
                rewrite (.*) $1/index.php break;
        }
        if (-f $request_filename) {
                break;
        }
        location / {
                try_files $uri /index.php?$args;
        }
        location ~ .*\.(php|php5)?$ {
                fastcgi_pass 9900.php.com;
                include common/fastcgi_params;
        }
        location ~ .*\.(js|css|gif|jpg|jpeg|png|bmp|swf|html|htm|xml|txt|ico|cur|crx|xpi)$ {
                expires 7d;
                access_log off;
        }
        access_log /usr/yupoo/logs/sharetronix.3.1.1/access.log main;
        error_log /usr/yupoo/logs/sharetronix.3.1.1/error.log;
}

php大量session存储到内存中、散列及过期回收

一台服务器流量比较大,因为程序的需要,session的过期时间设置的是3小时,导致/tmp下堆积了近20万的session文件。进而导致内核占用的cpu急剧上升。因为session的读写涉及到大量小文件的随机读写,并且是集中在一个目录下,iowait也急剧升高。

第一步,考虑将session放入内存中

最简单的办法莫过于将/tmp挂载为 tmpfs文件系统,也就是内存中。

具体见 使用内存作linux下的临时文件夹

第二步,将session存储到不通的目录中。

php本身支持session的多级散列

在php.ini中,将

;session.save_path = /tmp 

改为

session.save_path = "2;/tmp/session"

表示将session存储到 /tmp/session这个文件夹中,并且是用2及散列。保存退出,等第三步结束后重启php

第三步,创建session存储文件夹

php并不会自动去创建这些文件夹,不过在源文件中提供了一些创建文件夹的脚本。下面这个脚本也好用

#!/bin/sh
I="0 1 2 3 4 5 6 7 8 9 a b c d e f"
for acm in $I;do
  for x in $I;do
    mkdir -p /tmp/session/$acm/$x
  done
done
 
chown -R nobody:nobody /tmp/session
chmod -R 1777 /tmp/session

因为/tmp是用的内存,服务器重启后,里面的所有文件都会丢失,所以,需要把上面的脚本加入到 /etc/rc.local中,并且要放在启动php之前

第四步,session的回收

session在经过session.gc_maxlifetime后会过期,但并不会马上被删除,时间长了以后会造成/tmp空间占用很大。具体的删除算法懒得去研究。

下面这个命令可以删除过期的session,我这里定义的过期时间是3小时

find /tmp/session  -amin +180 -exec rm -rf {} \;

放入cron中,10分钟执行一次,完事。

为php安装额外的模块

有时候我们需要动态加载一个模块,最简单的方法可以如下操作,以mime_magic模块为例:

cd php-4.4.4/ext/mime_magic/
/usr/local/bin/phpize
./configure –with-mime-magic –with-php-config=/usr/local/bin/php-config
make -j 16
make install

接着修改php.ini,将原先的:

extension_dir = “./” 

去掉,换成如下的:

extension_dir = “/usr/local/lib/php/extensions/no-debug-non-zts-20020429/”

并加上:

extension=mime_magic.so 

最后重起apache即可,简单吧:)

PHP下设置时区

PHP5.2.4之前的版本无需设置时区。下面是修改PHP时区的三个办法。

1、修改PHP.ini这个文件

找到date.timezone这行,去掉前面的分号,改成:

date.timezone = Asia/Shanghai

2、修改 .htaccess文件

修改.htaccess文件有两种办法,下面的两条语句只要有一条即可

php_value date.timezone Asia/Shanghai
SetEnv TZ Asia/Shanghai

3、修改PHP代码

也是下面的两条语句只要其中的一句即可

date_default_timezone_set('Asia/Shanghai');
ini_set('date.timezone','Asia/Shanghai');

php上传文件的设置

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;
 
; Whether to allow HTTP file uploads.
file_uploads = On
 
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =
 
; Maximum allowed size for uploaded files.
upload_max_filesize = 80M
 
;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;
 
max_execution_time = 3600; Maximum execution time of each script, in seconds
max_input_time = 3600; Maximum amount of time each script may spend parsing request data
memory_limit = 100M ; Maximum amount of memory a script may consume (8MB)
 
; Maximum size of POST data that PHP will accept.
post_max_size = 80M

uploadmaxfilesize: 这是上传单一档案的大小限制,譬如我若允许上传超过20MB的影片档,那这数值就必须至少大于「20M」才可以。

postmaxsize: PHP允许一次上传档案的大小限制,若我一次要上传2个15MB的影片档,那麽这个数值就必须至少大于「30M」了。

postmaxsize 必须大于 uploadmaxfilesize

memory_limit: 执行每个scripts时使用的memory大小限制

memorylimit 必须大于 postmax_size

这三个数值的大小,根据php官方manual的要求,必须是 memorylimit > postmaxsize > uploadmax_filesize

确保 PHP 应用程序的安全

  • 使用 mysql_real_escape_string() 防止 SQL 注入问题。
  • 使用正则表达式过滤字符串 和 strlen() 来确保 GET 数据未被篡改。
  • 使用正则表达式过滤字符串 和 strlen() 来确保用户提交的数据不会使内存缓冲区溢出。
  • 使用 strip_tags() 和 htmlspecialchars() 防止用户提交可能有害的 HTML 标记。
  • 避免系统被 Tamper Data 这样的工具突破。
  • 重写功能,使用更安全的专用表单处理函数,避免使用隐藏表单变量。
  • 使用 md5() 或其他加密机制对隐藏表单变量中的表名或其他敏感信息进行加密。在 PHP 端不要忘记对它们进行解密。
  • 通过使用缩写或昵称让值的含义模糊,在 PHP 表单处理函数中再对这些值进行转换。例如,如果要引用 users 表,可以用 u 或任意字符串(比如 u8y90x0jkL)来引用它。
  • 使用惟一的令牌防止用户向服务器远程提交表单。

将用户可操作的文件限制在某目录下

open_basedir可将用户访问文件的活动范围限制在指定的区域,通常是其家目录的路径,也可用符号“.”来代表当前目录。

注意用open_basedir指定的限制实际上是前缀,而不是目录名。

举例来说:

若"open_basedir = /dir/user", 那么目录 "/dir/user" 和 "/dir/user1"都是可以访问的。

所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。例如设置成:

"open_basedir = /dir/user/"

openbasedir也可以同时设置多个目录, 在Windows中用分号分隔目录,在任何其它系统中用冒号分隔目录。当其作用于Apache模块时,父目录中的openbasedir路径自动被继承。

防止php木马

1.防止php木马执行webshell

  1. 打开safe_mode
  2. 在php.ini中设置
disable_functions = system,passthru,shell_exec,exec, proc_open,popen

二者选一即可,也可都选  

2.防止php木马读写文件目录 

在php.ini中的

disable_functions= passthru,exec,shell_exec,system   

后面加上php处理文件的函数,主要有

fopen,mkdir,rmdir,chmod,unlink,dir 
fopen,fread,fclose,fwrite,file_exists 
closedir,is_dir,readdir.opendir 
fileperms.copy,unlink,delfile 

即成为

disable_functions=passthru,exec,shell_exec,system,fopen,mkdir,rmdir,chmod,unlink,dir,fopen,fread,fclose,fwrite,file_exists,closedir,is_dir,readdir.opendir,fileperms.copy,unlink,delfile

ok,大功告成,php木马拿我们没辙了,^_^

遗憾的是这样的话,利用文本数据库的那些东西就都不能用了。 

PHP防止SQL注入攻击的方法

参考资料: http://php.net/manual/en/security.database.sql-injection.php

<?php
class secure
{
    function secureSuperGlobalGET(&$value, $key)
    {
        $_GET[$key] = htmlspecialchars(stripslashes($_GET[$key]));
        $_GET[$key] = str_ireplace("script", "blocked", $_GET[$key]);
        $_GET[$key] = mysql_escape_string($_GET[$key]);
        return $_GET[$key];
    }
 
    function secureSuperGlobalPOST(&$value, $key)
    {
        $_POST[$key] = htmlspecialchars(stripslashes($_POST[$key]));
        $_POST[$key] = str_ireplace("script", "blocked", $_POST[$key]);
        $_POST[$key] = mysql_escape_string($_POST[$key]);
        return $_POST[$key];
    }
 
    function secureGlobals()
    {
        array_walk($_GET, array($this, 'secureSuperGlobalGET'));
        array_walk($_POST, array($this, 'secureSuperGlobalPOST'));
    }
}
?>

用PHP脚本自动把纯文本文件转换成Web页面

Green for Mars!

John R. Doe

The idea of little green men from Mars, long a staple of science fiction, may soon turn out to be less fantasy and more fact. Recent samples sent by the latest Mars exploration team indicate a high presence of chlorophyll in the atmosphere. Chlorophyll, you will recall, is what makes plants green. It’s quite likely, therefore, that organisms on Mars will have, through continued exposure to the green stuff, developed a greenish tinge on their outer exoskeleton.

An interview with Dr. Rushel Bunter, the head of ASDA’s Mars Colonization Project blah blah…

What does this mean for you? Well, it means blah blahblah…

相当标准的文本:

它有一个标题、一个署名和很多段的文字。把这篇文档转换成为HTML真正需要做的是使用HTML的分行和分段标记把原文的布局保留在Web页面上。特殊的标点符号需要被转换成为对应的HTML符号,超链接需要变得可以点击。

下面的PHP代码就会完成上面所有的任务:

<?php
// set source file name and path
$source = "toi200686.txt";
// read raw text as array
$raw = file($source) or die("Cannot read file");
// retrieve first and second lines (title and author)
$slug = array_shift($raw);
$byline = array_shift($raw);
 
// join remaining data into string
$data = join('', $raw);
 
// replace special characters with HTML entities
// replace line breaks with <br />
$html = nl2br(htmlspecialchars($data));
 
// replace multiple spaces with single spaces
$html = preg_replace('/ss+/', ' ', $html);
 
// replace URLs with <a href...> elements
$html = preg_replace('/s(w+://)(S+)/', ' <a href="12" target="_blank">12</a>', $html);
 
// start building output page
// add page header
$output =<<< HEADER
<html>
<head>
<style>
.slug {font-size: 15pt; font-weight: bold}
.byline { font-style: italic }
</style>
</head>
<body>
HEADER;
 
// add page content
$output .= "<div class='slug'>$slug</div>";
$output .= "<div class='byline'>By $byline</div><p />";
$output .= "<div>$html</div>";
 
// add page footer
$output .=<<< FOOTER
</body>
</html>
FOOTER;
// display in browser
echo $output;
 
// AND/OR 
// write output to a new .html file
file_put_contents(basename($source, substr($source, strpos($source, '.'))) . ".html", $output) or die("Cannot write file");
?>

很赞的PHP字符串加密函数

/**
* @param string $string 原文或者密文
* @param string $operation 操作(ENCODE | DECODE), 默认为 DECODE
* @param string $key 密钥
* @param int $expiry 密文有效期, 加密时候有效, 单位 秒,0 为永久有效
* @return string 处理后的 原文或者 经过 base64_encode 处理后的密文
*
* @example
*
*  $a = authcode('abc', 'ENCODE', 'key');
*  $b = authcode($a, 'DECODE', 'key');  // $b(abc)
*
*  $a = authcode('abc', 'ENCODE', 'key', 3600);
*  $b = authcode('abc', 'DECODE', 'key'); // 在一个小时内,$b(abc),否则 $b 为空
*/
 
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 3600) {
        $ckey_length = 4;
        // 随机密钥长度 取值 0-32;
        // 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
        // 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
       // 当此值为 0 时,则不产生随机密钥
        $key = md5($key ? $key : 'default_key');  //这里可以填写默认key值
        $keya = md5(substr($key, 0, 16));
        $keyb = md5(substr($key, 16, 16));
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
        $cryptkey = $keya.md5($keya.$keyc);
        $key_length = strlen($cryptkey);
 
        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
        $string_length = strlen($string);
 
        $result = '';
        $box = range(0, 255);
 
        $rndkey = array();
        for($i = 0; $i <= 255; $i++) {
                $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
 
        for($j = $i = 0; $i < 256; $i++) {
             $j = ($j + $box[$i] + $rndkey[$i]) % 256;
             $tmp = $box[$i];
             $box[$i] = $box[$j];
             $box[$j] = $tmp;
         }
 
         for($a = $j = $i = 0; $i < $string_length; $i++) {
             $a = ($a + 1) % 256;
             $j = ($j + $box[$a]) % 256;
             $tmp = $box[$a];
             $box[$a] = $box[$j];
             $box[$j] = $tmp;
             $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
         }
         if($operation == 'DECODE') {
             if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
                 return substr($result, 26);
             } else {
                 return '';
             }
         } else {
             return $keyc.str_replace('=', '', base64_encode($result));
         }
 
     }
 
$a = authcode('abc', 'ENCODE', 'key');
$b = authcode($a, 'DECODE', 'key');  // $b(abc)
echo $a."\n";
echo $b."\n";

php的替换一次的str_replace函数

为了方便做seo用的, 把内页的关键字替换带链接的关键词指向首页,所以不能全替换,只替换一次:

php原来的str_replace函数是替换全部的,不能用,所以在网上找高人已写好的。

php的替换一次的函数:

function str_replace_once($needle, $replace, $haystack) {
$pos = strpos($haystack, $needle);
if ($pos === false) {
return $haystack;
}
return substr_replace($haystack, $replace, $pos, strlen($needle));
}

最后的就是应用效果不错.

php的Snoopy的类实在太好用了

以前总是自己用php代码模拟浏览器,总是写不好,当然我这种非专业出身就是学不好.

最近在写一个抓取Amazon商品php代码时,无意中从搜索引擎搜到的.那个Snoopy这个类实在太好用了, 记录一下怎样使用.

snoopy是一个php类,用来模仿web浏览器的功能,它能完成获取网页内容和发送表单的任务。

下面是它的一些特征:

  1. 方便抓取网页的内容
  2. 方便抓取网页的文字(去掉HTML代码)
  3. 方便抓取网页的链接
  4. 支持代理主机
  5. 支持基本的用户/密码认证模式
  6. 支持自定义用户agent,referer,cookies和header内容
  7. 支持浏览器转向,并能控制转向深度
  8. 能把网页中的链接扩展成高质量的url(默认)
  9. 方便提交数据并且获取返回值
  10. 支持跟踪HTML框架(v0.92增加)
  11. 支持再转向的时候传递cookies

下面是简单的例子

抓取我的blog的内容

<?php
include “Snoopy.class.php”;
$snoopy = new Snoopy;
$snoopy->fetch(“http://www.lpfrx.com”);
echo $snoopy->results;
?>

抓取我的blog的文字

<?php
include “Snoopy.class.php”;
$snoopy = new Snoopy;
$snoopy->fetchtext(“http://www.lpfrx.com”);
echo $snoopy->results;
?>

抓取链接

<?php
include “Snoopy.class.php”;
$snoopy = new Snoopy;
$snoopy->fetchlinks(“http://www.lpfrx.com”);
print_r($snoopy->results);

原来之前做的php抓取RSS里的MagpieRSS类也用到了,以后可以Snoopy做抓取,应该说采集时就爽了.

关于php-cgi 的 SIGSEGV 错误的一些想法

SIGSEGV信号一般表示

SIGSEGV --- Segment Fault. The possible cases of your encountering this error are: 
1.buffer overflow --- usually caused by a pointer reference out of range. 
2.stack overflow --- please keep in mind that the default stack size is 8192K. 
3.illegal file access --- file operations are forbidden on our judge system

其中的第三条,跟本问题的关系比较大。也就是php-cgi访问了一个不存在的或者没有权限访问的文件

我用的php-fpm补丁是0.5.8版的,按照一些说法,只要设置了

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;

之后,php-cgi如果找不到文件或者没有权限访问的话 会提示No input file specified. 或者Access denied.

问题到这里似乎又陷入了僵局

后来又在php.ini中找到了php-cgi的一个参数 cgi.fix_pathinfo

cgi.fix_pathinfo  boolean

对 CGI 提供了真正的 PATHINFO/PATHTRANSLATED 支持。

以前 PHP 的行为是将 PATHTRANSLATED 设为 SCRIPTFILENAME,而不管 PATH_INFO 是什么。

将此值设为 1 将使 PHP CGI 修正其路径以遵守规格。设为 0 将使 PHP 的行为和从前一样。默认为零。用户应该修正其脚本使用 SCRIPTFILENAME 而不是PATHTRANSLATED。

把这个参数的值设置为1 ,cgi会多做一些检查,来判断请求的路径中,那部分是文件名,哪部分是路径名

下面是google groups上的一段话

when cgi.fixpathinfo was set to “1” it caused a lot of checks in order to find which part of SCRIPTFILENAME is a file name and which is PATHINFO. In case of missing file it caused NULL in pathtranslated, which caused the crash.

PHP截取中文字符串方法(简单实用)

由于网站首页以及vTigerCRM里经常在截取中文字符串时出现乱码(使用substr),今天找到一个比较好的截取中文字符串方法,在此与大家共享。

function msubstr($str, $start, $len) {
  $tmpstr = "";
  $strlen = $start + $len;
  for($i = 0; $i < $strlen; $i++) {
    if(ord(substr($str, $i, 1)) > 0xa0) {
        $tmpstr .= substr($str, $i, 2);
        $i++;
    } else
        $tmpstr .= substr($str, $i, 1);
  }
  return $tmpstr;
}

PHP MVC设计

MVC模式涉及到三类对象

例如用户点击删除文章按钮后,控制器调用操作文章的模型,删除掉指定文章,最后通过视图显示成功删除文章的提示信息。

MVC 模式最大的作用就是分离逻辑和表现

一个业务逻辑在模型中实现,而处理结果在视图中呈现。控制器则充当中间人,根据用户请求调用模型,然后把处理结果传递给视图。

MVC分离的许多好处

  1. 清晰的将应用程序分隔为独立的部分;
  2. 业务逻辑代码能够很方便的在多处重复使用;
  3. 方便开发人员分工协作;
  4. 可以方便开发人员对应用程序各个部分的代码进行测试。

MVC模式的调用流程图

MVC 模式的调用流程

PHP模板框架

Qeephp

http://qeephp.com/

Thinkphp

http://www.thinkphp.cn/

ClearSilver

http://www.geodata.soton.ac.uk/software/php_clearsilver/

Easy Template System

http://ets.sourceforge.net/

http://ets.sourceforge.net/ets.pdf

http://prdownloads.sourceforge.net/ets/ets305b.zip?download

Smarty

http://smarty.php.net/

FastTemplate

http://www.thewebmasters.net/php/FastTemplate.phtml

bTemplate

http://www.massassi.com/bTemplate/

ModeliXe

http://modelixe.phpedit.com/

UltraTemplate

http://www.ultratemplate.com/main.php

PHPTemplate

http://nutbar.chemlab.org/

PHPLib

http://sourceforge.net/projects/phplib

XTemplate

http://sourceforge.net/projects/xtpl/

SmartTemplate

http://www.smartphp.net/download.php/smarttemplate_1_0_2.zip

Yapster

http://yapter.sourceforge.net/

http://www.phpclasses.org/browse.html/class/37.html

Zend专辑

https://www.zend.com/codex.php?CID=332

SledgeHammer

http://sledgehammer.sourceforge.net/

PHPtemplater

phpSavant

http://phpsavant.com/

SmashTemplate

http://www.phpclasses.org/goto/browse.html/package/1401.html

PHPTMPL

http://www.lri.fr/~gk/PHPTMPL/

AwesomeTemplateEngine

http://www.pinkgoblin.com/index.php?view=scripts

Virtual Template

http://sourceforge.net/projects/vtemplate/

TemplateTamer工具

http://www.templatetamer.org

Phemplate

http://pukomuko.esu.lt/phemplate/

http://pukomuko.esu.lt/phemplate/phemplate.class.php.txt

Templates engine for PHP

http://sourceforge.net/projects/php-templates

YATS

http://yats.sourceforge.net

iTemplate

http://sourceforge.net/projects/itemplate

Cached Fast Template

http://zoned.net:8000/~xkahn/php/fasttemplate/

AvanTemplate

http://avantemplate.sourceforge.net/

PHPWidgets

http://www.northern.ca/projects/phpwidgets

缓存技术

PHP变量、$GLOBALS变量

在处理一个请求的过程中

$_SESSION

同一用户的所有会话 适合存放和当前用户相关的数据

Xcache,APC等

php或webserver的进程 在进程结束前有效

文件系统

限定在当前机器

数据库、memcache

只要访问到,没有限制;但memcache的数据没有持久化保存

SEO优化

1、模板选择

尽量选择 sidebar 位于页面右侧的模板,“搜索引擎蜘蛛”的运动轨迹是从上到下,从左到右,所以网站内容最好在左侧。

2、确保网页有关键词

确保网页 head 标签中有 keywords 和 description

<head>
<meta name="keywords" content="关键词1, 关键词2, 关键词3, ...">
<meta name="description" content="网页描述">
</head>

关键词(Keywords):

提示搜索引擎:本网站内容围绕这些词汇展开。因此 keywords 书写的关键是每个词都能在内容中找到相应的匹配才有利于排名。另外最好不要堆砌关键词,物极必反,Google 不喜欢这样…

描述(Description):

描述部分用简短的句子告诉搜索引擎和访问者关于本网页的主要内容。用该网站的核心关键词搜索后得到的搜索结果中,描述往往显示为标题后的几行描述文字。Description 一般被认为重要性在 title 和 keywords 之后。描述的书写要注意以下问题:

3、title 标签的优化

网页优化可以说是从 Title 开始的。在搜索结果中,每个抓取内容的第一行显示的文字就是该页的Title,同样在浏览器中打开一个页面,地址栏上方显示的也是该页的Title。因此,Title可谓一个页面的核心。对Title的书写要注意以下问题:

1、title 简短精炼,高度概括,含有关键词,而不是只有一个博客名。但关键词不宜过多,不要超过3个词组。博客的 title 通常以博客名 + 关键词为内容

2、前几个词对搜索引擎最重要,因此关键词位置尽量靠前。

3、最好将 title 组织成符合语法结构和阅读习惯的短句或短语,避免无意义的词组罗列式 title

4、将 single 和 page 页标题栏的标题内容提前

每一篇文章或者页面都有相应标题,它都会显示在浏览器的标题栏上。最好的显示方式如下:

文章或页面标题位于最前面,后面才是站点的标题——让“蜘蛛”第一时间知道这张网页是干嘛的。

<title>
<?php 
wp_title('');
if (is_search()) { ?> 搜索 <?php echo $s; } 
if ( !(is_404()) and (is_search()) or (is_single()) or (is_page()) or (function_exists('is_tag') and is_tag()) or (is_archive()) ) { ?> &raquo; <?php } 
?> 
<?php bloginfo('name'); ?>
</title>

Wordpress 中具体 title 标签的写法请参照上面。

另外优化 Title 和 Meta 标签,Wordpress 有一个 SEO ALL IN ONE 的插件很不错,值得一试!

5、使用更有效的永久链接形式

高性能网站性能指南

减少HTTP请求

  1. 图片地图来取代多个导航图片
  2. 合并脚本和样式表

使用CDN加速

添加Expires头

  1. Cache-Control: max-age=
  2. Expires:
缓存的不仅仅是图片,还有脚本,样式表和flash组件,但不应该包括html

使用压缩组件

  1. Content-Encoding: gzip
  2. Vary: Accept-Encoding 指定代理缓存多个版本请求

将样式表放在顶部

  1. 使用LINK标签将CSS放在文档HEAD中

将脚本放在底部

避免CSS表达式

  1. 禁用expression语法

引用外部js和css资源

  1. 将javascript和CSS放到外部文件中
虽然单从速度而言,内嵌比引用少了http请求,速度加快,但考虑进“缓存及重用”因素,则引用更有利。

减少DNS查找

  1. 设置 Keep-Alive 长连接
  2. 页面中引用不要超过2个域名
  3. 修改浏览器参数
DnsCacheTimeout   -> 30 m 
KeepAliveTimeout  -> 1 m
ServerInfoTimeout -> 2 m

精简javascript

  1. 使用JSMin
  2. 使用ShrinkSafe
ShrinkSafe除了与jsmin一样精简代码,还会缩短变量名,这会造成一定的混淆的风险,当两者在压缩时,几乎没什么差别,因此,建议JSMin精简代码更为可靠

避免重复脚本

  1. 重复脚本损伤性能:不必要的HTTP请求和执行js所浪费的时间

利用php来避免重复脚本

<?php
function insertScripts($jsfile){
  if(alreadyInserted($jsfile)){
     return;
  }
  pushInserted($jsfile);
 
  if(hasDependencies($jsfile)){
     $dependencies = getDependencies($jsfile);
     foreach($dependencies as $scripts){
       insertScripts($scripts);
     }
  }
  echo '<script type="text/javascript" src="'.$jsfile.'"></script>';
}
?>

配置或者移除Etag

PHP网页根据来访者的浏览器语言不同自动跳转中英文页面,当来访者浏览器语言是中文就进入中文版面,国外的用户默认浏览器不是中文的就跳转英文页面

PHP代码:

<?
    $lan = substr($HTTP_ACCEPT_LANGUAGE,0,5);
    if ($lan == "zh-cn")
          print("<meta http-equiv='refresh' content = '0;URL = gb/index.htm'>");
    else
          print("<meta http-equiv='refresh' content = '0;URL = en/index.htm'>");
?>

HTML网页根据来访这的浏览器语言不同自动跳转多语言页面 在 <head> </head> 之间加入如下代码:

<script> 
var type=navigator.appName 
if (type=="Netscape") 
var lang = navigator.language 
else 
var lang = navigator.userLanguage 
 
//cut down to first 2 chars of country code 
var lang = lang.substr(0,2) 
 
// 英语
if (lang == "en") 
window.location.replace('url') 
 
// 简体中文
else if (lang == "zh-cn") 
window.location.replace('url') 
 
// 繁体中文
else if (lang == "zh-tw") 
window.location.replace('url') 
 
// 德语
else if (lang == "de") 
window.location.replace('url') 
 
 
// 除上面所列的语言
else 
window.location.replace('url')
 
</script>

OrangeHRM

OrangeHRM是一套开源的人力资源管理系统,帮助企业管理公司的人力资源。OrangeHRM是开源的就是说你可以免费的的使用。OrangeHRM基于PHP MySQL平台搭建,有多个模块构成方便日后的功能扩展和升级。OrangeHRM是SourceForge非常热门的一个开源项目,备受国内外关注。

配置环境使用了Nginx+PHP-FPM,因为OrangeHRM使用了symfony这个框架,所以,对php-fastcgi模式要做些调整

server {
        listen 80;
        server_name hrm.152153.com;
        root /usr/yupoo/app/orangehrm-2.6.12.1;
 
        index index.html index.htm index.php;
        expires off;
        access_log /usr/yupoo/logs/orangehrm-2.6.12.1/access.log main;
        error_log /usr/yupoo/logs/orangehrm-2.6.12.1/error.log;
 
        location ~ ^(.+\.php)(.*)$ {
                fastcgi_pass 9900.php.com;
                include common/fastcgi_params;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
                fastcgi_param HTTPS off;
        }
}

用PHP输出静态页面的两种方法

第一种:利用模板

目前PHP的模板可以说是很多了,有功能强大的smarty,还有简单易用的smarttemplate等。它们每一种模板,都有一个获取输出内容的函数。我们生成静态页面的方法,就是利用了这个函数。用这个方法的优点是,代码比较清晰,可读性好。

这里我用smarty做例子,说明如何生成静态页

<?php
require('smarty/Smarty.class.php');
$t = new Smarty;
$t->assign("title","Hello World!");
$content = $t->fetch("templates/index.htm");
//这里的 fetch() 就是获取输出内容的函数,现在$content变量里面,就是要显示的内容了
$fp = fopen("archives/2005/05/19/0001.Html", "w");
fwrite($fp, $content);
fclose($fp);
?>

第二种:利用ob函数

这里用到的函数主要是 obstart(), obendflush(), obgetcontent(),其中obstart()是打开浏览器缓冲区的意思,打开缓冲后,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区,直到你使用了obendflush().而这里最重要的一个函数,就是obgetcontents(),这个函数的作用是获取缓冲区的内容,相当于上面的那个fetch(),道理一样的。

<?php
ob_start();
echo "Hello World!";
$content = ob_get_contents();//取得php页面输出的全部内容
$fp = fopen("archives/2005/05/19/0001.html", "w");
fwrite($fp, $content);
fclose($fp);
?>

PHP网页代理器

<?
$ver = "1.0.0";
$copy="<!-- nsTWP v$ver :: nst.void.ru -->
       <!-- Network security team -->
       <!-- Public version -->";
if(!$_GET['address']){
die("
<title>nsT web proxy $ver</title>
<body bgcolor=black>
<center>
<form method=get><span id=\"more-89\"></span>
<font face=verdana size=1 color=silver>
PHP Web proxy :: <a href=http://nst.e-nex.com style='text-decoration:none'>nst.e-nex.com</a>\\ 
Address: <input name=address size=50 style='border: 1px; background-color: #1A1A1A; color: green;' autocomplete=off>
\\ 
Expl: <b>nst.e-nex.com</b> or <b>some_web.net/cmd.php?cmd=ls -la</b>
\\ 
nsTWP v$ver
</form></font></center>\n
$copy
");
}else{
$address = $_GET['address'];
$php_self= $_SERVER['PHP_SELF'];
# v1.1 #
 
$x=$address;
$c=strlen($x);
if($x{0}.$x{1}.$x{2}.$x{3}.$x{4}.$x{5}.$x{6}=="http://"){
for($i=7; $i<$c; $i++){
        $total.=$x{$i};
        }
$address=$total;
}
# end of v1.1 #
 
$get_add = explode("/",$address,2);
if($_GET['address']){
 
$fp = @fsockopen($get_add[0], 80);
$out = "GET /$get_add[1] HTTP/1.0\r\n";
$out .= "Host: $get_add[0]\r\n";
$out .= "\r\n";
$out .= "Connection: Close\r\n\r\n";
for(fwrite($fp, $out);trim(fgets($fp)););
while (!feof($fp)) {
$info.=fgets($fp, 128);
}
fclose($fp);
 
$script_url=$php_self;
 
$web=$info;
preg_match_all("#\s(href|src|action|codebase|url)=([\"\'])?(.*?)([\"\'])?([\s\>])#i", $web, $matches, PREG_SET_ORDER);
foreach ($matches as $match)
{
$uri = trim($match[3]);
$fragment = ($hash_pos = strpos($uri, '#') !== false) ? '#' . substr($uri, $hash_pos) : '';
$addr=parse_url("http://".$address."/");
 
$path=pathinfo($addr['path']);
$path=$path['dirname'];
$path=str_replace("\\","",$path);
 
if(!eregi("$address",$uri) and !eregi("http://",$uri)){$uri="http://".$addr['host']."/$path/$uri";}
if(substr_count($uri, "http://".$addr['host']."/")>1){$uri=str_replace("http://".$addr['host']."/","",$uri); $uri="http://".$addr['host']."/$uri";}
 
$url=$uri;
$c=strlen($url);
for($i=0; $i<$c; $i++){
$cp=substr($url, $i, $i+1);
if(substr($url,$i-2,2)=="//" and substr($url,$i-3,3)!="://"){
$url=substr_replace($url, '', $i-2, 1);
}
}
$uri=$url;
 
$replace = ' ' . $match[1] . '=' . $match[2] . $script_url . '?address=' . $uri . $fragment . $match[4] . $match[5];
$web = str_replace($match[0], $replace, $web);
}
 
print $web;
} #end of go
}
?>

PHP上传文件类型彻底判断方案

/**
* 读取文件前几个字节 判断文件类型
*
* @return String
*/
function checkTitle($filename) {
$file     = fopen($filename, "rb");
$bin      = fread($file, 2); //只读2字节
fclose($file);
$strInfo  = @unpack("c2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
$fileType = '';
switch ($typeCode)
{
case 7790:
$fileType = 'exe';
break;
case 7784:
$fileType = 'midi';
break;
case 8297:
$fileType = 'rar';
break;
case 255216:
$fileType = 'jpg';
break;
case 7173:
$fileType = 'gif';
break;
case 6677:
$fileType = 'bmp';
break;
case 13780:
$fileType = 'png';
break;
default:
$fileType = 'unknown'.$typeCode;
}
//Fix
if ($strInfo['chars1']=='-1' && $strInfo['chars2']=='-40' ) {
return 'jpg';
}
if ($strInfo['chars1']=='-119' && $strInfo['chars2']=='80' ) {
return 'png';
}
return $fileType;
}

对于上传文件类型的判断,一直没有太好的办法,即使使用上面的代码,也有办法构造假的图片的,有人使用getimagesize来判断,不失为一种好办法:

if(in_array($attach['ext'], array('jpg', 'jpeg', 'gif', 'png', 'swf', 'bmp')) && function_exists('getimagesize') && !@getimagesize($target)) {
    @unlink($target);
    upload_error('post_attachment_ext_notallowed', $attacharray);
   }

PHP下载的ZIP包为乱码的解决方法

header('Content-Type: application/force-download');
header(“Content-Transfer-Encoding: binary”);

if($type == 'html' || $type =='htm')
{
  header('Content-Disposition: attachment; filename="'.$name.'"');
  echo file_get_contents(dirname(__FILE__).'/..'.$path);
}
else if($type == 'xls')
{
  header("Content-Type: application/vnd.ms-excel; charset=utf8");
  header("Content-Disposition: attachment; filename=$name");
  echo file_get_contents(dirname(__FILE__).'/..'.$path);
}
elseif($type == 'zip'){
        header('Content-Type: application/force-download');
        header("Content-Transfer-Encoding: binary");
        header("Content-Disposition: attachment; filename=$name");
        echo file_get_contents(dirname(__FILE__).'/..'.$path);
}
 
function get_file_type($name)
{
  if(strpos($name,".") === false)
  {
    return "";
  }
  else
  {
    $arr=explode('.', $name);
    return array_pop($arr);
  }
}

php定时跳转

<meta http-equiv="refresh" content="3; url=http://www.google.com">
<?php
header("refresh:3;url=http://www.google.com");
print('正在加载,请稍等...三秒后自动跳转!');
/*
@功能:等待指定的时间,然后再跳转到指定页面(代替html meta方式)
 
补充说明:
若等待时间为0,则与header("location:")等效。
*/
?>

用php实现BigPipe

参考资料 BigPipe学习研究

<!doctype>
<html>
<head>
	<meta charset="utf-8" />
	<title>php实现BigPipe</title>
</head>
<style>
</style>
<body>
	<div class="wrapper">
		<hr>
		<div class="section" id="con1">内容1,正在加载……</div>
		<hr>
		<div class="section" id="con2">内容2,正在加载……</div>
		<hr>
		<div class="section" id="con3">内容3,正在加载……</div>
		<hr>
	</div>
	<?php
		/*
		 * 输出缓存区
		 */
		function flush_now(){
			ob_flush();
			flush();
		}
		flush_now();
	?>
	<?php sleep(2);?>
		<script>
			document.getElementById("con1").innerHTML="====内容1====";
		</script>
	<?php flush_now()?>
 
	<?php sleep(2);?>
		<script>
			document.getElementById("con2").innerHTML="====内容2====";
		</script>
	<?php flush_now()?>
 
	<?php sleep(2);?>
		<script>
			document.getElementById("con3").innerHTML="====内容3====";
		</script>
	<?php flush_now()?>
</body>
</html>
最后,别忘了修改php.ini的:

output_buffering=4096

将用户可操作的文件限制在某目录下

open_basedir可将用户访问文件的活动范围限制在指定的区域,通常是其家目录的路径,也可用符号“.”来代表当前目录。

注意用open_basedir指定的限制实际上是前缀,而不是目录名。

举例来说:

若"open_basedir = /dir/user", 那么目录 "/dir/user" 和 "/dir/user1"都是可以访问的。

所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。例如设置成:

"open_basedir = /dir/user/"

openbasedir也可以同时设置多个目录, 在Windows中用分号分隔目录,在任何其它系统中用冒号分隔目录。当其作用于Apache模块时,父目录中的openbasedir路径自动被继承。

又拍云CDN的WEBPHP升级

上传并解压软件包

ansible -i lists_web_new WEB-HGH-8@8-* -m copy -a "src=vivi_php_5328.tgz dest=/root/" -f5 
ansible -i lists_web_new WEB-HGH-8@8-* -a "tar zxvf /root/vivi_php_5328.tgz -C /" -f5

启动服务

ansible -i lists_web_new WEB-HGH-8@8-*  -a "/usr/local/vivi/update_vivi.sh" -f2
ansible -i lists_web_new WEB-HGH-8@8-*  -a "/etc/init.d/php-fpm start;/etc/init.d/vivi config;/etc/init.d/vivi start" -f2
新增了 API→PHP-FPM 变量
NGINX_API_UPSTREAM_PHP="
192.168.1.220:9901
192.168.1.221:9901
192.168.1.222:9901
192.168.1.223:9901
192.168.1.224:9901
192.168.1.225:9901
192.168.1.226:9901
192.168.1.227:9901
"

配置LVS

LVS_VIP_CTC="183.129.206.168"
LVS_VIP_CNC="121.52.229.71"
 
### Keepalived used parameters
LVS_MASTER=Y
LVS_HOSTS_CTC="183.129.206.169 183.129.206.170 183.129.206.171 183.129.206.172"
LVS_HOSTS_CNC="121.52.229.72 121.52.229.73 121.52.229.74 121.52.229.75"
LVS_DEV="eth0"
ansible -i lists_web_new UPWEB-PHP-220 -m shell -a "chkconfig keepalived on" -f10
ansible -i lists_web_new UPWEB-PHP-221 -m shell -a "chkconfig keepalived on" -f10
ansible -i lists_web_new WEB-HGH-8@8-WY -m shell -a "sed -r -i -e '/LVS_VIP_CTC=/s:.*:LVS_VIP_CTC=\"183.129.206.168\":g' /etc/upyun.cfg" -f10
ansible -i lists_web_new WEB-HGH-8@8-WY -m shell -a "sed -r -i -e '/LVS_VIP_CNC=/s:.*:LVS_VIP_CNC=\"121.52.229.71\":g' /etc/upyun.cfg" -f10

防火墙规则

#!/bin/sh
IPT="/usr/local/iptables/sbin/iptables"
SSH_PORT=`awk '/^Port/{print $2}' /etc/ssh/sshd_config`
[ -z $SSH_PORT ] && SSH_PORT=22
 
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 1 > /proc/sys/net/ipv4/conf/default/send_redirects
 
start(){
        $IPT -F
        $IPT -P INPUT DROP
        NETWORK=`ifconfig |awk '/inet.*addr.*Mask/{split($2,a,":");print a[2]}'`
        for addr in $NETWORK;do
                if [[ $addr =~ "127.0.0.1" ]];then
                        NET=$addr
                elif [[ $addr =~ "192.168." ]];then
                        NET=$addr/16
                else
                        NET=$addr/24
                fi
                $IPT -A INPUT -s $NET -j ACCEPT
        done
        $IPT -A INPUT -p icmp -j ACCEPT
        $IPT -A INPUT -p tcp -m multiport --dports $SSH_PORT,80,443 -j ACCEPT
}
 
stop(){ 
        $IPT -F
        $IPT -P INPUT ACCEPT
}
 
case $1 in
        start)  
                start;;
        stop)   
                stop;;
        *)
                echo "$0 start|stop";;
esac

添加路由

ip ro add 192.168.0.0/16 via 192.168.1.1 dev eth1
ip ro fl ca

php发送outlook日程安排

<?php
$to="lighthuang@audividi.com";
$subject="A calendar email testing";
$message="";
 
$body="aaaa\\nbbb";
$from="From: postmaster <postmaster@audividi.com>";
$start="DTSTART:20071009T073000Z";
$end="DTEND:20071009T093000Z";
$location="LOCATION: http://192.168.3.6/";
$uid="UID:333333333333333333";
$delay="TRIGGER:-PT10M";
 
$headers=$from;
$headers .='
X-Message-Flag: =?gb2312?B?x+u08rXnu7A=?=
MIME-Version: 1.0
Content-Type: text/calendar; method=REQUEST;charset=utf-8
Content-Transfer-Encoding: 8bit
 
BEGIN:VCALENDAR
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:GeminisShao@audividi.com
ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:postmaster@audividi.com
ORGANIZER:MAILTO:peterwang@audividi.com
';
$headers .=$start."\n";
$headers .=$end."\n";
$headers .=$location;
$headers .='
TRANSP:OPAQUE
SEQUENCE:0
';
$headers .=$uid;
$headers .='
DTSTAMP:20070912T090711Z
DESCRIPTION:..:\n..:\n\n*~*~*~*~*~*~*~*~*~*\n\n';
$headers .=$body."\n";
$headers .="SUMMARY:".$subject;
$headers .='
PRIORITY:5
X-MICROSOFT-CDO-IMPORTANCE:1
CLASS:PUBLIC
X-MICROSOFT-CDO-IMPORTANCE:1
CLASS:PUBLIC
BEGIN:VALARM
';
$headers .=$delay;
$headers .='
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR
';
mail($to,$subject,$message,$headers);
?>