学习PHP C扩展之面向对象开发方式

PHP OOP面向对象之C语言开发方式

学习PHP C扩展有一段时间了,PHP手册里大部分讲的PHP的函数开发方式,网上找OOP资料比较少,想起上个月测试redis 的时候,下载PHP扩展redis源代码是OOP方式的。所以拿来练练手,其它不说了开始

下面要扩展的代码是 ModelHelper.php

< ?php
/**
 * 助手类,用于放置需要使用的公共函数和常量
 *
 */
class ModelHelper {
		
		static public function escapePage($page)
		{		
			return max(1, intval($page));
		}
		
		/*
		 * 返回基于当前时间的唯一MD5哈希值
		 */
		static public function uuid()
		{
			return md5(rand());
		}
}
?>

然入 php源代码 ext\ext_skel –extname=ModelHelper
下面是进行修改的c代码

ModelHelper.c

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2007 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id: header 226204 2007-01-01 19:32:10Z iliaa $ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_ModelHelper.h"
#include "ext/standard/php_standard.h"
#include   
#define MAX(a, b)  (((a)>(b))?(a):(b))

/* If you declare any globals in php_ModelHelper.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(ModelHelper)
*/


/* True global resources - no need for thread safety here */
static int le_ModelHelper;

static zend_class_entry *ModelHelper_ce;
static zend_class_entry *ModelHelper_exception_ce;
static zend_class_entry *spl_ce_RuntimeException = NULL;


/* {{{ ModelHelper_functions[]
 *
 * Every user visible function must have an entry in ModelHelper_functions[].
 */
