<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[修行-走吧 - 【Work】]]></title>
<link>http://blog.cistadel.com/blog/</link>
<description><![CDATA[创造机会的人是勇者；等待机会的人是愚者]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog3 v2.8]]></copyright>
<webMaster><![CDATA[unrain@sina.com(西马|英雄无敌)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>修行-走吧</title>
	<url>http://blog.cistadel.com/blog/images/logos.gif</url>
	<link>http://blog.cistadel.com/blog/</link>
	<description>修行-走吧</description>
</image>

			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=583</link>
			<title><![CDATA[cloudstack 的坑]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Mon,30 Dec 2019 15:39:18 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=583</guid>
		<description><![CDATA[最近一客户单位要启用16年的备用环境，cloudstack正常启动后，kvm虚拟机启动了两台，发现应用收到影响，于是将虚拟机关闭，等到再次启动虚拟机时发现，启动失败。控制台给出的错误是&#34;Unable to start a VM due to insufficient capacity&#34;。一下子懵逼了，这cloudstack是个老古董啊，梁胜早就干别的去了，现在流行容器化，这cloudstack也没人管了，以前我也没整过这个啊。只好求助baidu和Google，一轮搜索下来发现&#34;Unable to start a VM due to insufficient capacity&#34;,这个错误是个表象，开启cloudstackmanagement日志的trace级别，和agent的trace基本日志，发现每次启动都是这个错误第一个出现。<br/>2019-12-27 09:29:15,224 INFO&nbsp;&nbsp;[c.c.v.VirtualMachineManagerImpl] (Work-Job-Executor-5:ctx-8cac4657 job-119455/job-119456 ctx-84437abc) (logid:ede314d7) Unable to contact resource.<br/>com.cloud.exception.ResourceUnavailableException: Resource [Pod:1] is unreachable: Unable to apply userdata and password entry on router<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at o&#114;g.apache.cloudstack.network.topology.BasicNetworkTopology.applyRules(BasicNetworkTopology.java:397)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at o&#114;g.apache.cloudstack.network.topology.BasicNetworkTopology.applyUserData(BasicNetworkTopology.java:185)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at com.cloud.network.element.VirtualRouterElement.addPasswordAndUserdata(VirtualRouterElement.java:1015)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at o&#114;g.apache.cloudstack.engine.orchestration.NetworkOrchestrator.prepareElement(NetworkOrchestrator.java:1266)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at o&#114;g.apache.cloudstack.engine.orchestration.NetworkOrchestrator.prepareNic(NetworkOrchestrator.java:1385)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at o&#114;g.apache.cloudstack.engine.orchestration.NetworkOrchestrator.prepare(NetworkOrchestrator.java:1321)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at com.cloud.vm.VirtualMachineManagerImpl.orchestrateStart(VirtualMachineManagerImpl.java:996)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at com.cloud.vm.VirtualMachineManagerImpl.orchestrateStart(VirtualMachineManagerImpl.java:4580)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at java.lang.reflect.Method.invoke(Method.java:498)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at com.cloud.vm.VmWorkJobHandlerProxy.handleVmWorkJob(VmWorkJobHandlerProxy.java:107)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at com.cloud.vm.VirtualMachineManagerImpl.handleVmWorkJob(VirtualMachineManagerImpl.java:4741)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at com.cloud.vm.VmWorkJobDispatcher.runJob(VmWorkJobDispatcher.java:102)<br/>&#34;nable to apply userdata and password entry on router&#34;,搜索这个错误，有很多说法，其中有人说把虚拟路由删除，再重设置一个就好了，这是粗处理，再搜索，找到这篇文章。“cloudstack 虚拟路由之痛”<br/><a href="https://selfsigned.wordpress.com/2014/06/27/cloudstack-virtual-router-pains/" target="_blank" rel="external">https://selfsigned.wordpress.com/2014/06/27/cloudstack-virtual-router-pains/</a><br/><br/>作为虚拟路由的deban系统内/var/log日志占满了磁盘，导致这个问题，进入VR的控制台删除日志就好了。这坑埋得太深了。<br/><br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=531</link>
			<title><![CDATA[新浪微博爬虫之htmlunit]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Fri,28 Feb 2014 20:45:41 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=531</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160;&nbsp;&nbsp;&nbsp;&nbsp;最近研究新浪微博的爬虫，微博api申请繁琐，限制很多，另想办法。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;爬微博，首先要登录，httpclient可以做，麻烦，而且微博的登录密码的加密方式不停的在变化，再找找，发现了这个开源htmlunit，完全在java下模拟浏览器行为，这个方便，用来写个登录小程序，几行代码就可以登录，并获取登录后的页面内容。简单方便。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;先继续琢磨一下。<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=493</link>
			<title><![CDATA[hibernate下自定义字段的实现探讨]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Tue,16 Mar 2010 17:36:25 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=493</guid>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;最近做内部开发平台，有个需求，权限系统中用户的基本信息外还有很多扩展信息，不同的项目要有不同的信息需求，用hibernate实现了一下，这里再记录一下备查，最近一段时间比较抑郁，脑子总是晕乎乎的，文字混乱，见谅。<br/>&nbsp;&nbsp; 公司程序员习惯于hibernate，平台集成了hibernate，h3支持动态组件“dynamic-component”，但是查一下dynamic-component，也必须在里面指定属性，网上搜索了一下发现了这篇文章<br/>&#34;<a target="_blank" href="http://www.infoq.com/cn/articles/hibernate-custom-fields" rel="external">用Hibernate实现领域对象的自定义字段</a>&#34;,大体的意思就是配置文件中设置完dynamic-component，然后在运行时根据添加的字段重定义内存配置文件，再更新磁盘上的配置文件，最后更改数据库结构。这个方法比较恐怖，更改数据库结构这个需求我们不需要，如果我们也搞成这个样子，程序员一操作，平台的库结构就不可控了，特别是这个设置<br/>&lt;property name=&#34;hibernate.hbm2ddl.auto&#34;&gt;up&#100;ate&lt;/property&gt;<br/>更新数据库的schema。这个方法还有一个问题，在集群处理的时候更新磁盘上的文件还有一个同步的问题。<br/>&nbsp;&nbsp;&nbsp;&nbsp;那能不能在系统初始化的时候，hibernate载入xml配置文件的时候动态插入修改呢，看了下hibernate的代码org.hibernate.cfg.AnnotationConfiguration下有个add的方法，断点测试，发现xml载入时要调用这个方法，思路就明显了，我们可以想办法重写这个方法，在载入xml时如果含有dynamic-component节点，那么我们就可以从另外的配置文件中取到此节点对应的扩展字段配置插入到这dynamic-component节点下，这样程序员在扩展user类的时候只需要数据库字段添加，form上字段添加，再配置dynamic-component节点的自定义扩展属性，那在自定义项目信息的时候不就ok了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;我们的平台用spring进行集成，派生了org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean这个类，因此在AnnotationSessionFactoryBean这个派生类中初始化的时候调用父类setConfigurationClass（）方法，吧自定义的AnnotationConfiguration设置进去，如果这个派生类叫AnnotationConfigurationEx，那么这个类可以这么写<br/><div class="UBBPanel codePanel"><div class="UBBTitle"><a onClick="copycode(code18467);" style="float:right;cursor: pointer;font-weight: normal; font-style: normal">复制内容到剪贴板</a><img src="http://blog.cistadel.com/blog/images/code.gif" style="margin:0px 2px -3px 0px;" alt="程序代码"/> 程序代码</div><div class="UBBContent" id=code18467><br/><br/><br/>import o&#114;g.hibernate.MappingException;<br/>import o&#114;g.hibernate.cfg.AnnotationConfiguration;<br/><br/>public class AnnotationConfigurationEx extends AnnotationConfiguration{<br/>&#160;&#160;&#160;&#160;//private static final long serialVersionUID = 7945995403611791535L;<br/>&#160;&#160;&#160;&#160;protected void add(org.dom4j.Document doc) throws MappingException {<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;super.add(DynamicComponentProccess(doc));<br/>&#160;&#160;&#160;&#160;}<br/><br/>}</div></div><br/><br/>这个DynamicComponentProccess(doc)方法里面就可以解析xml插入自定义扩展字段，我是这么写的<br/><div class="UBBPanel codePanel"><div class="UBBTitle"><a onClick="copycode(code10181);" style="float:right;cursor: pointer;font-weight: normal; font-style: normal">复制内容到剪贴板</a><img src="http://blog.cistadel.com/blog/images/code.gif" style="margin:0px 2px -3px 0px;" alt="程序代码"/> 程序代码</div><div class="UBBContent" id=code10181>Element hbm = doc.getRootElement();<br/>&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;List&lt;Element&gt; es = hbm.sel&#101;ctNodes(&#34;//class/dynamic-component&#34;);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(es.size()&gt;0)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for(int i = 0;i&lt;es.size();i++)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;String className=es.get(i).getParent().attributeValue(&#34;name&#34;);<br/>//这里从自己的配置文件中得到dynamic-component节点所在class的对应的扩展字段<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;List&lt;Element&gt; l = getExtPropertyMap().get(className);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(l!=null)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for(int j = 0;j&lt;l.size();j++)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;es.get(i).content().add(l.get(j));&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;else<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;es.get(i).getParent().content().remove(es.get(i));<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/><br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return doc;</div></div><br/><br/>这样hibernate在启动的时候就会载入自己需要的设置。扩展属性的配置文件是这么写的<br/><br/><div class="UBBPanel codePanel"><div class="UBBTitle"><a onClick="copycode(code88155);" style="float:right;cursor: pointer;font-weight: normal; font-style: normal">复制内容到剪贴板</a><img src="http://blog.cistadel.com/blog/images/code.gif" style="margin:0px 2px -3px 0px;" alt="程序代码"/> 程序代码</div><div class="UBBContent" id=code88155>&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;<br/>&lt;class&gt;<br/>&#160;&#160;&#160;&#160;&lt;ext classnme=&#34;apps.ldap.authority.mould.swordUserImpl&#34;&gt;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&lt;property name=&#34;email&#34; column=&#34;email&#34; type=&#34;string&#34;/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name=&#34;telephoneNumber&#34; column=&#34;telephoneNumber&#34; type=&#34;string&#34;/&gt;<br/>&#160;&#160;&#160;&#160;&lt;/ext&gt;<br/>&lt;/class&gt;</div></div><br/><br/>接下来我们要写mould和action里面的内容<br/>我们定义了一个abstract的类加CustomizableEntity。需要自定义字段的mould都派生自它，这个类有4个方法,这段代码我完全抄录自文章“用Hibernate实现领域对象的自定义字段”，<br/><div class="UBBPanel codePanel"><div class="UBBTitle"><a onClick="copycode(code27676);" style="float:right;cursor: pointer;font-weight: normal; font-style: normal">复制内容到剪贴板</a><img src="http://blog.cistadel.com/blog/images/code.gif" style="margin:0px 2px -3px 0px;" alt="程序代码"/> 程序代码</div><div class="UBBContent" id=code27676>public abstract class CustomizableEntity implements IEntity&lt;String&gt;,IAssignable {<br/>&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;private Map&lt;String,String&gt; customProperties;<br/><br/>&#160;&#160;&#160;&#160;public Map&lt;String,String&gt; getCustomProperties() {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (customProperties == null)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; customProperties = new HashMap&lt;String, String&gt;();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return customProperties;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&#160;&#160;&#160;&#160;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public void setCustomProperties(Map&lt;String,String&gt; customProperties) {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.customProperties = customProperties;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public Object getValueOfCustomField(String name) {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getCustomProperties().get(name);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;public void setValueOfCustomField(String name, String value) {<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getCustomProperties().put(name, value);<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/>} </div></div><br/><br/>很简单就是对自定义字段的操作。<br/>action里面需要加一个方法自动对扩展字段赋值，我是这么写的<br/><br/><div class="UBBPanel codePanel"><div class="UBBTitle"><a onClick="copycode(code9113);" style="float:right;cursor: pointer;font-weight: normal; font-style: normal">复制内容到剪贴板</a><img src="http://blog.cistadel.com/blog/images/code.gif" style="margin:0px 2px -3px 0px;" alt="程序代码"/> 程序代码</div><div class="UBBContent" id=code9113>/**<br/>&#160;&#160;&#160;&#160; * 预处理扩展字段<br/>&#160;&#160;&#160;&#160; */<br/>&#160;&#160;&#160;&#160;@SuppressWarnings(&#34;unchecked&#34;)<br/>&#160;&#160;&#160;&#160;public static &lt;T extends IEntity&gt; void preProcessExtProperty(T entity,Map&lt;String,String&gt; values)<br/>&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(entity instanceof CustomizableEntity)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Map&lt;String,List&lt;Element&gt;&gt; extPropertyMap = DynamicComponentProccess.getExtPropertyMap();<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;List&lt;Element&gt; es = extPropertyMap.get(entity.getClass().getName());<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(es!=null)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for(int i =0;i&lt;es.size();i++)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;String pName = es.get(i).attributeValue(&#34;name&#34;);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if (values.containsKey(pName))<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&nbsp;&nbsp;((CustomizableEntity) entity).setValueOfCustomField(pName, values.get(pName));<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;}</div></div><br/>判断如果是CustomizableEntity的派生类就把字段和扩展字段配置文件中字段对比，调用setValueOfCustomField方法，将扩展字段的值加进去。把这个方法放到action的父类中重写excute在里面调用就ok了，当然也可以手动调用，比较麻烦。<br/><br/>&nbsp;&nbsp; 这样我们的程序员在使用平台的过程中就可以自己定义user的扩展信息而不需要我们干预修改了。这里也只是只实现了一个string类型的字段值，其他类型的可以自己做扩展。spring里面怎么配置hibernate这里就不多说了。<br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=416</link>
			<title><![CDATA[apache用urlrewrite实现二级域名]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Thu,22 Nov 2007 16:12:25 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=416</guid>
		<description><![CDATA[服务器是apache带了iis和tomcat，又要加一个系统跑了一个第三方的类似iis的web服务还要加二级域名，烦，这就是集成？还要搞单点登录，哎<br/><br/>80端口给apache，iis给了6666，类iis给了801，tomcat给了8081，琢磨了一天才实现这个功能记一笔不要忘了。<br/>首先泛域名解析要找域名商设置的，其他的urlrewrite就在apache里做了<br/>一切尽在这段中<br/>&lt;VirtualHost *&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ServerAdmin hibj@letgoo.com<br/>&nbsp;&nbsp;&nbsp;&nbsp;DocumentRoot /webs/hosts/hibj/html/<br/>&nbsp;&nbsp;&nbsp;&nbsp;ServerName www.XXXX.cn<br/>&nbsp;&nbsp;&nbsp;&nbsp;ServerAlias www.XXXX.cn<br/>&nbsp;&nbsp;&nbsp;&nbsp;ErrorLog c:/webs/logs/www.XXXX.cn-error_log<br/>&nbsp;&nbsp;&nbsp;&nbsp;CustomLog c:/webs/logs/www.XXXX.cn-access_log common<br/>#前面的就不说了一个VirtualHost 的设置<br/>#这个是把iis代理到虚拟目录shop1上<br/>ProxyPass /shop1/ <a href="http://127.0.0.1:6666/" target="_blank" rel="external">http://127.0.0.1:6666/</a><br/>#这个是把类iis代理到虚拟目录store上<br/>ProxyPass /store/ <a href="http://127.0.0.1:801/" target="_blank" rel="external">http://127.0.0.1:801/</a><br/>#下面是rewrite的写法，三个rewritecond三个的关系默认是AND，第2和第3个rewritecond表示如果是www\.XXXX\.cn或者shop\.XXXX\.cn就不做url rewrite<br/>Rewriteengine on<br/>rewritecond %{HTTP_HOST} ^[^.]+\.XXXX\.cn$ [NC]<br/>rewritecond %{HTTP_HOST} !^www\.XXXX\.cn.*$ [NC]<br/>rewritecond %{HTTP_HOST} !^shop\.XXXX\.cn.*$ [NC]<br/>rewriterule ^(.+) %{HTTP_HOST}$1 [C] <br/>#这里就把符合条件的HTTP_HOST请求转发到/store/index.asp，并且把请求的地址作为参数传递给index.asp,当然在index.asp中怎么分配转发自己写了<br/>rewriterule ^([a-z-]+\.XXXX\.cn/.*) /store/index.asp?site=$1 [PT]<br/>&lt;/VirtualHost&gt;<br/>这样用户abc创建自己的账户后就可以用 abc.XXXX.com来访问了]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=384</link>
			<title><![CDATA[apache+Tomcat 会话通用问题]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Mon,09 Apr 2007 14:40:20 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=384</guid>
		<description><![CDATA[<br/>今天干活遇到一个问题，apache下shtml中包含的服务器端文件取到的会话和tomcat中取到的会话不一样，折腾半天突然想起去年也遇到同样的问题，就是想不起来怎么解决的，近一个小时后才弄出来就是tomcat的配置server.xml中这一节里<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Connector port=&#34;18009&#34; emptySessionPath=&#34;true&#34;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups=&#34;false&#34; redirectPort=&#34;8443&#34; protocol=&#34;AJP/1.3&#34; /&gt;<br/><br/> emptySessionPath=&#34;true&#34;<br/>tomcat站点里ajp是这么说的<br/>If set to true, all paths for session cookies will be set to /. This can be useful for portlet specification implementations, but will greatly affect performance if many applications are accessed on a given server by the client. If not specified, this attribute is set to false.<br/><br/><br/>cookies的路径问题啊，记录一下，下次别又忘了<br/>]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=271</link>
			<title><![CDATA[关于投票]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Thu,23 Mar 2006 10:04:14 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=271</guid>
		<description><![CDATA[上周六LP的领导给她一个任务每天给某地十佳青年评选的某美人投三票，因为一个IP一天只能投三票。我给LP用js简单写了个随机生成身份证号并且自动提交的东西，刷三下她就完成任务了，结果LP为了邀功就不停的拨号、断开给投了30票，第二天领导说，不错啊效率真高，这样吧你就一天投100票吧。LP回来说这么多人作弊，一天涨1k多票的，咱们送佛送到西天，也想办法给作弊得了。我就开始琢磨了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;这个投票程序写的也不咋的，IP限制一天投三票，身份证限制一个只能一票，其他没有任何限制，连流行的验证码都没有用。POST或者GET方式都能提交数据。想到了三个办法来作弊。<br/>&nbsp;&nbsp;&nbsp;&nbsp;一、能不能挂个东西在我们的网站上让我们网站的访问者访问时不知不觉就提交了数据，当然只能用客户端的JS代码，不然IP永远是我们服务器的，提交代码已经有了，但是如何解决提交成功或者失败时出现的这个对话框呢，就是JS生成的alert(&#39;投票成功&#39;),总不能让人访问我们网站的时候出现这个吧，想了一下没有想出办法来。结果LP的一个朋友给想出了办法，好办法&lt;img src=&#34;<a href="http://asdfasdf/XXX/vote.asp?cid=XXXXXX" target="_blank" rel="external">http://asdfasdf/XXX/vote.asp?cid=XXXXXX</a>&amp;vid=XXXXXX&#34;&gt;,这样同样的向那边服务器提交了数据，返回的alert还不会被执行，我怎么就没想到呢。<br/>&nbsp;&nbsp;&nbsp;&nbsp;二、原来单位有个刷流量的软件，看看能否用上，琢磨了一下，除非有这个软件的源码，我能修改才行，因为身份证号必须随机产生。哦，这个软件其实就是代理服务器，从代理服务器表里找能用的发送请求。虽然能用的代理不多，但是一天也可以多个上百票。那个朋友刚好手头有代理的源码，改把改把也能用上了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;三、网上不是有投票软件吗。我搜索了一下，能用的都是卖的，卖得还是需要定制的，遇到有IP限制的好像也没有太多的办法。就是需要把拨号程序断开再自动连接。伪造IP的事情好像没有一个人走，伪造IP还是上面的代理，而且IP还必须是代理服务器。其实想想其他都好说，这个投票软件的主要地方就在自动拨号了，还是自己写一个吧，找了相关资料，调用windows的远程访问服务（RAS）的API就能完成，正在研究中发现了有老外写的调用的代码，嘿嘿，好东西，copy上来共享一下吧，稍微改把改把就能用上。<br/>using System;<br/>using System.Runtime.InteropServices;<br/>using System.Text;<br/><br/>namespace Dailup.RAS<br/>{<br/>&#160;&#160;&#160;&#160;internal enum RasFieldSizeConstants<br/>&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxDeviceType&nbsp;&nbsp;&nbsp;&nbsp; =16,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxPhoneNumber&nbsp;&nbsp;&nbsp;&nbsp;=128,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxIpAddress&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=15,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxIpxAddress&nbsp;&nbsp;&nbsp;&nbsp; =21,<br/>#if WINVER4<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxEntryName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=256,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxDeviceName&nbsp;&nbsp;&nbsp;&nbsp; =128,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxCallbackNumber =RAS_MaxPhoneNumber,<br/>#else<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxEntryName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxDeviceName&nbsp;&nbsp;&nbsp;&nbsp; =32,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxCallbackNumber =48,<br/>#endif<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxAreaCode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =10,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxPadType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=32,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxX25Address&nbsp;&nbsp;&nbsp;&nbsp; =200,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxFacilities&nbsp;&nbsp;&nbsp;&nbsp; =200,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxUserData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =200,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxReplyMessage&nbsp;&nbsp; =1024,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS_MaxDnsSuffix&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=256,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;UNLEN&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&nbsp;&nbsp;=256,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;PWLEN&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&nbsp;&nbsp;=256,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DNLEN&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&nbsp;&nbsp;=15<br/>&#160;&#160;&#160;&#160;}<br/><br/><br/>&#160;&#160;&#160;&#160;[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;public struct GUID<br/>&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public uint&#160;&#160;&#160;&#160;&nbsp;&nbsp;Data1;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public ushort&nbsp;&nbsp; Data2;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public ushort&nbsp;&nbsp; Data3;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValArray,SizeConst=8)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public byte[] Data4;<br/>&#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;<br/><br/>&#160;&#160;&#160;&#160;[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;internal struct RASCONN <br/>&#160;&#160;&#160;&#160;{ <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int&nbsp;&nbsp;&nbsp;&nbsp; dwSize; <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public IntPtr&nbsp;&nbsp;hrasconn; <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxEntryName+1)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string&nbsp;&nbsp;&nbsp;&nbsp;szEntryName; <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxDeviceType+1)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string&nbsp;&nbsp;&nbsp;&nbsp;szDeviceType; <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxDeviceName+1)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string&nbsp;&nbsp;&nbsp;&nbsp;szDeviceName; <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=260)]//MAX_PAPTH=260<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string&nbsp;&nbsp;&nbsp;&nbsp;szPhonebook;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&nbsp;&nbsp;dwSubEntry;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public GUID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&nbsp;&nbsp;guidEntry;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#if (WINVER501)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int&nbsp;&nbsp;&nbsp;&nbsp; dwFlags;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; public LUID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;luid;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;#endif<br/>&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;internal struct LUID <br/>&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int LowPart;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int HighPart;<br/>&#160;&#160;&#160;&#160;}<br/><br/>&#160;&#160;&#160;&#160;[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;public struct RasEntryName <br/>&#160;&#160;&#160;&#160;{ <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwSize; <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxEntryName + 1)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string szEntryName; <br/>#if WINVER5<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwFlags;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=260+1)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string szPhonebookPath;<br/>#endif<br/>&#160;&#160;&#160;&#160;}<br/><br/>&#160;&#160;&#160;&#160;[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;public class RasStats <br/>&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwSize=Marshal.SizeOf(typeof(RasStats));<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwBytesXmited;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwBytesRcved;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwFramesXmited;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwFramesRcved;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwCrcErr;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwTimeoutErr;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwAlignmentErr;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwHardwareOverrunErr;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwFramingErr;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwBufferOverrunErr;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwCompressionRatioIn;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwCompressionRatioOut;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwBps;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int dwConnectDuration;<br/>&#160;&#160;&#160;&#160;} <br/><br/>&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;public class RAS<br/><br/>&#160;&#160;&#160;&#160;{<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[DllImport(&#34;Rasapi32.dll&#34;, EntryPoint=&#34;RasEnumConnectionsA&#34;,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SetLastError=true)]<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;internal static extern int RasEnumConnections<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;(<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ref RASCONN lprasconn, // buffer to receive connections data<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ref int lpcb, // size in bytes of buffer<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ref int lpcConnections // number of connections written to buffer<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;);<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[DllImport(&#34;rasapi32.dll&#34;,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;internal static extern uint RasGetConnectionStatistics(<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IntPtr hRasConn,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // handle to the connection<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[In,Out]RasStats lpStatistics&nbsp;&nbsp;// buffer to receive statistics<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[DllImport(&#34;rasapi32.dll&#34;,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public extern static uint RasHangUp(<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IntPtr hrasconn&nbsp;&nbsp;// handle to the RAS connection to hang up<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;);<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[DllImport(&#34;rasapi32.dll&#34;,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public extern static uint RasEnumEntries (<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string reserved,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// reserved, must be NULL<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string lpszPhonebook,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // pointer to full path and<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&nbsp;&nbsp;file name of phone-book file<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[In,Out]RasEntryName[] lprasentryname, // buffer to receive<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&nbsp;&nbsp;phone-book entries<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ref int lpcb,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// size in bytes of buffer<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;out int lpcEntries&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // number of entries written<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&nbsp;&nbsp;to buffer<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;);<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[DllImport(&#34;wininet.dll&#34;,CharSet=CharSet.Auto)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public extern static int InternetDial(<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IntPtr hwnd,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[In]string lpszConnectoid, <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;uint dwFlags,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ref int lpdwConnection,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;uint dwReserved<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;);<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public RAS()<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&#160;&#160;&#160;&#160;}<br/><br/>&#160;&#160;&#160;&#160;public class RASDisplay<br/>&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private string m_duration;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private string m_ConnectionName;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private string[] m_ConnectionNames;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private double m_TX;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private double m_RX;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private bool m_connected;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;private IntPtr m_ConnectedRasHandle;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public RASDisplay()<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_connected = true;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS lpras = new RAS();<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RASCONN lprasConn = new RASCONN();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lprasConn.dwSize = Marshal.SizeOf(typeof(RASCONN));<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lprasConn.hrasconn = IntPtr.Zero;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int lpcb = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int lpcConnections = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int nRet = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lpcb = Marshal.SizeOf(typeof(RASCONN));<br/>&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;nRet = RAS.RasEnumConnections(ref lprasConn, ref lpcb, ref<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lpcConnections);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(nRet != 0)<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_connected = false;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(lpcConnections &gt; 0)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//for (int i = 0; i &lt; lpcConnections; i++)<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RasStats stats = new RasStats();<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_ConnectedRasHandle = lprasConn.hrasconn;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS.RasGetConnectionStatistics(lprasConn.hrasconn, stats);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_ConnectionName = lprasConn.szEntryName;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int Hours = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int Minutes = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int Seconds = 0;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Hours = ((stats.dwConnectDuration /1000) /3600);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Minutes = ((stats.dwConnectDuration /1000) /60) - (Hours * 60);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Seconds = ((stats.dwConnectDuration /1000)) - (Minutes * 60) - (Hours * 3600);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_duration = Hours&nbsp;&nbsp;+&nbsp;&nbsp;&#34; hours &#34;&nbsp;&nbsp;+ Minutes + &#34; minutes &#34; + Seconds + &#34; secs&#34;;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_TX = stats.dwBytesXmited;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_RX = stats.dwBytesRcved;<br/><br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//}<br/><br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;else<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_connected = false;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int lpNames = 1;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int entryNameSize = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int lpSize = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RasEntryName[] names = null;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;entryNameSize=Marshal.SizeOf(typeof(RasEntryName));<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lpSize=lpNames*entryNameSize;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;names=new RasEntryName[lpNames];<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;names[0].dwSize=entryNameSize;<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;uint retval = RAS.RasEnumEntries(null,null,names,ref lpSize,out lpNames);<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//if we have more than one connection, we need to do it again<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(lpNames &gt; 1)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;names=new RasEntryName[lpNames];<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for(int i=0;i&lt;names.Length;i++)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;names[i].dwSize=entryNameSize;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;retval = RAS.RasEnumEntries(null,null,names,ref lpSize,out lpNames);<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_ConnectionNames = new string[names.Length];<br/>&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(lpNames&gt;0)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;for(int i=0;i&lt;names.Length;i++)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;m_ConnectionNames[i] = names[i].szEntryName;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string Duration<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return m_connected ? m_duration : &#34;&#34;;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string[] Connections<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return m_ConnectionNames;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public double BytesTransmitted<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return m_connected ? m_TX : 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public double BytesReceived<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return m_connected ? m_RX :&nbsp;&nbsp;0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public string ConnectionName<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return m_connected ? m_ConnectionName : &#34;&#34;;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public bool IsConnected<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;get<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return m_connected;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/><br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public int Connect(string Connection)<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int temp = 0;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;uint INTERNET_AUTO_DIAL_UNATTENDED = 2;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int retVal = RAS.InternetDial(IntPtr.Zero,Connection,INTERNET_AUTO_DIAL_UNATTENDED,ref temp,0);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;return retVal;<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public void Disconnect()<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RAS.RasHangUp(m_ConnectedRasHandle);<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}<br/>&#160;&#160;&#160;&#160;}<br/><br/><br/>}<br/><br/>在disconnect和connect中线程挂起5秒，因为发现如果太快了IP不变。<br/>在投票的循环中，每次投完票，也把线程挂起5秒，如果不这样，那边网站反应不过来，出现网站正在维护中的错误。算上可能遇上的身份证号重复和IP重复，一个小时估计能投100多票。一个晚上能刷出1k的票来。<br/>送佛送到西天了。]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=270</link>
			<title><![CDATA[伪造cookies偷数据]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Mon,20 Mar 2006 09:57:22 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=270</guid>
		<description><![CDATA[现在网站很多信息都是从其他网站的信息系统里偷来的，比如新闻小偷，最近我们的短信系统想上天气预报的功能，短信策划部的人说了就从XXXX那里拿数据吧，我就回来干活了。<br/>&nbsp;&nbsp;&nbsp;&nbsp;正常的，得到了页面需要的参数，给Ypost过去吧，哦~不对，返回错误信息，再看看参数都是对的，难道不成有会话存在？关闭所有浏览器窗口，清除cookies，重新直接进入结果页面，果然出错，试了几把确定是从首页产生了cookies，通过这个cookies才能访问结果页，目的肯定是为了防止盗链。<br/>&nbsp;&nbsp;&nbsp;&nbsp;如果能知道这个cookies的内容，我们伪造一个不久能直接访问结果页面了吗？我们来试试吧，首先想想，浏览器怎么访问一个网站呢？把请求发送到服务器，服务器根据请求返回相应的页面代码和其他信息，这个其他信息里面就包含了我们要的cookies的信息。怎么知道浏览器给服务器发送了什么信息？可以上网查查相关资料了，我是从我们的服务器访问日志中copy来一段稍微修改了一下。ok准备好了，我们就假冒浏览器发送请求了，telnet是个好东西。<br/>&nbsp;&nbsp;&nbsp;&nbsp;telnet www.XXXXXXgov.cn 80<br/>&nbsp;&nbsp;&nbsp;&nbsp; 这样就出来telnet的命令行模式，输入<br/>GET /XXXXXXX/index.jsp HTTP/1.1<br/>HOST: www.nmc.gov.cn<br/><br/>什么？输入的字都不显示！直接copy再粘贴进去得了。然后回车回车回车...直到有反应为止，这个时候屏幕哗哗哗的现实结果了，注意，我们要的结果在信息的最上面，可要看好了<br/><br/>HTTP/1.1 200 OK<br/>Server: Apache-Coyote/1.1<br/>Set-Cookie: JSESSIONID=36F4829CD68F71110C6480B4F1C373B4; Path=/XXXXX<br/>Content-Type: text/html;charset=GB18030<br/>Transfer-Encoding: chunked<br/>Date: Mon, 20 Mar 2006 01:11:13 GMT<br/><br/>第一行是状态码，第二行是web服务器应该是tomcat吧，注意第三行就是偶们要的cookies了，所有java产生的cookies都是这个样子&#34;JSESSIONID=&#34;。嘿嘿其他就不管了，要得就是这个。<br/><br/>接下来我们看看带上cookies的浏览器请求是什么样子的<br/><br/><br/>GET /XXXXXX/citySearch.do?inputMode=citysearch&amp;type=second&amp;cityid=52896 HTTP/1.1<br/>Referer: /XXXX/index.jsp\nUser-Agent: TAX<br/>Cookie: $Version=\&#34;1\&#34;; JSESSIONID=XXXXXXXXXXXXXXX; Path=/XXXX<br/>HOST: 127.0.0.1<br/><br/>ok，好像我们只要把从index.jsp这个页面产生的JSESSIONID=36F4829CD68F71110C6480B4F1C373B4; Path=/XXXX放到相应的位置，然后把这个请求发给对方网站就行了就行了。编辑后就是这样了<br/><br/>GET /XXXX/citySearch.do?inputMode=citysearch&amp;type=second&amp;cityid=52896 HTTP/1.1<br/>Referer: /XXXX/index.jsp\nUser-Agent: TAX<br/>Cookie: $Version=\&#34;1\&#34;; JSESSIONID=36F4829CD68F71110C6480B4F1C373B4; Path=/XXXX<br/>HOST: 127.0.0.1<br/><br/>同样的telnet给发送过去，ok结果正确出来了。回来看看其实也不算伪造，就是截了我需要的cookies信息，然后把他带在请求里发送过去。<br/><br/>至于在程序里怎么写，我想这个各自的语言有各自的写法，只要把上面的过程体现出来就行了。<br/><br/>给段java写的吧<br/>HttpClient client = new HttpClient();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetMethod method = new GetMethod(&#34;<a href="http://www.XXXX.gov.cn/XXXX/index.jsp" target="_blank" rel="external">http://www.XXXX.gov.cn/XXXX/index.jsp</a>&#34;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.executeMethod(method);<br/>&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String tt = method.getResponseHeaders()[1].getValue(); //取得“Set-Cookie”的值<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tt = tt.replace(&#34;Path=/XXXX&#34;, &#34;$path=\&#34;/XXXX\&#34;&#34;); //修改成合适HEADer的值<br/>&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//**********************创建Header<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetMethod get = new GetMethod();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Header aaa = new Header();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aaa.setName(&#34;Cookie: &#34;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aaa.setValue(&#34;$Version=\&#34;1\&#34;; &#34; + tt);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//*********************************<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get.setRequestHeader(aaa);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//********************再次请求真正的城市天气页面<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get.setPath(&#34;<a href="http://www.XXXX.gov.cn/XXXX/citySearch.do?inputMode=citysearch" target="_blank" rel="external">http://www.XXXX.gov.cn/XXXX/citySearch.do?inputMode=citysearch</a>&amp;type=second&amp;cityid=&#34; +<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oCity.getId());<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.executeMethod(get);<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(method.getResponseHeaders()[i].getName()+&#34;=&#34;+method.getResponseHeaders()[i].getValue());<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response = new String(get.getResponseBodyAsString().getBytes(&#34;gb2312&#34;));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get.releaseConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.releaseConnection();<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response = response.replace(&#34;\r\n&#34;, &#34;&#34;);<br/><br/>再回想一下，其实还有网站这么干的，判断请求页面的上一个页面是不是某个页面，如果不是就不给显示，或者强制转向到那个页面。其实这个依据就是上面的请求中的<br/>Referer: /XXXX/index.jsp\nUser-Agent: TAX<br/><br/>呵呵，我们也同样的方式修改请求的head中的Referer属性，就能达到相同的效果。<br/><br/>欢迎使用我们的短信查天气，发送“武进天气”或者“武进气象”或者“武进的天气”任何带地区名字和“天气”或“气象”关键字的短语到80021598（移动）90021598（联通），一条三毛钱哦。]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=170</link>
			<title><![CDATA[桑拿天很不爽]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Sun,14 Aug 2005 16:12:47 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=170</guid>
		<description><![CDATA[桑拿天又来了，难受的很，昨天还在没有冷气的办公室干到了晚上8点说不出的不舒服。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 今天因为需要，我做了一个小工具，可以从www.273.cn上下载汽车品牌和型号数据，本想想自己一个个的存的但是算算居然有近1500个XML文件，要一个个自己存不累死，就做了这个东西，太小了才几K，有兴趣可以玩玩，呵呵，这里的数据真的很全的，国外品牌都有。<img src="http://blog.cistadel.com/blog/images/download.gif" alt="下载文件" style="margin:0px 2px -4px 0px"/> <a href="http://blog.cistadel.com/blog/attachments/month_0508/p200581416540.rar" target="_blank">点击下载此文件</a>，压缩包里有说明。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前两天一直在考虑局域网内即时通讯的问题，去年做的一个OA因为需要即时通讯的问题，设计的时B/s结构下常用的刷新方式，但是没有想到，他们需要使用的信息实在太多，一开即时通讯功能服务器就死机，恶心死了，前天他们和我说起这个事，我想只能用Socket方式来解决了。DotNet框架下Socket封装的很彻底，写起来应该不会太困难，就实现了一个简单的客户和服务器通讯，就几行代码，呵呵有点意思，继续研究一下。]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=162</link>
			<title><![CDATA[网页上打开本地程序]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Thu,04 Aug 2005 18:10:34 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=162</guid>
		<description><![CDATA[最近有个需求要在网页上打开本地程序，我记得一年多前也遇到过这个问题，当时出了两个解决方案，一种是用客户端脚本调用windows shell来调用，可以倒是可以，但是该死的杀毒软件总是把这段代码给删掉，于是出了第二个解决方案用VB6做一个ActiveX让用户访问页面的时候自动下载安装，但是用户安装的程序不一定装载什么目录下，所以只好加上一个操作数据库的功能，幸好客户没有说用户可能会在不同的机器登陆，如果真那样岂不是还要找出某台机器的网卡MAC或者cpu的序列号对应程序路径啊。<br/>&nbsp;&nbsp;&nbsp;&nbsp;这次也遇到这个问题，翻出一年多前的vb程序，想想现在都vs2005了还用vb寒碜啊，就改成DOTnet的，其实代码很简单就几行，两种方式调用本地程序，一种是调用winAPI的shell32.dll的shellexecute函数来执行，调用代码如下（C#）<br/>[DllImport(&quot;shell32.dll&quot;, EntryPoint=&quot;ShellExecute&quot;)]<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;public static extern int ShellExecute (<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int hwnd,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string lpOperation,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string lpFile,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string lpParameters,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;string lpDirectory,<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;int nShowCmd<br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;);<br/><br/>程序中直接：ShellExecute(0,&quot;open&quot;,YourFilepath,null,null,1);还需要引用System.Runtime.InteropServices; <br/>还有一种是用。net的Process对象，调用代码如下：<br/>System.Diagnostics.Process p = new System.Diagnostics.Process(); <br/>p.StartInfo.FileName = path;<br/>p.Start(); <br/><br/>呵呵，才三行。<br/>代码是这样，那么activeX怎么做出来呢，我搜索了一下，找到一篇文章，写得不错，就回忆一下，记录一下大概步骤。<br/>&nbsp;&nbsp;&nbsp;&nbsp;首先建立一个winform的空间Project，界面上就随便画了，一个按钮一个TextBox，textbox输入路径，按钮运行了。<br/>编译成Dll后用vc++的工具取得一个GUID，将[Guid(&quot;8F1FAA75-2FA8-4436-9FE4-4B6EED2DF6AF&quot;)]放到本类定义前面，将项目属性中配置属性-〉生成-〉为COM Interop注册改成true，ok再在c++工具ole/com对象查看器中就能看到了，右键点击它，选择最后一个“copy HTML&lt;object&gt; Tag to Clipboard”,生成了classid，直接粘贴到网页中就能用了类似这样<br/>&lt;body&gt;<br/>&lt;object id=&quot;shell&quot; classid=&quot;clsid:8F1FAA75-2FA8-4436-9FE4-4B6EED2DF6AF&quot; codebase=&quot;shell/Setup.Exe&quot;&gt;&lt;/object&gt;<br/>&lt;/body&gt;<br/>呵呵，访问者安装后就能使用了。当然还有访问者IE安全设置的问题，必须实现IObjectSafety接口，代码如下[Guid(&quot;CB5BDC81-93C1-11CF-8F20-00805F2CD064&quot;),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] <br/>&nbsp;&nbsp;&nbsp;&nbsp;public interface IObjectSafety <br/>&nbsp;&nbsp;&nbsp;&nbsp;{ <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// methods <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void GetInterfacceSafyOptions( <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Int32 riid, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out System.Int32 pdwSupportedOptions, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out System.Int32 pdwEnabledOptions); <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void SetInterfaceSafetyOptions( <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Int32 riid, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Int32 dwOptionsSetMask, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Int32 dwEnabledOptions);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;} <br/>然后在自己的winform控件类中实现这个接口<br/>public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// TODO:&nbsp;&nbsp;添加 WebCamControl.GetInterfacceSafyOptions 实现 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pdwSupportedOptions = 1; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pdwEnabledOptions = 2; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br/> <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions) <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// TODO:&nbsp;&nbsp;添加 WebCamControl.SetInterfaceSafetyOptions 实现&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br/> 编译后就ok了。<br/>这篇文章真不错<a href="http://www.cnblogs.com/homer/archive/2005/01/08/88780.aspx" target="_blank" rel="external">http://www.cnblogs.com/homer/archive/2005/01/08/88780.aspx</a>]]></description>
		</item>
		
			<item>
			<link>http://blog.cistadel.com/blog/article.asp?id=149</link>
			<title><![CDATA[一棵树]]></title>
			<author>unrain@sina.com(英雄无敌)</author>
			<category><![CDATA[【Work】]]></category>
			<pubDate>Tue,12 Jul 2005 21:14:38 +0800</pubDate>
			<guid>http://blog.cistadel.com/blog/default.asp?id=149</guid>
		<description><![CDATA[经过两个星期断断续续的努力，终于把这棵树种下了，这是棵可以拖拽修改树结构的树，中间有700行javascript代码，用了5个sql存储过程，或许有点复杂，或许有比这更简单的办法，不过我想再简单这700行js代码是免不了的。这过程也体会到“sql语法的博大精深”（某老大语），比如递归是树用的算法中最经典的，但是在sql中怎么办？不能用递归，怎么编历树？一个循环加一个临时表就能解决问题<br/>&nbsp;&nbsp; 表的结构是这样的<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;id int，pid int<br/>－－创建一个临时表<br/> cr&#101;ate table #a(id int,pid int)<br/>&nbsp;&nbsp;declare @pare int<br/>&#160;&#160;&#160;&#160; set @pare=@pID<br/>&#160;&#160;&#160;&#160;ins&#101;rt into #a (id,pid) values (@id,0) <br/> WHILE(@@ROWCOUNT&lt;&gt;0)<br/>&#160;&#160;&#160;&#160;begin<br/>&#160;&#160;&#160;&#160;ins&#101;rt into #a <br/>&#160;&#160;&#160;&#160;&nbsp;&nbsp; sel&#101;ct id,parent from tb_user_topic <br/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;wh&#101;re parent in (sel&#101;ct ID&nbsp;&nbsp;from #a) and id not in(sel&#101;ct ID from #a)<br/>&#160;&#160;&#160;&#160;end<br/><br/>这样临时表中存放的就是编历过后的节点，简单啊<br/><br/><img src="http://blog.cistadel.com/blog/attachments/month_0508/a20058413142.GIF" border="0" alt=""/><br/>]]></description>
		</item>
		
</channel>
</rss>
