分类目录归档:PHP

PHP客户端使用.NET发布的WEB服务

Web服务相关知识在此不叙述,还有保证PHP SOAP扩展已开启。

.NET发布Web服务相当容易。步骤简单叙述如下:

1)在Visual Studio环境(2010为例)的资源管理器,右键点击网站项目,然后选“添加web引用”,弹出如下图框:

2)因为本地测试,选择“此解决方案中的Web服务”,然后选择已经建立好的.asmx文件(在此以Service.asmx为例)。

3)到此便建立好Web Service服务。例:http://localhost:3395/WebSite2/Service.asmx

App_Code/Service.cs代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

///
///MyWebService 的摘要说明
///
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService {
    public Service () {
        //如果使用设计的组件,请取消注释以下行
        //InitializeComponent();
    }

    [WebMethod(Description = "This is a test"]
    public string getName(string name) {
        return "This is " + name;
    }
}

 

现在由PHP SOAP扩展使用该Web服务:

$wsdl = "http://localhost:3395/WebSite2/Service.asmx?wsdl";
$client = new SoapClient($wsdl, array('trace' => true));

// 传递函数
$params = array('name' => 'php');
$ret = $client->__soapCall('getName', array('parameters' => $params));

echo $ret->getNameResult  // 最后打印: This is PHP

因为不同的程序通信,这里必须用soapCall()方法调用一个SOAP操作。调用后可以在WSDL(http://localhost:3395/WebSite2/Service.asmx?wsdl)查找其自动产生的属性或方法。

PHP 5.4.0 正式版发布

PHP开发团队很荣幸的宣布PHP 5.4.0的发布。这个版本在5.x系列基础上有很大的飞跃,此版本包括很多的新的功能,同时也修复了许多的bug.

一些主要的功能包括:traits缩短数组语法特性(a shortened array syntax)用于测试的内置web服务器(a built-in webserver for testing purposes)。PHP5.4.0显著的提高了性能和内存,修复了超过100个的bug.

PHP解析大型XML文档

PHP中有两种主要的XML解析器

1)基于树的解析器。它是把整个文档存储为树的数据结构中,即需要把整个文档都加载到内存中才能工作。所以,当处理大型XML文档时候,性能剧减。SimpleXML和DOM扩展属于此类型解析器。

2)基于流的解析器。它不会一次把整个文档加载到内存中,而是每次分别读取其中的一个节点并允许实时与之交互(当移向下一个节点时,上一个节点是被丢弃,但也设置为保留)。很明显,其效率要高且占内存少,不便之处代码量大点。

所以,PHP中处理大型XML文档可以用XMLReader扩展方案(基于流的解析器)。它在PHP 5.1中默认是启用的。

举例:

// 创建对象
$reader = new XMLReader();

// 从一个文档或URL中加载XML数据
$reader->open('filename.xml');
// 或从变量加载
$reader->XML($document);

// 遍历
while($reader->read()) {
  // statement
}

XMLReader节点类型值:

节点类型说明
XMLReader::NONE非节点类型
XMLReader::ELEMENT开始元素
XMLReader::ATTRIBUTE属性节点
XMLReader::TEXT文本节点
XMLReader::CDATACDATA节点
XMLReader::ENTITY_REF实体引用节点
XMLReader::ENTITY实体声明节点
XMLReader::PI处理指令节点
XMLReader::COMMENT注释节点
XMLReader::DOC文档节点
XMLReader::DOC_TYPE文档类型节点
XMLReader::DOC_FRAGMENT文档片段节点
XMLReader::NOTATION符号节点
XMLReader::WHITESPACE空白节点
XMLReader::SIGNFICANT_WHITESPACE显著空白节点
XMLReader::END_ELEMENT结束元素
XMLReader::END_ENTITY结束实体
XMLReader::XML_DECLARATIONXML声明节点

XMLReader节点的类型值:

名称类型说明
attributeCountint节点的属性
baseURIstring节点的Base URI
depthint节点的树结构深度
hasAttributesbool节点是否包含属性
havValuebool节点是否包含文本值
isDefaultbool属性值是否来自默认的DTD
isEmptyElementbool节点是否是一个空的元素标签
localNamestring节点的本地(local)名
namestring节点的资格(Qualified)名
nameSpaceURIstring与节点相关的名称空间的URI
nodeTypestring节点的节点类型
prefixstring与节点相关的名称空间前缀