static zend_function_entry ModelHelper_functions[] = {
	 PHP_ME(ModelHelper,escapePage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
     PHP_ME(ModelHelper,uuid, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
	 /* For testing, remove later. */
	{NULL, NULL, NULL}	/* Must be the last line in ModelHelper_functions[] */
};
/* }}} */

/* {{{ ModelHelper_module_entry
 */
zend_module_entry ModelHelper_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"ModelHelper",
	ModelHelper_functions,
	PHP_MINIT(ModelHelper),
	PHP_MSHUTDOWN(ModelHelper),
	PHP_RINIT(ModelHelper),		/* Replace with NULL if there's nothing to do at request start */
	PHP_RSHUTDOWN(ModelHelper),	/* Replace with NULL if there's nothing to do at request end */
	PHP_MINFO(ModelHelper),
#if ZEND_MODULE_API_NO >= 20010901
	"0.1", /* Replace with version number for your extension */
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_MODELHELPER
ZEND_GET_MODULE(ModelHelper)
#endif

/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
PHP_INI_BEGIN()
    STD_PHP_INI_ENTRY("ModelHelper.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_ModelHelper_globals, ModelHelper_globals)
    STD_PHP_INI_ENTRY("ModelHelper.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_ModelHelper_globals, ModelHelper_globals)
PHP_INI_END()
*/
/* }}} */

/* {{{ php_ModelHelper_init_globals
 */
/* Uncomment this function if you have INI entries
static void php_ModelHelper_init_globals(zend_ModelHelper_globals *ModelHelper_globals)
{
	ModelHelper_globals->global_value = 0;
	ModelHelper_globals->global_string = NULL;
}
*/
/* }}} */




/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(ModelHelper)
{
	/* If you have INI entries, uncomment these lines 
	REGISTER_INI_ENTRIES();
	*/
	
   zend_class_entry ModelHelper_class_entry;
   INIT_CLASS_ENTRY(ModelHelper_class_entry, "ModelHelper", ModelHelper_functions);
   ModelHelper_ce = zend_register_internal_class(&ModelHelper_class_entry TSRMLS_CC);
   return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(ModelHelper)
{
	/* uncomment this line if you have INI entries
	UNREGISTER_INI_ENTRIES();
	*/
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(ModelHelper)
{
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(ModelHelper)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(ModelHelper)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "ModelHelper support", "enabled");
    php_info_print_table_row(2, "URL", "http://www.hucde.com");
    php_info_print_table_row(2, "author", "Summer.Hu");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini
	DISPLAY_INI_ENTRIES();
	*/
}
/* }}} */



PHP_METHOD(ModelHelper,escapePage)
{
	long return_i;
	zval **n;
	if (zend_get_parameters_ex(1, &n) == FAILURE) {
			WRONG_PARAM_COUNT;
	}
	
	convert_to_long_ex(n);
	return_i=MAX(1,Z_LVAL_PP(n));
	RETURN_LONG(return_i);
	//convert_to_long_base(return_value, 10);
}


PHP_METHOD(ModelHelper,uuid)
{
	long number;
	number = php_rand(TSRMLS_C);
	PHP_MD5_CTX context;
	unsigned char digest[16];
	char md5str[33];
	char string_number[25];
	int len;
	char *strg;
	len = spprintf(&strg, 0, "%u",number);
	PHP_MD5Init(&context);
	PHP_MD5Update(&context,strg,len);
	PHP_MD5Final(digest, &context);
	make_digest(md5str, digest);
	RETVAL_STRING(md5str, 1);
}

php_ModelHelper.h 的头文件

/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2007 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id: header 226204 2007-01-01 19:32:10Z iliaa $ */

#ifndef PHP_MODELHELPER_H
#define PHP_MODELHELPER_H

extern zend_module_entry ModelHelper_module_entry;
#define phpext_ModelHelper_ptr &ModelHelper_module_entry

#ifdef PHP_WIN32
#define PHP_MODELHELPER_API __declspec(dllexport)
#else
#define PHP_MODELHELPER_API
#endif

#ifdef ZTS
#include "TSRM.h"
#endif

PHP_MINIT_FUNCTION(ModelHelper);
PHP_MSHUTDOWN_FUNCTION(ModelHelper);
PHP_RINIT_FUNCTION(ModelHelper);
PHP_RSHUTDOWN_FUNCTION(ModelHelper);
PHP_MINFO_FUNCTION(ModelHelper);

PHP_METHOD(ModelHelper,escapePage);
PHP_METHOD(ModelHelper,uuid);
/* For testing, remove later. */

/* 
  	Declare any global variables you may need between the BEGIN
	and END macros here:     

ZEND_BEGIN_MODULE_GLOBALS(ModelHelper)
	long  global_value;
	char *global_string;
ZEND_END_MODULE_GLOBALS(ModelHelper)
*/

/* In every utility function you add that needs to use variables 
   in php_ModelHelper_globals, call TSRMLS_FETCH(); after declaring other 
   variables used by that function, or better yet, pass in TSRMLS_CC
   after the last function argument and declare your utility function
   with TSRMLS_DC after the last declared argument.  Always refer to
   the globals in your function as MODELHELPER_G(variable).  You are 
   encouraged to rename these macros something shorter, see
   examples in any other php module directory.
*/

#ifdef ZTS
#define MODELHELPER_G(v) TSRMG(ModelHelper_globals_id, zend_ModelHelper_globals *, v)
#else
#define MODELHELPER_G(v) (ModelHelper_globals.v)
#endif

#endif	/* PHP_MODELHELPER_H */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */

然后编译,生成后输入 phpinfo.php 找到ModelHelper

编译成功,然后输入测试一下:

< ?
//$obj=new ModelHelper();
//echo $obj->escapePage(5);
//echo $obj->escapePage(-1);
//echo  echo qsyhcd_md5();
//echo $obj->uuid();
//var_dump($obj);

echo ModelHelper::escapePage(5)."
"; echo ModelHelper::escapePage(-1)."
"; echo ModelHelper::escapePage("d'")."
"; echo ModelHelper::uuid()."
"; ?>

得到

PHP多进程写入文件的问题

这是面试题和实践中经常遇到的哈,分享给大家

< ?php
/**
 * 写入
 *
 * @param string 文件名
 * @param string 内容
 */
function _fwrite($filename,$content)
{
 $filename_lock=$filename.'.lock';
 while(1)
 {
  if(file_exists($filename_lock))
  {
   usleep(1000);
  }else{
   touch($filename_lock);//加锁
   $f=fopen($filename,'w');
   fwrite($f,$content);
   fclose($f);
   unlink($filename_lock);
   break;
  }
 
 }
 if(file_exists($filename_lock))
 {
  unlink($filename_lock);
 }
}
_fwrite('test.txt','http://www.hucde.com');
?>

MySql里面英文和中文字符长度的比较:length与char_length

最近公司再做分词词库的收集,其中一个需求是要按字数长度来搜索,数据库基于MYSQL,当时想到用length来得到字段的大小,但发现搜索出来的结果不对,字段里的内容90%都是中文,后来查手册看到还一个char_length 比较好用,用法:
length:是计算字段的长度一个汉字是算三个字符,一个数字或字母算一个字符
char_length:不管汉字还是数字或者是字母都算是一个字符
SQL语句如下:

SELECT *   FROM `fenci`  WHERE char_length( `keywords` )=5    LIMIT 0 , 30

浅谈PHP安全防范

由于所在公司对WEB应用程序性的重视,平台开发语言大部分也是PHP,以我在PHP开发上经验列出几项常见的PHP安全问题进行梳理或解决办法。

跨站脚本攻击(CSS or XSS, Cross Site Scripting)

这个是最常见的 POST 都要过滤可以使用

strip_tags, 删除string中所有html标签

htmlspecialchars,只对”<”,”>”,”;”,”’”字符进行转义

htmlentities,对所有html进行转义

用户提交数据常见过程的处理流程

用户提交处理过程

过滤输入

把识别输入做为第一步是因为如果你不知道它是什么,你也就不能正确地过滤它。输入是指所有源自外部的数据。例如,所有发自客户端的是输入,但客户端并不是唯一的外部数据源,其它如数据库和RSS推送等也是外部数据源。

1.永远不要相信你的用户。

2.Fliter input,Escape output.

由用户输入的数据非常容易识别,PHP用两个超级公用数组$_GET 和$_POST来存放用户输入数据。其它的输入要难识别得多,例如,$_SERVER数组中的很多元素是由客户端所操纵的。常常很难确认$_SERVER 数组中的哪些元素组成了输入,所以,最好的方法是把整个数组看成输入。

SQL注入问题

查询条件尽量使用数组方式,这是更为安全的方式;

开启数据字段类型验证,可以对数值数据类型做强制转换;

使用自动验证和自动完成机制进行针对应用的自定义过滤;

会话劫持

最常见的针对会话的攻击手段是会话劫持。它是所有攻击者可以用来访问其它人的会话的手段的总称。所有这些手段的第一步都是取得一个合法的会话标识来伪装成合法用户,因此保证会话标识不被泄露非常重要。

PHP自带的函数使用注意事项

1.include(),require()和fopen(),include_once(),require_once()这些都可以远程调用文 件:除了依靠php.ini里的allow_url_fopen设为off禁止远程使用文件和open_base_dir禁止使用目录以外的文件外,你还 得事先声明好只能包含哪些文件

2.fopen(),file(),readfile(),openfile(),等也是该特别留意的地方。函数本身并没什么,它们的作用是去打开文件,可是如果对变量过滤不彻底的话,就会泄露源代码。

3.fwrite()和它的变体函数这种漏洞想想都想得出,对于用户提交的字符没过滤的话,写入一段php后门又不是不可以。

4.unlink()函数,前段时间,phpwind里任意删除文件就是利用这个函数,对于判断是否删除的变量没过滤,变量可以指定为任意文件,当然就可以删除任意文件的变量。

5.eval(),preg_replace()函数,它们的作用是执行php代码,如果字符串没被经过任何过滤的话,会发生什么呢,我就常看见一些cms里面使用,想想,一句话的php木马不就是根据eval()原理制作的吗?

6.对于system()这些系统函数,你会说在php.ini里禁止系统函数,对,这也是好办法,可是象一些程序里需要,那是不是就不用了呢?就 像上次我看到的一套很漂亮的php相册一样。另外对于popen(),proc_open(),proc_close()函数你也得特别注意,尽管他们执 行命令后并没有直接的输出,但你想这到底对黑客们有没有用呢。再这里php提供提供了两个函 数,escapeshellarg(),escapeshellcmd(),这两个函数用来对抗系统函数的调用攻击,也就是过滤。

7.禁用PHP.ini 中的register_globals。这可以防止攻击者通行URL访问PHP指令或变量。

8.使用php.ini 里的“安全模式”作为最终的错误捕捉方法,但是不能指望用它来得到充分的安全性。

9.不能依靠session.referrer_check 来进行错误检查

10.用户从应用程序 注销时,使用session_destroy 显式地结束会话。

总之,要注意每一个细节

其他安全建议

1.有公共的操作方法做必要的安全检查,防止用户通过URL直接调用;

2.缓存需要用户认证的页面;

3.用户的上传文件,做必要的安全检查,例如上传路径和非法格式,官方的扩展类库中的ORG.Net.UploadFile类提供了上传类的安全解决方案。

4.非必要,不要开启服务器的目录浏览权限;

5.于项目进行充分的测试,不要生成业务逻辑的安全隐患(这可能是最大的安全问题);

6.保护模板文件,因为模板文件中可能会泄露数据表的字段信息(如Smarty 里template)源码暴露 .inc 结尾的文件 index.php.bak (如EditPlus等编辑器生的备份文件)Require 或 include 的文件使用不安全的数据

7.再次强调:不要相信不是你自己显式声明的数据。不要 Include 或 require 从$_GET, $_POST 或 $_COOKIE 中得到的文件。

安全是一种相对的度量,而不是绝对的标准。

如果你在设计你的应用的时候没有考虑安全,你命中注定将要坚持不懈的来寻找新的安全漏洞。仔细的写程序并不能弥补糟糕的设计。

/* 算然说凡事都可“亡羊补牢”,但终究还是“防胜于补”。当安全成为系统本身的一部分,而不是额外的开销时,不但能降低实现安全所产生的成本,同时也能提高 系统的完整性。至少,在整体上系统是处于安全的保护中。但是,不论是系统设计时期还是编码时期,安全总是应当是随时考虑的一部分。 */

一个系统是否安全,很大程度上取决于开发人员是否关注安全。

MongoDB与PHP

MD,原来那个服务器关了,R,图片和CSS样式全没的,过几天空了补上来
==========================================
最近NoSQL 炒的很火,我也不想Out了,也来凑一下热闹。

目前了解的有Redis、Tokyo Cabinet、MongoDB等NoSQL数据库.前三者都使用过,我比较看好MongoDB。

先看一下mongodb的介绍
Mongodb是 集文档数据库,键值对存储和关系型数据库的优点于一身.

MongoDB (名称来自”humongous”) 是一个可扩展的,高性能,开源,模式自由,面向文档的数据库.使用C++编写,MongoDB特点:

1.面向文档存储(类JSON数据模式简单而强大)

2.动态查询

3.全索引支持,扩展到内部对象和内嵌数组

4. 查询记录分析

5. 快速,就地更新

6. 高效存储二进制大对象 (比如照片和视频)

7.复制和故障切换支持

8.Auto-Sharding自动分片支持云级扩展性

9.MapReduce 支持复杂聚合

10.商业支持,培训和咨询

MongoDB 在键值存储(快速并有高扩展性) 和传统 RDBMS 系统(提供结构化模式和强大的查询)之间建立了一个桥梁.

介绍
MongoDB 是一个面向集合的,模式自由的文档型数据库.

面向集合, 意思是数据被分组到若干集合,这些集合称作聚集(collections). 在数据库里每个聚集有一个唯一的名字,可以包含无限个文档. 聚集是RDBMS中表的同义词,区别是聚集不需要进行模式定义.
模式自由, 意思是数据库并不需要知道你将存入到聚集中的文档的任何结构信息.实际上,你可以在同一个聚集中存储不同结构的文档.
文档型, 意思是我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作 “[BSON]” 即 “Binary Serialized dOcument Notation.”

MongoDB 运行概述
MongoDB 是一个服务器进程可以运行在 Linux, Windows 和OS X等操作系统. 支持 32 和 64位模式,我们推荐使用64位模式,因为在32位模式下Mongo的数据库大小有2GB的限制.

MongoDB 进程默认情况下使用监听端口为 27017 (可以在启动时用命令行参数修改,详细信息参考 [Command Line Parameters] ).
Clients 连接 MongoDB 进程(如果安全认证系统激活的话需要进行用户认证),执行一系列的操作,比如插入,查询,更新等.
MongoDB 使用文件存储数据. (默认位置 /data/db/), 使用内存映射文件进行高效的数据管理.
MongoDB 还能配置成 [自动数据复制], 即 [自动故障切换].
有关 MongoDB 的更多管理信息,参见 [Mongo 管理指南].

MongoDB 功能
对于开发人员, MongoDB 驱动提供了丰富的操作:

查询:基于查询对象或者类SQL语句搜索文档. 查询结果可以排序,进行返回大小限制,可以跳过部分结果集,也可以返回文档的一部分.
插入和更新 : 插入新文档,更新已有文档.
索引管理 : 对文档的一个或者多个键(包括子结构)创建索引,删除索引等等
常用命令: 所有MongoDB 操作都可以通过socket传输的DB命令来执行.
============================================================

官方地址

http://www.mongodb.org/

中文

http://www.mongodb.org/display/DOCSCN/Home

下载地址

http://www.mongodb.org/display/DOCS/Downloads

我这里下载 Linux 32 bit 1.2.4 做测试

下载后直接解压就能用了哈

然后

?View Code PHP
1234
mkdir -p /data/db // mongodb 默认目录存放数据目录cd bin ./mongod

启动成功默认端口是 27017

目前MongoDB支持很多语言

C | C++ | C# | ColdFusion | Erlang | Factor | Java | Javascript | PHP | Python | Ruby | Perl

Mongodb 的提供工具自带客户端也可以直接操作

详细内容可能查看

http://www.mongodb.org/display/DOCS/Overview+-+The+MongoDB+Interactive+Shell

进行了解

下面我们下载下来跟 PHP驱动使用一下

http://www.php.net/manual/en/mongo.installation.php

具体按文档的操作

一步一步安装成功后

然后用phpinfo() 查看一下。

OK PHP的扩展安装完成

下面写代码测试一下

?View Code PHP
12345678910111213141516171819202122232425262728
// connect$m = new Mongo(“mongodb://192.168.179.129:27017”); // select a database$db = $m->comedy;$collection = $db->test; // add an element$obj = array( “title” => “hello world1”, “author” => “summer”,”url”=>”http://www.hucde.com”);$collection->insert($obj); // add another element, with a different “shape”$obj = array( “title” => “hello world2”, “author” => “summer”,”url”=>”http://www.hucde.com” );$collection->insert($obj); // find everything in the collection$cursor = $collection->find(); // iterate through the resultsforeach ($cursor as $obj) {echo $obj[“title”] . ”
“;echo $obj[“author”] . ”
“;echo $obj[“url”] . ”
“;} // disconnect$m->close();

运行mongo.php

成功

其它接口请参照

http://cn2.php.net/manual/en/class.mongodb.php