Read It Later 集成到 Google Reader Wed, Nov 5. 2008
洒家阅读新闻用的两个最重要的工具:Read It Later 和 Google Reader 终于能够直接集成了。实在是美哉。
Read It Later Comes To Google Reader
Read It Later,一个流行的 Firefox 插件,最近发布了升级版本,该版本给 Google Reader
增加了一些新功能。这个新扩展同时兼容 Firefox 和 IE,这个新扩展让你能够在阅读你所订阅的 RSS
种子的时候勾选出需要稍后再做详细阅读的新闻,以此来加快你的浏览速度。 你还能够使用任何浏览器访问到这些你想稍后阅读的这些新闻,不管是在家里的
Firefox,在单位的 IE,甚至你的 iPhone 手机都可以。
这个升级版的 Read It Later
扩展给你的 Google Reader 的种子列表增加了一个 Greasemonkey-esque
功能,就是在每个新闻条目的旁边,星标的右边增加一个对勾符号。在你浏览你的订阅的时候,你勾选上的帖子会自动增加到你的阅读列表中——你可以随时在 readitlaterlist.com
网站上访问到你保存的阅读列表。通过内置的离线浏览功能,你还能在准备要离开网络的时候,下载一系列文章供你以后阅读——比如说当你乘飞机旅行的时候。
如果你使用书签插件来管理你的阅读列表,那么现在你有更多的选项供你定制。你可以使用“普通”模式或者“紧凑”模式查看阅读列表、选择每页显示的条目数、是否在侧边栏打开阅读列表、以及是否启用上下文关联菜单和附加的工具栏按钮。
不过,新加的功能中最棒的就是可以按照 PostRank
对阅读列表进行排序。我们在读写网好几次都非常关注这个曾经名为 AideRSS 的功能。在启用 PostRank
后,你的阅读列表会智能的按照流行度进行过滤。 有几种方式给一个帖子打分,包括该帖子收到的评论数、在美味书签上被标记的次数,被 digg
的次数,以及被引用的连接数。 你现在可以按照帖子的重要程度来浏览你的阅读列表,这对那些被过量的信息所困扰的人特别有用。
该插件还有一些其他的改进,例如升级了的隐私控制、现有功能的更强大技巧等,这些改进让 Read It Later 逐渐成你的浏览器中一个重要的插件,不管你用的是 Fireofox 还是 IE。 现在,我们就只需要的就是能够在 iPhone 上使用的书签插件,那就就齐活了。
Popout
真实世界让你很沮丧吗?IBM 邀请你到超越时空的紫禁城一游。 Mon, Oct 13. 2008
原文:Real World Got You Down? IBM Invites You To A Virtual Forbidden City.。
想去中国游览紫禁城又买不起机票?现在,你只要有台计算机就行了。IBM——虚拟世界最忠实的信徒——和中国故宫博物院共同把这个占地 178 英亩的紫禁城在虚拟世界里重现。在三年时间里,他们非常细致的重建了所有的建筑物和数以千计的重要文物,现在,“超越时空的紫禁城”已经可供下载(有 Windows、Mac 和 Linux 版)。这个软件可以免费下载,不过先提醒你,Mac 版的可是一个实实在在的 275M 的安装包。
当你进去后,你能够选择你的形象、穿上清朝的服装、进行虚拟的浏览、和计算机控制的角色玩耍、查找地图、浏览建筑物和里面的文物,你还可以点击这些建筑物或者文物以得到进一步信息。这个虚拟世界构建在名为 Torque 的游戏平台,这个游戏平台来自 Garage Games。(我估计是因为 OpenSim 不够好,因为没有评论说虚拟时空紫禁城时候会和第二人生进行互动)
如果你想找个地方躲避现在金融风暴,但是有没钱真的出去旅游的话,那么你可以来 IBM 的超越时空紫禁城里闲逛上几个钟头。


