Featured Posts

CentOS LAMP Setup 很土鳖的问题,浪费我几个小时,终于搞定! 在 CentOS 下使用 xampp 的集成套件搭建 LAMP 环境,启动 Apache 后,用浏览器访问 web 程序,居然提示下载源文件!! 也就是...

Readmore

看看我写的 GFW 小故事 我是一个乖孩子,喜欢上网跟朋友们聊天、玩游戏 警察叔叔说,网上很黄很暴力,我却很傻很天真,不让我再看到我最爱的网站 直到有一天,一个无辜的小鸟被无情地封杀,我才意识到问题的严重性 面对河蟹坚硬的钳子,小鸟不能改变什么,唯一能做的,就是送上几句脱口秀解解气 据说那个墙,又黑又高,看到朋友们发来的结构图,我哭了 我再也看不见可爱的...

Readmore

Apache ReWrite QUERY_STRING 问号 ? 看一条应用中简单的 rewrite 规则: 将请求: http://www.leakon.com/soft/install?ver=2.0 rewrite 为: http://www. leakon.com/my/soft/install.php 配置文件 httpd.conf...

Readmore

  • Prev
  • Next

Raw POST Data PHP 获取 HTTP 原始 body 部分的数据

Posted on : 16-06-2009 | By : leakon | In : Web开发

2

通常做网站开发时,POST 数据都是从页面 form 表单中提交到服务器,POST Data 都是 key_1=value_1&key_2=value_2 这样的形式。这样的字符串,PHP 会自动解析到 $_POST 数组中。

有另外一种应用场景,在开发基于 HTTP 协议的接口时,客户端把一段 XML 文本直接作为 POST Data 提交到服务器,这时 $_POST 是空数组。大家可以试试,用 Curl 实现 POST 请求,BODY 字段直接写上一段文本。

通过 WireShark Network Analyzer 这样的软件抓包,可以看到 HTTP 的 Header 之后,有 0d 0a 0d 0a 共 4 个字符,也就是 \r\n\r\n,代表 2 个 Windows 平台的换行符。这是 HTTP Header 与 Body 之间的分割标志。在这之后,Body 的内容可以提交给服务器,但 $_POST 变量为空。

发现问题后立刻头大,这可怎麽办啊!!

在 Google 用 'php post raw' 这个关键词搜了一下,立刻找到答案,原来解决方法是如此的简单:

$strRawData = file_get_contents("php://input");

php://input 是一个资源标识,用 file_get_contents 从这个资源中获取的内容,就是原始的 Raw POST Data。

记录一下,留作日后备查。

FCKeditor 2.6 安装 配置 问题 图片上传

Posted on : 09-04-2009 | By : leakon | In : Symfony, Web开发

0

今天给使用 Symfony 的项目装了 FCKeditor 编辑器,配了图片上传。

遇到一些问题,总结下。

安装时,为了简单,最好把解压的 fckeditor 文件夹放在 web/ 目录下。

在模板中加入编辑器很简单:

$webDir = sfConfig::get('sf_web_dir'); // DocumentRoot 的服务端路径
$editorInclude = $webDir . "fckeditor/fckeditor.php";
require_once($editorInclude);

$oFCKeditor = new FCKeditor('detail') ; // form 表单字段名称是 detail
$oFCKeditor->BasePath = '/fckeditor/' ; // 客户端访问编辑器资源文件的路径
$oFCKeditor->Width = '100%'; // 宽
$oFCKeditor->Height = '100%'; // 高
$oFCKeditor->Value = $articleItem->detail; // $articleItem 是 ORM 对象,直接引用 detail 字段
$oFCKeditor->Config = array(
        'AutoDetectLanguage' => false, // 关闭浏览器语言自动检测
        'DefaultLanguage' => 'zh-cn' // 设置简体中文
);
$oFCKeditor->Create() ;

设置完了,刷新页面,直接可用!很简单。

已经检查的问题,可以很好地处理 XSS 问题,在编辑器里填写 <script>alert(123)</script> 这样的字符串,都会转义成纯字符,不会被浏览器解析为 HTML 代码。这在编辑器和最终页面都可以正常显示,需要注意的是输出的时候都要加 htmlspecialchars 转义,这是必须养成的习惯!

图片上传的问题。

默认是关闭的,修改 fckeditor/editor/filemanager/connectors/php/config.php 为:

$Config['Enabled'] = true;

$Config['UserFilesPath'] = '/uploads/'; // 这是 Symfony 自动生成的目录。

现在可以上传了,不过会遇到 2 个问题。