Ecshop的MySQL类autoReplace()方法重写

如题:

    // autoReplace
    public function autoReplace($table, $field_values, $update_values, $where = '')
    {
        $field_descs = $this->getAll('DESC ' . $table);

        // primary key | fields
        $primary_keys = $field_names = array();
        foreach ($field_descs as $value) {
            $field_names[] = $value['Field'];
            
            if ($value['Key'] == 'PRI')  {
                $primary_keys[] = $value['Field'];
            }
        }

        // action fields
        $fields = $values = array();
        foreach ($field_names as $value) {
            if (array_key_exists($value, $field_values) ) {
                $fields[] = $value;
                $values[] = "'" . $field_values[$value] . "'";
            }
        }

        // sets
        $sets = array();
        foreach ($update_values as $key => $value) {
            if (array_key_exists($key, $field_values) ) {
                if (is_int($value) || is_float($value)) {
                    $sets[] = $key . ' = ' . $key . ' + ' . $value;
                } else {
                    $sets[] = $key . " = '" . $value . "'";
                }
            }
        }
        
        // not exists primary key
        if (empty($primary_keys) && !empty($fields)) {
        	$sql = 'INSERT INTO ' . $table . '(' . implode(', ', $fields) . ') VALUES(' . implode(', ', $values) . ')';
        } else {
        	if ($this->version() >= 40102) {
        		$sql = 'INSERT INTO '. $table .'('. implode(',', $fields) .') VALUES('. implode(',', $values) .')';
        		
        		if (!empty($sets)) {
        			$sql .= ' ON DUPLICATE KEY UPDATE  '. implode(',', $sets);	
        		}
        	} else {
        		// where
        		if (empty($where)) {
        			$where = array();
        			
        			foreach ($primary_keys as $key) {
        				$where[] = $key = "'". $field_values[$key] ."'" ;
        			}
        			
        			$where = implode(' AND ', $where);
        		}
        		
        		if (!empty($where) && (!empty($sets) || !empty($fields))) {
        			if (intval($GLOBALS['db']->getOne("SELECT COUNT(*) FROM $table WHERE $where")) > 0) {
        				if (!empty($sets)) {
        					$sql = 'UPDATE '. $table .' SET '. implode(',', $sets) .' WHERE '. $where;
        				}
        			} else {
        				if (!empty($fields)) {
        					$sql = 'REPLACE INTO '. $table .'('. implode(',', $fields) .') VALUES('. implode(',', $values) .')';
        				}
        			} // else
        		}
        	} // else
        } // end if
        
        return empty($sql) ? false : $this->query($sql);
    }

已经重写过MySQL类(使用MySQLi方法),需要者Email:ljlwill@gmail.com。

php基本安全

复习下PHP安全的基础知识:

1)关闭注册全局变量功能

即是在php.ini中register_globals=off(也是默认)。它决定是否将 EGPCS(Environment,GET,POST,Cookie,Server)变量注册为全局变量。 如果register_globals=on, 客户端提交的数据中含有GLOBALS变量名, 就会覆盖服务器上的$GLOBALS变量。

2)在使用变量之前,进行初始化。

3)过滤全部输入数据。

其方式主要取决于数据的类型。

4)防止SQL的注入。

应该使用特定语言的数据库转义函数。如mysql_real_escape_data()。

5)谨慎使用执行命令的函数。