地图聚合的数据格式前三名:KML、GeoRSS 和 GeoJSON Thu, Aug 28. 2008
原文地址:3 Top Data Formats for Map Mashups: KML, GeoRSS and GeoJSON。
随着地图聚合给最终用户提供的一系列更广泛的工具和应用程序,它在完善程度和功能性两方面逐渐走向成熟。 因此,我们需要一些预定义好的方法在传统的地理空间数据和新一代的地图聚合之间交换、发布这些地理空间数据,并且使用一种对 web 友好的方式使用这些数据。
为了满足这种需求,出现了一些新的地理空间数据格式,这能够让更大范围的用户和开发者来聚合地理相关的信息。 下面是当前可供从事地理信息聚合的开发者使用的三种主要数据格式的一个概括:
KML
你知道 Google 地球的前身,那个流行的名为 Keyhole 的三维地球浏览器吗? 如果你知道,那么这个基于 XML 的,Google 地球自己的文件格式被叫做 KML,意为 Keyhole 标记语言,就不值得惊讶了。 在地理空间相关的网站上,KML 无处不在,KML 支持从类似 Google 地图、微软的虚拟地球这样商业化的地图 API 和 OpenLayers 这样开源的地图 API 中导入、导出数据。 今年早些时候,Google 把 KML 作为一种开放标准发布,并且被开放地理空间联盟 (OGC) 采用。 你可以研读最新的 KML 规范 (当前是 2.2 版) 或者学习如何让 KML 与 Google 地图 API、虚拟地球或者 OpenLayers 集成。
GeoRSS
GeoRSS 提供了一种在 RSS (或者 Atom) 种子里通过特定的编码来包含地理参考信息的方法。GeoRSS 站点上说:
RSS 和 Atom 作为一种发布、共享信息的方法,正在逐渐流行起来, 因此,使用互操作的方式描述位置信息,来让程序能够请求、聚合、共享、地图化地理标记过的种子变得益发重要。
嵌入 GeoRSS 非常简单,仅仅在每个条目中增加一个类似 <georss:point>45.256 -71.92</georss:point> 这样的元素就行了,这里使用的是简易GeoRSS 格式, 如果要需要复杂完整的编码格式,可以选择支持更多的特性的 GeoRSS-GML 格式。这两种 GeoRSS 格式都支持基本的地理特征 (点、线、边框和多边形)。 和 KML 一样,商业化的地图 API 和开源地图 API 都支持 GeoRSS,并且主要作为导入数据的格式使用。 GeoRSS 许诺对整合内容的会有更好的支持。
GeoJSON
GeoJSON 是基于 JavaScript 对象表示法 (JSON)的一种新的数据格式,用来对大量的地理特征进行编码,支持的地理特征有点、线、多边形、多多边形和地理信息集合。
{ "type": "Point", "coordinates": [43.542, -118.454] }
GeoJSON 可以被 JavaScript 简单、快速的解析,而且 GeoJSON 还提供了一个可以很容易的进行交换的轻量级数据格式。 自从 GeoJSON 正式发表 1.0 版后,GeoJSON 的魅力逐渐增加,得到了包括 FireEagle 和 OpenLayers 在内的一些流行的 API 的支持 (但是不确定将来是否能够得到类似 Google 地图或者虚拟地球这样的商业 API 的支持)。
注意 GeoRSS 和 GeoJSON 都采用创作共用授权协议授权。
我们饶有兴趣的看着这些格式如何发展,而且很想知道类似 GeoRSS 和 GeoJSON 这样的格式能否得到地图 API 和地图聚合开发者的采用。
做好准备迎接新的平台大战。Google Gears 直指微软领地 Mon, Jun 16. 2008
原文:Get Ready For A New Platform War. Google Gears Drives Straight At Microsoft’s Profits.。
Google 在去年五月发布了 Gears,之后的一年里 Gears 被认为是一个小众产品,只会有很少开发者和用户用它来开发能够离线访问的 web 程序。兴许你还能回想起当年的争论:在到处都有网络连接的情况下,究竟谁需要离线访问功能,而且还没有足够的程序支持,等等。不到一年的时间,就在几周前,Google 亮出了他的王牌:Gears 助力 MySpace 加速邮件系统。其实 Google 早就加入了这场提供新 web API 的比赛,但是居然一年了都没有人注意到。
将来的浏览器很可能会变成运行所有程序的虚拟机。在这种情况下,操作系统会变的透明,就像 Adobe 所作的,它的 Flash 技术是现在使用的最普遍、最统一的 web 虚拟机,而微软则要自保(它的利润的来源)了。Google 不隐瞒他们想瞄准并且攻击微软的野心,他们知道,要做到这点的最好方法就是上移一层把操作系统架空,让浏览器成为标准且强劲的应用程序虚拟机。
很难在一片评论里表达清楚 Gears 如何改变并且增加 web 程序的功能。以前使用基于浏览器的 Javascript 脚本,MySpace 中的一些类似邮件列表和排序、根据好友列表过滤这样的功能会让人感觉很慢,而当浏览器向服务器发送多个请求时,进度条还可能会定住,沙漏图标在不停的旋转。而现在,安装 Gears 只要在确认框点击一下并且等待几秒钟,安装之后,以前让用户抓狂的那些功能现在感觉起来就好象是浏览器自带功能一样。Google 给我们秀了一把 Gears 与 MySpace 集成后的能力,这唤醒了大部分人关注他真正的意图:不再仅是离线浏览,而是直接针对 Adobe 和微软所采取的行动。
截至目前为止,Google 拥有一系列共计 28 个基于 web 的程序, 这些程序在全世界有数百万的用户。Google 开发 web 程序的技术都是基于标准的 HTML、CSS 和 Javascript。选择 Ajax 仅仅是因为这是最好的解决方案,但是 Google 还要做更多以面对现实,那就是每个类似的 web 开发技术体系都是被一个直接的竞争者所开发、控制。Google 对开源浏览器 Firefox 的开发给予了强大的支持,并且支持开放 web 标准作为他们的技术体系之选。Google 这么做是因为他们的 web 程序都依赖于开放标准,Firefox 的失败会导致 Internet Explorer 复生并且把 web 的控制权拱手让给微软。
以前,只用基于浏览器的 Javascript 来支持 web 程序对 Google 来说不是个问题。直到竞争者领先一步发布了他们自己的第二代 web 平台,分别是 Flex/AIR 和 Silverlight,情况才发生了变化。基于 web 的程序在有了类桌面的界面和功能后能够做什么,从这一方面开说,微软和 Adobe 已经超前了一大步。用不了多久,大大小小的竞争者就会使用竞争性技术平台创建竞争性程序,那会使 Google 的产品看起来像是还停留在上个世纪九十年代的样子。
留给 Google 的选择现在很明了了:要么放弃使用基于浏览器的 Javascript 和开放标准进行开发,转而接受新技术中的一种,要么继续坚持使用核心 web 技术并且发展这些技术直到成为可行的替代技术。Google 的问题是,新标准和预期的浏览器功能很快就会带来富 web 技术,但是开发那些标准的进度却如此缓慢,以至于很可能需要几年时间才能看到那些标准被广泛的应用。新的 HTML 标准,HTML5,特别关注扩展本地浏览器对 web 程序的支持能力,在不用附加私有运行时的情况下。Google web API 的基础就是这些同样的功能以及其他的附加功能。
由于标准开发的极其缓慢,导致通向更快更好,而且仍旧免费开放的 web 程序之路被堵死了,所以 Google 决定通过 Gears 自己进入这个市场。想法其实很简单:把明天的 web 技术带到今天的浏览器里。这些特定的功能大部分都来自新的 HTML5 规范,但是标准制定小组已经在上面花费了好几年。不想再等这个小组完成规范,Google 自己通过件对浏览器进行扩展,实现了这些功能并且达到了那个小组能达到的最高水平。他们宁愿在短期内抛弃标准(原话是“以后再考虑实现”)也要把他们的 web 程序带到能够对抗 Flash 和 Silverlight 的下一代标准。
Gears 有一个 30 人左右的小组开发,这个小组是 Google 内部开源小组的一部分。这个小组由 Vic Gundotra 带领,再一次讽刺的转变过程中,他由微软的传教士成为 Google 的高级开发者。这个一小组开发者着手进行开发,并且保持 Google 对 Javascript 和开放浏览器虚拟机的兴趣。理论上,他们看起来很可能被大组织或者微软和 Adobe 正在投入各自平台的预算所超过。为了改变这个状况,他们把 Gears 从 Google 中分离出来(字面上也是——现在这个项目名称就只是“Gears”)并且在开源协议下发布源代码。
第一个发行版将只关注于 HTML5 里面提议的新功能中他们认为最重要的功能:基于客户端的结构化数据和对象存储。由于选择了首先实现客户端存储,所以下一年里 Gears 会被构架成一个离线应用程序解决方案,由于其他的竞争者好像都没有注意到这个这么巨大目标,所以如果他们不是有意而为之,那么肯定会发展的很好。Google 本来有可能开发他们自己的浏览器,某些博客里的推测和谣言也都指出了这一点,但是浏览器市场竞争激烈,却平淡乏味,而且通常会失败。另外,即使他们开发了自己的新浏览器,他们还要驱使用户接受这个新浏览器,在决定性的市场聚集起来之前只能等待,就是这样,市场上还会有 70% 或者 80% 甚至 90% 的人不使用 Google 的浏览器,却想使用 Google 的程序。
这种情况下,可选的捷径就是跳过浏览器直接在上面增加一层——Google 自己的 web 层。所有常用浏览器都提供了让开发者扩展功能的机制,这样一来,Google 要做的就是对每个浏览器开发对应的插件。这能让新的 web API 能够适应所有的桌面而不需要用户去适应,最重要的,这比起进入浏览器市场来说见效快而且痛苦少。现在可以让浏览器来做所有无聊的事情:渲染 HTML、显示界面、用户选项等等,与此同时 Google 却在改变现状,埋头向前冲。
现在 Gears 支持大量完整的新功能,有一些新功能是和微软、Adobe 他们的下一代 web API 相同的,而其他的则是 Google 自己创造出来的。现在函数调用已经对开发者开放了,包括后台处理(不会再有沙漏出现)、客户端图像处理、位置感知、更好的文件上传功能,还有浏览器内本地数据库。
要让新 API 和开发平台的应用被采用需要两方面的支持,一方面是用户的支持,因为这需要用户安装新的插件;另一方面是开发者的支持,使用 Gears 不会让开发变得更容易,这是因为这和开发其他的使用基于浏览器的 Javascript 的程序没有区别,Gears 只是给开发者提供了一系列更多的可以在浏览器内实现的功能而已。Javascript 和 web 开发者不需要学习任何新知识,用户也要做的也只是安装一个插件(与浏览器绑定的交易肯定会发生,所以这一步都可以忽略了)。Flash 花了 5 到 6 年才足够普及,能够让开发者有信心专注于使用 Flash 开发,不过有了 Google 的支持,Gears 可能只需要用一半甚至更小的时间就能做到。
在这场竞赛中,Google 没有任何损失反而赢得盆满钵丰,Google 一下子就启动了这个新 web API 的基于标准且开源的替代方案。与其他的竞争对手不一样,Google 没有兴趣控制这个平台或者直接用来盈利。相反他们却在试图维持现状:大部分程序使用浏览器里的 Javascript 开发,如果有更多需求那就使用 Flash 或者类似的技术。
上一次平台大战结束了很久了,但是每次你都能看到类似的技术经验:大公司失败,小公司成功。给这个平衡增加点开源的砝码,结果还是没有一个单独的公司能够占优势。有这么多大公司的加入,而且如此的利益攸关,我们肯定要亲眼见证一场漫长的持久战。只有时间能够告诉我们 Google 的做法能不能带领 web 向前发展。
本文是 Nik Cubrilovic 写的下一代 web 系列中的一篇,在这阅读其他同系列文章。
下一代 web:浏览器存储支持 Sat, Jun 7. 2008
原文:The Next-Gen Web: Browser Storage Support。
下一代的 web 已经开始上路了,就在这个星期,MySpace 集成了 Google Gears,雅虎发布了新的 BrowserPlus,Google 的浏览器版三维地球也上线了。类似 AIR、Silverlight、JavaFX、Gears、XUL、Web Applications 1.0 (DOM5, HTML5 等) 这样的技术和格式让开发者能够超过 AJAX 加速冲向下一代的,有着更好的性能、更多的功能,而且和桌面集成的更加紧密的 web 程序。
现在,因为各个公司都急于展示他们自己的下一代 web 的样子,导致开发者和用户都被前所未有的超多 web 技术所压迫;“DLL 地狱”也被“插件地域”所取代。但是在 web 上,这样过多的选择会导致用户和开发者的成本增加。第一次 web 格式大战已经过去十多年了,那个时候微软、网景、苹果、美国在线还有其他公司都在浏览器标准、脚本语言、web 服务等方面成立了不同的基金会。这次大战的影响一直持续到现在,例如 Javascript 来发展需要依赖整套的代码库来开发跨浏览器代码,CSS 开发者需要一系列 hack 才能让他们的站点能够在不同的浏览器中看起来都一样。
现在新一代的富 web 程序技术还都在开发阶段,所以还有机会采用基于标准的态度,来避免重蹈覆辙。幸亏有了过去十多年的教训,现在连微软这样的公司都在以更加开放的姿态来接纳开放标准、数据迁移还有跨平台支持。不管是用户还是开发者,对开放标准的广泛支持都能简化他们用到的技术,但是明显的,并不是所有当前发布的新技术都能支持开放标准。
在 Techcrunch 这一系列帖子里,我们来看看这些组成新一代 web 的各种元素,并且评估可用的选项,当前支持的标准以及对标准的采用情况。由于 MySpace 刚刚宣布他们在程序里面使用了 Google Gears,那么我们的第一篇就来评估基于浏览器的本地缓存。
基于浏览器的本地存储
随着基于 web 的应用程序逐渐流行,就有了希望能够离线运行这些程序的需求。第一个不需要任何插件或者独立程序的解决方案是那些靠缓存 HTTP 头信息来在浏览器缓存里存储信息的方法。类似 Dojo 对离线 web 应用的支持这样的 Javascript 库使用的就是这样的原理,但是这样的程序应用范围非常狭窄,因为没有一个好的办法在浏览器里存储结构化的数据。(Dojo 现在引用了很多包括 Gears 在内的其他的存储引擎——提示:Dylan)
在 2007 年 5 月,Google 发布了Google Gears,一个浏览器插件,它允许 web 程序把数据同步到本地存储器,然后可以离线使用这些 web 程序。在 Gears 发布会上,Google Reader 被重写以支持 Gears,Gears 的突出的重点是离线访问应用程序。但是不被所知的是,Gears 不仅仅能够用来离线访问,它还提供这三大功能:
- 缓存资源(HTML 页面、图片等)
- 在数据库中存储结构化数据
- 异步后台工作线程
在这部分我们关注的是本地对象和结构化数据存储。Gears 通过 Javascript API 来提供相应的功能,这些 API 可以被任何 web 程序访问到。Sqlite,一个轻量级 RDBMS,提供了结构化存储的支持。由于使用了本地数据库,开发者不仅可以执行查询、插入新纪录这样的操作,还能执行更复杂的 SQL 操作,例如连接多表查询等。尽管你可以有多个使用 Gears 的程序,但是每个程序都要运行在一个基于域名的安全模型的沙盒环境里(类似 cookie 和 AJAX 请求)。虽然 Sqlite 已经嵌入 Firefox 2.0 以后的版本,但是它的 API 只能够被 Firefox 核心组件或者附加模块访问到。Gears 插件弥补了这个缺陷,让客户端脚本环境也能够访问到这些 API。
在 Gears 发布前,万维网超文本应用程序技术工作组 (WHATWG) 已经着手制定 Web 程序规范 1.0 草案,这个草案把结构化数据存储包括到了 HTML5 里。该草案当前版本包含了对访问数据库对象和查询本地数据存储的定义。实现的细节虽然交给了各个公司去完成,不过规范里面已经详细说明了 API 的细节。Firefox 将会在 3.0 版里实现一部分和 WHATW 规范一样的存储 API,不过这个版本现在只有预览版可用。WHATWG 规范里的关键部分有:
- 程序缓存 ——在本地浏览器缓存里存储对象(包含校验)。
- navigator.onLine——测试浏览器是否在线(使用缓存,如果需要则加上本地数据存储)。
- 存储界面和事件——用来通过 sessionStorage DOM 属性存储“名称/值”对。
- 数据库界面——用来连接本地数据库。支持 SQL语法(或者其子集,取决于使用的服务器)、版本控制和错误回调事件。
- 线程和回调——这样多个请求就能够异步发送给本地数据存储。
调用本地存储、缓存和离线访问相对来说很简单。程序首先检查是否支持相应的函数,然后通过在后台同步用户数据进程来设置本地缓存。当一个线程在运行的时候,不管是上传还是下载,你可以查询进程状态并且给用户一个反馈(例如一个进度条)。一旦数据本地化,由于是在本地机器上运行数据库,开发者就能大幅度的提高查询性能。当下很多 web 程序仅仅把浏览器用作展示层,例如,电子表格软件就是做 =1+1 这样简单的计算也要进行一次到服务器再返回的请求。通过使用本地数据存储和客户端代码,开发者可以减少到处理和存储到客户端的负荷,同时还能提供给用户更加平滑、类似桌面程序的体验。
当前和将来的支持情况
现在的问题是大部分 WHATW 规范都是在 Gears 发布后才写的,导致 Gears 使用的数据库和本地服务器对象和 WHATW 规范不兼容——至少当下是这样的。好消息是 Google 已经发现了这个问题,完全支持 WHATWG HTML5 规范中的存储部分,因此,对于那些运行在安装了 Gears 的 Firefox 3 中的程序的开发者来说,他们可以选择使用 Firefox 原生的还是 Google 实现的存储。Google 还说他们很可能会提供额外的功能,以激励开发者关注那些 Gears 超越 HTML5 的实现(例如桌面快捷方式等)。
其他的本地数据存储可选方案,例如 Flash 本地存储,和 WHATW 规范完全不兼容。WebKit 的开发人员很快声明他们也开始实现 HTML5 规范中的存储部分。而且在每晚构建的代码里已经可用了,因此很快我们就能看到 Konquror 和 Safari 对本地存储的支持。Opera 也声明了类似的计划,而且当然他实现了 HTML5 和 web 表单后他们会领先于所有人。雅虎 BrowserPlus 昨天才发布,所以现在还不明确他们他们的本地存储支持和工作组发布的规范是否兼容。
本地存储是新一代的 web API 中重要的新功能,开发者不仅有跨浏览器的一致支持,还可以选择使用 Google Gears(已经可用)还是 Yahoo! BrowserPlus(取决于它如果工作)。还有一个浏览器厂商我们到现在一直没有谈到,那就是微软。微软发布了 IE8 的一个早期预览版,而且预告了大量的新特性,其中很多都是基于开放标准的,例如更好的 CSS 和 Javascript 支持(内涵一个更加标准化的对象模型)。最大问题是,IE8 在本地存储方面会不会遵循和其他浏览器厂商一致规范。IE 开发小组声称 IE8 将会支持 DOM 存储,但是这只是全部本次存储规范的一部分(即前面提到的 Storage 对象)。
当前和将来的支持情况
| Gears | BrowserPlus | Firefox | IE8 | Webkit | |
| 程序缓存 |
很快 |
|
|
|
|
|
侦测在线与否 |
|
|
|
|
|
|
本地服务器 |
|
|
|
|
|
|
存储 |
|
|
|
|
|
|
数据库 |
|
|
|
|
|
|
线程 |
|
|
|
|
|
|
SQL |
|
|
|
|
|
注:一旦得知 BrowserPlus 的细节,我们就会完成这个表格。Google 保证 Gears 能够适应标准。IE8 宣称不完全的支持。WebKit 的每晚构建里面大部分功能都可用了。Flash 和 Silverlight 支持某种形式的本次存储但是不是 HTML5 标准 API。
一个类似本地浏览器存储这样的新技术被如此广泛的提倡和支持,而且大部分都是基于一个规范,实在是一件罕见的事情。虽然微软还没有宣称完全支持,但是毫无疑问的,他们会朝向正确的方向。Google Gears 和 Firefox 3 的实现都遵循着 HTML5 的工作组规范也是很鼓舞人心的。虽然短时间内这些新版本的浏览器不可能被广泛的使用,但是 Google Gears 已经可用了,而且,因为所有的厂商都瞄准了同样的 API,开发者现在就可以安心的锁定 Gears 存储 API 然后开工——者在不久以前还是不可能的事情。
有了本地浏览器存储和缓存,开放标准到现在为止都是赢家。而其他的替代解决方案很可能会半途而废,或者改变以实现同样的 API。
PHP 基准测试 Thu, Jun 5. 2008
原文:The PHP Benchmark | Web Resources | WebAppers。
创建 PHPBench 的目的是让你看到每一个 PHP 代码段的运行速度不都是一样的。看到 PHPBench 生成的结果,你很可能会大吃一惊。这个网站还有一个目的就是让你自己去发现一些规律,然后在你自己的服务器环境里,使用示例代码重新运行这些测试来验证你的发现。而且你还可以看到一些 PHPBench 测到的有趣的结论:
- 很奇怪的结果表明,如果你执行sizeof(),那么是否预先计算循环的次数基本上没有什么区别。
- 事实上,each 和 print 执行的功能完全一样,因此都适用于同样的代码段。有一小点需要注意的就是,当你使用逗号分隔输出列表并且使用 echo 输出,则会运行的稍微快一丁点。
- while 循环在 90% 的情况下确实能够快一点点。
需求: -
演示: http://www.phpbench.com/
协议: 自由协议
胡言乱语之男人女人 Wed, Feb 27. 2008
这年头,男人除了生孩子什么都得学会,女人还天天腻腻歪歪的不想生孩子——最近几对同学结婚有感。
--------------------结婚多可怕的分割线--------------------
去年过年时,一异性死党跟偶讨教感情问题,偶立下三个关于她有了男友之后的预言(注:其实该女当时已经有了男友,就是不说),年中时电话偶,第一个预言已经实现了。
该预言是:他二位定会在一个美好的下午,在温馨的小家里,沐浴着首都的夕阳,然后用各种高级的厨具,搭配着精致的调料,一起做出一桌幸福的晚餐——然后全都到掉,出门下馆子去。
PHP Security / Sessions / Session Fixation Sun, Jul 1. 2007
Session Fixation
会话固定攻击
Session security is a sophisticated topic, and it's no surprise that sessions are a frequent target of attack. Most session attacks involve impersonation, where the attacker attempts to gain access to another user's session.
会话安全是一个老生常谈的话题了,会话作为一个常见的攻击目标一点也不稀奇。 绝大多数的会话攻击都用的是会话伪装,攻击者要试图用这种方法访问另外一个用户的会话。
The most crucial piece of information for an attacker is the session identifier, because this is required for any impersonation attack. There are three common methods used to obtain a valid session identifier:
对于攻击者来说,最重要的信息就是会话 ID,因为这对任何伪装攻击都是非常重要的。 要想得到一个合法的会话 ID,有三种常见的办法:
- Prediction
- Capture
- Fixation
- 预测
- 捕获
- 固定
Prediction refers to guessing a valid session identifier. With PHP's native session mechanism, the session identifier is extremely random, and this is unlikely to be the weakest point in your implementation.
预测就是猜想一个合法会话 ID。根据 PHP 原生的会话机制,会话 ID 非常的随机, 所以不太可能是你程序的最薄弱的环节。
Capturing a valid session identifier is the most common type of session attack, and there are numerous approaches. Because session identifiers are typically propagated in cookies or as GET variables, the different approaches focus on attacking these methods of transfer. While there have been a few browser vulnerabilities regarding cookies, these have mostly been Internet Explorer, and cookies are slightly less exposed than GET variables. Thus, for those users who enable cookies, you can provide them with a more secure mechanism.
捕获一个合法的会话 ID 是会话攻击中最常用的方法,而且有很多不同的方式。 因为会话 ID 通常都是通过 cookie 或者 GET 变量传递, 所以各种攻击方法的区别之处就在于攻击哪种传输 ID 的方法。 虽然有几个关于处理 cookie 的浏览器漏洞,IE 的漏洞最多, 而且比起 GET 变量来,cookie 不太可能被暴露。 所以,对于那些启用了 cookie 的用户,你可以给他们提供更安全的会话机制。
Fixation is the simplest method of obtaining a valid session identifier. While it's
not very difficult to defend against, if your session mechanism consists of nothing
more than session_start(), you are vulnerable.
会话固定是得到一个合法的会话 ID 的最简单的方法。
虽然防御这种攻击不是很难,但是如果你的会话机制只使用了 session_start() 的话,
你的系统非常容易受到攻击。
In order to demonstrate session fixation, I will use the following script,
session.php:
我用下面这个 session.php 脚本来示范一下会话固定:
- <?php
- {
- $_SESSION['visits'] = 1;
- }
- else
- {
- $_SESSION['visits']++;
- }
- echo $_SESSION['visits'];
- ?>
Upon first visiting the page, you should see 1 output to the screen. On each
subsequent visit, this should increment to reflect how many times you have
visited the page.
在你第一次访问这个页面的时候,你应该能够看到屏幕上输出的 1。
接下来的每一次访问,这个输出结果应该每次加一,以反映你访问了这个页面多少次。
To demonstrate session fixation, first make sure that you do not have an existing
session identifier (perhaps delete your cookies), then visit this page with
?PHPSESSID=1234 appended to the URL. Next, with a completely different
browser (or even a completely different computer), visit the same URL again with
?PHPSESSID=1234 appended. You will notice that you do not see 1 output on
your first visit, but rather it continues the session you previously initiated.
为了演示会话固定攻击,首先要确保你现在没有任何已存在的会话 ID(可以试着删除 cookie),
然后访问这个页面,访问的时候在 URL 后面附加上 ?PHPSESSID=1234。
然后,用一个完全不同的浏览器(最好换一台计算机),同样在 URL 后面附加上 ?PHPSESSID=1234
再次访问这个页面。你会发现你在首次访问的时候看见的输出不是 1,
而是继续刚才初始化的那个会话。
Why can this be problematic? Most session fixation attacks simply use a link or a protocol-level redirect to send a user to a remote site with a session identifier appended to the URL. The user likely won't notice, since the site will behave exactly the same. Because the attacker chose the session identifier, it is already known, and this can be used to launch impersonation attacks such as session hijacking.
为什么会话固定会成问题?大多数会话固定攻击者都是简单的使用一个链接, 或者一个协议层的重定向来给远程站点发送用户信息,也是通过在 URL 后面附加会话 ID 的方法。 因为这个站点的行为完全的一样,所以用户不太可能注意到。 又因为会话 ID 是攻击者选定的,这是已知的,所以这可以用来发动更加类似会话劫持这样的攻击。
A simplistic attack such as this is quite easy to prevent. If there isn't an active session associated with a session identifier that the user is presenting, then regenerate it just to be sure:
我们可以很容易的防范这种非常简单的攻击。如果用户提供了一个会话 ID, 但是没有任何活动的会话与之相关联,那么就重新声称一个 ID 以确保保险。
- <?php
- {
- $_SESSION['initiated'] = true;
- }
- ?>
The problem with such a simplistic defense is that an attacker can simply initialize a session for a particular session identifier, and then use that identifier to launch the attack.
这种简单的防御有一个问题,就是攻击者很容易就能初始化一个有着特定 ID 的会话, 然后用这个 ID 来发动攻击。
To protect against this type of attack, first consider that session hijacking is only really useful after the user has logged in or otherwise obtained a heightened level of privilege. So, if we modify the approach to regenerate the session identifier whenever there is any change in privilege level (for example, after verifying a username and password), we will have practically eliminated the risk of a successful session fixation attack.
要防御这种类型的攻击首先要考虑的是会话劫持只有在用户登录了,或者得到了更高权限后才能发挥作用。 所以,如果我们在权限状态发生任何变化(例如,确认和用户名和密码)后都重新生成会话 ID, 这样就能够消除因为成功的会话固定攻击所带来的风险。
PHP Security / Databases and SQL / SQL Injection Tue, Jun 19. 2007
SQL Injection
SQL 注入
SQL injection attacks are extremely simple to defend against, but many applications are still vulnerable. Consider the following SQL statement:
SQL 注入攻击很容易就能防范,但是很多程序在这方面还是很脆弱的。 看下面的 SQL 语句:
- <?php
- $sql = "INSERT
- INTO users (reg_username,
- reg_password,
- reg_email)
- VALUES ('{$_POST['reg_username']}',
- '$reg_password',
- '{$_POST['reg_email']}')";
- ?>
This query is constructed with $_POST, which should immediately look
suspicious.
这个查询使用 $_POST 进行构造,这样一眼就能够看出问题。
Assume that this query is creating a new account. The user provides a desired username and an email address. The registration application generates a temporary password and emails it to the user to verify the email address. Imagine that the user enters the following as a username:
假设这个查询时用来创建新帐号用的。用户指定他们想要用户名和 email 地址。 然后注册程序生成一个临时密码并且发送给用户以验证 email 地址。 假设用户输入了一个这样的用户名;
bad_guy', 'mypass', ''), ('good_guy
This certainly doesn't look like a valid username, but with no data filtering in
place, the application can't tell. If a valid email address is given
(shiflett@php.net, for example), and 1234 is what the application generates
for the password, the SQL statement becomes the following:
这个用户名看起来肯定不是一个合法的用户名,但是如果没有适当的数据过滤,
程序是区分不出来的。如果给定了一个合法的 email 地址(例如 shiflett@php.net),
程序生成的密码是 1234,那么这个 SQL 语句就变成下面这个样子:
- <?php
- $sql = "INSERT
- INTO users (reg_username,
- reg_password,
- reg_email)
- VALUES (' bad_guy', 'mypass', ''),
- ('good_guy',
- '1234',
- 'shiflett@php.net')";
- ?>
Rather than the intended action of creating a single account (good_guy) with a
valid email address, the application has been tricked into creating two accounts,
and the user supplied every detail of the bad_guy account.
本来预期的动作是创建一个有合法 email 地址的单一帐号(good_guy),
但是程序实际上被欺骗而创建了两个帐号,而且用户还指定了 bad_guy 帐号的所有信息。
While this particular example might not seem so harmful, it should be clear that worse things could happen once an attacker can make modifications to your SQL statements.
虽然这个特定的例子看起来没有那么大的危害,但是这说明了一旦攻击者能够修改你的 SQL 语句, 不定发生什么糟糕的事情呢。
For example, on the database you are using, it might be possible to send multiple queries to the database server in a single call. Thus, a user can potentially terminate the existing query with a semicolon and follow this with a query of the user's choosing.
例如,根据你用的数据库,很可能允许在一次调用中发送多个查询请求。 这样,用户就可能能够用一个分号终止当前的查询,然后紧跟着加入用户所选择的查询。
MySQL, until recently, does not allow multiple queries, so this particular risk is
mitigated. Newer versions of MySQL allow multiple queries, but the
corresponding PHP extension (ext/mysqli) requires that you use a separate
function if you want to send multiple queries (mysqli_multi_query() instead
of mysqli_query()). Only allowing a single query is safer, because it limits
what an attacker can potentially do.
到目前为止,MySQL 还不允许多重查询,所以这个特定的风险倒是不大。
MySQL 的新版支持多重查询,不过对应的 PHP 扩展(ext/mysqli)
要求你在希望进行多重查询的时候使用单独的函数(用 mysqli_multi_query() 替代 mysqli_query())。
因为单一查询能够限制攻击者可能做的事情,所以使用单一查询更加安全。
Protecting against SQL injection is easy:
防范 SQL 注入还是很简单的:
-
Filter your data.
This cannot be overstressed. With good data filtering in place, most security concerns are mitigated, and some are practically eliminated.
-
过滤数据。
这是绝对不能被越过的。如果在适当的地方有很好的数据过滤, 大多数安全隐患都能够减轻,甚至差不多都能够消除。
-
Quote your data.
If your database allows it (MySQL does), put single quotes around all values in your SQL statements, regardless of the data type.
-
给数据加引号。
如果你的数据库支持,在 SQL 语句里给所有的值都加上单引号,不管是什么类型的数据。
-
Escape your data.
Sometimes valid data can unintentionally interfere with the format of the SQL statement itself. Use
mysql_escape_string()or an escaping function native to your particular database. If there isn't a specific one,addslashes()is a good last resort. -
数据转义。
有一些数据,虽然是合法的,但是可能会在无意中和 SQL 语句的格式产生冲突。 那么就使用
mysql_escape_string()函数,或者你的数据库原生的转义函数进行数据转义。 如果没有特定的转义函数,addslashes()是最后手段。
PHP Security / Databases and SQL / Exposed Access Credentials Mon, Jun 18. 2007
Exposed Access Credentials
连接信息泄漏
Most PHP applications interact with a database. This usually involves connecting to a database server and using access credentials to authenticate:
绝大多数的 PHP 程序都要和数据库交互。 这个交互过程通常都是首先连接到数据数据库,然后通过连接信息认证。
- <?php
- $host = 'example.org';
- $username = 'myuser';
- $password = 'mypass';
- ?>
This could be an example of a file called db.inc that is included whenever a
connection to the database is needed. This approach is convenient, and it keeps
the access credentials in a single file.
这可以作为一个用来演示 db.inc 文件的例子,你可以在任何需要数据库连接的时候引用这个文件。
这样就可以把连接信息保存在单一文件里,这倒是挺方便的。
Potential problems arise when this file is somewhere within document root. This
is a common approach, because it makes include and require statements
much simpler, but it can lead to situations that expose your access credentials.
如果你把这个文件放在文档根目录里面的话,潜在的问题就会显现出来。
这样放是很常见的,因为能够让 include 和 require 语句写起来很简单,
但是这会引起连接信息的泄露。
Remember that everything within document root has a URL associated with it.
For example, if document root is /usr/local/apache/htdocs, then a file
located at /usr/local/apache/htdocs/inc/db.inc has a URL such as
http://example.org/inc/db.inc.
请记住,在文档根目录里面的所有文件都有一个对应的 URL。
例如,如果文档根目录是 /usr/local/apache/htdocs,
那么一个位于 /usr/local/apache/htdocs/inc/db.inc 的文件,
就对应着一个类似 http://example.org/inc/db.inc 这样的 URL。
Combine this with the fact that most Web servers will serve .inc files as plain
text, and the risk of exposing your access credentials should be clear. A bigger
problem is that any source code in these modules can be exposed, but access
credentials are particularly sensitive.
大多数 Web 服务器都把 .inc 文件作为普通文本处理,把这个事实和上面的规则一起考虑,
由于泄露连接信息所引发的风险就很明了了。
还有一个更大的问题,就是任何在这些模块里面的源代码都有泄露的可能,
当然了,连接信息是最为敏感的。
Of course, one simple solution is to place all modules outside of document root,
and this is a good practice. Both include and require can accept a filesystem
path, so there's no need to make modules accessible via URL. It is an
unnecessary risk.
当然了,一个简单但是很好的解决方法就是把这些模块都放到文档根目录外面。
include 和 require 语句都能够接受文件系统路径作为参数,
因此,没有必要让人通过 URL 访问这些模块。这是一个不必要的风险。
If you have no choice in the placement of your modules, and they must be within
document root, you can put something like the following in your httpd.conf file
(assuming Apache):
如果你无法选择放置这些模块的地方,而且必须放置到文档根目录里,
那么你可以在你的 httpd.conf 文件(假设你使用的是 Apache 服务器)里增加如下语句:
- <Files ~ "\.inc$">
- Order allow, deny
- Deny from all
- </Files>
It is not a good idea to have your modules processed by the PHP engine. This
includes renaming your modules with a .php extension as well as using
AddType to have .inc files treated as PHP files. Executing code out of context
can be very dangerous, because it's unexpected and can lead to unknown
results. However, if your modules consist of only variable assignments (as an
example), this particular risk is mitigated.
允许 PHP 引擎直接处理这些模块可不是什么好主意。
这包括如下两个方面,一、把你的模块都命名为使用 .php 扩展名的文件名,
二、通过 AddType 指令让 Apache 把 .inc 等同于 PHP 文件处理。
在上下文外的环境执行这些代码很可能会很危险,因为这不是所预期的,而且可能会引起未知的后果。
不过,如果这个模块只由一些变量赋值语句组成(就像上面的例子一样),这个风险还是很小的。
My favorite method for protecting your database access credentials is described
in the PHP Cookbook (O'Reilly) by David Sklar and Adam Trachtenberg. Create
a file, /path/to/secret-stuff, that only root can read (not nobody) :
我最喜欢使用 David Sklar and Adam Trachtenberg 写的 《PHP指导手册》(由 O'Reilly 出版)
一书中的方法来保护数据的连接信息。
创建一个文件 /path/to/secret-stuff,
这个文件只有 root(而不是 nobody)能够访问到。
- SetEnv DB_USER "myuser"
- SetEnv DB_PASS "mypass"
Include this file within httpd.conf as follows:
像下面这样把这个文件包含在 httpd.conf 里:
- Include "/path/to/secret-stuff"
Now you can use $_SERVER['DB_USER'] and $_SERVER['DB_PASS'] in
your code. Not only do you never have to write your username and password in
any of your scripts, the Web server can't read the secret-stuff file, so no
other users can write scripts to read your access credentials (regardless of
language). Just be careful not to expose these variables with something like
phpinfo() or print_r($_SERVER).
现在,你可以在程序里面直接使用 $_SERVER['DB_USER'] 和 $_SERVER['DB_PASS']。
不仅你不用在任何程序里直接写用户名和密码,而且 Web 服务器也读不到 secret-stuff 文件,
这样,没有人能够写程序访问到你的连接信息了(不管是什么语言)。
只需要小心不要让类似 phpinfo() 或 print_r($_SERVER) 这样的代码暴露这些变量信息。






