<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="css/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>AUG Team</title><link>http://www.augweb.net/blog/</link><description>welcome。。。</description><generator>RainbowSoft Studio Z-Blog 1.8 Walle Build 100427</generator><language>zh-CN</language><copyright>Copyright @ 2003-2008 AUG.(专业网站建设 北京) All Rights Reserved.</copyright><pubDate>Wed, 22 Dec 2010 16:21:53 +0800</pubDate><item><title>Coldfusion MX XML-RPC Component</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/236.html</link><pubDate>Sun, 19 Dec 2010 21:53:31 +0800</pubDate><guid>http://www.augweb.net/blog/post/236.html</guid><description><![CDATA[<h5>Coldfusion MX XML-RPC Component</h5><blockquote>I've decided to release this little component to the world for two reasons:<ol>    <li>There is a scary dearth of CF-related <a href="http://xmlrpc.org/">XML-RPC</a> info out there. Aside from a <a href="http://www.macromedia.com/cfusion/exchange/index.cfm?view=sn131&amp;extID=1002479">CF5 custom tag</a> that relied on a special installation of MSXML (I never managed to get it working, personally), there have been no tools available. And aside from a Java-centric couple articles in <a href="http://www.sys-con.com/coldfusion/">CFDJ</a>, no one is talking about it. The Flash community is <a href="http://sourceforge.net/projects/xmlrpcflash/">way ahead of us</a> on this one, and we need to catch up.</li>    <li>I searched my ass off, looking for guidance on kick-starting XML-RPC support in CFMX. I found nothing but obscure bugs and &quot;I have no idea&quot; responses. With any luck, the next person down the line won't have to spend as much time scratching her head.</li></ol><p>DESCRIPTION:</p><p>The XML-RPC CFC (Coldfusion Component) streamlines the conversion of XML-RPC packages to and from CFML data structures. It is to XML-RPC payloads as CFWDDX is to WDDX packets. You don't need to know anything about CFMX's XML parsing abilities to use it, either.</p><p>REQUIREMENTS:</p><p>A Coldfusion MX server running Updater 3+. (Previous CFMX releases had a GetHttpRequestData() bug that kept you from getting at the raw request info you need for XML-RPC.)</p><p>DOWNLOAD:</p><p><a href="http://www.journurl.com/support/users/admin/cfmx/xmlrpc.zip">xmlrpc.zip</a> (2,146 bytes)</p><div class="wlWriterEditableSmartContent" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:453e0229-f612-4cb4-97d0-0e8f03658430" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><p><a target="_blank" href="http://www.augweb.net/blog/UPLOAD/2010/12/ColdfusionMXXMLRPCComponent_13249/xmlrpc_4.cfc">xmlrpc.cfc</a></p></div><p>EXAMPLES:</p><p><code>&lt;cfinvoke component=&quot;pathtopackage.xmlrpc&quot;&nbsp; <br />&nbsp;&nbsp; method=&quot;XMLRPC2CFML&quot; <br />&nbsp;&nbsp; returnvariable=&quot;rpcCall&quot; <br />&nbsp;&nbsp; data=&quot;#GetHttpRequestData().content#&quot;&gt;</code></p><p>This will take any incoming XML-RPC packet and convert it into a CFML struct with two members:</p><ul>    <li><em>rpcCall.method</em> (The name of the XML-RPC method that is being called.)</li>    <li><em>rpcCall.params</em> (An array of params containing input data. Per the XML-RPC spec, any of these params may contain complex data types like nested arrays and structs.)</li></ul><p><code>&lt;cfinvoke component=&quot;pathtopackage.xmlrpc&quot;&nbsp; <br />&nbsp;&nbsp;&nbsp; method=&quot;CFML2XMLRPC&quot; <br />&nbsp;&nbsp;&nbsp; returnvariable=&quot;rpcCall&quot; <br />&nbsp;&nbsp;&nbsp; data=&quot;#myArray#&quot; <br />&nbsp;&nbsp;&nbsp; type=&quot;responsefault&quot;&gt;</code></p><p>This is the complimentary opposite of the first method. It takes a CFML array and converts it into an XML-RPC package that you can subsequently send to another client or server. The contents of the array should vary depending upon the value of the <em>type</em> attribute.</p><p>(NOTE: Due to CFML's loosely-typed variables, you may run into problems when serializing data for a web service or client that is expecting specific types. <a href="http://support.journurl.com/#datatypes">See below for details</a>.)</p><ul>    <li><em>type=&quot;call&quot; <br />    </em>You'll use this <em>type</em> when your app is acting as a client of an external web service.    <ul>        <li><em>myArray[1]</em> should be a string containing the name of the requested XML-RPC method.</li>        <li><em>myArray[2]</em> and beyond can contain data of the types defined in the <a href="http://www.xmlrpc.com/spec">spec</a>. Each of these array elements will be transformed into top level params in the resulting package.</li>    </ul>    </li>    <li><em>type=&quot;response&quot;</em> <br />    You'll use this <em>type</em> when your app is returning data to a client in response to a method call.    <ul>        <li><em>myArray[1]</em> should be the only element in the array. It can contain data of the types defined in the spec.</li>    </ul>    </li>    <li><em>type=&quot;responsefault&quot;</em> <br />    You'll use this type when your app is reporting an error to a client.    <ul>        <li><em>myArray[1]</em> should be an integer representing an error code.</li>        <li><em>myArray[2]</em> should be a string that describes the error.</li>    </ul>    </li></ul><p><a name="datatypes">DATATYPE ISSUES:</a></p><p>CFML's variables are loosely typed, as you're no doubt aware. XML-RPC expects narrowly defined types in its input and output. This creates a problem.</p><p>For example, the number 324 is just a numeric variable. It could be a floating point, it could be an integer. Hey, it could be a string in many cases. I went through about a dozen iterations of the private <em>serialize()</em> method, trying to sort out all the possible priorities and the problems they created. In the end, I gave up and cheated. Here's how it works:</p><ul>    <li>An array is always interpreted as an &lt;array&gt;.</li>    <li>A struct is always interpreted as a &lt;struct&gt;.</li></ul><p>So far so good, right?</p><ul>    <li>If a variable passes an <em>isNumeric()</em> test, it is an XML-RPC &lt;double&gt; value. It could really be an &lt;int&gt; or a &lt;boolean&gt; or a &lt;string&gt;, but by default, it's a &lt;double&gt;.</li>    <li>To force your variable to map to a different element, treat the contents of your variable as a string and prepend the name of the desired element and a dollar sign ($) like so:    <ul>        <li><code>&lt;cfset myvar = &quot;0&quot;&gt; <br />        &lt;cfset myvar = &quot;$boolean&quot; &amp; myvar&gt;</code></li>        <li><code>&lt;cfset myvar = 324&gt; <br />        &lt;cfset myvar = &quot;$i4&quot; &amp; myvar&gt;</code></li>        <li><code>&lt;cfset myvar = &quot;435644543.09&quot;&gt; <br />        &lt;cfset myvar = &quot;$string&quot; &amp; myvar&gt;</code></li>    </ul>    </li>    <li>If a variable does not pass an <em>isNumeric()</em> test but does pass an <em>isDate()</em> test, it is an XML-RPC &lt;dateTime.iso8601&gt; value. Even if you meant for it to be a &lt;string&gt;, by default, it's a date.</li>    <li>To force the variable to map to a &lt;string&gt;, follow the same procedure set out above... prepend &quot;$string&quot; to the contents of your variable.</li></ul><p>Yeah, I know. It's ugly. If you come up with something better, send it to me.</p><p>NOTES:</p><ul>    <li>To help with your first Adventures in XML-RPC, be sure to read the <a href="http://www.xmlrpc.com/spec">spec</a>, and test your server against an <a href="http://www.dscpl.com.au/xmlrpc-debugger.php">XML-RPC debugger</a>.</li></ul></blockquote>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/236.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=236</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=236&amp;key=76cfd1ef</trackback:ping></item><item><title>PHP中的魔术方法总结</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/235.html</link><pubDate>Sun, 19 Dec 2010 17:45:18 +0800</pubDate><guid>http://www.augweb.net/blog/post/235.html</guid><description><![CDATA[<p>PHP中的魔术方法总结 :__construct, __destruct , __call, __callStatic,__get, __set, __isset, __unset , __sleep, __wakeup, __toString, __set_state, __clone and __autoload</p><p><strong>1、__get、__set</strong> <br />这两个方法是为在类和他们的父类中没有声明的属性而设计的 <br />__get( $property ) 当调用一个未定义的属性时访问此方法 <br />__set( $property, $value ) 给一个未定义的属性赋值时调用 <br />这里的没有声明包括当使用对象调用时，访问控制为proteced,private的属性（即没有权限访问的属性） <br /><strong>2、__isset、__unset</strong> <br />__isset( $property ) 当在一个未定义的属性上调用isset()函数时调用此方法 <br />__unset( $property ) 当在一个未定义的属性上调用unset()函数时调用此方法 <br />与__get方法和__set方法相同，这里的没有声明包括当使用对象调用时，访问控制为proteced,private的属性（即没有权限访问的属性） <br /><strong>3、__call</strong> <br />__call( $method, $arg_array ) 当调用一个未定义的方法是调用此访求 <br />这里的未定义的方法包括没有权限访问的方法</p><p><strong>4、__autoload</strong> <br />__autoload 函数，它会在试图使用尚未被定义的类时自动调用。通过调用此函数，脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。 <br />注意: 在 __autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。</p><p><strong>5、__construct、__destruct</strong> <br />__construct 构造方法，当一个对象创建时调用此方法，使用此方法的好处是：可以使构造方法有一个独一无二的名称,无论它所在的类的名称是什么.这样你在改变类的名称时,就不需要改变构造方法的名称 <br />__destruct 析构方法，PHP将在对象被销毁前（即从内存中清除前）调用这个方法 <br />默认情况下,PHP仅仅释放对象属性所占用的内存并销毁对象相关的资源. <br />析构函数允许你在使用一个对象之后执行任意代码来清除内存. <br />当PHP决定你的脚本不再与对象相关时,析构函数将被调用. <br />在一个函数的命名空间内,这会发生在函数return的时候. <br />对于全局变量,这发生于脚本结束的时候.如果你想明确地销毁一个对象,你可以给指向该对象的变量分配任何其它值.通常将变量赋值勤为NULL或者调用unset. <br /><strong>6、__clone</strong> <br />PHP5中的对象赋值是使用的引用赋值，如果想复制一个对象则需要使用clone方法，在调用此方法是对象会自动调用__clone魔术方法 <br />如果在对象复制需要执行某些初始化操作，可以在__clone方法实现 <br /><strong>7、__toString </strong><br />__toString方法在将一个对象转化成字符串时自动调用，比如使用echo打印对象时 <br />如果类没有实现此方法，则无法通过echo打印对象，否则会显示：Catchable fatal error: Object of class test could not be converted to string in <br />此方法必须返回一个字符串</p><p>在PHP 5.2.0之前，__toString方法只有结合使用echo() 或 print()时 才能生效。PHP 5.2.0之后，则可以在任何字符串环境生效（例如通过printf()，使用%s修饰符），但 不能用于非字符串环境（如使用%d修饰符）。从PHP 5.2.0，如果将一个未定义__toString方法的对象 转换为字符串，会报出一个E_RECOVERABLE_ERROR错误。 <br /><strong>8、__sleep、__wakeup</strong> <br />__sleep 串行化的时候用 <br />__wakeup 反串行化的时候调用 <br />serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样，该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。 <br />使用 __sleep 的目的是关闭对象可能具有的任何数据库连接，提交等待中的数据或进行类似的清除任务。此外，如果有非常大的对象而并不需要完全储存下来时此函数也很有用。 <br />相反地，unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在，此函数可以重建对象可能具有的任何资源。 <br />使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。 <br /><strong>9、__set_state</strong> <br />当调用var_export()时，这个静态 方法会被调用（自PHP 5.1.0起有效）。 <br />本方法的唯一参数是一个数组，其中包含按array(&rsquo;property&rsquo; =&gt; value, &hellip;)格式排列的类属性。 <br /><strong>10、__invoke</strong> <br />当尝试以调用函数的方式调用一个对象时，__invoke 方法会被自动调用。 <br />PHP5.3.0以上版本有效 <br /><strong>11、__callStatic</strong> <br />它的工作方式类似于 __call() 魔术方法，__callStatic() 是为了处理静态方法调用， <br />PHP5.3.0以上版本有效 <br />PHP 确实加强了对 __callStatic() 方法的定义；它必须是公共的，并且必须被声明为静态的。同样，__call() 魔术方法必须被定义为公共的，所有其他魔术方法都必须如此。</p><p>&lt;? <br />/*当试图调用类中一个不存在或者不可用的方法时，会执行该类中的__call（）__call（）必须接受两个参数，第一个参数存放方法名称，第二个参数存放不存在的方法的参数（此参数会放在与该参数同名的数组中）*/ <br />class callclass <br />&nbsp;&nbsp; { <br />function __call($method_name,$p) <br />&nbsp;&nbsp;&nbsp; { <br />echo &quot;使用__call尝试调用一个不存在/不可用的成员方法&lt;br&gt;&quot;; <br />echo $method_name; <br />echo &quot;&lt;pre&gt;&quot;; <br />print_r($p); <br />echo &quot;&lt;/pre&gt;&quot;; <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp; } <br />$obj = new callclass(); <br />$obj-&gt;method(1,2,&quot;Hello&quot;,&quot;HP&quot;) <br />?&gt; <br />&lt;? <br />/* 当试图调用不存在或者不可见的属性时，调用__set(),必须要接受两个参数，属性名和属性值*/ <br />class myShop&nbsp; <br />{ <br />private $p = array(); <br />function __set($name,$value) <br />&nbsp; { <br />echo 'set::属性名称:'.$name; <br />echo 'set::属性值为:'.$value;echo &quot;&lt;br&gt;&quot;; <br />$this-&gt;p[$name] = $value; <br />&nbsp;&nbsp; } <br />function __get($name) //取得属性的名称 <br />&nbsp; { <br />echo &quot;get::$name&lt;br&gt;&quot;; <br />return array_key_exists($name,$this-&gt;p) ? $this-&gt;p[$name] : null; <br />&nbsp; } <br />} <br />$shop = new myShop(); <br />$shop-&gt;feiker=2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //访问不存在的属性,调用__set()； <br />$shop-&gt;pear = 5; <br />$shop-&gt;pear ++;&nbsp; //先调用__get(),因一开始只有名字，之后调用__set(); <br />echo $shop-&gt;feiker; <br />echo $shop-&gt;pear; <br />echo '------------------------------------------------------------------------------------------'.&quot;&lt;br&gt;&quot;; <br />?&gt; <br />&lt;? <br />//__unset()和__isset() <br />class person <br />&nbsp;&nbsp; {//私有属性 <br />private $name,$sex,$age; <br />function __get($property_name) <br />&nbsp;&nbsp;&nbsp; {//获取私有属性的名称 <br />if ( isset( $property_name ) ) echo $this-&gt;$property_name; <br />&nbsp;&nbsp;&nbsp; } <br />function __set($property_name,$value) <br />&nbsp;&nbsp;&nbsp; { <br />$this-&gt;$property_name = $value; <br />echo &quot;名称为:{$property_name}值为:{$value}&lt;br&gt;&quot;; <br />&nbsp;&nbsp;&nbsp; } <br />function __isset($ff) <br />&nbsp;&nbsp;&nbsp; {//__isset() <br />echo &quot;isset()函数测定私有成员属性是，自动调用&lt;br&gt;&quot;; <br />return isset($this-&gt;$ff); <br />&nbsp;&nbsp;&nbsp; } <br />function __unset($kk) <br />&nbsp;&nbsp;&nbsp; {//__unset() <br />echo &quot;unset()是当在类的外部调用是，自动调用方法来删除私有成员变量&lt;br&gt;&quot;; <br />unset($this-&gt;$kk); <br />&nbsp;&nbsp;&nbsp; } <br />function a() <br />&nbsp;&nbsp;&nbsp; { <br />echo 'bb'.$this-&gt;name; <br />&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp; } <br />$obj = new person(); <br />$obj-&gt;name = &quot;飞客&quot;; <br />//isset()测定私有成员变量 <br />isset($obj-&gt;name); <br />//自动调用删除私有成员变量 <br />unset($obj-&gt;name); <br />echo $obj-&gt;a(); <br />//echo 'aaa'.$obj-&gt;name.'bbb';&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //result : 飞客aaabbb <br />?&gt;</p>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/235.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=235</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=235&amp;key=416ddfc7</trackback:ping></item><item><title>PHP中使用XML-RPC构造Web Service简单入门</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/234.html</link><pubDate>Fri, 17 Dec 2010 14:50:08 +0800</pubDate><guid>http://www.augweb.net/blog/post/234.html</guid><description><![CDATA[<p>&nbsp;</p><p><strong>[&nbsp; Web Service介绍 ]</strong></p><p>Web Service就是为了异构系统的通信而产生的，它基本的思想就是使用基于XML的HTTP的远程调用提供一种标准的机制，而省去建立一种新协议的需求。目前进行Web Service通信有两种协议标准，一种是XML-RPC，另外一种是SOAP。XML-RPC比较简单，出现时间比较早，SOAP比较复杂，主要是一些需要稳定、健壮、安全并且复杂交互的时候使用。</p><p>PHP中集成了XML-RPC和SOAP两种协议的访问，都是集中在xmlrpc扩展当中。另外，在PHP的PEAR中，不管是PHP 4还是PHP 5，都已经默认集成了XML-RPC扩展，而且该扩展跟xmlrpc扩展无关，能够独立实现XML-RPC的协议交互，如果没有xmlrpc扩展，建议使用PEAR::XML-RPC扩展。</p><p>我们这里主要是以XML-RPC来简单描述Web Service的交互过程，部分内容来自PHP手册，更详细内容，建议参考手册。</p><p><strong>[&nbsp; 安装xmlrpc扩展 ]</strong></p><p>如果你的系统中没有安装xmlrpc的php扩展，那么请正确安装。</p><p>在Windows平台下，首先把PHP安装目录下的扩展php_xmlrpc.dll放到C:\Windows或者C:\Winnt目录下，(PHP4的扩展在C:\php\extensions目录中，PHP5的扩展在C:\php\ext目录中)，同时在C:\Windows\php.ini或者C:\Winnt\php.ini中把extension=php_xmlrpc.dll前面的分号&quot;;&quot;去掉，然后重启Web服务器后查看phpinfo()有没有XML-RPC项目就能够确定是否已经正确安装xmlrpc扩展。</p><p>在Unix/Linux平台下，如果没有安装xmlrpc扩展，请在重新编译PHP，在configure的时候请加入 --with-xmlrpc 选项，然后查看phpinfo()看是否正常安装xmlrpc。</p><p>(注意：以下操作都是建立在xmlrpc扩张正常安装前提下，请务必正确安装。)</p><p><strong>[&nbsp; XML-RPC工作原理 ]</strong></p><p>XML-RPC大致就是整个过程就是使用XML来进行通信。首先构造一个RPC 服务器端用来出来从RPC客户端传递过来的使用XML封装的请求，并且把处理结果通过XML的形式返回给RPC客户端，客户端就去分析XML获取自己需要的数据。</p><p>XML-RPC的服务器端必须有现成的函数提供给客户端调用，并且客户端提交的请求中的函数和方法必须和服务器端的一致，否则将无法获取所需要的结果。</p><p>下面我进行简单的代码来描述整个过程。</p><p><strong>[&nbsp; XML-RPC实践 ]</strong></p><p>服务器端使用xmlrpc_server_create函数产生一个服务器端，然后把需要需要暴露的RPC调用接口进行注册，接受RPC客户端POST过来的XML数据，然后进行处理，处理结果通过XML的形式显示给客户端。</p><p>代码如下： rpc_server.php</p><p>&lt;?php <br />/** <br />* 函数：提供给RPC客户端调用的函数 <br />* 参数： <br />* $method 客户端需要调用的函数 <br />* $params 客户端需要调用的函数的参数数组 <br />* 返回：返回指定调用结果 <br />*/ <br />function rpc_server_func($method, $params) { <br />$parameter = $params[0]; <br />&nbsp;&nbsp; if ($parameter == &quot;get&quot;) <br />&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $return = 'This data by get method'; <br />&nbsp;&nbsp; } <br />&nbsp;&nbsp; else <br />&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $return = 'Not specify method or params'; <br />&nbsp;&nbsp; } <br />&nbsp;&nbsp; return $return; <br />}</p><p>//产生一个XML-RPC的服务器端 <br />$xmlrpc_server = xmlrpc_server_create();</p><p>//注册一个服务器端调用的方法rpc_server，实际指向的是rpc_server_func函数 <br />xmlrpc_server_register_method($xmlrpc_server, &quot;rpc_server&quot;, &quot;rpc_server_func&quot;);</p><p>//接受客户端POST过来的XML数据 <br />$request = $HTTP_RAW_POST_DATA;</p><p>//执行调用客户端的XML请求后获取执行结果 <br />$xmlrpc_response = xmlrpc_server_call_method($xmlrpc_server, $request, null);</p><p>//把函数处理后的结果XML进行输出 <br />header('Content-Type: text/xml'); <br />echo $xmlrpc_response;</p><p>//销毁XML-RPC服务器端资源 <br />xmlrpc_server_destroy($xmlrpc_server); <br />?&gt;</p><p>服务器端构造好了，那么再构造我们的RPC客户端。客户端大致通过Socket访问XML-RPC服务器端的80端口，然后把需要调用的RPC接口封装到XML里，通过POST请求提交给RPC服务器端，最后获取服务器端返回结果。</p><p>代码如下：rpc_client.php</p><p>&lt;?php <br />/** <br />* 函数：提供给客户端进行连接XML-RPC服务器端的函数 <br />* 参数： <br />* $host&nbsp; 需要连接的主机 <br />* $port&nbsp; 连接主机的端口 <br />* $rpc_server XML-RPC服务器端文件 <br />* $request&nbsp; 封装的XML请求信息 <br />* 返回：连接成功成功返回由服务器端返回的XML信息，失败返回false <br />*/ <br />function rpc_client_call($host, $port, $rpc_server, $request) {</p><p>&nbsp;&nbsp; //打开指定的服务器端 <br />&nbsp;&nbsp; $fp = fsockopen($host, $port);</p><p>&nbsp;&nbsp; //构造需要进行通信的XML-RPC服务器端的查询POST请求信息 <br />&nbsp;&nbsp; $query = &quot;POST $rpc_server HTTP/1.0\nUser_Agent: XML-RPC Client\nHost: &quot;.$host.&quot;\nContent-Type: text/xml\nContent-Length: &quot;.strlen($request).&quot;\n\n&quot;.$request.&quot;\n&quot;;</p><p>&nbsp;&nbsp; //把构造好的HTTP协议发送给服务器，失败返回false <br />&nbsp;&nbsp; if (!fputs($fp, $query, strlen($query))) <br />&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $errstr = &quot;Write error&quot;; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false; <br />&nbsp;&nbsp; } <br />//获取从服务器端返回的所有信息，包括HTTP头和XML信息 <br />&nbsp;&nbsp; $contents = ''; <br />&nbsp;&nbsp; while (!feof($fp)) <br />&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $contents .= fgets($fp); <br />&nbsp;&nbsp; }</p><p>//关闭连接资源后返回获取的内容 <br />&nbsp;&nbsp; fclose($fp); <br />&nbsp;&nbsp; return $contents; <br />}</p><p>//构造连接RPC服务器端的信息 <br />$host&nbsp; = 'localhost'; <br />$port&nbsp; = 80; <br />$rpc_server = '/~heiyeluren/rpc_server.php';</p><p>//把需要发送的XML请求进行编码成XML，需要调用的方法是rpc_server，参数是get <br />$request = xmlrpc_encode_request('rpc_server', 'get');</p><p>//调用rpc_client_call函数把所有请求发送给XML-RPC服务器端后获取信息 <br />$response = rpc_client_call($host, $port, $rpc_server, $request);</p><p>//分析从服务器端返回的XML，去掉HTTP头信息，并且把XML转为PHP能识别的字符串 <br />$split = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot;?&gt;'; <br />$xml =&nbsp; explode($split, $response); <br />$xml = $split . array_pop($xml); <br />$response = xmlrpc_decode($xml);</p><p>//输出从RPC服务器端获取的信息 <br />print_r($response);</p><p>?&gt;</p><p>大致我们上面的例子就是提交一个叫做rpc_server的方法过去，参数是get，然后获取服务器端的返回，服务器端返回的XML数据是：</p><p>&lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot;?&gt; <br />&lt;methodResponse&gt; <br />&lt;params&gt; <br />&lt;param&gt; <br />&nbsp; &lt;value&gt; <br />&nbsp;&nbsp; &lt;string&gt;This data by get method&lt;/string&gt; <br />&nbsp; &lt;/value&gt; <br />&lt;/param&gt; <br />&lt;/params&gt; <br />&lt;/methodResponse&gt;</p><p>那么我们再通过xmlrpc_decode函数把这个XML编码为PHP的字符串，我们就能够随意处理了，整个Web Service交互完成。</p><p><strong>[&nbsp; 结束语 ]</strong></p><p>不管是XML-RPC也好，SOAP也罢，只要能够让我们稳定、安全的进行远程过程的调用，完成我们的项目，那么就算整个Web Service就是成功的。另外，如果可以的话，也可以尝试使用PEAR中的XML-RPC来实现上面类似的操作，说不定会更简单，更适合你使用。</p><p>简单的使用XML-RPC进行Web Service交互就完成了，部分代码参考PHP手册，想获取详细信息建议参考手册，如果文章有不正确，请指正。</p>]]></description><category>PHP + Mysql</category><comments>http://www.augweb.net/blog/post/234.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=234</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=234&amp;key=28bb9eff</trackback:ping></item><item><title>用XML-RPC协议读写WordPress上的文章</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/233.html</link><pubDate>Tue, 30 Nov 2010 20:37:08 +0800</pubDate><guid>http://www.augweb.net/blog/post/233.html</guid><description><![CDATA[<p>WordPress提供了XML-RPC接口使得第三方的博客写作软件(如windows live writer等)可以与之通信来发布和修改博客。我们也可以在网站上使用这个接口做一些工作，例如：在网站首页显示最新的博客、在博客之外的页面上发表博客文章、把博客与其他内容管理系统结合，等等。</p><p><strong>一、开启XML-RPC支持</strong></p><p>XML-RPC协议默认是未开启的，需要到WordPress管理后台的&ldquo;设置--&gt;撰写&rdquo;里的&ldquo;远程发布&rdquo;给XML-RPC打上勾。其说明文字为：启用 WordPress，Movable Type，MetaWeblog和Blogger 的 XML-RPC发布协议。</p><p><strong>二、获取接口的信息</strong></p><p>我们查看博客首页的源代码，在head中可以发现类似这样的link项</p><blockquote><p>&lt;link title=&quot;RSD&quot; href=&quot;<a href="http://blog.bluesky.cn/xmlrpc.php?rsd&quot;">http://blog.bluesky.cn/xmlrpc.php?rsd&quot;</a> type=&quot;application/rsd+xml&quot; rel=&quot;EditURI&quot; /&gt;</p></blockquote><p>其中的&quot;RSD&quot;是&ldquo;Really Simple Discovery&rdquo;的意思，也就是说这是一个&ldquo;简单的发现博客编辑接口&rdquo;的地址。我们用浏览器直接访问这个地址就可以在其返回XML中获知博客的ID(blogID，一般这个的值是&ldquo;1&rdquo;)以及它所支持的接口类型和接口地址。</p><p><strong>三、API接口选择</strong></p><p>WordPress提供了对<a href="http://www.blogger.com/developers/api/">Blogger API</a>、<a href="http://www.xmlrpc.com/metaWeblogApi">metaWeblog API</a>、<a href="http://www.sixapart.com/developers/xmlrpc/movable_type_api/">Movable Type API</a>以及其自身的<a href="http://codex.wordpress.org/XML-RPC_wp">WordPress API</a>的支持。其中WordPress API最为丰富，提供了包括操作评论文章在内的各种各样的支持。Blogger API功能较少，基本上淘汰不用了；而metaWeblog API提供了常用的接口且参数比较简洁，用得较多一些。</p><p><strong>四、例子代码</strong></p><p>以下是使用<a href="http://scripts.incutio.com/xmlrpc/">Incutio的XML-RPC库</a>和Blogger API发布文章的例子，其中IXR库也是Wordpress自身所用的库，可以在&ldquo;wp-includes/class-IXR.php&rdquo;找到。</p><pre>&lt;?php$xmlrpcurl='http://blog.bluesky.cn/xmlrpc.php';$blogid='1';$username='admin';$password='pass';$postTitle='标题';$postContent='正文内容';require('class-IXR.php');  // /wordpress/wp-includes/class-IXR.php$client = new IXR_Client($xmlrpcurl);$params=array(   '',   'blog_ID'=&gt;$blogid,   'user_login'=&gt;$username,   'user_pass'=&gt;$password,   'post_content'=&gt;'' . $postContent,   'publish'=&gt;true);$params=array_values($params);$client-&gt;query(&quot;blogger.newPost&quot;,$params);$response=$client-&gt;getResponse();if ($response['faultCode']==0){   print 'Success';} else {   print 'Fail:' . $response['faultString'];}?&gt;</pre><p>以下是用<a href="http://phpxmlrpc.sourceforge.net/">XML-RPC for PHP</a>库和metaWeblog接口发布文章的例子。要先下载<a href="http://phpxmlrpc.sourceforge.net/">phpxmlrpc</a>库取出其中的xmlrpc.inc来用。</p><pre>&lt;?phpinclude(&quot;xmlrpc.inc&quot;); // 这里要改成xmlrpc.inc所在的路径$GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';define ('DOMAIN', 'blog.bluesky.cn'); // 博客的域名define ('BLOGID', 1); // 博客ID，一般为1define ('USER', 'admin'); // 博客登录的用户名define ('PASSWORD', 'pass'); // 博客登录的密码// 创建 xml-rpc client$cl = new xmlrpc_client ( &quot;/xmlrpc.php&quot;, DOMAIN, 80);// 准备请求$req = new xmlrpcmsg('metaWeblog.newPost');// 逐个列出请求的参数:$req-&gt;addParam ( new xmlrpcval ( BLOGID, 'int')); // 博客ID$req-&gt;addParam ( new xmlrpcval ( USER, 'string' )); // 用户名$req-&gt;addParam ( new xmlrpcval ( PASSWORD, 'string' )); // 密码$struct = new xmlrpcval (    array (        &quot;title&quot; =&gt; new xmlrpcval ( '标题', 'string' ), // 标题        &quot;description&quot; =&gt; new xmlrpcval ( '正文内容', 'string'), // 内容    ), &quot;struct&quot;);$req-&gt;addParam ( $struct );$req-&gt;addParam ( new xmlrpcval (1, 'int')); // 立即发布// 发送请求$ans = $cl-&gt;send($req);var_dump ( $ans );?&gt;</pre><p>注意一定要加上：$GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';这一句，否则不能正确处理中文。</p><p>另一段也是用phpxmlrpc库和metaWeblog接口发表文章的例子代码，该代码使用了返回类型为&ldquo;phpvals&rdquo;，这样可以直接用返回结果的$r-&gt;val来获取文章ID号。</p><pre>&lt;?php  include(&quot;xmlrpc.inc&quot;);  $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';   $c = new xmlrpc_client(&quot;/xmlrpc.php&quot;, &quot;blog.bluesky.cn&quot;, 80);  $content['title']=&quot;标题&quot;;  //标题  $content['description']=&quot;正文内容&quot;; //内容  $content['mt_keywords']=&quot;标签1,标签2&quot;;  //标签  $content['wp_password']=&quot;&quot;;  //文章密码，输入后显示加密  $content['categories'] = array(&quot;分类1&quot;,&quot;分类2&quot;); //分类名  $x = new xmlrpcmsg(&quot;metaWeblog.newPost&quot;,                      array(php_xmlrpc_encode(&quot;1&quot;), //BLOG ID                      php_xmlrpc_encode(&quot;admin&quot;),  //用户名                      php_xmlrpc_encode(&quot;pass&quot;),  //密码                      php_xmlrpc_encode($content),                      php_xmlrpc_encode(&quot;1&quot;)));    //立即发表  $c-&gt;return_type = 'phpvals';  $r =$c-&gt;send($x);  if ($r-&gt;errno==&quot;0&quot;)    echo &quot;发表成功，文章序号为：&quot;.$r-&gt;val;  else {    echo &quot;出错了&quot;;    print_r($r);  }?&gt;</pre><p>以下是读取最新一篇文章的例子代码：</p><pre>&lt;?php  include(&quot;xmlrpc.inc&quot;);  $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';  $c = new xmlrpc_client(&quot;/xmlrpc.php&quot;, &quot;blog.bluesky.cn&quot;, 80);  $msg = new xmlrpcmsg('metaWeblog.getRecentPosts',                        array(php_xmlrpc_encode(&quot;1&quot;),                        php_xmlrpc_encode(&quot;admin&quot;),                        php_xmlrpc_encode(&quot;pass&quot;),                        php_xmlrpc_encode(&quot;1&quot;)) );  $res = $c-&gt;send($msg);  $val = $res-&gt;value();  $val-&gt;arraymem(0)-&gt;structreset();  while (list($key, $v) = $val-&gt;arraymem(0)-&gt;structeach())  {    echo &quot;Element: $key; Type: &quot;.$v-&gt;kindOf().&quot;; Value:&quot;.$v-&gt;scalarval().&quot;\n&quot;;  }?&gt;</pre>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/233.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=233</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=233&amp;key=448c4e1e</trackback:ping></item><item><title>PHP中使用XML-RPC构造Web Service简单入门</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/232.html</link><pubDate>Tue, 30 Nov 2010 20:12:51 +0800</pubDate><guid>http://www.augweb.net/blog/post/232.html</guid><description><![CDATA[<p><strong>[&nbsp; Web Service介绍 ]</strong></p><p>Web Service就是为了异构系统的通信而产生的，它基本的思想就是使用基于XML的HTTP的远程调用提供一种标准的机制，而省去建立一种新协议的需求。目前进行Web Service通信有两种协议标准，一种是XML-RPC，另外一种是SOAP。XML-RPC比较简单，出现时间比较早，SOAP比较复杂，主要是一些需要稳定、健壮、安全并且复杂交互的时候使用。</p><p>PHP中集成了XML-RPC和SOAP两种协议的访问，都是集中在xmlrpc扩展当中。另外，在PHP的PEAR中，不管是PHP 4还是PHP 5，都已经默认集成了XML-RPC扩展，而且该扩展跟xmlrpc扩展无关，能够独立实现XML-RPC的协议交互，如果没有xmlrpc扩展，建议使用PEAR::XML-RPC扩展。</p><p>我们这里主要是以XML-RPC来简单描述Web Service的交互过程，部分内容来自PHP手册，更详细内容，建议参考手册。</p><p><strong>[&nbsp; 安装xmlrpc扩展 ]</strong></p><p>如果你的系统中没有安装xmlrpc的php扩展，那么请正确安装。</p><p>在Windows平台下，首先把PHP安装目录下的扩展php_xmlrpc.dll放到C:\Windows或者C:\Winnt目录下，(PHP4的扩展在C:\php\extensions目录中，PHP5的扩展在C:\php\ext目录中)，同时在C:\Windows\php.ini或者C:\Winnt\php.ini中把extension=php_xmlrpc.dll前面的分号&quot;;&quot;去掉，然后重启Web服务器后查看phpinfo()有没有XML-RPC项目就能够确定是否已经正确安装xmlrpc扩展。</p><p>在Unix/Linux平台下，如果没有安装xmlrpc扩展，请在重新编译PHP，在configure的时候请加入 --with-xmlrpc 选项，然后查看phpinfo()看是否正常安装xmlrpc。</p><p>(注意：以下操作都是建立在xmlrpc扩张正常安装前提下，请务必正确安装。)</p><p><strong>[&nbsp; XML-RPC工作原理 ]</strong></p><p>XML-RPC大致就是整个过程就是使用XML来进行通信。首先构造一个RPC 服务器端用来出来从RPC客户端传递过来的使用XML封装的请求，并且把处理结果通过XML的形式返回给RPC客户端，客户端就去分析XML获取自己需要的数据。</p><p>XML-RPC的服务器端必须有现成的函数提供给客户端调用，并且客户端提交的请求中的函数和方法必须和服务器端的一致，否则将无法获取所需要的结果。</p><p>下面我进行简单的代码来描述整个过程。</p><p><strong>[&nbsp; XML-RPC实践 ]</strong></p><p>服务器端使用xmlrpc_server_create函数产生一个服务器端，然后把需要需要暴露的RPC调用接口进行注册，接受RPC客户端POST过来的XML数据，然后进行处理，处理结果通过XML的形式显示给客户端。</p><p>代码如下： rpc_server.php</p><p>&lt;?php    <br />/**    <br />* 函数：提供给RPC客户端调用的函数    <br />* 参数：    <br />* $method 客户端需要调用的函数    <br />* $params 客户端需要调用的函数的参数数组    <br />* 返回：返回指定调用结果    <br />*/    <br />function rpc_server_func($method, $params) {    <br />$parameter = $params[0];    <br />&nbsp;&nbsp; if ($parameter == &quot;get&quot;)    <br />&nbsp;&nbsp; {     <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $return = 'This data by get method';     <br />&nbsp;&nbsp; }    <br />&nbsp;&nbsp; else    <br />&nbsp;&nbsp; {    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $return = 'Not specify method or params';    <br />&nbsp;&nbsp; }     <br />&nbsp;&nbsp; return $return;     <br />}</p><p>//产生一个XML-RPC的服务器端   <br />$xmlrpc_server = xmlrpc_server_create();</p><p>//注册一个服务器端调用的方法rpc_server，实际指向的是rpc_server_func函数   <br />xmlrpc_server_register_method($xmlrpc_server, &quot;rpc_server&quot;, &quot;rpc_server_func&quot;);</p><p>//接受客户端POST过来的XML数据   <br />$request = $HTTP_RAW_POST_DATA;</p><p>//执行调用客户端的XML请求后获取执行结果   <br />$xmlrpc_response = xmlrpc_server_call_method($xmlrpc_server, $request, null);</p><p>//把函数处理后的结果XML进行输出   <br />header('Content-Type: text/xml');     <br />echo $xmlrpc_response;</p><p>//销毁XML-RPC服务器端资源   <br />xmlrpc_server_destroy($xmlrpc_server);     <br />?&gt;</p><p>服务器端构造好了，那么再构造我们的RPC客户端。客户端大致通过Socket访问XML-RPC服务器端的80端口，然后把需要调用的RPC接口封装到XML里，通过POST请求提交给RPC服务器端，最后获取服务器端返回结果。</p><p>代码如下：rpc_client.php</p><p>&lt;?php   <br />/**    <br />* 函数：提供给客户端进行连接XML-RPC服务器端的函数    <br />* 参数：    <br />* $host&nbsp; 需要连接的主机    <br />* $port&nbsp; 连接主机的端口    <br />* $rpc_server XML-RPC服务器端文件    <br />* $request&nbsp; 封装的XML请求信息    <br />* 返回：连接成功成功返回由服务器端返回的XML信息，失败返回false    <br />*/    <br />function rpc_client_call($host, $port, $rpc_server, $request) {</p><p>&nbsp;&nbsp; //打开指定的服务器端   <br />&nbsp;&nbsp; $fp = fsockopen($host, $port);</p><p>&nbsp;&nbsp; //构造需要进行通信的XML-RPC服务器端的查询POST请求信息   <br />&nbsp;&nbsp; $query = &quot;POST $rpc_server HTTP/1.0\nUser_Agent: XML-RPC Client\nHost: &quot;.$host.&quot;\nContent-Type: text/xml\nContent-Length: &quot;.strlen($request).&quot;\n\n&quot;.$request.&quot;\n&quot;;</p><p>&nbsp;&nbsp; //把构造好的HTTP协议发送给服务器，失败返回false   <br />&nbsp;&nbsp; if (!fputs($fp, $query, strlen($query)))     <br />&nbsp;&nbsp; {     <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $errstr = &quot;Write error&quot;;     <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;     <br />&nbsp;&nbsp; }     <br />//获取从服务器端返回的所有信息，包括HTTP头和XML信息    <br />&nbsp;&nbsp; $contents = '';     <br />&nbsp;&nbsp; while (!feof($fp))    <br />&nbsp;&nbsp; {     <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $contents .= fgets($fp);     <br />&nbsp;&nbsp; }</p><p>//关闭连接资源后返回获取的内容   <br />&nbsp;&nbsp; fclose($fp);     <br />&nbsp;&nbsp; return $contents;     <br />}</p><p>//构造连接RPC服务器端的信息   <br />$host&nbsp; = 'localhost';     <br />$port&nbsp; = 80;     <br />$rpc_server = '/~heiyeluren/rpc_server.php';</p><p>//把需要发送的XML请求进行编码成XML，需要调用的方法是rpc_server，参数是get   <br />$request = xmlrpc_encode_request('rpc_server', 'get');</p><p>//调用rpc_client_call函数把所有请求发送给XML-RPC服务器端后获取信息   <br />$response = rpc_client_call($host, $port, $rpc_server, $request);</p><p>//分析从服务器端返回的XML，去掉HTTP头信息，并且把XML转为PHP能识别的字符串   <br />$split = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot;?&gt;';    <br />$xml =&nbsp; explode($split, $response);    <br />$xml = $split . array_pop($xml);    <br />$response = xmlrpc_decode($xml);</p><p>//输出从RPC服务器端获取的信息   <br />print_r($response);</p><p>?&gt;</p><p>大致我们上面的例子就是提交一个叫做rpc_server的方法过去，参数是get，然后获取服务器端的返回，服务器端返回的XML数据是：</p><p>&lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot;?&gt;   <br />&lt;methodResponse&gt;    <br />&lt;params&gt;    <br />&lt;param&gt;    <br />&nbsp; &lt;value&gt;    <br />&nbsp;&nbsp; &lt;string&gt;This data by get method&lt;/string&gt;    <br />&nbsp; &lt;/value&gt;    <br />&lt;/param&gt;    <br />&lt;/params&gt;    <br />&lt;/methodResponse&gt;</p><p>那么我们再通过xmlrpc_decode函数把这个XML编码为PHP的字符串，我们就能够随意处理了，整个Web Service交互完成。</p><p><strong>[&nbsp; 结束语 ]</strong></p><p>不管是XML-RPC也好，SOAP也罢，只要能够让我们稳定、安全的进行远程过程的调用，完成我们的项目，那么就算整个Web Service就是成功的。另外，如果可以的话，也可以尝试使用PEAR中的XML-RPC来实现上面类似的操作，说不定会更简单，更适合你使用。</p><p>简单的使用XML-RPC进行Web Service交互就完成了，部分代码参考PHP手册，想获取详细信息建议参考手册，如果文章有不正确，请指正。</p>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/232.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=232</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=232&amp;key=a2e840fb</trackback:ping></item><item><title>IIRF伪静态Discuz规则完整经实测验证</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/230.html</link><pubDate>Mon, 08 Nov 2010 18:28:05 +0800</pubDate><guid>http://www.augweb.net/blog/post/230.html</guid><description><![CDATA[<p>RewriteLog&#160; D:\rewriter\discuz\iirfLog.out   <br />RewriteLogLevel 0    <br /># Discuz! Rewrite 规则 </p>  <p>RewriteRule ^(.*)/archiver/((fid|tid)-[\w\-]+)\.html\?*(.*)$ $1/archiver/index.php?$2&amp;$4 [L]   <br />RewriteRule ^(.*)/forum-([0-9]+)-([0-9]+)\.html\?*(.*)$ $1/forumdisplay.php?fid=$2&amp;page=$3&amp;$4 [L]    <br />RewriteRule ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html\?*(.*)$ $1/viewthread.php?tid=$2&amp;extra=page%3D$4&amp;page=$3&amp;$4 [L]    <br />RewriteRule ^(.*)/space-(username|uid)-(.+)\.html\?*(.*)$ $1/space.php?$2=$3&amp;$4 [L]    <br />RewriteRule ^(.*)/tag-(.+)\.html\?*(.*)$ $1/tag.php?name=$2&amp;$3 [L] </p>  <p># SupeSite Rewrite规则 </p>  <p>RewriteRule ^(.*)/([0-9]+)$ $1/index.php?uid/$2 [L]   <br />RewriteRule ^(.*)/([0-9]+)/spacelist(.+)$ $1/index.php?uid/$2/action/spacelist/type$3 [L]    <br />RewriteRule ^(.*)/([0-9]+)/viewspace(.+)$ $1/index.php?uid/$2/action/viewspace/itemid$3 [L]    <br />RewriteRule ^(.*)/([0-9]+)/viewbbs(.+)$ $1/index.php?uid/$2/action/viewbbs/tid$3 [L]    <br />RewriteRule ^(.*)/([0-9]+)/(.*)$ $1/index.php?uid/$2/$3 [L]    <br />RewriteRule ^(.*)/action(.+)$ $1/index.php?action$2 [L]    <br />RewriteRule ^(.*)/category(.+)$ $1/index.php?action/category/catid$2 [L]    <br />RewriteRule ^(.*)/viewnews(.+)$ $1/index.php?action/viewnews/itemid$2 [L]    <br />RewriteRule ^(.*)/viewthread-(.+)$ $1/index.php?action/viewthread/tid-$2 [L]    <br />RewriteRule ^(.*)/mygroup(.+)$ $1/index.php?action/mygroup/gid$2 [L] </p>  <p># UCHome Rewrite规则   <br />RewriteRule ^(.*)/(space|network)-(.+)\.html$ $1/$2.php?rewrite=$3 [L]    <br />RewriteRule ^(.*)/(space|network)\.html$ $1/$2.php [L]    <br />RewriteRule ^(.*)/([0-9]+)$ $1/space.php?uid=$2 [L] </p>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/230.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=230</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=230&amp;key=a7a224d9</trackback:ping></item><item><title>从一则笑话分析需求的陷阱</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/229.html</link><pubDate>Tue, 02 Nov 2010 16:09:09 +0800</pubDate><guid>http://www.augweb.net/blog/post/229.html</guid><description><![CDATA[<h6>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 某日，老师在课堂上想考考学生们的智商，就问一个男孩:&ldquo;树上有十只鸟，开枪打死一只，还剩几只？&rdquo;</h6><p>男孩反问:&ldquo;是无声枪么？&rdquo;</p><p>&ldquo;不是。&rdquo;</p><p>&ldquo;枪声有多大？&rdquo;</p><p>&ldquo;80~100分贝。&rdquo;</p><p>&ldquo;那就是说会震的耳朵疼？&rdquo;</p><p>&ldquo;是。&rdquo;</p><p>&ldquo;在这个城市里打鸟犯不犯法？&rdquo;</p><p>&lsquo;不犯。&rdquo;</p><p>&ldquo;您确定那只鸟真的被打死啦？&rdquo;</p><p>&ldquo;确定。&rdquo;老师已经不耐烦了，&rdquo;拜托，你告诉我还剩几只就行了，OK？&rdquo;</p><p>&ldquo;OK。鸟里有没有聋子？&rdquo;</p><p>&ldquo;没有。&rdquo;</p><p>&ldquo;有没有关在笼子里的？&rdquo;</p><p>&ldquo;没有。&rdquo;</p><p>&ldquo;边上还有没有其他的树，树上还有没有其他鸟？&rdquo;</p><p>&ldquo;没有。&rdquo;</p><p>&ldquo;方圆十里呢？&rdquo;</p><p>&ldquo;就这么一棵树!&rdquo;</p><p>&ldquo;有没有残疾或饿的飞不动的鸟？&rdquo;</p><p>&ldquo;没有，都身体倍棒。&rdquo;</p><p>&ldquo;算不算怀孕肚子里的小鸟？&rdquo;</p><p>&ldquo;都是公的。&rdquo;</p><p>&ldquo;都不可能怀孕？&rdquo;</p><p>&ldquo;&hellip;&hellip;&hellip;，决不可能。&rdquo;</p><p>&ldquo;打鸟的人眼里有没有花？保证是十只？&rdquo;</p><p>&ldquo;没有花，就十只。&rdquo;</p><p>老师脑门上的汗已经流下来了，下课铃响起，但男孩仍继续问:&ldquo;有没有傻的不怕死的？&rdquo;</p><p>&ldquo;都怕死。&rdquo;</p><p>&ldquo;有没有因为情侣被打中，自己留下来的？&rdquo;</p><p>&ldquo;笨蛋，之前不是说都是公的嘛!&rdquo;</p><p>&ldquo;同志可不可以啊!&rdquo;</p><p>&ldquo;&hellip;&hellip;&hellip;&hellip;，性取向都很正常!&rdquo;</p><p>&ldquo;会不会一枪打死两只？&rdquo;</p><p>&ldquo;不会。&rdquo;</p><p>&ldquo;一枪打死三只呢？&rdquo;</p><p>&ldquo;不会。&rdquo;</p><p>&ldquo;四只呢？&rdquo;</p><p>&ldquo;更不会!&rdquo;</p><p>&ldquo;五只呢？&rdquo;</p><p>&ldquo;绝对不会!!!&rdquo;</p><p>&ldquo;那六只总有可能吧？&rdquo;</p><p>&ldquo;除非你他妈的是猪生的才有可能!&rdquo;</p><p>&ldquo;&hellip;好吧，那么所有的鸟都可以自由活动么？&rdquo;</p><p>&ldquo;完全可以。&rdquo;</p><p>&ldquo;它们受到惊吓起飞时会不会惊慌失措而互相撞上？&rdquo;</p><p>&ldquo;不会，每只鸟都装有卫星导航系统，而且可以自动飞行。&rdquo;</p><p>&ldquo;恩，如果您的回答没有骗人，&rdquo;学生满怀信心的回答，&ldquo;打死的鸟要是挂在树上没掉下来，那么就剩一只，如果掉下来，就一只不剩。&rdquo;</p><p>老师当即倒!</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正值六一儿童节之际，用这篇笑话故事来做开头，笑过之后可能不少能会认为这个小朋友是需求调研的最佳人选。回顾软件开发上的许多案例，软件开发失败率一直居高不下，特别在外包开发这个领域中，这个值可能会更高一筹。在分析项目失败的原因的时候，需求的因素可能是失败的关键原因、需求不明确，客户对需求的变更频频等等。</p><p>&nbsp;&nbsp;&nbsp; 1．需求的调研</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 需求调研是为需要说明书做前期工作，可以说需要说明书是从需求调研表中得到或抽取而出。需求调研是要了解客户希望所要开发的系统能够解决他们的问题，以及了解他们对系统的期望等等。需求调研是整个开发的基础，经过需求调研的结果整理出需求说明书作为后续开发使用。</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果做的项目是一个陌生的一个行业（专业），这是往往需要专家或者顾问等角色的协助，但是作为调研人员最少要想办法了解个专业，或许你需要成为这个行业的专家，但最少要了解一定的专业知识（最少专业词汇你要知道）。这样客户的沟通才能达到顺畅，不会出现牛头不对马嘴的现象。</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在某些难度不是很大的行业或者项目，做需求调研的时候可以通过自学的方式了解行业的特点，这些项目往往因为规模比较小，也不会有专家的影子出现。但是作为调研的时候我们最需要了解的一些问题如：</p><p>1）：客户目前的问题与苦难</p><p>2）：客户现在的工作模式</p><p>3）：客户对系统的期望</p><p>4）：客户哪些要求是自己能做到的，那些是依靠系统来做</p><p>5）：还有客户对系统开发方式以及时间的要求等等</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实做需求调研的时候最重要的目的在于资料收集，或许小孩的那种打破砂锅的方式会引起客户的反感，但是实际项目中往往需要的就是这些比较周全的调研方式，能够考虑到的问题点都需要和客户确认，尽量避免想当然的做法，只是采用的方式可能需要优化一下，采用良好的方式，尽量得到客户的最大配合。</p>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/229.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=229</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=229&amp;key=55bc25e4</trackback:ping></item><item><title>澄清Java（接口与继承）</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/228.html</link><pubDate>Mon, 27 Sep 2010 17:30:38 +0800</pubDate><guid>http://www.augweb.net/blog/post/228.html</guid><description><![CDATA[<p>计算机<a href="http://school.it168.com/">学院</a>研二的兄弟与我讨论Java，一见面，几个问题全是关于接口，接口有什么用？为什么要用接口？什么时候该使用接口？很庆幸他们不是问我Java如何连接SQL Server，或者是如何开发J2EE应用，这类问题有杀伤力，避之则吉。今年计算机学院本科有个毕业设计课题是做J2ME，选这个题目的学生在5月末都还在苦着脸研究java.util.*这个包，这个这个&hellip;&hellip;唉。</p><p>&nbsp;&nbsp;&nbsp; 大多数人认为，接口的意义在于顶替多重继承。众所周知Java没有c++那样多重继承的机制，但是却能够实作多个接口。其实这样做是很牵强的，接口和继承是完全不同的东西，接口没有能力代替多重继承，也没有这个义务。接口的作用，一言以蔽之，就是标志类的类别（type of class）。把不同类型的类归于不同的接口，可以更好的管理他们。OO的精髓，我以为，是对对象的抽象，最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言（比如c++、java、c#等），就是因为设计模式所研究的，实际上就是如何合理的去抽象。（cowboy的名言是&ldquo;抽象就是抽去像的部分&rdquo;，看似调侃，实乃至理）。</p><p>&nbsp;&nbsp;&nbsp; 设计模式中最基础的是工厂模式（Factory），在我最近的一个很简单的应用中，我想尽量的让我的程序能够在多个数据库间移植，当然，这涉及很多问题，单是如何兼容不同DBMS的SQL就让人头痛。我们不妨先把问题简单化，只考虑如何连接不同的数据库。</p><p>&nbsp;&nbsp;&nbsp; 假设我有很多个类，分别是Mysql.java、SQLServer.java、Oracle.java、DB2.java，他们分别连接不同的数据库，统一返回一个Connection对象，并且都有一个close方法，用于关闭连接。只需要针对你的DBMS，选择不同的类，就可以用了，但是我的用户他会使用什么数据库？我不知道，我希望的是尽量少的修改代码，就能满足他的需要。我可以抽象如下接口：</p><p>&nbsp;&nbsp;&nbsp; package org.bromon.test;   <br />&nbsp;&nbsp;&nbsp; public interface DB    <br />&nbsp;&nbsp;&nbsp; {    <br />&nbsp;&nbsp;&nbsp; java.sql.Connection openDB(String url,String user,String password);    <br />&nbsp;&nbsp;&nbsp; void close();    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; 这个接口只定义两个方法，没有任何有实际意义的代码，具体的代码由实作这个接口的类来给出，比如Mysql.java：</p><p>&nbsp;&nbsp;&nbsp; Package org.bromon.test;   <br />&nbsp;&nbsp;&nbsp; import java.sql.*;    <br />&nbsp;&nbsp;&nbsp; public class Mysql implements DB    <br />&nbsp;&nbsp;&nbsp; {    <br />&nbsp;&nbsp;&nbsp; private String url=&rdquo;jdbc:mysql:localhost:3306/test&rdquo;;    <br />&nbsp;&nbsp;&nbsp; private String user=&rdquo;root&rdquo;;    <br />&nbsp;&nbsp;&nbsp; private String password=&rdquo;&rdquo;;    <br />&nbsp;&nbsp;&nbsp; private Connection conn;    <br />&nbsp;&nbsp;&nbsp; public Connection openDB(url,user,password)</p><p>&nbsp;&nbsp;&nbsp; {   <br />&nbsp;&nbsp;&nbsp; //连接数据库的代码    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; public void close()</p><p>&nbsp;&nbsp;&nbsp; {   <br />&nbsp;&nbsp;&nbsp; //关闭数据库    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; 类似的当然还有Oracle.java等等，接口DB给这些类归了个类，在应用程序中我们这样定义对象：</p><p>&nbsp;&nbsp;&nbsp; org.bromon.test.DB myDB;   <br />&nbsp;&nbsp;&nbsp; 使用myDB来操作数据库，就可以不用管实际上我所使用的是哪个类，这就是所谓的&ldquo;开-闭&rdquo;原则。但是问题在于接口是不能实例化的，myDB=new DB()，这样的代码是绝对错误的，我们只能myDB=new Mysql()或者myDB=new Oracle()。麻烦了，我还是需要指定具体实例化的是哪个类，用了接口跟没用一样。所以我们需要一个工厂：</p><p>&nbsp;&nbsp;&nbsp; package org.bromon.test;   <br />&nbsp;&nbsp;&nbsp; public class DBFactory    <br />&nbsp;&nbsp;&nbsp; {    <br />&nbsp;&nbsp;&nbsp; public static DB Connection getConn()</p><p>&nbsp;&nbsp;&nbsp; {   <br />&nbsp;&nbsp;&nbsp; Return(new Mysql());    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; 所以实例化的代码变成：myDB=DBFactory.getConn()；    <br />&nbsp;&nbsp;&nbsp; 这就是23种模式中最基础的普通工厂(Factory)，工厂类负责具体实例化哪个类，而其他的程序逻辑都是针对DB这个接口进行操作，这就是&ldquo;针对接口编程&rdquo;。责任都被推卸给工厂类了，当然你也可以继续定义工厂接口，继续把责任上抛，这就演变成抽象工厂(Abstract Factory)。</p><p>&nbsp;&nbsp;&nbsp; 整个过程中接口不负责任何具体操作，其他的程序要连接数据库的话，只需要构造一个DB对象就OK，而不管工厂类如何变化。这就是接口的意义----抽象。</p><p>&nbsp;&nbsp;&nbsp; 继承的概念不用多说，很好理解。为什么要继承呢？因为你想重用代码？这绝对不是理由，继承的意义也在于抽象，而不是代码重用。如果对象A有一个run()方法，对象B也想有这个方法，所以有人就Class B extends A。这是不经大脑的做法。如果在B中实例化一个A，调用A的Run()方法，是不是可以达到同样的目的？如下：</p><p>&nbsp;&nbsp;&nbsp; Class B   <br />&nbsp;&nbsp;&nbsp; {    <br />&nbsp;&nbsp;&nbsp; A&nbsp; a=new A();    <br />&nbsp;&nbsp;&nbsp; a.run();    <br />&nbsp;&nbsp;&nbsp; }    <br />&nbsp;&nbsp;&nbsp; 这就是利用类的聚合来重用代码，是委派模式的雏形，是GoF一贯倡导的做法。</p><p>&nbsp;&nbsp;&nbsp; 那么继承的意义何在？其实这是历史原因造成的，最开始的OO语言只有继承，没有接口，所以只能以继承来实现抽象，请一定注意，继承的本意在于抽象，而非代码重用（虽然继承也有这个作用），这是很多Java烂书最严重的错误之一，它们所造成的阴影，我至今还没有完全摆脱，坏书害人啊，尤其是入门类的，流毒太大。什么时候应该使用继承？只在抽象类中使用，其他情况下尽量不使用。抽象类也是不能实例化的，它仅仅提供一个模版而已，这就很能说明问题。</p><p>软件开发的万恶之源，一是重复代码而不是重用代码，二是烂用继承，尤以c++程序员为甚。Java中取缔多重继承，目的就是制止烂用继承，实是非常明智的做法，不过很多人都不理解。Java能够更好的体现设计，这是让我入迷的原因之一。</p>]]></description><category>Java</category><comments>http://www.augweb.net/blog/post/228.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=228</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=228&amp;key=ae90a435</trackback:ping></item><item><title>adobe creative suite 5</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/227.html</link><pubDate>Wed, 18 Aug 2010 13:42:55 +0800</pubDate><guid>http://www.augweb.net/blog/post/227.html</guid><description><![CDATA[<p><a href="http://www.augweb.net/blog/upload/2010/8/image_2.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="407" alt="image" width="795" border="0" src="http://www.augweb.net/blog/upload/2010/8/image_thumb.png" /></a></p>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/227.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=227</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=227&amp;key=9368b68b</trackback:ping></item><item><title>ADOBE Creative Suite 5</title><author>lorrons@gmail.com (lorron)</author><link>http://www.augweb.net/blog/post/226.html</link><pubDate>Wed, 18 Aug 2010 13:21:36 +0800</pubDate><guid>http://www.augweb.net/blog/post/226.html</guid><description><![CDATA[<p><dl><dt><a href="http://www.adobe.com/cn/products/creativesuite/design/">Creative Suite 5 Design Premium</a></dt><dd><a href="http://www.adobe.com/cn/products/photoshop/photoshopextended/">Photoshop CS5 Extended</a></dd><dd><a href="http://www.adobe.com/cn/products/illustrator/">Illustrator CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/indesign/">InDesign CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flashcatalyst/">Flash Catalyst CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flash/">Flash Professional CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/dreamweaver/">Dreamweaver CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/fireworks/">Fireworks CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/acrobatpro/">Acrobat 9 Pro</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/bridge/">Bridge CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/devicecentral/">Device Central CS5</a></dd><dd><a href="http://www.adobe.com/go/cslive_cn">与 CS Live 在线服务集成**</a></dd></dl><dl><dt><a href="http://www.adobe.com/cn/products/creativesuite/web/">Creative Suite 5 Web Premium</a></dt><dd><a href="http://www.adobe.com/cn/products/dreamweaver/">Dreamweaver CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flashcatalyst/">Flash Catalyst CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flash/">Flash Professional CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/flashbuilder/">Flash Builder 4 Standard</a></dd><dd><a href="http://www.adobe.com/cn/products/photoshop/photoshopextended/">Photoshop CS5 Extended</a></dd><dd><a href="http://www.adobe.com/cn/products/illustrator/">Illustrator CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/acrobatpro/">Acrobat 9 Pro</a></dd><dd><a href="http://www.adobe.com/cn/products/fireworks/">Fireworks CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/contribute/">Contribute CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/bridge/">Bridge CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/devicecentral/">Device Central CS5</a></dd><dd><a href="http://www.adobe.com/go/cslive_cn">与 CS Live 在线服务集成**</a></dd></dl><dl><dt><a href="http://www.adobe.com/cn/products/creativesuite/production/">Creative Suite 5 Production Premium</a></dt><dd><a href="http://www.adobe.com/cn/products/premiere/">Adobe Premiere Pro CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/aftereffects/">After Effects CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/photoshop/photoshopextended/">Photoshop CS5 Extended</a></dd><dd><a href="http://www.adobe.com/cn/products/illustrator/">Illustrator CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flashcatalyst/">Flash Catalyst CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flash/">Flash Professional CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/soundbooth/">Soundbooth CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/premiere/onlocation/">Adobe OnLocation CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/premiere/encore/">Encore CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/bridge/">Bridge CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/devicecentral/">Device Central CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/dynamiclink/">Dynamic Link</a></dd><dd><a href="http://www.adobe.com/go/cslive_cn">与 CS Live 在线服务集成**</a></dd></dl><dl><dt><a href="http://www.adobe.com/cn/products/creativesuite/mastercollection/">Creative Suite 5 Master Collection</a></dt><dd><a href="http://www.adobe.com/cn/products/photoshop/photoshopextended/">Photoshop CS5 Extended</a></dd><dd><a href="http://www.adobe.com/cn/products/illustrator/">Illustrator CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/indesign/">InDesign CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/acrobatpro/">Acrobat 9 Pro</a></dd><dd><a href="http://www.adobe.com/cn/products/flashcatalyst/">Flash Catalyst CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/flash/">Flash Professional CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/flashbuilder/">Flash Builder 4 Standard</a></dd><dd><a href="http://www.adobe.com/cn/products/dreamweaver/">Dreamweaver CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/fireworks/">Fireworks CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/contribute/">Contribute CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/premiere/">Adobe Premiere Pro CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/aftereffects/">After Effects CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/soundbooth/">Soundbooth CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/premiere/onlocation/">Adobe OnLocation CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/premiere/encore/">Encore CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/bridge/">Bridge CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/devicecentral/">Device Central CS5</a></dd><dd><a href="http://www.adobe.com/cn/products/creativesuite/dynamiclink/">Dynamic Link</a></dd><dd><a href="http://www.adobe.com/go/cslive_cn">与 CS Live 在线服务集成**</a></dd></dl></p>]]></description><category>杂记</category><comments>http://www.augweb.net/blog/post/226.html#comment</comments><wfw:comment>http://www.augweb.net/blog/</wfw:comment><wfw:commentRss>http://www.augweb.net/blog/feed.asp?cmt=226</wfw:commentRss><trackback:ping>http://www.augweb.net/blog/cmd.asp?act=tb&amp;id=226&amp;key=58ac61ae</trackback:ping></item></channel></rss>