如eval(), exec(), system(), passsthru(), popen(), 反撇号(`)。如果在命令中含有变量,无比进行安全检查。还应该再使用escapeshellarg()和escapeshellcom()进行预处理。

6)谨慎使用变量引用包含文件。

7)session会话安全。可改变其默认目录或利用数据库存储其数据。

8)重命名通过HTTP(浏览器)上传的文件。

9)隐藏站点错误消息,把错误报告级别设置为最高。

10)在显示提交的数据时,过滤其HTML和Javascript(如可用strip_tags()函数)

等等

PHP官方称PHP代码源或被污染 用户下载需谨慎

转载:http://chinaz.com/Webmaster/report/03251CV52011.html

3月25日消息:据PHP官方网站发布新闻得知其wiki账号被盗,原因是wiki.php.net漏洞导致的,而wiki的账号和php代码源的SVN提交权限相关联,从而导致PHP代码受污染。

据了解,PHP5.3.6以及其后续版本的代码有可能被污染,目前只能把未受污染的代码版本确保到PHP5.3.5,下载PHP代码的用户,需谨慎。

原文内容:
The wiki.php.net box was compromised and the attackers were able to collect wiki account credentials. No other machines in the php.net infrastructure appear to have been affected. Our biggest concern is, of course, the integrity of our source code. We did an extensive code audit and looked at every commit since 5.3.5 to make sure that no stolen accounts were used to inject anything malicious. Nothing was found. The compromised machine has been wiped and we are forcing a password change for all svn accounts.
We are still investigating the details of the attack which combined a vulnerability in the Wiki software with a Linux root exploit.

内容大致是:

由于wiki账号被盗,PHP的代码源极有可能被污染,当然,PHP团队已经做最大的努力以保证自PHP5.3.5版本的代码没有收到污染,并且强迫SVN修改现有的密码。

而事件目前的状态是,他们仍然没法锁定漏洞所在,因为他们仍在排查。

一个很明显的问题是,PHP5.3.6以及其后续版本的代码可能已经被污染,目前只能把未受污染的代码版本确保到PHP5.3.5,下载PHP代码的人,要小心了。

而windows.php.net和wiki.php.net也已经暂停访问。

———————————-

作为一款被广泛使用的开发语言,经过此事,已经表明了php源码存在风险的可能,php源码的安全性令人堪忧。

使用数组语法访问的重载

PHP支持联合数组把整型或字符串的值映射到任何其它的值,这是一个关键字/值得映射模式,像在应用框架中查找字典一样,很是方便。

假设这么个例子,在海里的记录查找某个ID的记录。联合数组中少量数据放在一起,用其值如查字典般确认所需要的数据,非常快捷。但如果数据大,为查找某ID的数据而把所有的数据都加载到一个数组中就不实际了。

实际上,可以使用数组的语法轻松实现。这实际是PHP调用自定义的方法,由此方法执行相关的数据库调用,返回所对应的值。实现这些功能,定义的类需要实现ArrayAccess接口(如下):

bool offsetExists($index);

mixed offsetGet($index);

void offsetSet($index, $new_value);

void offsetUnset($index);

class userMap implements ArrayAccess
{
     private $_db;  // 只是简单的举例,这里不详述其实现

    function offsetExists($user_name)
      {
           return $this->_db->userExists($user_name);
      }

      function offsetGet($user_name)
      {
          return $this->_db->getUserID($user_name);
      }

      function offsetSet($user_name, $id)
      {
          $this->_db->setUserID($user_name, $id);
      }

      function offsetUnset($user_name)
      {
          $this->_db->unsetUser($user_name);
      }
}

$userMap = new userMap();

echo "ljlwill's ID is ". $userMap['ljlwill'];

可以看到,对象userMap的使用就像Array一样。在实际开发中,有时使用这重载功能会比冗长调用一个方法更加便捷。

PHP 5.3.4 发布

PHP 开发团队宣布 PHP 5.3.4 发布。

PHP 5.3.4 特性:
1)增加对zip 流的统计支持
2)新增 follow_location (默认启用)支持
3)增加一个 3rd parameter to get_html_translation_table
4)Implemented FR #52348, added new constant ZEND_MULTIBYTE to detect zend multibyte at runtime.
5)Multiple improvements to the FPM SAPI.
6)修复 100 多处bug

WIN7下IIS7的PHP环境配置

IIS下配置PHP环境,有CGI方式,ISAPI方式和FastCGI方式,具体它们之间明细,网上可搜索相关资料。

现在配置的PHP 5.3.3 VC9的版本(在windows下,Apache+PHP采用VC6版本,而IIS+PHP采用VC9版本)。在php.net/download中下载installer版本,然后按提示安装,在Web Server Setup选择IIS FastCGI便非常容易安装好,win7下的IIS7便可运行PHP文件了。

小小注意:

1) Windows/Temp目录的权限设置为erverone,否则PHP不可上传文件,还有ASP,.NET等不可访问Access

2)Windows 7中PHP连接Mysql时默认只能使用IP地址连接Mysql,而无法使用localhost连接Mysql,解决方法为打开C:\Windows\System32\drivers\etc下的hosts文件,将# 127.0.0.1 localhost中的注释去除即可。或者将数据库地址设置为127.0.0.1。