问题 1:点击“发送到服务器上”按钮,浏览器 alert 一个错误,显示“Error creating folder "redirect:/index.php" (Can't create redirect: directory)”。参考了“在symfony中使用FCKeditor上传图片附件” 这篇文章,得到了很好的解决。是 .htaccess 造成的。最简单的办法是在 uploads 目录下再放置一个 .htaccess,关闭 rewrite 即可,内容如下:

Options +FollowSymLinks +ExecCGI
<IfModule mod_rewrite.c>
  RewriteEngine Off
</IfModule>

问题 2:上传文件后修改文件名。fckeditor 默认是保留原有文件名。英文名的文件还勉强能用,如果是中文文件名就麻烦了。最好是统一按照自己的命名规则修改文件名。这时编辑 fckeditor/editor/filemanager/connectors/php/io.php,修改一个函数:

function SanitizeFileName( $sNewFileName ) {
  $arr = explode('.', $sNewFileName);
  $ext = array_pop($arr);
  $filename = date('Ymd_His_') . rand(1000, 9999) . '.' . $ext;
  return $filename;

把原函数改名作为备份。这函数就是保留了扩展名,把主文件名按照日期编码。呃,为了更好地保存文件,其实还应该把扩展名统一大小写,我记得有一个 pathinfo 函数,返回值有一个 extension 字段就是扩展名。其实过程都差不多,您自选吧。

总的说来,fckeditor 给我的感觉是安装简单,功能强大,代码逻辑清晰,便于修改。

赞一个~~

另:推荐一个 Blog

4’s symfony blog

这兄弟很深入地了解 Symfony 框架,我已订阅了他的 RSS,每天学习中……

睡了,晚安……

Apache ReWrite QUERY_STRING 问号 ?

Posted on : 28-03-2009 | By : leakon | In : Web开发

1

看一条应用中简单的 rewrite 规则:
将请求:
http://www.leakon.com/soft/install?ver=2.0
rewrite 为:
http://www. leakon.com/my/soft/install.php

配置文件 httpd.conf 加上如下配置:

RewriteCond %{QUERY_STRING} ^ver\=([0-9]+\.[0-9]+)?$ [NC]
RewriteRule ^/soft/install$ http://www. leakon.com/my/soft/install.php?[L]

请注意配置中的两个问号。

请求时,从 QUERY_STRING 取得 url 的查询字符串,这里只获取了 ver 的值,而且限定是带浮点的数字,ver 之后的查询字符都被忽略。实际上是用到 ? 来终结。

官方文档解释为:
注意:查询字符串
Pattern 不会按照查询字符串进行匹配。为了达到这个目的,你必须使用一个带有 %{QUERY_STRING} 变量的 RewriteCond 指令。

当 然,你也可以在替换字符串中创建包含查询字符串的 url:在替换字符串中使用问号,以标明其后的部分应该被重新注入到QUERY_STRING中。

而要删除一个已有的请求串,则可以用问号来终结替换字符串。为了联合新旧查询字符串,请使用[QSA]标志。

链接 样式 定义 顺序 link visited hover active

Posted on : 11-02-2009 | By : leakon | In : Web开发

1

这是我 3 年前遇到的问题了,当时解决过,后来记不太清楚,今天又复习了一遍。

给 A 标签定义样式,有四种状态:

  • link 没被点过的链接
  • visited 点过的
  • hover 鼠标悬停在链接上
  • active 鼠标点击按键后 至 松开按键前这段时间

当年不懂,在 IE 这个死浏览器上怎么都不能设置正确,后来百度搜了一下,意识到定义的顺序很关键,马上实践,果然灵验。

为了记这个顺序,我还给他起了个顺口溜呢,“路哈”。

v 字母可以看做是 u,那么发音就顺畅了:l - v - h - a。

读成 l - u - h - a,就是“路哈”的音。

仅供参考和回忆……

Web 前端开发 Firefox 扩展

Posted on : 24-01-2009 | By : leakon | In : Web开发

0

我在搞 Web 前端开发时用 Firefox 浏览器,有几个必备的扩展,非常好用,今天整理一下,给大家分享,也给自己列个清单备忘。

  • Firebug 不用说了,必备
  • YSlow 网站性能优化建议
  • Web Developer 必备
  • Tamper Data 这个需要重点介绍,当你也要做服务端开发时,客户端和服务器交互的 http 头部和 body 到底是什么样,都能准确地列出来,这曾经帮我发现并解决过重要的问题,强烈推荐。
  • MeasureIt 可以测量 html 元素的尺寸
  • DNS Flusher 更改 hosts 时,不必关闭 Firefox 即可访问新生效的服务器
  • View Source Chart 查看浏览器生成的 DOM 树,虽然 Firebug 可以完成 DOM 树的浏览和更改,但这个扩展可以用不同的颜色缩进代码,更直观,不过可惜的是暂时不支持 Firefox 3.0 以上的版本
  • Rainbow for Firebug 0.7 Javascript 语法高亮,用于 Firebug 1.2
  • FireGestures 1.1.6 鼠标动作,这个不能算是开发工具,不过我习惯了向左滑动一下鼠标代表“后退”动作

其他的工具也有好多,大家去 https://addons.mozilla.org/en-US/firefox/ 挖掘吧~~

http header Expires not modified 304

Posted on : 20-01-2009 | By : leakon | In : Web开发

0

困扰了我好久,看了 YSlow 的文档,也看了好多网站优化的书,按照书上的说法,加了 expires 和 cache-control 头,静态文件被缓存后,浏览器就不会再次发送请求了。

可是我看 apache 日志,仍然是有请求发到服务器,apache 发送 304 响应头。虽然起到了缓存的作用,但我希望是完全的客户端缓存,也就是说浏览器根本不会向服务器发请求询问。

今天又 google 了下,恍然大悟,原来是浏览器加载页面的策略不同:按刷新按钮与在地址栏输入网址按回车分别代表不同的动作。

地址栏输入,浏览器会优先使用缓存,如果图片文件缓存时设置了 expires ,那么在有效期内,浏览器不向服务端发任何请求,这样速度最快。

按刷新按钮,尽管本地有缓存,浏览器也会向服务器发一个询问请求,如果服务器端文件没有改变,则会返回一个 304 的相应头,告诉浏览器可以使用本地缓存,否则就返回新的文件。

这就解释了我之前遇到的问题。我配置了 Apache 后,每次按 F5 刷新页面,同时观察日志,总是有浏览器请求,总是返回 304 响应。

今天我又试了下,每次都在地址栏按回车,这回只有 html 的请求,图片都使用了本地的缓存。

土了一把……

ExpiresActive On

ExpiresDefault "access plus 1 month"

SofavDB_Debug_PDO MySQL 执行时间 日志

Posted on : 09-01-2009 | By : leakon | In : MySQL, PHP, Web开发, 原创

0

这个类可以完全替代 PDO,如果你需要知道自己的程序跟 MySQL 交互花费多少时间,而你又有洁癖,不想把自己的代码搞得一团糟,那我强烈地建议你试试这个 SofavDB_Debug_PDO。

通常,创建一个 PDO 连接,都是 new PDO()。

在开发环境中,你只需要把上面那个语句替换成 new SofavDB_Debug_PDO() 即可。

然后,凡是通过 prepare 的 statement 执行的任何查询和修改的语句,执行时间都能记录下来。

最后,通过 SofavDB_Debug_PDO::getTimer() 就可以得到一个数组,极其方便……

当然,这个类的执行效率会有一些小小的下降,不适合用于生产环境。

源码请见 GoogleCode:

http://leakon.googlecode.com/svn/trunk/leakon/php/sofav_db/SofavDB_Debug_PDO.php

MySQL 索引 优化 Using filesort

Posted on : 07-01-2009 | By : leakon | In : MySQL, Web开发, 原创

2

MySQL 数据库,MyISAM 类型的表 table_item,有 5、6 个字段,主键是 id。

user_id 和 item_id 两个字段都是单独的 INDEX 类型的索引。

问题是如何发现的?

今天搞程序,在自己的开发环境下,打开一个简单的页面都要好长时间,不知道问题出在哪里,只发现硬盘灯闪个不停。

观察 Windows 的任务管理器,看到 mysqld-nt.exe 这个进程的 "I/O 读取字节" 高达十几 G!!!

再次测试,发现每次刷新页面,这个进程要读取几十 M 的数据。

奇了怪了,查看 SQL 语句,还有表结构,字段都建了索引了呀。

后来 EXPLAIN 了一下,看到结果是 Using where; Using filesort。

explain SELECT * FROM table_item WHERE user_id = 2 ORDER BY item_id LIMIT 0, 5

翻了 MySQL 手册,仔细看下 filesort 的说明,知道了 Using filesort 是一种速度很慢的外部排序。

不过我不理解为什么会使用 filesort 排序,WHERE 和 ORDER BY 用到的字段都是有索引的呀。

赶紧 Google,找到几篇解释 Using filesort 的文章,得到的启示就是索引定义不当,MySQL 没有用到索引。

记得以前 Chenbin 给俺们培训过 MySQL 的优化,我还参加了两次,总感觉自己了解了如何优化 MySQL,没想到这么简单的语句我都没能优化。

现在想起来一些 MySQL 的特性了。

  1. 一条 SQL 语句只能使用 1 个索引 (5.0-),MySQL 根据表的状态,选择一个它认为最好的索引用于优化查询
  2. 联合索引,只能按从左到右的顺序依次使用

这 2 点刚好可以解决我的问题。

user_id 和 item_id 是 2 个索引,我的语句中,MySQL 选择了 user_id,那么 item_id 的索引没有起到任何用处,所以,当我要排序的时候,由于记录数较多,内存中的排序 buffer 满了,只能 Using filesort 进行外部排序,因此每次查询要从磁盘读取几十 M 的数据,太慢了。

修改表结构,删除 user_id 和 item_id 的 INDEX 索引,建立一个名为 user_item 的联合 UNIQUE 索引,顺序是先 user_id 后 item_id,再 EXPLAIN,这回只有 Using where 了。

再刷新页面,观察任务管理器,mysqld-nt.exe 只读取了 2K 的数据,页面咔的一下就出来了……

Javascript 字符串 数字 浏览器 性能差别

Posted on : 30-10-2008 | By : leakon | In : Web开发, 原创, 默认分类

0

我在做一个 Javascript 版的公历农历转换程序,功能完成后,需要对性能做优化。计算算法是在网上找的,原作者对历法的转换很精通,但对程序性能没有仔细考虑,当计算量大的时候,会给用户的浏览器造成很大压力,给用户的感觉就好像浏览器假死一样。

我花了2天时间在性能优化上,并在不同的浏览器下做对比测试,发现一个比较重要的差别,IE、Firefox 和 Chrome 之间的区别很大。

通常,生成一个月的日历,最多需要计算42天(可参考Google Calendar,每行代表一周7天,最多可能有6行)。

性能测试的时候,我让程序连续计算3年,共36个月,1000多天。

总的运行时间是:

IE7: 2.828 s
Safari3: 1.016 s
Firefox3: 0.885 s 
Opera9: 0.765 s
Chrome: 0.281 s

这下终于见识了 Chrome 采用的 Javascript V8 引擎的强大实力! 

以上统计结果都是测试3次取结果平均值。

程序运行到这个时间量级,已经是我优化过了的,最开始的程序,完成2年的计算,也就是上述运算量的三分之二,Firefox3用了8秒左右,Chrome很棒,用了2秒,而IE,30秒过后,浏览器直接问我是否要强制停止脚本运行,实际上我还从来没有在IE上成功执行过!

关于浏览器性能的差别,你可以用IE和Chrome打开淘宝的同一个比较复杂的页面,感受一下拖拉机与飞机的区别。

上面是浏览器的差别,下面我再给一些 Javascript 程序上的差别。

我的农历转换算法,有一个关键函数,需要多次调用,这个正是性能的瓶颈所在。

观察了调用方式和次数,这个函数运行了33000多次,而总共参数的变化只有1000次左右,如果加入缓存,可以减少97%的运算量!!!

我采用hash表的方式对每个输入的key做缓存,由于函数的参数是年月日,共3个,所以需要把这3个参数拼接成一个key。

最开始,我用字符串拼接,y m d 之间用 "_" 下划线连接起来,但仅仅是一个这样的字符串操作,程序运行时间就从0.8秒增加到1.1秒,增加了将近40%的时间!!

这是不能接受的,这将使我的缓存优化方式变得毫无意义。

农历算法的大部分关键代码,都是数字上的计算,代码很多,但好像没有产生性能瓶颈,这给了我启发。

我改用数字索引,把 y m d 用加法和乘法算出类似于 20081026 这样的整数,这样运行时间从0.789 s增加到0.853 s,只有不到10%的增加。

我的缓存,只能把运行时间降低20%到30%,所以用整数索引,可以达到优化的目的。

http://leakon.googlecode.com/svn/trunk/leakon/javascript/wannianli/nice/

很愿意与大家一起分享,一起分析,一起应用~~

原创文章,请尊重我对互联网的贡献,谢谢!

关注 Sphinx, Ratproxy

Posted on : 21-07-2008 | By : leakon | In : Web开发

0

今天听到 2 个新名词,看看都挺感兴趣的,不过工作太忙,没时间仔细看,记下来,回家看~~

一句话概括:

  • Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL, PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。
  • Ratproxy: Google 的 XSS 检测工具

http://www.sphinxsearch.com/

http://www.dbanotes.net/security/ratproxy_google_xss.html

上个图图吧,挺 PP 的: