<?xml version="1.0" encoding="gb2312"?>

<!-- RSS generated by oioj.net on 4/16/2004 ; 感谢LeXRus提供 RSS 2.0 文档; 此文件可自由使用，但请保留此行信息 --> 
<!-- Source download URL: http://blogger.org.cn/blog/rss2.asp       -->
<rss version="2.0">

<channel>
<title>西门吹火车</title>
<link>http://blogger.org.cn/blog/blog.asp?name=angle800</link>
<description>angle800的博客</description>
<copyright>blogger.org.cn</copyright>
<generator>W3CHINA Blog</generator>
<webMaster>webmaster@blogger.org.cn</webMaster>
<item>
<title><![CDATA[男人需要红颜知己]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=13093</link>
<author>angle800</author>
<pubDate>2006/4/2 13:04:38</pubDate>
<description><![CDATA[<A><FONT size=4>这个世界上男人需要的除了老婆还得有一个红颜知己。做红颜知最重要的是恪守界限。</FONT></A> 
<P><FONT size=4>当你卧病在床的时候，拉着你的手慌张无措泪流满面的那个人必是老婆。她怕你痛、怕你死、恨不得替你痛，替你死，她哭哭啼啼，缠缠绵绵，让你感动，让你心灵难安。而红颜知不。她只是站在床头静静地疑望着你，阅读你的心灵，然后用她的口她的眼她的心告诉你她知道你痛在哪何处，她理解你愿意为你默默分担，让你灵魂不再孤寂，令你欣慰。由此可见二者的区别了：哭,是因为爱你；不哭，是因为懂你。</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 一个男人，假如生命中有一个刻骨铭心爱你的女人，又能有一个心有灵犀懂你的女人夫复何求？</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 红颜知己全是些绝顶智慧的女孩，她们心底里最明白一个女人要想在男人的生命里永恒，要么做他的母亲，要么做他永远敢得不到的红颜知己。懂他，但就是不属于他。给他适可而止的关 照，但不让他产生爱上你的冲动与热情，这是做红颜知的技巧。</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 你出门远行，音信全无，红颜知心有牵挂，多次拨打电话，但每次均打不通，因为你关机。待你漂泊够了，蓬头垢面地站在她面前时，她只是盈盈地笑问：“好久不见，玩得开心吗”？她不会提及她的牵挂，她的焦虑，她的气恼，永远不提。她知道那些东西不是她的事，她不想爱情，只想友情。她就像一个顽皮的勾魂鬼，一只眼睛对着你就那么一挤一眨，便能把你身上所有的男孩的那部分淘气，活泼的分子勾了出来。在她面前，你惟有投降，无路可逃。</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 通常情况下，老婆是倾听者，而红颜知则是聆听者。在她面前男人可以是倦鸟是浪子，可以疲惫、无助、逃避、怠惰，而她是能接纳你的黑夜，给你安静，给你恢复能量的空间。如果说情人是月亮，那么红颜知则是星星。太阳月亮有疲倦的时候，星星却没有，它闪闪烁烁若即若离，甘于寂寞却又灿烂而长久。</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 无论你在别人面前多么地高高在上，不可仰视，在红颜知眼里都只有尊严而没有威严。她能穿过层层面具，如入无人之境地走进你的心灵，用一种你与她都懂的语言来和你进行灵魂的对话与交流。</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 故能做红颜知的必是女人中的精品。</FONT></P>
<P><FONT size=4>&nbsp;&nbsp;&nbsp; 而能拥有红颜知的也必是男人中的智者</FONT></P>]]></description>
</item><item>
<title><![CDATA[游戏外挂设计技术探讨]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=12059</link>
<author>angle800</author>
<pubDate>2006/2/27 10:31:29</pubDate>
<description><![CDATA[<P align=left>一、 前言 <BR><BR>　　所谓游戏外挂，其实是一种游戏外辅程序，它可以协助玩家自动产生游戏动作、修改游戏网络数据包以及修改游戏内存数据等，以实现玩家用最少的时间和金钱去完成功力升级和过关斩将。虽然，现在对游戏外挂程序的“合法”身份众说纷纭，在这里我不想对此发表任何个人意见，让时间去说明一切吧。<BR><BR>　　不管游戏外挂程序是不是“合法”身份，但是它却是具有一定的技术含量的，在这些小小程序中使用了许多高端技术，如拦截Sock技术、拦截API技术、模拟键盘与鼠标技术、直接修改程序内存技术等等。本文将对常见的游戏外挂中使用的技术进行全面剖析。<BR><BR>　　二、认识外挂<BR><BR>　　游戏外挂的历史可以追溯到单机版游戏时代，只不过当时它使用了另一个更通俗易懂的名字??游戏修改器。它可以在游戏中追踪锁定游戏主人公的各项能力数值。这样玩家在游戏中可以达到主角不掉血、不耗费魔法、不消耗金钱等目的。这样降低了游戏的难度，使得玩家更容易通关。<BR><BR>　　随着网络游戏的时代的来临，游戏外挂在原有的功能之上进行了新的发展，它变得更加多种多样，功能更加强大，操作更加简单，以至有些游戏的外挂已经成为一个体系，比如《石器时代》，外挂品种达到了几十种，自动战斗、自动行走、自动练级、自动补血、加速、不遇敌、原地遇敌、快速增加经验值、按键精灵……几乎无所不包。<BR><BR>　　游戏外挂的设计主要是针对于某个游戏开发的，我们可以根据它针对的游戏的类型可大致可将外挂分为两种大类。<BR><BR>　　一类是将游戏中大量繁琐和无聊的攻击动作使用外挂自动完成，以帮助玩家轻松搞定攻击对象并可以快速的增加玩家的经验值。比如在《龙族》中有一种工作的设定，玩家的工作等级越高，就可以驾驭越好的装备。但是增加工作等级却不是一件有趣的事情，毋宁说是重复枯燥的机械劳动。如果你想做法师用的杖，首先需要做基本工作--?砍树。砍树的方法很简单，在一棵大树前不停的点鼠标就可以了，每10000的经验升一级。这就意味着玩家要在大树前不停的点击鼠标，这种无聊的事情通过"按键精灵"就可以解决。外挂的"按键精灵"功能可以让玩家摆脱无趣的点击鼠标的工作。<BR><BR>　　另一类是由外挂程序产生欺骗性的网络游戏封包，并将这些封包发送到网络游戏服务器，利用这些虚假信息欺骗服务器进行游戏数值的修改，达到修改角色能力数值的目的。这类外挂程序针对性很强，一般在设计时都是针对某个游戏某个版本来做的，因为每个网络游戏服务器与客户端交流的数据包各不相同，外挂程序必须要对欺骗的网络游戏服务器的数据包进行分析，才能产生服务器识别的数据包。这类外挂程序也是当前最流利的一类游戏外挂程序。<BR><BR>　　另外，现在很多外挂程序功能强大，不仅实现了自动动作代理和封包功能，而且还提供了对网络游戏的客户端程序的数据进行修改，以达到欺骗网络游戏服务器的目的。我相信，随着网络游戏商家的反外挂技术的进展，游戏外挂将会产生更多更优秀的技术，让我们期待着看场技术大战吧......<BR><BR>　　三、外挂技术综述<BR><BR>　　可以将开发游戏外挂程序的过程大体上划分为两个部分：<BR><BR>　　前期部分工作是对外挂的主体游戏进行分析，不同类型的外挂分析主体游戏的内容也不相同。如外挂为上述谈到的外挂类型中的第一类时，其分析过程常是针对游戏的场景中的攻击对象的位置和分布情况进行分析，以实现外挂自动进行攻击以及位置移动。如外挂为外挂类型中的第二类时，其分析过程常是针对游戏服务器与客户端之间通讯包数据的结构、内容以及加密算法的分析。因网络游戏公司一般都不会公布其游戏产品的通讯包数据的结构、内容和加密算法的信息，所以对于开发第二类外挂成功的关键在于是否能正确分析游戏包数据的结构、内容以及加密算法，虽然可以使用一些工具辅助分析，但是这还是一种坚苦而复杂的工作。<BR><BR>　　后期部分工作主要是根据前期对游戏的分析结果，使用大量的程序开发技术编写外挂程序以实现对游戏的控制或修改。如外挂程序为第一类外挂时，通常会使用到鼠标模拟技术来实现游戏角色的自动位置移动，使用键盘模拟技术来实现游戏角色的自动攻击。如外挂程序为第二类外挂时，通常会使用到挡截Sock和挡截API函数技术，以挡截游戏服务器传来的网络数据包并将数据包修改后封包后传给游戏服务器。另外，还有许多外挂使用对游戏客户端程序内存数据修改技术以及游戏加速技术。<BR><BR>　　本文主要是针对开发游戏外挂程序后期使用的程序开发技术进行探讨，重点介绍的如下几种在游戏外挂中常使用的程序开发技术：<BR><BR>　　● 动作模拟技术：主要包括键盘模拟技术和鼠标模拟技术。<BR><BR>　　● 封包技术：主要包括挡截Sock技术和挡截API技术。<BR><BR><BR>四、动作模拟技术<BR><BR>　　我们在前面介绍过，几乎所有的游戏都有大量繁琐和无聊的攻击动作以增加玩家的功力，还有那些数不完的迷宫，这些好像已经成为了角色游戏的代名词。现在，外挂可以帮助玩家从这些繁琐而无聊的工作中摆脱出来，专注于游戏情节的进展。外挂程序为了实现自动角色位置移动和自动攻击等功能，需要使用到键盘模拟技术和鼠标模拟技术。下面我们将重点介绍这些技术并编写一个简单的实例帮助读者理解动作模拟技术的实现过程。<BR><BR>　　１． 鼠标模拟技术<BR>　　<BR>　　几乎所有的游戏中都使用了鼠标来改变角色的位置和方向，玩家仅用一个小小的鼠标，就可以使角色畅游天下。那么，我们如何实现在没有玩家的参与下角色也可以自动行走呢。其实实现这个并不难，仅仅几个Windows API函数就可以搞定，让我们先来认识认识这些API函数。<BR><BR>　　(1) 模拟鼠标动作API函数mouse_event，它可以实现模拟鼠标按下和放开等动作。<BR><BR>　　　　VOID mouse_event(<BR>　　　　　　DWORD dwFlags, // 鼠标动作标识。<BR>　　　　　　DWORD dx, // 鼠标水平方向位置。<BR>　　　　　　DWORD dy, // 鼠标垂直方向位置。<BR>　　　　　　DWORD dwData, // 鼠标轮子转动的数量。<BR>　　　　　　DWORD dwExtraInfo // 一个关联鼠标动作辅加信息。<BR>　　　　); <BR><BR>　　其中，dwFlags表示了各种各样的鼠标动作和点击活动，它的常用取值如下：<BR><BR>　　　MOUSEEVENTF_MOVE　表示模拟鼠标移动事件。<BR><BR>　　　MOUSEEVENTF_LEFTDOWN 表示模拟按下鼠标左键。<BR><BR>　　　MOUSEEVENTF_LEFTUP 表示模拟放开鼠标左键。<BR><BR>　　　MOUSEEVENTF_RIGHTDOWN 表示模拟按下鼠标右键。<BR><BR>　　　MOUSEEVENTF_RIGHTUP 表示模拟放开鼠标右键。<BR><BR>　　　MOUSEEVENTF_MIDDLEDOWN 表示模拟按下鼠标中键。<BR><BR>　　　MOUSEEVENTF_MIDDLEUP 表示模拟放开鼠标中键。<BR><BR>　　(2)、设置和获取当前鼠标位置的API函数。获取当前鼠标位置使用GetCursorPos()函数，设置当前鼠标位置使用SetCursorPos()函数。<BR><BR>　　　　BOOL GetCursorPos(<BR>　　　　　LPPOINT　lpPoint // 返回鼠标的当前位置。<BR>　　　　);<BR>　　　　BOOL SetCursorPos(<BR>　　　　int X, // 鼠标的水平方向位置。<BR>　　　　　　int Y //鼠标的垂直方向位置。<BR>　　　　); <BR><BR>　　通常游戏角色的行走都是通过鼠标移动至目的地，然后按一下鼠标的按钮就搞定了。下面我们使用上面介绍的API函数来模拟角色行走过程。<BR><BR>　　　CPoint oldPoint,newPoint;<BR>　　　GetCursorPos(&amp;oldPoint); //保存当前鼠标位置。<BR>　　　newPoint.x = oldPoint.x+40;<BR>　　　newPoint.y = oldPoint.y+10;<BR>　　　SetCursorPos(newPoint.x,newPoint.y); //设置目的地位置。<BR>　　　mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);//模拟按下鼠标右键。<BR>　　　mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);//模拟放开鼠标右键。 <BR><BR>　　2． 键盘模拟技术<BR><BR>　　在很多游戏中，不仅提供了鼠标的操作，而且还提供了键盘的操作，在对攻击对象进行攻击时还可以使用快捷键。为了使这些攻击过程能够自动进行，外挂程序需要使用键盘模拟技术。像鼠标模拟技术一样，Windows API也提供了一系列API函数来完成对键盘动作的模拟。<BR><BR>　　模拟键盘动作API函数keydb_event，它可以模拟对键盘上的某个或某些键进行按下或放开的动作。<BR><BR>　　　VOID keybd_event(<BR>　　　　　BYTE bVk, // 虚拟键值。<BR>　　　　　BYTE bScan, // 硬件扫描码。<BR>　　　　　DWORD dwFlags, // 动作标识。<BR>　　　　　DWORD dwExtraInfo // 与键盘动作关联的辅加信息。<BR>　　　); <BR><BR>　　其中，bVk表示虚拟键值，其实它是一个BYTE类型值的宏，其取值范围为1-254。有关虚拟键值表请在MSDN上使用关键字“Virtual-Key Codes”查找相关资料。bScan表示当键盘上某键被按下和放开时，键盘系统硬件产生的扫描码，我们可以MapVirtualKey()函数在虚拟键值与扫描码之间进行转换。dwFlags表示各种各样的键盘动作，它有两种取值：KEYEVENTF_EXTENDEDKEY和KEYEVENTF_KEYUP。<BR><BR>　　下面我们使用一段代码实现在游戏中按下Shift+R快捷键对攻击对象进行攻击。<BR><BR>　　　keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0); //按下CTRL键。<BR>　　　keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//键下R键。<BR>　　　keybd_event(0x52,MapVirtualKey(0x52,0), KEYEVENTF_KEYUP,0);//放开R键。<BR>　　　keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0), <BR>　　　KEYEVENTF_KEYUP,0);//放开CTRL键。 <BR><BR>　　3． 激活外挂<BR><BR>　　上面介绍的鼠标和键盘模拟技术实现了对游戏角色的动作部分的模拟，但要想外挂能工作于游戏之上，还需要将其与游戏的场景窗口联系起来或者使用一个激活键，就象按键精灵的那个激活键一样。我们可以用GetWindow函数来枚举窗口，也可以用Findwindow函数来查找特定的窗口。另外还有一个FindWindowEx函数可以找到窗口的子窗口，当游戏切换场景的时候我们可以用FindWindowEx来确定一些当前窗口的特征，从而判断是否还在这个场景，方法很多了，比如可以GetWindowInfo来确定一些东西，比如当查找不到某个按钮的时候就说明游戏场景已经切换了等等办法。当使用激活键进行关联，需要使用Hook技术开发一个全局键盘钩子，在这里就不具体介绍全局钩子的开发过程了，在后面的实例中我们将会使用到全局钩子，到时将学习到全局钩子的相关知识。<BR><BR><BR>　　4． 实例实现<BR><BR>　　通过上面的学习，我们已经基本具备了编写动作式游戏外挂的能力了。下面我们将创建一个画笔程序外挂，它实现自动移动画笔字光标的位置并写下一个红色的“R”字。以这个实例为基础，加入相应的游戏动作规则，就可以实现一个完整的游戏外挂。这里作者不想使用某个游戏作为例子来开发外挂（因没有游戏商家的授权啊！），如读者感兴趣的话可以找一个游戏试试，最好仅做测试技术用。<BR><BR>　　首先，我们需要编写一个全局钩子，使用它来激活外挂，激活键为F10。创建全局钩子步骤如下：<BR><BR>　　(1)．选择MFC AppWizard(DLL)创建项目ActiveKey，并选择MFC Extension DLL（共享MFC拷贝）类型。<BR><BR>　　(2).插入新文件ActiveKey.h，在其中输入如下代码：<BR><BR>　　　#ifndef _KEYDLL_H<BR>　　　#define _KEYDLL_H<BR><BR>　　　class AFX_EXT_CLASS CKeyHook:public CObject<BR>　　　{<BR>　　　　public:<BR>　CKeyHook();<BR>　~CKeyHook();<BR>　HHOOK Start();　//安装钩子<BR>　BOOL Stop(); //卸载钩子<BR>　　　};<BR>　　　#endif <BR><BR>　　(3).在ActiveKey.cpp文件中加入声明＂＃i nclude ActiveKey.h＂。<BR><BR>　　(4).在ActiveKey.cpp文件中加入共享数据段，代码如下：<BR><BR>　　　//Shared data section<BR>　　　#pragma data_seg("sharedata")<BR>　　　HHOOK glhHook=NULL; //钩子句柄。<BR>　　　HINSTANCE glhInstance=NULL; //DLL实例句柄。<BR>　　　#pragma data_seg() <BR><BR>　　(5).在ActiveKey.def文件中设置共享数据段属性，代码如下：<BR><BR>　　　SETCTIONS<BR>　　　shareddata READ WRITE SHARED <BR><BR>　　(6).在ActiveKey.cpp文件中加入CkeyHook类的实现代码和钩子函数代码：<BR><BR>　　　//键盘钩子处理函数。<BR>　　　extern "C" LRESULT WINAPI KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)<BR>　　　{<BR>　　　if( nCode &gt;= 0 )<BR>　　　{<BR>　　　if( wParam == 0X79 )//当按下F10键时，激活外挂。<BR>　{<BR>　　//外挂实现代码。<BR>CPoint newPoint,oldPoint;<BR>　　 GetCursorPos(&amp;oldPoint);<BR>　　 newPoint.x = oldPoint.x+40;<BR>　　 newPoint.y = oldPoint.y+10;<BR>　　 SetCursorPos(newPoint.x,newPoint.y);<BR>　　 mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模拟按下鼠标左键。<BR>　　mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模拟放开鼠标左键。<BR>　　keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),0,0); //按下SHIFT键。<BR>　　keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//按下R键。<BR>　　keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放开R键。<BR>　　keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),KEYEVENTF_KEYUP,0);//放开SHIFT键。<BR>　　　　　　SetCursorPos(oldPoint.x,oldPoint.y);<BR>　}<BR>　　　}<BR>　　　return CallNextHookEx(glhHook,nCode,wParam,lParam);<BR>　　　}<BR><BR>　　　CKeyHook::CKeyHook(){}<BR>　　　CKeyHook::~CKeyHook()<BR>　　　{　<BR>　　　if( glhHook )<BR>Stop();<BR>　　　}<BR>　　　//安装全局钩子。<BR>　　　HHOOK CKeyHook::Start()<BR>　　　{ <BR>glhHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);//设置键盘钩子。<BR>return glhHook;<BR>}<BR>　　　//卸载全局钩子。<BR>　　　BOOL CKeyHook::Stop()<BR>　　　{<BR>　　　BOOL bResult = TRUE;<BR>　if( glhHook )<BR>　　　bResult = UnhookWindowsHookEx(glhHook);//卸载键盘钩子。<BR>　　　return bResult;<BR>　　　} <BR><BR>　　(7).修改DllMain函数，代码如下：<BR><BR>　　　extern "C" int APIENTRY<BR>　　　DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)<BR>　　　{<BR>//如果使用lpReserved参数则删除下面这行 <BR>UNREFERENCED_PARAMETER(lpReserved);<BR><BR>if (dwReason == DLL_PROCESS_ATTACH)<BR>{<BR>　　TRACE0("NOtePadHOOK.DLL Initializing!\n");<BR>　　 //扩展DLL仅初始化一次 <BR>　　if (!AfxInitExtensionModule(ActiveKeyDLL, hInstance))<BR>return 0;<BR>　　new CDynLinkLibrary(ActiveKeyDLL);<BR>　　　　　　//把DLL加入动态MFC类库中 <BR>　　glhInstance = hInstance;<BR>　　//插入保存DLL实例句柄 <BR>}<BR>else if (dwReason == DLL_PROCESS_DETACH)<BR>{<BR>　　TRACE0("NotePadHOOK.DLL Terminating!\n");<BR>　　//终止这个链接库前调用它 <BR>　　AfxTermExtensionModule(ActiveKeyDLL);<BR>}<BR>return 1; <BR>　　　} <BR><BR>　　(8).编译项目ActiveKey，生成ActiveKey.DLL和ActiveKey.lib。<BR><BR>　　接着，我们还需要创建一个外壳程序将全局钩子安装了Windows系统中，这个外壳程序编写步骤如下：<BR><BR>　　(1).创建一个对话框模式的应用程序，项目名为Simulate。<BR><BR>　　(2).在主对话框中加入一个按钮，使用ClassWizard为其创建CLICK事件。<BR><BR>　　(3).将ActiveKey项目Debug目录下的ActiveKey.DLL和ActiveKey.lib拷贝到Simulate项目目录下。<BR><BR>　　(4).从“工程”菜单中选择“设置”，弹出Project Setting对话框，选择Link标签，在“对象/库模块”中输入ActiveKey.lib。<BR><BR>　　(5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中，并在Stdafx.h中加入＃i nclude ActiveKey.h。<BR><BR>　　(6).在按钮单击事件函数输入如下代码：<BR><BR>　　　void CSimulateDlg::OnButton1() <BR>　　　{<BR>// TODO: Add your control notification handler code here<BR>if( !bSetup )<BR>{<BR>m_hook.Start();//激活全局钩子。<BR>}<BR>else<BR>{<BR>m_hook.Stop();//撤消全局钩子。<BR>}<BR>bSetup = !bSetup;<BR><BR>　　　} <BR><BR>　　(7).编译项目，并运行程序，单击按钮激活外挂。<BR><BR>　　(8).启动画笔程序，选择文本工具并将笔的颜色设置为红色，将鼠标放在任意位置后，按F10键，画笔程序自动移动鼠标并写下一个红色的大写R。图一展示了按F10键前的画笔程序的状态，图二展示了按F10键后的画笔程序的状态。<BR></P>
<DIV align=left><IMG onmousewheel="return bbimg(this)" style="ZOOM: 90%" src="http://www.czvc.com/articles/151.jpg" border=0><BR>图一：按F10前状态(001.jpg)</DIV>
<P align=left><BR><BR>&nbsp;</P>
<DIV align=left><IMG onmousewheel="return bbimg(this)" style="ZOOM: 70%" src="http://www.czvc.com/articles/152.jpg" border=0><BR>图二：按F10后状态(002.jpg)</DIV>
<DIV align=left>五、封包技术<BR><BR>　　通过对动作模拟技术的介绍，我们对游戏外挂有了一定程度上的认识，也学会了使用动作模拟技术来实现简单的动作模拟型游戏外挂的制作。这种动作模拟型游戏外挂有一定的局限性，它仅仅只能解决使用计算机代替人力完成那么有规律、繁琐而无聊的游戏动作。但是，随着网络游戏的盛行和复杂度的增加，很多游戏要求将客户端动作信息及时反馈回服务器，通过服务器对这些动作信息进行有效认证后，再向客户端发送下一步游戏动作信息，这样动作模拟技术将失去原有的效应。为了更好地“外挂”这些游戏，游戏外挂程序也进行了升级换代，它们将以前针对游戏用户界面层的模拟推进到数据通讯层，通过封包技术在客户端挡截游戏服务器发送来的游戏控制数据包，分析数据包并修改数据包；同时还需按照游戏数据包结构创建数据包，再模拟客户端发送给游戏服务器，这个过程其实就是一个封包的过程。<BR><BR>　　封包的技术是实现第二类游戏外挂的最核心的技术。封包技术涉及的知识很广泛，实现方法也很多，如挡截WinSock、挡截API函数、挡截消息、VxD驱动程序等。在此我们也不可能在此文中将所有的封包技术都进行详细介绍，故选择两种在游戏外挂程序中最常用的两种方法：挡截WinSock和挡截API函数。<BR><BR>　　1． 挡截WinSock<BR><BR>　　众所周知，Winsock是Windows网络编程接口，它工作于Windows应用层，它提供与底层传输协议无关的高层数据传输编程接口。在Windows系统中，使用WinSock接口为应用程序提供基于TCP/IP协议的网络访问服务，这些服务是由Wsock32.DLL动态链接库提供的函数库来完成的。<BR><BR>　　由上说明可知，任何Windows基于TCP/IP的应用程序都必须通过WinSock接口访问网络，当然网络游戏程序也不例外。由此我们可以想象一下，如果我们可以控制WinSock接口的话，那么控制游戏客户端程序与服务器之间的数据包也将易如反掌。按着这个思路，下面的工作就是如何完成控制WinSock接口了。由上面的介绍可知，WinSock接口其实是由一个动态链接库提供的一系列函数，由这些函数实现对网络的访问。有了这层的认识，问题就好办多了，我们可以制作一个类似的动态链接库来代替原WinSock接口库，在其中实现WinSock32.dll中实现的所有函数，并保证所有函数的参数个数和顺序、返回值类型都应与原库相同。在这个自制作的动态库中，可以对我们感兴趣的函数（如发送、接收等函数）进行挡截，放入外挂控制代码，最后还继续调用原WinSock库中提供的相应功能函数，这样就可以实现对网络数据包的挡截、修改和发送等封包功能。<BR><BR>　　下面重点介绍创建挡截WinSock外挂程序的基本步骤：<BR><BR>　　(1) 创建DLL项目，选择Win32 Dynamic-Link Library，再选择An empty DLL project。<BR><BR>　　(2) 新建文件wsock32.h，按如下步骤输入代码：<BR><BR>　　① 加入相关变量声明：<BR><BR>　　　HMODULE hModule=NULL; //模块句柄<BR>　　　char buffer[1000]; //缓冲区<BR>　　　FARPROC proc; //函数入口指针 <BR><BR>　　② 定义指向原WinSock库中的所有函数地址的指针变量，因WinSock库共提供70多个函数，限于篇幅，在此就只选择几个常用的函数列出，有关这些库函数的说明可参考MSDN相关内容。<BR><BR>　　　//定义指向原WinSock库函数地址的指针变量。<BR>　　　SOCKET (__stdcall *socket1)(int ,int,int);//创建Sock函数。<BR>　　　int　(__stdcall *WSAStartup1)(WORD,LPWSADATA);//初始化WinSock库函数。<BR>　　　int　(__stdcall *WSACleanup1)();//清除WinSock库函数。<BR>　　　int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );//接收数据函数。<BR>　　　int (__stdcall *send1)(SOCKET ,const char * ,int ,int);//发送数据函数。<BR>　　　int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);//创建连接函数。<BR>　　　int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );//绑定函数。<BR>　　　......其它函数地址指针的定义略。 <BR><BR>　　(3) 新建wsock32.cpp文件，按如下步骤输入代码：<BR><BR>　　① 加入相关头文件声明：<BR><BR>　　　＃i nclude "windows.h"<BR>　　　＃i nclude "stdio.h"<BR>　　　＃i nclude "wsock32.h" <BR><BR>　　② 添加DllMain函数，在此函数中首先需要加载原WinSock库，并获取此库中所有函数的地址。代码如下：<BR><BR>　　　BOOL WINAPI DllMain (HANDLE hInst,ULONG ul_reason_for_call,LPVOID lpReserved)<BR>　　　{<BR>　　　　if(hModule==NULL){<BR>　　　　　//加载原WinSock库，原WinSock库已复制为wsock32.001。<BR>　　　hModule=LoadLibrary("wsock32.001"); <BR>　　}<BR>　　　　else return 1;<BR>//获取原WinSock库中的所有函数的地址并保存，下面仅列出部分代码。<BR>if(hModule!=NULL){<BR>　　　　　//获取原WinSock库初始化函数的地址，并保存到WSAStartup1中。<BR>proc=GetProcAddress(hModule,"WSAStartup");<BR>　　　WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))proc;<BR>　　　　　//获取原WinSock库消除函数的地址，并保存到WSACleanup1中。<BR>　　　　proc=GetProcAddress(hModule i,"WSACleanup");<BR>　　　　WSACleanup1=(int (_stdcall *)())proc;<BR>　　　　　//获取原创建Sock函数的地址，并保存到socket1中。<BR>　　　　proc=GetProcAddress(hModule,"socket");<BR>　　　　　socket1=(SOCKET (_stdcall *)(int ,int,int))proc;<BR>　　　　　//获取原创建连接函数的地址，并保存到connect1中。<BR>　　　　　proc=GetProcAddress(hModule,"connect");<BR>　　　　　connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))proc;<BR>　　　　　//获取原发送函数的地址，并保存到send1中。<BR>　　　　　proc=GetProcAddress(hModule,"send");<BR>　　　　　send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))proc;<BR>　　　　　//获取原接收函数的地址，并保存到recv1中。<BR>　　　　　proc=GetProcAddress(hModule,"recv");<BR>　　　　　recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))proc;<BR>　　　　　......其它获取函数地址代码略。<BR>　　　}<BR>　　　else return 0;<BR>　　　return 1;<BR>} <BR><BR>　　③ 定义库输出函数，在此可以对我们感兴趣的函数中添加外挂控制代码，在所有的输出函数的最后一步都调用原WinSock库的同名函数。部分输出函数定义代码如下：<BR><BR>//库输出函数定义。<BR>//WinSock初始化函数。<BR>　　　　int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)<BR>　　　　{<BR>　　　　　//调用原WinSock库初始化函数<BR>　　　　　return WSAStartup1(wVersionRequired,lpWSAData);<BR>　　　　}<BR>　　　　//WinSock结束清除函数。<BR>　　　　int PASCAL FAR WSACleanup(void)<BR>　　　　{<BR>　　　　　return WSACleanup1(); //调用原WinSock库结束清除函数。<BR>　　　　}<BR>　　　　//创建Socket函数。<BR>　　　　SOCKET PASCAL FAR socket (int af, int type, int protocol)<BR>　　　　{<BR>　　　　　//调用原WinSock库创建Socket函数。<BR>　　　　　return socket1(af,type,protocol);<BR>　　　　}<BR>　　　　//发送数据包函数<BR>　　　　int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)<BR>　　　　{<BR>　　　//在此可以对发送的缓冲buf的内容进行修改，以实现欺骗服务器。<BR>　　　外挂代码......<BR>　　　//调用原WinSock库发送数据包函数。<BR>　　　　　return send1(s,buf,len,flags);<BR>　　　　}<BR>//接收数据包函数。<BR>　　　　int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)<BR>　　　　{<BR>　　　//在此可以挡截到服务器端发送到客户端的数据包，先将其保存到buffer中。<BR>　　　strcpy(buffer,buf);<BR>　　　//对buffer数据包数据进行分析后，对其按照玩家的指令进行相关修改。<BR>　　　外挂代码......<BR>　　　//最后调用原WinSock中的接收数据包函数。<BR>　　　　　return recv1(s, buffer, len, flags);<BR>　　　　　}<BR>　　　　.......其它函数定义代码略。 <BR><BR>　　(4)、新建wsock32.def配置文件，在其中加入所有库输出函数的声明，部分声明代码如下：<BR><BR>　　　LIBRARY "wsock32"<BR>　　　EXPORTS <BR>　　　　WSAStartup @1<BR>　　　WSACleanup @2<BR>　　　　recv @3<BR>　　　　send @4<BR>　　　　socket @5<BR>　　　bind @6<BR>　　　closesocket @7<BR>　　　connect @8 <BR><BR>　　　......其它输出函数声明代码略。<BR><BR>　　(5)、从“工程”菜单中选择“设置”，弹出Project Setting对话框，选择Link标签，在“对象/库模块”中输入Ws2_32.lib。<BR><BR>　　(6)、编译项目，产生wsock32.dll库文件。<BR><BR>　　(7)、将系统目录下原wsock32.dll库文件拷贝到被外挂程序的目录下，并将其改名为wsock.001；再将上面产生的wsock32.dll文件同样拷贝到被外挂程序的目录下。重新启动游戏程序，此时游戏程序将先加载我们自己制作的wsock32.dll文件，再通过该库文件间接调用原WinSock接口函数来实现访问网络。上面我们仅仅介绍了挡载WinSock的实现过程，至于如何加入外挂控制代码，还需要外挂开发人员对游戏数据包结构、内容、加密算法等方面的仔细分析（这个过程将是一个艰辛的过程），再生成外挂控制代码。关于数据包分析方法和技巧，不是本文讲解的范围，如您感兴趣可以到网上查查相关资料。<BR><BR><BR>　　2.挡截API<BR><BR>　　挡截API技术与挡截WinSock技术在原理上很相似，但是前者比后者提供了更强大的功能。挡截WinSock仅只能挡截WinSock接口函数，而挡截API可以实现对应用程序调用的包括WinSock API函数在内的所有API函数的挡截。如果您的外挂程序仅打算对WinSock的函数进行挡截的话，您可以只选择使用上小节介绍的挡截WinSock技术。随着大量外挂程序在功能上的扩展，它们不仅仅只提供对数据包的挡截，而且还对游戏程序中使用的Windows API或其它DLL库函数的挡截，以使外挂的功能更加强大。例如，可以通过挡截相关API函数以实现对非中文游戏的汉化功能，有了这个利器，可以使您的外挂程序无所不能了。<BR><BR>　　挡截API技术的原理核心也是使用我们自己的函数来替换掉Windows或其它DLL库提供的函数，有点同挡截WinSock原理相似吧。但是，其实现过程却比挡截WinSock要复杂的多，如像实现挡截Winsock过程一样，将应用程序调用的所有的库文件都写一个模拟库有点不大可能，就只说Windows API就有上千个，还有很多库提供的函数结构并未公开，所以写一个模拟库代替的方式不大现实，故我们必须另谋良方。<BR><BR>　　挡截API的最终目标是使用自定义的函数代替原函数。那么，我们首先应该知道应用程序何时、何地、用何种方式调用原函数。接下来，需要将应用程序中调用该原函数的指令代码进行修改，使它将调用函数的指针指向我们自己定义的函数地址。这样，外挂程序才能完全控制应用程序调用的API函数，至于在其中如何加入外挂代码，就应需求而异了。最后还有一个重要的问题要解决，如何将我们自定义的用来代替原API函数的函数代码注入被外挂游戏程序进行地址空间中，因在Windows系统中应用程序仅只能访问到本进程地址空间内的代码和数据。<BR><BR>　　综上所述，要实现挡截API函数，至少需要解决如下三个问题：<BR><BR>　　● 如何定位游戏程序中调用API函数指令代码？<BR><BR>　　● 如何修改游戏程序中调用API函数指令代码？<BR><BR>　　● 如何将外挂代码（自定义的替换函数代码）注入到游戏程序进程地址空间？<BR><BR>　　下面我们逐一介绍这几个问题的解决方法：<BR><BR>　　(1) 、定位调用API函数指令代码<BR><BR>　　我们知道，在汇编语言中使用CALL指令来调用函数或过程的，它是通过指令参数中的函数地址而定位到相应的函数代码的。那么，我们如果能寻找到程序代码中所有调用被挡截的API函数的CALL指令的话，就可以将该指令中的函数地址参数修改为替代函数的地址。虽然这是一个可行的方案，但是实现起来会很繁琐，也不稳健。庆幸的是，Windows系统中所使用的可执行文件（PE格式）采用了输入地址表机制，将所有在程序调用的API函数的地址信息存放在输入地址表中，而在程序代码CALL指令中使用的地址不是API函数的地址，而是输入地址表中该API函数的地址项，如想使程序代码中调用的API函数被代替掉，只用将输入地址表中该API函数的地址项内容修改即可。具体理解输入地址表运行机制，还需要了解一下PE格式文件结构，其中图三列出了PE格式文件的大致结构。<BR><BR></DIV>
<DIV align=left><IMG onmousewheel="return bbimg(this)" style="ZOOM: 90%" src="http://www.czvc.com/articles/153.jpg" border=0><BR>图三：PE格式大致结构图</DIV>
<DIV align=left><BR><BR>　　PE格式文件一开始是一段DOS程序，当你的程序在不支持Windows的环境中运行时，它就会显示“This Program cannot be run in DOS mode”这样的警告语句，接着这个DOS文件头，就开始真正的PE文件内容了。首先是一段称为“IMAGE_NT_HEADER”的数据，其中是许多关于整个PE文件的消息，在这段数据的尾端是一个称为Data Directory的数据表，通过它能快速定位一些PE文件中段（section）的地址。在这段数据之后，则是一个“IMAGE_SECTION_HEADER”的列表，其中的每一项都详细描述了后面一个段的相关信息。接着它就是PE文件中最主要的段数据了，执行代码、数据和资源等等信息就分别存放在这些段中。<BR><BR>　　在所有的这些段里，有一个被称为“.idata”的段（输入数据段）值得我们去注意，该段中包含着一些被称为输入地址表（IAT，Import Address Table）的数据列表。每个用隐式方式加载的API所在的DLL都有一个IAT与之对应，同时一个API的地址也与IAT中一项相对应。当一个应用程序加载到内存中后，针对每一个API函数调用，相应的产生如下的汇编指令： <BR><BR>　　JMP DWORD PTR [XXXXXXXX] <BR><BR>　　或<BR><BR>　　CALL DWORD PTR [XXXXXXXX]<BR><BR>　　其中，[XXXXXXXX]表示指向了输入地址表中一个项，其内容是一个DWORD，而正是这个DWORD才是API函数在内存中的真正地址。因此我们要想拦截一个API的调用，只要简单的把那个DWORD改为我们自己的函数的地址。<BR><BR>　　(2) 、修改调用API函数代码<BR><BR>　　从上面对PE文件格式的分析可知，修改调用API函数代码其实是修改被调用API函数在输入地址表中IAT项内容。由于Windows系统对应用程序指令代码地址空间的严密保护机制，使得修改程序指令代码非常困难，以至于许多高手为之编写VxD进入Ring0。在这里，我为大家介绍一种较为方便的方法修改进程内存，它仅需要调用几个Windows核心API函数，下面我首先来学会一下这几个API函数：<BR><BR>　　　DWORD VirtualQuery(<BR>　　　LPCVOID lpAddress, // address of region<BR>　　　PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer<BR>　　　DWORD dwLength // size of buffer<BR>　　　); <BR><BR>　　该函数用于查询关于本进程内虚拟地址页的信息。其中，lpAddress表示被查询页的区域地址；lpBuffer表示用于保存查询页信息的缓冲；dwLength表示缓冲区大小。返回值为实际缓冲大小。<BR><BR>　　　BOOL VirtualProtect(<BR>　　　LPVOID lpAddress, // region of committed pages<BR>　　　SIZE_T dwSize, // size of the region<BR>　　　DWORD flNewProtect, // desired access protection<BR>　　　PDWORD lpflOldProtect // old protection<BR>　　　); <BR><BR>　　该函数用于改变本进程内虚拟地址页的保护属性。其中，lpAddress表示被改变保护属性页区域地址；dwSize表示页区域大小；flNewProtect表示新的保护属性，可取值为PAGE_READONLY、PAGE_READWRITE、PAGE_EXECUTE等；lpflOldProtect表示用于保存改变前的保护属性。如果函数调用成功返回“T”，否则返回“F”。<BR><BR>　　有了这两个API函数，我们就可以随心所欲的修改进程内存了。首先，调用VirtualQuery()函数查询被修改内存的页信息，再根据此信息调用VirtualProtect()函数改变这些页的保护属性为PAGE_READWRITE，有了这个权限您就可以任意修改进程内存数据了。下面一段代码演示了如何将进程虚拟地址为0x0040106c处的字节清零。<BR><BR>　　　BYTE* pData = 0x0040106c;<BR>　　　MEMORY_BASIC_INFORMATION mbi_thunk; <BR>　　　//查询页信息。<BR>　　　VirtualQuery(pData, &amp;mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); <BR>　　　//改变页保护属性为读写。<BR>　　　VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, <BR>　　　PAGE_READWRITE, &amp;mbi_thunk.Protect); <BR>　　　//清零。<BR>　　　*pData = 0x00;<BR>　　　//恢复页的原保护属性。<BR>　　　DWORD dwOldProtect; <BR>　　　VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, <BR>　　　mbi_thunk.Protect, &amp;dwOldProtect); <BR><BR><BR>　　(3)、注入外挂代码进入被挂游戏进程中<BR><BR>　　完成了定位和修改程序中调用API函数代码后，我们就可以随意设计自定义的API函数的替代函数了。做完这一切后，还需要将这些代码注入到被外挂游戏程序进程内存空间中，不然游戏进程根本不会访问到替代函数代码。注入方法有很多，如利用全局钩子注入、利用注册表注入挡截User32库中的API函数、利用CreateRemoteThread注入（仅限于NT/2000）、利用BHO注入等。因为我们在动作模拟技术一节已经接触过全局钩子，我相信聪明的读者已经完全掌握了全局钩子的制作过程，所以我们在后面的实例中，将继续利用这个全局钩子。至于其它几种注入方法，如果感兴趣可参阅MSDN有关内容。<BR><BR>　　有了以上理论基础，我们下面就开始制作一个挡截MessageBoxA和recv函数的实例，在开发游戏外挂程序 时，可以此实例为框架，加入相应的替代函数和处理代码即可。此实例的开发过程如下：<BR><BR>　　(1) 打开前面创建的ActiveKey项目。<BR><BR>　　(2) 在ActiveKey.h文件中加入HOOKAPI结构，此结构用来存储被挡截API函数名称、原API函数地址和替代函数地址。<BR><BR>　　　typedef struct tag_HOOKAPI <BR>　　　{ <BR>　　　LPCSTR szFunc;//被HOOK的API函数名称。<BR>　　　PROC pNewProc;//替代函数地址。<BR>　　　PROC pOldProc;//原API函数地址。<BR>　　　}HOOKAPI, *LPHOOKAPI; <BR><BR>　　(3) 打开ActiveKey.cpp文件，首先加入一个函数，用于定位输入库在输入数据段中的IAT地址。代码如下：<BR><BR>　　　extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR <BR>　　　LocationIAT(HMODULE hModule, LPCSTR szImportMod) <BR>　　　//其中，hModule为进程模块句柄；szImportMod为输入库名称。<BR>　　　{ <BR>　　　//检查是否为DOS程序，如是返回NULL，因DOS程序没有IAT。<BR>　　　PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) hModule; <BR>　　　if(pDOSHeader-&gt;e_magic != IMAGE_DOS_SIGNATURE) return NULL; <BR>　　　　//检查是否为NT标志，否则返回NULL。<BR>　　　　PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDOSHeader+ (DWORD)(pDOSHeader-&gt;e_lfanew)); <BR>　　　　if(pNTHeader-&gt;Signature != IMAGE_NT_SIGNATURE) return NULL; <BR>　　　　//没有IAT表则返回NULL。<BR>　　　　if(pNTHeader-&gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL; <BR>　　　　//定位第一个IAT位置。 <BR>　　　　PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDOSHeader + (DWORD)(pNTHeader-&gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); <BR>　　　　//根据输入库名称循环检查所有的IAT，如匹配则返回该IAT地址，否则检测下一个IAT。<BR>　　　　while (pImportDesc-&gt;Name) <BR>　　　　{ <BR>　　　　　//获取该IAT描述的输入库名称。<BR>　　　PSTR szCurrMod = (PSTR)((DWORD)pDOSHeader + (DWORD)(pImportDesc-&gt;Name)); <BR>　　　if (stricmp(szCurrMod, szImportMod) == 0) break; <BR>　　　pImportDesc++; <BR>　　　　} <BR>　　　　if(pImportDesc-&gt;Name == NULL) return NULL; <BR>　　　return pImportDesc; <BR>　　　} <BR><BR>　　再加入一个函数，用来定位被挡截API函数的IAT项并修改其内容为替代函数地址。代码如下：<BR><BR>　　　extern "C" __declspec(dllexport) <BR>　　　HookAPIByName( HMODULE hModule, LPCSTR szImportMod, LPHOOKAPI pHookApi) <BR>　　　//其中，hModule为进程模块句柄；szImportMod为输入库名称；pHookAPI为HOOKAPI结构指针。<BR>　　　{ <BR>　　　　//定位szImportMod输入库在输入数据段中的IAT地址。<BR>　　　　PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule, szImportMod); <BR>　　if (pImportDesc == NULL) return FALSE; <BR>　　　　//第一个Thunk地址。<BR>　　　　PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc-&gt;OriginalFirstThunk)); <BR>　　 //第一个IAT项的Thunk地址。<BR>　　　　PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule + (DWORD)(pImportDesc-&gt;FirstThunk)); <BR>　　　　//循环查找被截API函数的IAT项，并使用替代函数地址修改其值。<BR>　　　while(pOrigThunk-&gt;u1.Function) <BR>{ <BR>　//检测此Thunk是否为IAT项。<BR>if((pOrigThunk-&gt;u1.Ordinal &amp; IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG) <BR>{<BR>　 //获取此IAT项所描述的函数名称。<BR>　PIMAGE_IMPORT_BY_NAME pByName =(PIMAGE_IMPORT_BY_NAME)((DWORD)hModule+(DWORD)(pOrigThunk-&gt;u1.AddressOfData)); <BR>　if(pByName-&gt;Name[0] == '\0') return FALSE; <BR>　　//检测是否为挡截函数。<BR>if(strcmpi(pHookApi-&gt;szFunc, (char*)pByName-&gt;Name) == 0) <BR>　 { <BR>　　　　　　　MEMORY_BASIC_INFORMATION mbi_thunk;<BR>　　　　　　　//查询修改页的信息。<BR>　　　　　　　VirtualQuery(pRealThunk, &amp;mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); <BR>//改变修改页保护属性为PAGE_READWRITE。<BR>　　　　　　　VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize, PAGE_READWRITE, &amp;mbi_thunk.Protect); <BR>//保存原来的API函数地址。<BR>　　　 　　if(pHookApi-&gt;pOldProc == NULL) <BR>pHookApi-&gt;pOldProc = (PROC)pRealThunk-&gt;u1.Function; <BR>　 //修改API函数IAT项内容为替代函数地址。<BR>pRealThunk-&gt;u1.Function = (PDWORD)pHookApi-&gt;pNewProc; <BR>//恢复修改页保护属性。<BR>DWORD dwOldProtect; <BR>　　　　　　　VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &amp;dwOldProtect); <BR>　　　　　 } <BR>} <BR>　 pOrigThunk++; <BR>　 pRealThunk++; <BR>} <BR>　　SetLastError(ERROR_SUCCESS); //设置错误为ERROR_SUCCESS，表示成功。<BR>　　return TRUE; <BR>　　　} <BR><BR>　　(4) 定义替代函数，此实例中只给MessageBoxA和recv两个API进行挡截。代码如下：<BR><BR>　　　static int WINAPI MessageBoxA1 (HWND hWnd , LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)<BR>　　　{<BR>　　　　//过滤掉原MessageBoxA的正文和标题内容，只显示如下内容。<BR>return MessageBox(hWnd, "Hook API OK!", "Hook API", uType); <BR>　　　} <BR>　　　static int WINAPI recv1(SOCKET s, char FAR *buf, int len, int flags )<BR>　　　{<BR>　　　//此处可以挡截游戏服务器发送来的网络数据包，可以加入分析和处理数据代码。<BR>　　　return recv(s,buf,len,flags);<BR>　　　} <BR><BR>　　(5) 在KeyboardProc函数中加入激活挡截API代码，在if( wParam == 0X79 )语句中后面加入如下else if语句：<BR><BR>　　　......<BR>　　　//当激活F11键时，启动挡截API函数功能。<BR>　　　else if( wParam == 0x7A )<BR>　　　{ <BR>　　　　HOOKAPI api[2];<BR>api[0].szFunc ="MessageBoxA";//设置被挡截函数的名称。<BR>api[0].pNewProc = (PROC)MessageBoxA1;//设置替代函数的地址。<BR>api[1].szFunc ="recv";//设置被挡截函数的名称。<BR>api[1].pNewProc = (PROC)recv1; //设置替代函数的地址。<BR>//设置挡截User32.dll库中的MessageBoxA函数。<BR>HookAPIByName(GetModuleHandle(NULL),"User32.dll",&amp;api[0]);<BR>//设置挡截Wsock32.dll库中的recv函数。<BR>HookAPIByName(GetModuleHandle(NULL),"Wsock32.dll",&amp;api[1]);<BR>　　　}<BR>　　　...... <BR><BR>　　(6) 在ActiveKey.cpp中加入头文件声明 "＃i nclude "wsock32.h"。 从“工程”菜单中选择“设置”，弹出Project Setting对话框，选择Link标签，在“对象/库模块”中输入Ws2_32..lib。<BR><BR>　　(7) 重新编译ActiveKey项目，产生ActiveKey.dll文件，将其拷贝到Simulate.exe目录下。运行Simulate.exe并启动全局钩子。激活任意应用程序，按F11键后，运行此程序中可能调用MessageBoxA函数的操作，看看信息框是不是有所变化。同样，如此程序正在接收网络数据包，就可以实现封包功能了。<BR><BR>　　六、结束语<BR><BR>　　除了以上介绍的几种游戏外挂程序常用的技术以外，在一些外挂程序中还使用了游戏数据修改技术、游戏加速技术等。在这篇文章里，就不逐一介绍了。</DIV>]]></description>
</item><item>
<title><![CDATA[制作游戏外挂，更改封包 WPE pro]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=12058</link>
<author>angle800</author>
<pubDate>2006/2/27 10:30:06</pubDate>
<description><![CDATA[
<P><FONT size=2><B>WPE pro部分功能</B></FONT><FONT size=2>让我们来看一下网络游戏的工作原理：<BR>　　网络游戏是这样工作的：<BR>1.由服务器记录保存所有用户资料，所有信息的修改都是服务器完成的<BR>2.服务器接受客户机的请求发送必要的信息给客户机，以使玩家正常游戏<BR>3.服务器接收客户机的信息反馈，并根据反馈信息，对游戏帐号作相应修改<BR>　　从以上简单的介绍，我们可以看出，网络游戏可以认为是这样工作的：<BR>　　</FONT><FONT color=#ff0000><FONT size=2>由客户机电脑操作服务器器电脑，对游戏帐号信息进行修改！<BR></FONT><FONT color=#006699><FONT size=2>　　要操纵本地的电脑是很容易的，因此，要显示所有已经从服务器得到的信息是完全可能的，这就可以做到以下功能：<BR>　　 1、游戏没有黑夜，因为地图在本地，全部显示是完全可以做到的！<BR>　　 2.自动加血是没有问题的，因为血的多少也已经发到本地电脑，完全可以用外挂检测到，并在必要时加血，加血本身只是一个鼠标动作，完全可以交给外挂去做。类似的，自动加魔法，自动加气，自动回城、自动打怪、自动采矿卖钱然后再自动回去采、自动练级等等都可以做到！<BR>　　3.卖东西的过程很经典：你卖东西时，实际就是告诉服务器电脑，你已经将一个东西卖了，真实过程是：你向服务器发送了一个具体物品的封包，如果这个封包正确，服务器就向你的游戏帐号加一定数量的钱，然后再反馈给你一些信息，假如封包不正确，自然就卖不到钱，因此，我们可以利用外挂不断向服务器发送封包，只要正确，那么服务器就认为我们再卖东西，即使我们什么都没有卖，服务器也不断给我们钱，这就是所谓的</FONT><FONT color=#ff0000><FONT size=2>刷钱。</FONT><FONT color=#006699 size=2>如果封包没有加密，那么这个功能是非常容易实现的，如果封包加密，其实同样可以做到，只是要解密而已，稍微复杂些而已！类似的，就可以实现买东西用假钱（不用钱）。攻击、防御增加，原理都是类似的！<BR>　　以上的讲解，大家应该明白，其实外挂是每个游戏都可能出现的，只要有人想做，那么就<FONT color=#ff0000>没有做不出外挂的游戏</FONT>！除非这个游戏不能玩！！</FONT></FONT></FONT></FONT></P>
<P><FONT color=#ff0000><B>WPE的使用</B></FONT><FONT color=#ff3300>：</FONT><B>本站提供资料供大家学习使用，有了成果也拿出来分享啊&nbsp;&nbsp; ：）</B></P>
<P>明天你来自己做外挂 随着网络游戏的日益火爆，很多玩家都投身到游戏中。目前很多玩家都依赖于一些游戏的外挂程序来进行游戏。那么做一个游戏的外挂程序是否是一件很困难的事呢？回答是"否"，诚然编写一些程序是需要一些基本知识的，所以我们想以最简单的语言来给你讲授编写外挂程序的一些技巧，一些方法，并提供给你一些基本的辅助工具，即使你是一个菜鸟，看了我们的教程，并技巧地使用我们提供给你的工具，你完全能够编写出一个完全属于你自己的外挂。在本教程内，我们提供了金庸群侠传，以及网络三国这两个游戏的修改实际例子，因为这两款游戏都是对封包进行过加密运算的，如果你对这两个游戏的修改有了一定的了解后，相信你在其他游戏中也能非常好地做出属于自己的外挂。我们提供了金庸打增援20个NPC和网络三国在PK中自动吃药，自动发镖这两个实际的例子，让你上手更容易。我们也会本教程内附上这两个软件以提供给你使用和学习。我们会在教程内讲授给你怎么去破解封包的加密算法，怎么利用我们提供给你工具来伪造和发送封包。本教程除了文字教程外，我们还会提供金庸群侠和三国的外挂程序，另外还提供6个外挂制作工具，以供你使用。希望在以后的游戏中，每一个玩家都能够在游戏中成长起来，不但游戏玩的出色，修改游戏也同样出色，做一个真正的游戏DIY。 要想在修改游戏中做到百战百胜，是需要相当丰富的计算机知识的。有很多计算机高手就是从玩游戏，修改游戏中，逐步对计算机产生浓厚的兴趣，逐步成长起来的。不要在羡慕别人能够做到的，因为别人能够做的你也能够！我相信你们看了本教程后，会对游戏有一个全新的认识，呵呵，因为我是个好老师！（别拿鸡蛋砸我呀，救命啊！#￥%……*） 　　不过要想从修改游戏中学到知识，增加自己的计算机水平，可不能只是*修改游戏呀！ 要知道，修改游戏只是一个验证你对你所了解的某些计算机知识的理解程度的场所，只能给你一些发现问题、解决问题的机会，只能起到帮助你提高学习计算机的兴趣的作用，而决不是学习计算机的捷径。 <BR><BR>-------------------------------------------------------------------------------- <BR>一：什么叫外挂？ <BR>现在的网络游戏多是基于Internet上客户／服务器模式，服务端程序运行在游戏服务器上，游戏的设计者在其中创造一个庞大的游戏空间，各地的玩家可以通过运行客户端程序同时登录到游戏中。简单地说，网络游戏实际上就是由游戏开发商提供一个游戏环境，而玩家们就是在这个环境中相对自由和开放地进行游戏操作。那么既然在网络游戏中有了服务器这个概念，我们以前传统的修改游戏方法就显得无能为力了。记得我们在单机版的游戏中，随心所欲地通过内存搜索来修改角色的各种属性，这在网络游戏中就没有任何用处了。因为我们在网络游戏中所扮演角色的各种属性及各种重要资料都存放在服务器上，在我们自己机器上（客户端）只是显示角色的状态，所以通过修改客户端内存里有关角色的各种属性是不切实际的。那么是否我们就没有办法在网络游戏中达到我们修改的目的？回答是"否"。我们知道Internet客户／服务器模式的通讯一般采用TCP/IP通信协议，数据交换是通过IP数据包的传输来实现的，一般来说我们客户端向服务器发出某些请求，比如移动、战斗等指令都是通过封包的形式和服务器交换数据。那么我们把本地发出消息称为SEND，意思就是发送数据，服务器收到我们SEND的消息后，会按照既定的程序把有关的信息反馈给客户端，比如，移动的坐标，战斗的类型。那么我们把客户端收到服务器发来的有关消息称为RECV。知道了这个道理，接下来我们要做的工作就是分析客户端和服务器之间往来的数据（也就是封包），这样我们就可以提取到对我们有用的数据进行修改，然后模拟服务器发给客户端，或者模拟客户端发送给服务器，这样就可以实现我们修改游戏的目的了。 目前除了修改游戏封包来实现修改游戏的目的，我们也可以修改客户端的有关程序来达到我们的要求。我们知道目前各个服务器的运算能力是有限的，特别在游戏中，游戏服务器要计算游戏中所有玩家的状况几乎是不可能的，所以有一些运算还是要依*我们客户端来完成，这样又给了我们修改游戏提供了一些便利。比如我们可以通过将客户端程序脱壳来发现一些程序的判断分支，通过跟踪调试我们可以把一些对我们不利的判断去掉，以此来满足我们修改游戏的需求。 在下几个章节中，我们将给大家讲述封包的概念，和修改跟踪客户端的有关知识。大家准备好了吗？ <BR><BR>游戏数据格式和存储： <BR><BR>在进行我们的工作之前，我们需要掌握一些关于计算机中储存数据方式的知识和游戏中储存数据的特点。本章节是提供给菜鸟级的玩家看的，如果你是高手就可以跳过了，呵呵！　　如果，你想成为无坚不摧的剑客，那么，这些东西就会花掉你一些时间；如果，你只想作个江湖的游客的话，那么这些东西，了解与否无关紧要。是作剑客，还是作游客，你选择吧！ <BR><BR>现在我们开始！首先，你要知道游戏中储存数据的几种格式，这几种格式是：字节(BYTE)、字(WORD)和双字(DOUBLE WORD)，或者说是8位、16位和32位储存方式。字节也就是8位方式能储存0~255的数字；字或说是16位储存方式能储存0~65535的数；双字即32位方式能储存0~4294967295的数。 <BR><BR>为何要了解这些知识呢？在游戏中各种参数的最大值是不同的，有些可能100左右就够了，比如，金庸群侠传中的角色的等级、随机遇敌个数等等。而有些却需要大于255甚至大于65535，象金庸群侠传中角色的金钱值可达到数百万。所以，在游戏中各种不同的数据的类型是不一样的。在我们修改游戏时需要寻找准备修改的数据的封包，在这种时候，正确判断数据的类型是迅速找到正确地址的重要条件。 <BR><BR>　　在计算机中数据以字节为基本的储存单位，每个字节被赋予一个编号，以确定各自的位置。这个编号我们就称为地址。 <BR><BR>在需要用到字或双字时，计算机用连续的两个字节来组成一个字，连续的两个字组成一个双字。而一个字或双字的地址就是它们的低位字节的地址。 现在我们常用的Windows 9x操作系统中，地址是用一个32位的二进制数表示的。而在平时我们用到内存地址时，总是用一个8位的16进制数来表示它。 <BR><BR>二进制和十六进制又是怎样一回事呢？ <BR><BR>　　简单说来，二进制数就是一种只有0和1两个数码，每满2则进一位的计数进位法。同样，16进制就是每满十六就进一位的计数进位法。16进制有0--F十六个数字，它为表示十到十五的数字采用了A、B、C、D、E、F六个数字，它们和十进制的对应关系是：A对应于10，B对应于11，C对应于12，D对应于13，E对应于14，F对应于15。而且，16进制数和二进制数间有一个简单的对应关系，那就是；四位二进制数相当于一位16进制数。比如，一个四位的二进制数1111就相当于16进制的F，1010就相当于A。 <BR><BR>了解这些基础知识对修改游戏有着很大的帮助，下面我就要谈到这个问题。由于在计算机中数据是以二进制的方式储存的，同时16进制数和二进制间的转换关系十分简单，所以大部分的修改工具在显示计算机中的数据时会显示16进制的代码，而且在你修改时也需要输入16进制的数字。你清楚了吧？ <BR><BR>　　在游戏中看到的数据可都是十进制的，在要寻找并修改参数的值时，可以使用Windows提供的计算器来进行十进制和16进制的换算，我们可以在开始菜单里的程序组中的附件中找到它。 <BR><BR>　　现在要了解的知识也差不多了！不过，有个问题在游戏修改中是需要注意的。在计算机中数据的储存方式一般是低位数储存在低位字节，高位数储存在高位字节。比如，十进制数41715转换为16进制的数为A2F3，但在计算机中这个数被存为F3A2。 <BR><BR>看了以上内容大家对数据的存贮和数据的对应关系都了解了吗？ 好了，接下来我们要告诉大家在游戏中，封包到底是怎么一回事了，来！大家把袖口卷起来，让我们来干活吧！</P>
<P>二：什么是封包？ <BR>怎么截获一个游戏的封包？怎么去检查游戏服务器的ip地址和端口号？ Internet用户使用的各种信息服务，其通讯的信息最终均可以归结为以IP包为单位的信息传送，IP包除了包括要传送的数据信息外，还包含有信息要发送到的目的IP地址、信息发送的源IP地址、以及一些相关的控制信息。当一台路由器收到一个IP数据包时，它将根据数据包中的目的IP地址项查找路由表，根据查找的结果将此IP数据包送往对应端口。下一台IP路由器收到此数据包后继续转发，直至发到目的地。路由器之间可以通过路由协议来进行路由信息的交换，从而更新路由表。 <BR><BR>那么我们所关心的内容只是IP包中的数据信息，我们可以使用许多监听网络的工具来截获客户端与服务器之间的交换数据，下面就向你介绍其中的一种工具：WPE。 <BR><BR>WPE使用方法：执行WPE会有下列几项功能可选择： <BR><BR>SELECT GAME选择目前在记忆体中您想拦截的程式，您只需双击该程式名称即可。 <BR><BR>TRACE追踪功能。用来追踪撷取程式送收的封包。WPE必须先完成点选欲追踪的程式名称，才可以使用此项目。 按下Play键开始撷取程式收送的封包。您可以随时按下 | | 暂停追踪，想继续时请再按下 | | 。按下正方形可以停止撷取封包并且显示所有已撷取封包内容。若您没按下正方形停止键，追踪的动作将依照OPTION里的设定值自动停止。如果您没有撷取到资料，试试将OPTION里调整为Winsock Version 2。WPE 及 Trainers 是设定在显示至少16 bits 颜色下才可执行。 <BR><BR>FILTER过滤功能。用来分析所撷取到的封包，并且予以修改。 <BR><BR>SEND PACKET送出封包功能。能够让您送出假造的封包。 <BR><BR>TRAINER MAKER制作修改器。 <BR><BR>OPTIONS设定功能。让您调整WPE的一些设定值。 <BR><BR>FILTER的详细教学 <BR><BR>- 当FILTER在启动状态时 ，ON的按钮会呈现红色。- 当您启动FILTER时，您随时可以关闭这个视窗。FILTER将会保留在原来的状态，直到您再按一次 on / off 钮。- 只有FILTER启用钮在OFF的状态下，才可以勾选Filter前的方框来编辑修改。- 当您想编辑某个Filter，只要双击该Filter的名字即可。 <BR><BR>NORMAL MODE： <BR><BR>范例： <BR><BR>当您在 Street Fighter Online ﹝快打旋风线上版﹞游戏中，您使用了两次火球而且击中了对方，这时您会撷取到以下的封包：SEND-&gt; 0000 08 14 21 06 01 04 SEND-&gt; 0000 02 09 87 00 67 FF A4 AA 11 22 00 00 00 00 SEND-&gt; 0000 03 84 11 09 11 09 SEND-&gt; 0000 0A 09 C1 10 00 00 FF 52 44 SEND-&gt; 0000 0A 09 C1 10 00 00 66 52 44 <BR><BR>您的第一个火球让对方减了16滴﹝16 = 10h﹞的生命值，而您观察到第4跟第5个封包的位置4有10h的值出现，应该就是这里了。 <BR><BR>您观察10h前的0A 09 C1在两个封包中都没改变，可见得这3个数值是发出火球的关键。 <BR><BR>因此您将0A 09 C1 10填在搜寻列﹝SEARCH﹞，然后在修改列﹝MODIFY﹞的位置4填上FF。如此一来，当您再度发出火球时，FF会取代之前的10，也就是攻击力为255的火球了！ <BR><BR>ADVANCED MODE： <BR><BR>范例： 当您在一个游戏中，您不想要用真实姓名，您想用修改过的假名传送给对方。在您使用TRACE后，您会发现有些封包里面有您的名字出现。假设您的名字是Shadow，换算成16进位则是﹝53 68 61 64 6F 77﹞；而您打算用moon﹝6D 6F 6F 6E 20 20﹞来取代他。1) SEND-&gt; 0000 08 14 21 06 01 042) SEND-&gt; 0000 01 06 99 53 68 61 64 6F 77 00 01 05 3) SEND-&gt; 0000 03 84 11 09 11 094) SEND-&gt; 0000 0A 09 C1 10 00 53 68 61 64 6F 77 00 11 5) SEND-&gt; 0000 0A 09 C1 10 00 00 66 52 44 <BR><BR>但是您仔细看，您的名字在每个封包中并不是出现在相同的位置上 <BR><BR>- 在第2个封包里，名字是出现在第4个位置上- 在第4个封包里，名字是出现在第6个位置上 <BR><BR>在这种情况下，您就需要使用ADVANCED MODE- 您在搜寻列﹝SEARCH﹞填上：53 68 61 64 6F 77 ﹝请务必从位置1开始填﹞- 您想要从原来名字Shadow的第一个字母开始置换新名字，因此您要选择从数值被发现的位置开始替代连续数值﹝from the position of the chain found﹞。- 现在，在修改列﹝MODIFY﹞000的位置填上：6D 6F 6F 6E 20 20 ﹝此为相对应位置，也就是从原来搜寻栏的+001位置开始递换﹞- 如果您想从封包的第一个位置就修改数值，请选择﹝from the beginning of the packet﹞ <BR><BR>了解一点TCP/IP协议常识的人都知道，互联网是将信息数据打包之后再传送出去的。每个数据包分为头部信息和数据信息两部分。头部信息包括数据包的发送地址和到达地址等。数据信息包括我们在游戏中相关操作的各项信息。那么在做截获封包的过程之前我们先要知道游戏服务器的IP地址和端口号等各种信息，实际上最简单的是看看我们游戏目录下，是否有一个SERVER.INI的配置文件，这个文件里你可以查看到个游戏服务器的IP地址，比如金庸群侠传就是如此，那么除了这个我们还可以在DOS下使用NETSTAT这个命令， <BR><BR>NETSTAT命令的功能是显示网络连接、路由表和网络接口信息，可以让用户得知目前都有哪些网络连接正在运作。或者你可以使用木马客星等工具来查看网络连接。工具是很多的，看你喜欢用哪一种了。 <BR><BR>NETSTAT命令的一般格式为：NETSTAT [选项] <BR><BR>命令中各选项的含义如下：-a 显示所有socket，包括正在监听的。-c 每隔1秒就重新显示一遍，直到用户中断它。-i 显示所有网络接口的信息。-n 以网络IP地址代替名称，显示出网络连接情形。-r 显示核心路由表，格式同"route -e"。-t 显示TCP协议的连接情况。-u 显示UDP协议的连接情况。-v 显示正在进行的工作。 <BR><BR>-------------------------------------------------------------------------------- <BR>三：怎么来分析我们截获的封包？ <BR>首先我们将WPE截获的封包保存为文本文件，然后打开它，这时会看到如下的数据（这里我们以金庸群侠传里PK店小二客户端发送的数据为例来讲解）： <BR><BR>第一个文件：SEND-&gt; 0000 E6 56 0D 22 7E 6B E4 17 13 13 12 13 12 13 67 1BSEND-&gt; 0010 17 12 DD 34 12 12 12 12 17 12 0E 12 12 12 9BSEND-&gt; 0000 E6 56 1E F1 29 06 17 12 3B 0E 17 1ASEND-&gt; 0000 E6 56 1B C0 68 12 12 12 5ASEND-&gt; 0000 E6 56 02 C8 13 C9 7E 6B E4 17 10 35 27 13 12 12SEND-&gt; 0000 E6 56 17 C9 12 <BR><BR>第二个文件：SEND-&gt; 0000 83 33 68 47 1B 0E 81 72 76 76 77 76 77 76 02 7ESEND-&gt; 0010 72 77 07 1C 77 77 77 77 72 77 72 77 77 77 6DSEND-&gt; 0000 83 33 7B 94 4C 63 72 77 5E 6B 72 F3SEND-&gt; 0000 83 33 7E A5 21 77 77 77 3FSEND-&gt; 0000 83 33 67 AD 76 CF 1B 0E 81 72 75 50 42 76 77 77SEND-&gt; 0000 83 33 72 AC 77 <BR><BR>我们发现两次PK店小二的数据格式一样，但是内容却不相同，我们是PK的同一个NPC，为什么会不同呢？ 原来金庸群侠传的封包是经过了加密运算才在网路上传输的，那么我们面临的问题就是如何将密文解密成明文再分析了。 <BR><BR>因为一般的数据包加密都是异或运算，所以这里先讲一下什么是异或。 简单的说，异或就是"相同为0，不同为1"（这是针对二进制按位来讲的），举个例子，0001和0010异或，我们按位对比，得到异或结果是0011，计算的方法是：0001的第4位为0，0010的第4位为0，它们相同，则异或结果的第4位按照"相同为0，不同为1"的原则得到0，0001的第3位为0，0010的第3位为0，则异或结果的第3位得到0，0001的第2位为0，0010的第2位为1，则异或结果的第2位得到1，0001的第1位为1，0010的第1位为0，则异或结果的第1位得到1，组合起来就是0011。异或运算今后会遇到很多，大家可以先熟悉熟悉，熟练了对分析很有帮助的。 <BR><BR>下面我们继续看看上面的两个文件，按照常理，数据包的数据不会全部都有值的，游戏开发时会预留一些字节空间来便于日后的扩充，也就是说数据包里会存在一些"00"的字节，观察上面的文件，我们会发现文件一里很多"12"，文件二里很多"77"，那么这是不是代表我们说的"00"呢？推理到这里，我们就开始行动吧！ <BR><BR>我们把文件一与"12"异或，文件二与"77"异或，当然用手算很费事，我们使用"M2M 1.0 加密封包分析工具"来计算就方便多了。得到下面的结果： <BR><BR>第一个文件：1 SEND-&gt; 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09SEND-&gt; 0010 05 00 CF 26 00 00 00 00 05 00 1C 00 00 00 892 SEND-&gt; 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 083 SEND-&gt; 0000 F4 44 09 D2 7A 00 00 00 484 SEND-&gt; 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 005 SEND-&gt; 0000 F4 44 05 DB 00 <BR><BR>第二个文件：1 SEND-&gt; 0000 F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09SEND-&gt; 0010 05 00 70 6B 00 00 00 00 05 00 05 00 00 00 1A2 SEND-&gt; 0000 F4 44 0C E3 3B 13 05 00 29 1C 05 843 SEND-&gt; 0000 F4 44 09 D2 56 00 00 00 484 SEND-&gt; 0000 F4 44 10 DA 01 B8 6C 79 F6 05 02 27 35 01 00 005 SEND-&gt; 0000 F4 44 05 DB 00 <BR><BR>哈，这一下两个文件大部分都一样啦，说明我们的推理是正确的，上面就是我们需要的明文！ <BR><BR>接下来就是搞清楚一些关键的字节所代表的含义，这就需要截获大量的数据来分析。 <BR><BR>首先我们会发现每个数据包都是"F4 44"开头，第3个字节是变化的，但是变化很有规律。我们来看看各个包的长度，发现什么没有？对了，第3个字节就是包的长度！ 通过截获大量的数据包，我们判断第4个字节代表指令，也就是说客户端告诉服务器进行的是什么操作。例如向服务器请求战斗指令为"30"，战斗中移动指令为"D4"等。 接下来，我们就需要分析一下上面第一个包"F4 44 1F 30 6C 79 F6 05 01 01 00 01 00 01 75 09 05 00 CF 26 00 00 00 00 05 00 1C 00 00 00 89"，在这个包里包含什么信息呢？应该有通知服务器你PK的哪个NPC吧，我们就先来找找这个店小二的代码在什么地方。 我们再PK一个小喽罗（就是大理客栈外的那个咯）：SEND-&gt; 0000 F4 44 1F 30 D4 75 F6 05 01 01 00 01 00 01 75 09SEND-&gt; 0010 05 00 8A 19 00 00 00 00 11 00 02 00 00 00 C0 我们根据常理分析，游戏里的NPC种类虽然不会超过65535（FFFF），但开发时不会把自己限制在字的范围，那样不利于游戏的扩充，所以我们在双字里看看。通过"店小二"和"小喽罗"两个包的对比，我们把目标放在"6C 79 F6 05"和"CF 26 00 00"上。（对比一下很容易的，但你不能太迟钝咯，呵呵）我们再看看后面的包，在后面的包里应该还会出现NPC的代码，比如移动的包，游戏允许观战，服务器必然需要知道NPC的移动坐标，再广播给观战的其他玩家。在后面第4个包"SEND-&gt; 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00"里我们又看到了"6C 79 F6 05"，初步断定店小二的代码就是它了！（这分析里边包含了很多工作的，大家可以用WPE截下数据来自己分析分析） <BR><BR>第一个包的分析暂时就到这里（里面还有的信息我们暂时不需要完全清楚了） <BR><BR>我们看看第4个包"SEND-&gt; 0000 F4 44 10 DA 01 DB 6C 79 F6 05 02 27 35 01 00 00"，再截获PK黄狗的包，（狗会出来2只哦）看看包的格式：SEND-&gt; 0000 F4 44 1A DA 02 0B 4B 7D F6 05 02 27 35 01 00 00SEND-&gt; 0010 EB 03 F8 05 02 27 36 01 00 00 <BR><BR>根据上面的分析，黄狗的代码为"4B 7D F6 05"（100040011），不过两只黄狗服务器怎样分辨呢？看看"EB 03 F8 05"（100140011），是上一个代码加上100000，呵呵，这样服务器就可以认出两只黄狗了。我们再通过野外遇敌截获的数据包来证实，果然如此。 <BR><BR>那么，这个包的格式应该比较清楚了：第3个字节为包的长度，"DA"为指令，第5个字节为NPC个数，从第7个字节开始的10个字节代表一个NPC的信息，多一个NPC就多10个字节来表示。 <BR><BR>大家如果玩过网金，必然知道随机遇敌有时会出现增援，我们就利用游戏这个增援来让每次战斗都会出现增援的NPC吧。 <BR><BR>通过在战斗中出现增援截获的数据包，我们会发现服务器端发送了这样一个包：F4 44 12 E9 EB 03 F8 05 02 00 00 03 00 00 00 00 00 00 第5-第8个字节为增援NPC的代码（这里我们就简单的以黄狗的代码来举例）。 那么，我们就利用单机代理技术来同时欺骗客户端和服务器吧！ <BR><BR>好了，呼叫NPC的工作到这里算是完成了一小半，接下来的事情，怎样修改封包和发送封包，我们下节继续讲解吧。 <BR><BR>-------------------------------------------------------------------------------- <BR>四：怎么冒充"客户端"向"服务器"发我们需要的封包？ <BR>这里我们需要使用一个工具，它位于客户端和服务器端之间，它的工作就是进行数据包的接收和转发，这个工具我们称为代理。如果代理的工作单纯就是接收和转发的话，这就毫无意义了，但是请注意：所有的数据包都要通过它来传输，这里的意义就重大了。我们可以分析接收到的数据包，或者直接转发，或者修改后转发，或者压住不转发，甚至伪造我们需要的封包来发送。 <BR><BR>下面我们继续讲怎样来同时欺骗服务器和客户端，也就是修改封包和伪造封包。 通过我们上节的分析，我们已经知道了打多个NPC的封包格式，那么我们就动手吧！ <BR><BR>首先我们要查找客户端发送的包，找到战斗的特征，就是请求战斗的第1个包，我们找"F4 44 1F 30"这个特征，这是不会改变的，当然是要解密后来查找哦。 找到后，表示客户端在向服务器请求战斗，我们不动这个包，转发。 继续向下查找，这时需要查找的特征码不太好办，我们先查找"DA"，这是客户端发送NPC信息的数据包的指令，那么可能其他包也有"DA"，没关系，我们看前3个字节有没有"F4 44"就行了。找到后，我们的工作就开始了！ <BR><BR>我们确定要打的NPC数量。这个数量不能很大，原因在于网金的封包长度用一个字节表示，那么一个包可以有255个字节，我们上面分析过，增加一个NPC要增加10个字节，所以大家算算就知道，打20个NPC比较合适。 <BR><BR>然后我们要把客户端原来的NPC代码分析计算出来，因为增加的NPC代码要加上100000哦。再把我们增加的NPC代码计算出来，并且组合成新的封包，注意代表包长度的字节要修改啊，然后转发到服务器，这一步在编写程序的时候要注意算法，不要造成较大延迟。 <BR><BR>上面我们欺骗服务器端完成了，欺骗客户端就简单了，^-^ <BR><BR>发送了上面的封包后，我们根据新增NPC代码构造封包马上发给客户端，格式就是"F4 44 12 E9 NPC代码 02 00 00 03 00 00 00 00 00 00",把每个新增的NPC都构造这样一个包，按顺序连在一起发送给客户端，客户端也就被我们骗过了，很简单吧。 <BR><BR>以后战斗中其他的事我们就不管了，尽情地开打吧。</P>]]></description>
</item><item>
<title><![CDATA[WPE封包外挂教程]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=12057</link>
<author>angle800</author>
<pubDate>2006/2/27 10:28:08</pubDate>
<description><![CDATA[Wpe工作原理和可行性分析<BR><BR>wpe所要改的，不是[游戏里面的数值]，而是[伪造信息封包]。 什么意思咧??就是我们用wpe所要改的，并不是"生命力由100变成10000"之类的东西， 这种东西无法用wpe改， 我们要改的可能是把"我卖了一个500元的东西" 改成"我卖了一个50000元的东西"或把"我得了10的exp"改成"我得了10000的exp"之类 的， 或者是明明身上没东西还一直卖"500元的东西"或没怪物还"一直打10的exp"。<BR><BR>因为wpe是个一封包截取软件，它能截取网络上的数据封包，《传奇》采用了Client/server模式，我们的信息全在服务器上面，想从服务器上修改我们的个人用户信息，可能性为微乎其微，客户端安装在你的机器上， 玩游戏的时候，你发出指令，其实就是向服务器发送封包，服务器接收到封包后进行分析，然后返回结果，结果也是以封包的形式发送到你的机器上，你的机器接收到後就可以看到结果了。<BR><BR>这就给我们修改造成了机会，如果我们把封包里的数据改了会怎么样呢？？比如我发了一小火球，截取到代码，然后改成闪电的代码，那么我在机器上的效果应该就是闪电的效果了（已经试验过，可行）。这种方法理论上是可行的，可是为什么有时实现不了呢？？因为服务器还有应对措施，对一些重要的数据往往需要检测多项，我们修改的时候只是修改了其中一项，是不行的。而且往往数据包是加密传输的，这也给我们找正确的数据制造了麻烦。<BR><BR>但是服务器的监测工作是有限度的，因此不可能全部都由服务器完成，很多耗资源的监测都放到了客户端上，早期的免腊，半月，穿人都是在本机上进行了监测，服务端并没有相应的监测机制，只有最近的更新才加入了一些监测，但也造成了整个服务端的狂慢。所以对一些服务器并没有监测的东西我们还是可以修改的，当然这些东西需要大家一起探索。<BR><BR>一点技术提示： <BR><BR>传奇 的c/s通信采用了字节流套接字，这种通信可靠，双向，顺序，因此，封包只要按照原来的顺序就可以了。游戏采用了32位加密(crc/32)，故我们不能随便篡改其中的信息，否这服务器在校验时，发现出错，就会断开服务器连接哦,故采用李代桃疆之法更有效。身份认证信息的篡改当然没问题了（通一台机器，同一用户嘛!）我们发送的数据含有坐标码，改包时不要改坐标哦。 <BR><BR><BR><BR>WPE教学之-截取操作篇<BR><BR>一开始,当然是执行游戏了,进入游戏后再按[Alt+Tab]跳出游戏 ,打开wpe程序（WPE ver1.3 界面如下图）<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 50%" src="http://www.czvc.com/articles/133.gif" border=0></CENTER><BR><BR>双击SELECT GAME打开如上图中. <BR>我们以传奇为例，当你运行传奇的时候在这里我们可以看见传奇的执行文件，双击mir.dat，现在我们将拦截传奇的封包!<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 70%" src="http://www.czvc.com/articles/134.gif" border=0></CENTER><BR><BR>请看上图标题栏现在显示的是拦截传奇的封包.<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 50%" src="http://www.czvc.com/articles/135.gif" border=0></CENTER><BR><BR>双击TRACE，打开如图中所示，用来截取封包，按图中三角按钮开始截取封包，按红色方块按纽停止.<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/136.gif" border=0></CENTER><BR><BR>若您没按下红色方形停止键，追踪的动作将依照OPTION里的设定值自动停止.<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 40%" src="http://www.czvc.com/articles/137.gif" border=0></CENTER><BR><BR>截获封包后，s框后面的数字是发送封包的内容，r框后面的数字是接收封包的内容，以16进制数和acsII两种方式体现！整个程序的上面有储存清除查找3个选项！至此，第一步截取完成了。下面进行的是要过滤了,呵呵,不要打瞌睡,重头戏出场了! <BR><BR><BR>WPE教学之-Filter篇<BR><BR>Filter 执行的是滤镜功能，它能把截获到的封包中的数据进行修改，然后将修改后的数据传输到服务器，达到欺骗服务器的目的，这也是我们所要完成的任务。<BR><BR>首先作一下介绍,首先双击Filter打开Filter窗口<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/138.gif" border=0></CENTER><BR><BR>详细功能如下图所示<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/139.gif" border=0></CENTER><BR><BR>当FILTER在启动状态时　，ON的按钮会呈现红色。当您启动FILTER时，您随时可以关闭这个视窗。FILTER将会保留在原来的状态，直到您再按一次 on / off 钮。只有FILTER启用钮在OFF的状态下，才可以勾选Filter前的方框来编辑修改。 当您想编辑某个Filter，只要双击该Filter的名字即可。 <BR><BR>双击Filter名字（如Filter 1）进入编辑状态，请看下图<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 90%" src="http://www.czvc.com/articles/140.gif" border=0></CENTER><BR><BR>这里有几个名词，需要注意一下： <BR><BR>Normal 一般模式 <BR>如果你所修改的数据在数据包中的位置是固定的，可以用一般模式，这也是我们常用的模式 <BR>Advanced 递进模式 <BR>如果你所修改的数据在数据包中的位置不是固定的，只能用递进模式，后面会有例子说明 <BR>以下两项只有选择了Advanced模式后才可以选择 <BR>Form the beginning of the packet <BR>从截获到的封包的第一个位置开始替换 <BR>Form the position of the chain found <BR>从数值被发现的位置开始替换连续数值 <BR>例一：<BR><BR><BR>下面举一个例子，修改游戏中的大火球变闪电术： <BR>在游戏中发两次次大火球，截获到的封包如下 <BR>SEND-&gt; 0000 23 33 60 4C 43 60 3C 48 60 47 3C 3C 3C 41 3C 3C 3C 3C 21 <BR>SEND-&gt; 0000 23 34 60 4C 43 60 3C 48 60 47 3C 3C 3C 41 3C 3C 3C 3C 21 <BR>在游戏中发两次次闪电，截获到的封包如下 <BR>SEND-&gt; 0000 23 31 60 4C 43 60 3C 48 60 47 3C 3C 3C 47 3C 3C 3C 3C 21 <BR>SEND-&gt; 0000 23 32 60 4C 43 60 3C 48 60 47 3C 3C 3C 47 3C 3C 3C 3C 21 <BR>先进性分析 <BR>因为游戏中都是在同一位置发的魔法，排除位置因素，分析只有2处不同，而每次封包中只有第2处的位置上相同，故很有可能第2出代表的就是魔法的代码 <BR>这种情况下有正常模式就行了，封包中数值的位置是固定的： <BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/141.gif" border=0></CENTER><BR><BR>例二： <BR><BR>当您在一个游戏中，您不想要用真实姓名，您想用修改过的假名传送给对方。 <BR>
<CENTER><IMG onmousewheel="return bbimg(this)" src="http://www.czvc.com/articles/142.gif" border=0></CENTER><BR><BR>在您使用TRACE後，您会发现有些封包里面有您的名字出现。<BR><BR>假设您的名字是Shadow，换算成16进位则是"53 68 61 64 6F 77〔；而您打算用moon"6D 6F 6F 6E 20 20〔来取代他。<BR><BR>1) SEND-&gt; 0000 08 14 21 06 01 04 ......<BR>2) SEND-&gt; 0000 01 06 99 53 68 61 64 6F 77 00 01 05 ...Shadow...<BR>3) SEND-&gt; 0000 03 84 11 09 11 09 ......<BR>4) SEND-&gt; 0000 0A 09 C1 10 00 53 68 61 64 6F 77 00 11 .....Shadow.<BR>5) SEND-&gt; 0000 0A 09 C1 10 00 00 66 52 44 .......<BR><BR>但是您仔细看，您的名字在每个封包中并不是出现在相同的位置上<BR><BR>　- 在第2个封包里，名字是出现在第4个位置上<BR>　- 在第4个封包里，名字是出现在第6个位置上<BR><BR>在这种情况下，您就需要使用ADVANCED MODE<BR><BR>　- 您在搜寻列"SEARCH〔填上：53 68 61 64 6F 77 "请务必从位置1开始填<BR>　- 您想要从原来名字Shadow的第一个字母开始置换新名字，因此您要选择从数值被发现的位置开始替代连续数值（from the position of the chain found）。<BR>　- 现在，在修改列"MODIFY〔000的位置填上：6D 6F 6F 6E 20 20 "此为相对应位置，也就是从原来搜寻栏的001位置开始递换 <BR><BR>退出编辑状态，享受我们的修改成果吧!! <BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/143.gif" border=0></CENTER><BR><BR>WPE教学之-Trainer Maker篇<BR><BR><BR>至此我们已经可以进行扑获，过滤数据包了，也可以进行修改游戏了。但是每次修改都要进WPE，好罗嗦啊，有没有简单的办法呢？？？有！！！WPE自带了修改器生成器，就是TRAINER MAKER功能 ，可以把你自己做好的FLT文件做成单独运行的一个程序。 这样每次用到你就不需要打开WPE进行烦琐的操作进入传奇，打开WPE，点选SELECT GAME双攻击MIR.DAT 接着再点选TRAINER MAKER。<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 50%" src="http://www.czvc.com/articles/144.gif" border=0></CENTER><BR><BR>按NEXT继续，如下图，这里是让你填入你所要生成的EXE文件的文件名和执行后的窗口栏名称<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/145.gif" border=0></CENTER><BR><BR>输入完毕后按NEXT，你会看到<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 50%" src="http://www.czvc.com/articles/146.gif" border=0></CENTER><BR><BR>点“打开文件”的按钮，选择你所要生成EXE程序的FLT滤镜文件。<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 60%" src="http://www.czvc.com/articles/147.gif" border=0></CENTER><BR><BR>下一步输入本程序的说明。<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 70%" src="http://www.czvc.com/articles/148.gif" border=0></CENTER><BR><BR>这里选择winsock的版本，及其选项（推荐使用默认值）。<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" style="ZOOM: 70%" src="http://www.czvc.com/articles/149.gif" border=0></CENTER><BR><BR>OK了一路NEXT，捎后片刻你的WPE目录下就 会生成一个EXE文件。<BR>注意：该程序不能与WPE同一时间运行<BR>
<CENTER><IMG onmousewheel="return bbimg(this)" src="http://www.czvc.com/articles/150.gif" border=0></CENTER>
<P><BR><BR>哈哈，看看我们的程序吧！现在你就可以拿到别的机器上用了！</P>
<P>虽然好多外挂都被封了，可是现在回头看看，对我们的学习使用wpe还是有很大的帮助，以下的几篇文章都是实际的经验，而且里面的方法更是值得我们学习，如何分析问题，如何查找关键数据，从何处入手，等等。这些文章都是从网站上抄来的，首先向他们的作者致歉，因为经过好多次的转载，有些作者都找不到了，因此没有署名。下面让我们一起来看看：<BR><BR><A name=虎卫版的破解>虎卫版的破解</A><BR><BR>虎卫版更新了mir.dat文件，在我们进入游戏时会有一个验证身份的过程，类似答考卷。举个例子：服务器给mir.dat文件的试卷题目是“天王盖地虎”然后虎卫的mir.dat答案是“宝塔镇蛇妖”，这样，服务器就知道了mir.dat是合法的。而半月看血的那个mir.dat文件并不知道正确的答案是什么，只有硬着头皮随便说了个答案。所以它的身份很快就被揭穿了。最终的结果就是，我们被服务器踢出来了！<BR><BR>现在，我们需要做的就是----欺骗服务器，让它认为半月看血的mir.dat文件是合法的。我们知道，软件WPE的主要功能之一就是更换发送给服务器的数据包。只要在服务器没有收到半月看血的mir.dat文件提交的答案之前，利用WPE将答案修改成正确的，服务器就会认为半月看血的mir.dat文件是合法的。这样，挥半月，全屏看血，一步起跑，超负重等功能就又可以实现了。<BR><BR>下面就是具体的做法。（所需工具：WPE）<BR><BR>准备工作：将patch这个文件改个名，这样可以避免服务器将半月版的mir.dat文件自动更新成虎卫版的（两个版本的mir.dat文件大小不一样），这样做的话进入游戏的时候会提示patch.exe程序不能使用，别管他，点OK就可以了。<BR><BR>最关键的一步，是要知道合法的mir.dat文件所提交的试卷中的正确答案。在每次进入游戏前，我们需要做的是选择自己的游戏帐号在哪个服务器、选择人物等等。这里的每次选择，都会向服务器发送相应的封包。虎卫版和半月版在进入游戏之前所进行的前几个步骤并没有太大的区别。在最后选择人物，点“开始”以后就有区别了----使用半月看血的会被服务器踢出来。所以，我们可以初步认定，正是这一步在提交试卷。所以我们可以使用不同的mir.dat进入游戏，在点开始之前用WPE截一下数据就可以知道正确的答案和错误的答案都是什么了。<BR><BR>注意：在使用WPE之前最好先对这个软件进行一下设置，让它只截取我们发送给服务器的封包。这样的封包才是我们能够随意修改的。下面是我截取的数据<BR><BR>使用半月mir.dat<BR><BR>SEND-&gt; 0000 23 35 3C 3C 3C 3C 3C 42 58 3C 3C 3C 3C 3C 3C 3C #5&lt;&lt;&lt;&lt;<BX<<<<<<<<BR> <BR>SEND-&gt; 0010 3C 3C 56 62 61 5D 57 63 5D 65 57 5F 3C 6C 49 6E &lt;<VBA]WC]EW_<LIN<BR> <BR>SEND-&gt; 0020 7B 47 7A 58 47 5A 6C 78 53 52 67 68 63 5B 21 {GzXGZlxSRghc[!<BR><BR>SEND-&gt; 0000 23 36 46 5E 65 66 56 52 41 6A 5A 42 61 6A 48 3F #6F^efVRAjZBajH?<BR><BR>SEND-&gt; 0010 3C 73 47 78 6B 75 6C 69 77 3F 6D 59 56 6A 6E 59 <SGXKULIW?MYVJNY<BR><BR>SEND-&gt; 0020 78 6B 48 4F 4C 70 4A 3F 58 70 47 6F 44 6C 48 3F xkHOLpJ?XpGoDlH?<BR><BR>SEND-&gt; 0030 40 6D 48 3F 3C 72 47 6F 3C 21 @mH?<RGO<!<BR> <BR>SEND-&gt; 0000 23 37 3C 3C 3C 3C 3C 4B 64 3F 3C 3C 3C 3C 3C 3C #7&lt;&lt;&lt;&lt;<KD?<<<<<<<BR> <BR>SEND-&gt; 0010 3C 3C 21 &lt;<!<BR> <BR>SEND-&gt; 0000 2A *<BR><BR>SEND-&gt; 0000 23 38 3C 3C 3C 3C 3C 41 40 3C 3C 3C 3C 3C 3C 3C #8&lt;&lt;&lt;&lt;<A@<<<<<<<<BR> <BR>SEND-&gt; 0010 3C 3C 21 &lt;<! <BR> <BR>使用虎卫mir.dat<BR><BR>SEND-&gt; 0000 23 34 3C 3C 3C 3C 3C 42 58 3C 3C 3C 3C 3C 3C 3C #4&lt;&lt;&lt;&lt;<BX<<<<<<<<BR> <BR>SEND-&gt; 0010 3C 3C 56 62 61 5D 57 63 5D 65 57 5F 3C 6C 49 6E &lt;<VBA]WC]EW_<LIN<BR> <BR>SEND-&gt; 0020 7B 47 7A 58 47 5A 6C 78 53 52 67 68 63 5B 21 {GzXGZlxSRghc[!<BR><BR>SEND-&gt; 0000 23 35 46 5E 65 66 56 52 41 6A 5A 42 61 6A 48 3F #5F^efVRAjZBajH?<BR><BR>SEND-&gt; 0010 3C 73 47 78 6B 75 6C 69 77 3F 6D 59 56 6A 6E 59 <SGXKULIW?MYVJNY<BR><BR>SEND-&gt; 0020 78 6B 48 4F 4C 73 48 4F 40 6F 47 6F 44 6C 48 3F xkHOLsHO@oGoDlH?<BR><BR>SEND-&gt; 0030 44 6C 49 4F 44 6E 47 6F 3C 21 DlIODnGo<!<BR> <BR>SEND-&gt; 0000 23 36 3C 3C 3C 3C 3C 4B 64 3F 3C 3C 3C 3C 3C 3C #6&lt;&lt;&lt;&lt;<KD?<<<<<<<BR> <BR>SEND-&gt; 0010 3C 3C 21 &lt;<!<BR> <BR>SEND-&gt; 0000 2A *<BR><BR>SEND-&gt; 0000 23 37 3C 3C 3C 3C 3C 41 40 3C 3C 3C 3C 3C 3C 3C #7&lt;&lt;&lt;&lt;<A@<<<<<<<<BR> <BR>SEND-&gt; 0010 3C 3C 21 &lt;<!<BR> <BR>SEND-&gt; 0000 2A *<BR><BR>SEND-&gt; 0000 2A *<BR><BR>可以看到，半月版截到了5组封包，虎卫版是7组。在这里我们大可不必理会数据的多少，对比的时候以半月版为准。虎卫版数据多的原因是因为我们已经正常进入游戏了。多出来的数据可能是客户端告诉服务器自己已经正常进入了，这样服务器才会告诉客户端，他有什么物品，等级是多少……<BR><BR>没得到我是神的指点前，我前半夜的时间就是浪费在这里了。<BR><BR>再观察这些数据可以看到，每组数据大多以23开头，紧跟在后面的是3x（x代表0-9的数字），这些是数据包编号信息，可以不理会它。右边是这些16进制数据对应的符号，我们对比右边的符号就能知道两个版本同一组包里面的信息有什么不同了。可以发现，两个版本所发送的第二组包差别最大。所以，这组数据成了重点！<BR><BR>那天，我利用WPE的滤镜功能，（教程里有滤镜的使用说明），把半月版的除了数据编号以外的所有信息写到了滤镜的正确值里，又把虎卫的信息写到了伪造值中，运行滤镜。满以为这次会成功，结果服务器照踢不误。在这里我又浪费掉了后半夜时间~~~~~~<BR><BR>后来得到我是神的指点，才知道即使是用同一个ID，使用同一个版本的mir.dat文件登陆，所得到的第二组数据也会有所不同，个人认为那些不同的数据可能和登陆的时间，服务器的状态有关。知道了这些，就可以把随机变化的不同部分排除掉。然后再对比两个版本截到的数据中其他部分，发现只有SEND-&gt; 0030这一行的第1-6个数值是不一样的。把半月版的这6个数值填到滤镜中的正确值里，再把虎卫版相同位置上的6个数值填到伪造值里就可以欺骗服务器了。<BR><BR>在使用滤镜的时候应该用它的“递进模式”，并且选上“自定位修改”，（这样设置后，WPE只要发现连续的这6个正确数值，就会连续的把这6个数值替换成为伪造值）滤镜的“查找长度最大值”（我理解成在多长的一组包里查找相关数据）默认是40，可是我们知道我们要修改的那组数值所在的封包长度已经超过40个字节了，所以我们可以将“查找长度最大值”设置成大于封包长度的值。（我是神设的是80，我自己设的是64）另外，当我们选上“递进模式”并且选上“自定位修改”后，伪造值的范围变成了-124到+124，应该从000处开始填入伪造值才能使滤镜真正生效。<BR><BR>好了，运行滤镜吧，试着使用半月版进入传奇，结果是----成功。到了这一步，我高兴的不得了，终于成功了！<BR><BR>可是好景不长，休息了几个小时后这个滤镜竟然失效了。重新按前面的方法截获数据，发现和以前截获的数据不一样了。我倒，原来服务器考试还分A、B卷啊。于是照改不误，多做了两个滤镜----这回彻底把服务器摆平了。（做成能够脱离WPE单独运行的封包后就可以给朋友用了） <BR><BR>由于要将patch解决掉才能使用这个封包，没了自动更新的功能，换成其他区的用户登陆就会出现ID不存在的错误提示。好多朋友发表了解决这个问题的方法，有手工修改mir.ini文件的、有用WIN2000做模拟FTP服务器的、还有用防火墙截住patch不让它自动更新的。个人认为在网吧使用以上方法还是有点费事。<BR><BR>我是在家里上网的，那个patch文件改名后进入游戏会出现“patch.exe程序不能使用”的提示，每次都要点“OK”，太罗嗦了。我把半月版的mir.dat设成只读属*了，所以那个patch就没法把它更新成虎卫版了。不过，换其它区的ID登陆还是有问题。大家想想办法把这个问题彻底解决。<BR><BR><BR><A name=WPE系列教程之封包用法篇>WPE系列教程之封包用法篇</A><BR><BR><BR>由于不同区不同服务器的的数据不同，一个封包要想在每个服务器都能使用是不可能的。这就需要我们对原有的封包进行修改。 <BR>大家不必要一味的要这个封包，要那个封包，学会了修改封包，就能自己动手了. 大家在发封包之前，都会和NPC说话，然后进行搜寻，得到一批数据，就是16进制代码我们要做的是打开所要发送的封包，然后选择要发送的命令如：Packet n 1，发送。现在一个封包命令就发出去了，这就是WPE的用法，我要说的是怎么修改，大家继续看：<BR>现在，我们双击左边的Packet n 1，会出来一条对话框，里面也有16进制代码我所需要做的是把第一排第3。4。5。6。4组数据修改成你刚才搜索的相应数据（注意：他的相应数据是在搜索的时候，左边带S符号的那几排数据）<BR>如果在搜索的时候，出现了许多带S符号的数据排，则证明，有地方出错，你退出传奇再进或者再次搜索一遍，一般只会出现2-3排的S，而其他带R的不用管他。你现在已经把其他服务器的封包改成你这个服务器能用的封包了。<BR>比如赌场封包，在1号房搜索并修改1号封包数据后发送，撒6到了7号房，再搜索并修改2号封包数据后发送，依次类推就可以到40号房间。注意，修改9号封包也就是拿钱封包的时候必须等你出来与NPC对话出现成功字样的时候才能修改，如果你拿不到钱，你所修改的封包则无任何用处，所以要修改拿钱封包，必须你先得拿到一次钱，但是如果成功了和NPC说话后立即开始修改，而且要一次成功，慢点都无所谓，想想修改步骤，否则你失败了再点NPC就会送你回去。 <BR>那么，现在虽然赌场的封了，你们还可以去试试神秘商店或者未知暗殿的封包，一样能改好了。<BR><BR><BR><BR><A name=WPE系列教程之刷钱封包制作资料篇>WPE系列教程之刷钱封包制作资料篇</A><BR><BR>第一位23 表示 # 是 开头 <BR>第二位 是数据传递的id从0-9（ascii码） <BR>第三四位是你放在物品篮的数据 <BR>后面不变的则为此物品的数据<BR><BR>请大家自己研究！<BR><BR><BR><BR><A name=WPE系列教程之祝福油和幽灵手套篇>WPE系列教程之祝福油和幽灵手套篇</A><BR><BR>现在让你站在比奇的人给新人2捆随机(随机带多少,随便,看你自己了),4000gold <BR>现在开始长征,我随机.......(此处省略若干过程),进比奇找老兵,给他4000到盟重! <BR>在跑!跑到仓库旁边的客栈里面!找到林小姐......,切出传奇,现在使用封包 <BR><BR>打开wpe如果大家有找不到我说明里面点击的地方在那里的!请下载此版本对照. <BR><BR>双击 SELECT 选择 mir.dat(现在你的传奇应该是打开的哦,别告诉我你关了) <BR><BR>双击 trace 选择 开始,就是哪个箭头标志 <BR><BR>切回传奇 点林小姐 <BR><BR>切出传奇,停止截取,就是哪个方的按纽 <BR><BR>现在开始用脑袋,你应该可以看到你刚才打开wpe哪一大片空白的地方有数据了吧! 看看数据最前面,看到以S或者以R开头的小按纽了吗?现在找到以S开头的这样一段数据 <BR>xx xx yy yy yy yy oo xx xx xx xx xx xx xx xx xx <BR>xx xx xx <BR>ok,现在继续 <BR><BR>双击你看到的任意一个S或者R的小按纽,你会看到跳一个窗口出来,里面写了个数字,这个数字不固定,但是一般是 44 或者 56 <BR><BR>双击 SEND PACKET,看到&lt;&lt;封包列出&gt;&gt;下面的哪本打开的小书没有?,对了,点他选择祝福油AND幽灵手套封包,然后点&lt;&gt;右边的哪个垃圾箱 <BR><BR>双击 &lt;&lt;封包列出&gt;&gt; 下面的 packet n 1 <BR>又开始用脑袋,你应该可以看到如下数据 <BR>xx xx zz zz zz zz oo xx xx xx xx xx xx xx xx xx <BR>xx xx xx xx xx xx xx xx xx xx xx xx xx <BR><BR>现在继续 <BR><BR>把 zz zz zz zz 用yy yy yy yy替换掉!看清楚!为什么要替换掉!因为每个服务器的林小姐的代码是不一样的 <BR><BR>写完了点离开就可以可!现在把 packet n 1 点一下!你会发现 packet n 1 变蓝色了哦!对了,现在点哪个有3层的,有立体感的,画了个向右指的尖头的按纽,你会看到 &lt;&gt;,变成了1%,而且右边也有了个 packet n 1 ,ok,.你已经接近成功了! <BR><BR>如果你用的我告诉你的哪个wpe版本的话,你可以看到在 &lt;&lt;开启插座我&gt;&gt; 右边有个数字,如果没有的话就不对!如果没有,重复第6 步. <BR><BR>点击 阜 右边的那个 画了个黑色箭头的按纽,开始发送!现在切换回传奇,你就会看到一个对话框了!选择3,就是幽灵手套了! <BR><BR>注意!在你没有退出整个传奇的情况下!你新人一走到!只需要执行第13步就可以了<BR><BR>我们7个人!一个盟重,一个比奇,剩下的5个都在跑新人.............. 好累!如果还有人不会用的话!我就没有话说了<BR><BR><A name=WPE系列教程之神秘封包制作篇>WPE系列教程之神秘封包制作篇</A><BR><BR>大家先到这里看看 （既然有现成的东西，何乐而不为，CC ）<BR><BR>再来说说我们现在玩的传奇。我这里就举个神秘商店的例子说明吧。<BR><BR>1，进入传奇跑到兽人2F刘老头那<BR>2，打开WPE点选SELECT GAME双击MIR.DAT<BR>3，点选WPE上的TRACE按钮（此时出现一个3角的播放键和4方的停止键）点播放键开始截取数据<BR>4，立刻切换回传奇点击刘老头，出现对话框（刘老头对你说XXX很厉害的字样）后切换回WPE点4方型的停止键。<BR><BR>这样我们就截取一组S和R数据（发给服务器点击刘老头和从服务器接收到的数据）<BR>排除掉接收数据我们就会看到一组发送数据类下<BR>23 3? ?? ?? ?? ?? 3F 4B 48 3F 3C 3C 3C 3C 3C 3C 3C 3C 21<BR>（具体多少自己看了，都那个样）<BR><BR>接着我们点选SEND PACKET按钮。打开（下载或者别人提供）进神秘的封包。查看刘老头的数据，抄下或者用截图程序截下。关闭SEND PACKET窗口。回到WPE主窗口点选FILTER按钮，（这里用NORMAL模式即可）把你自己截取到的刘老头的数据填入第一行然后开始对比自己截取的数据与封包内的数据的差别。。。找到不同的数据就填入第2行相同位置。<BR><BR>比如： 位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19<BR>原 数据 23 3? ?? ?? ?? ?? 3F 4B [48] 3F 3C 3C 3C 3C 3C 3C 3C 3C [21]<BR>修改数据 23 3? ?? ?? ?? ?? 3F 4B [44] 3F 3C 3C 3C 3C 3C 3C 3C 3C [4C] ?? ?? ??<BR><BR>这样你只需在第2行的第9位置填入44和19位置填入4C即可，如果修改数据长度超过原数据， 就把他当做不同数据在19位置后继续填入。但是在右边的封包长度框内必须自定义封包长度，不然FILTER只过滤1-19位置的数据。封包长度要看你修改数据的长度了，大与修改数据长度也可以。<BR><BR>如何实现全区通用---在传奇版本相同的情况下，各区封包是相同的。不同的只是位置代码而已，大家看一下上面的2排数据，第一位 23 是开始代码，第 2位是 31-39的数字，是数据编号，3-6位就是位置代码。在FILTER中把原数据行的3-6位清空不进行过滤，就能简单的实现全区通用。<BR><BR>再检查一次看看有没有错误，如果可以的话按QUIT推出FILTER编辑框。回到FILTER控制窗口，勾上刚才修改的FILTER，启动FILTER（从左到右第5个按钮）进入传奇，点刘老头，如果正常的话刘老头会拿走你5000块钱跟你说起废话<BR><BR>回到WPE的FILTER控制框保存刚才修改的FILTER为FLT文件<BR><BR><A name=WPE系列教程之攻击代码篇>WPE系列教程之攻击代码篇</A><BR><BR>特殊修理：点普通修理，有时候（特别第一次点击）会出不来什么什么“正好有材料，价格是3倍什么什么的废话，你需要点返回再点修理到一直出来为止，基本上第2次就可以了。<BR><BR>传奇出错：（个人想法）主要是封包长度问题。进行封包过滤的时候由于过滤封包长度要大于待过滤封包。导致传奇非法。出错。目前还没解决，希望高手们能多发发帖子。。。<BR><BR>攻击方式：战士在传奇里攻击方式有空放3种（按住SHIFT打空），打怪4种（基本，攻杀，刺杀，烈火），攻击方向有8个，代码3C，3D，3E，3F，41，42等。攻杀代码是64，刺杀是68，放出攻杀和刺杀是由客户机随即决定的。刺杀是有条件的（也是客户机根据条件决定的）。所以只要对截取到的封包过滤攻击方式那一字节就可以放出。<BR><BR><BR><A name=WPE的另类用法>WPE的另类用法</A><BR><BR><BR>WPE不仅可以用来抓取封包，也可以用来蒙蔽木马，嘿嘿，看仔细了<BR>木马可以偷密码，但大多都是键盘侦听一级的，也就是记录你的键盘操作，然后把记录下来的数据通过网络发出去，达到偷取密码的目的。传奇里的木马够多了，现在基本上都属于这类情况。防木马的方法也有好多，安装木马可行，防火墙等等，其实WPE软件也可以做的到<BR><BR><BR>原理：<BR>输入用户名和密码的时候如果故意输错，结果会怎么样？？盛大的服务器肯定不会认的，但是数据是需要网上传输的，也就是有封包可以截获，通过WPE截取到错误的封包，然后用滤镜功能修改成正确的用户名和密码，服务器还会拒绝吗！可是木马会截取封包吗？嘿嘿，目的基本实现,放心现在的木马基本上还没有这个功能，以后可能会有，555555555555555！<BR><BR><BR>操作：<BR><BR><BR>1. 输入错误的用户名和密码，截取传送的封包<BR>2. 输入正确的用户名和密码，截取传送的封包<BR>3. 分析两次截获的封包，查找不同的地方<BR>4. 启用滤镜功能，做出滤镜封包，存成FLI文件<BR>5. 用TRANINER MAKER做出可执行文件<BR><BR><BR>现在，在进传奇之前先运行做好的可执行文件，然后输入错误的用户名和密码进传奇，爽吧<BR><BR><BR>后记：本文以前有人做过，可惜原文找不到了，可是原理很好，想法也很特别，我记得就这么多，其实，WPE软件的动能很多，可不仅仅是修改游戏啊，网络上的嗅探器很多都是黑客高手们自己编的，WPE的功能也是其中一个。再说，这种办法不仅可以修改传奇,对需要网络上验证的程序都有效，哈哈，大家自己试试吧！！<BR></P>]]></description>
</item><item>
<title><![CDATA[[转帖]XML的简单读取与写入(ASP)]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=5989</link>
<author>angle800</author>
<pubDate>2005/5/23 9:40:21</pubDate>
<description><![CDATA[<A>　已知有一个XML文件（bookstore.xml）如下：&nbsp;<BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="gb2312"?&gt;&nbsp;<BR>&lt;bookstore&gt;&nbsp;<BR>&lt;book&nbsp;genre="fantasy"&nbsp;ISBN="2-3631-4"&gt;&nbsp;<BR>&lt;title&gt;Oberon's&nbsp;Legacy&lt;/title&gt;&nbsp;<BR>&lt;author&gt;Corets,&nbsp;Eva&lt;/author&gt;&nbsp;<BR>&lt;price&gt;5.95&lt;/price&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;/bookstore&gt;&nbsp; 
<P></P>
<P>1、往&lt;bookstore&gt;节点中插入一个&lt;book&gt;节点：&nbsp;<BR>XmlDocument&nbsp;xmlDoc=new&nbsp;XmlDocument();&nbsp;<BR>xmlDoc.Load("bookstore.xml");&nbsp;<BR>XmlNode&nbsp;root=xmlDoc.SelectSingleNode("bookstore");//查找&lt;bookstore&gt;&nbsp;<BR>XmlElement&nbsp;xe1=xmlDoc.CreateElement("book");//创建一个&lt;book&gt;节点&nbsp;<BR>xe1.SetAttribute("genre","李赞红");//设置该节点genre属性&nbsp;<BR>xe1.SetAttribute("ISBN","2-3631-4");//设置该节点ISBN属性&nbsp;</P>
<P>XmlElement&nbsp;xesub1=xmlDoc.CreateElement("title");&nbsp;<BR>xesub1.InnerText="CS从入门到精通";//设置文本节点&nbsp;<BR>xe1.AppendChild(xesub1);//添加到&lt;book&gt;节点中&nbsp;<BR>XmlElement&nbsp;xesub2=xmlDoc.CreateElement("author");&nbsp;<BR>xesub2.InnerText="候捷";&nbsp;<BR>xe1.AppendChild(xesub2);&nbsp;<BR>XmlElement&nbsp;xesub3=xmlDoc.CreateElement("price");&nbsp;<BR>xesub3.InnerText="58.3";&nbsp;<BR>xe1.AppendChild(xesub3);&nbsp;</P>
<P>root.AppendChild(xe1);//添加到&lt;bookstore&gt;节点中&nbsp;<BR>xmlDoc.Save("bookstore.xml");&nbsp;<BR>//===============================================&nbsp;<BR>结果为：&nbsp;<BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="gb2312"?&gt;&nbsp;<BR>&lt;bookstore&gt;&nbsp;<BR>&lt;book&nbsp;genre="fantasy"&nbsp;ISBN="2-3631-4"&gt;&nbsp;<BR>&lt;title&gt;Oberon's&nbsp;Legacy&lt;/title&gt;&nbsp;<BR>&lt;author&gt;Corets,&nbsp;Eva&lt;/author&gt;&nbsp;<BR>&lt;price&gt;5.95&lt;/price&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;book&nbsp;genre="李赞红"&nbsp;ISBN="2-3631-4"&gt;&nbsp;<BR>&lt;title&gt;CS从入门到精通&lt;/title&gt;&nbsp;<BR>&lt;author&gt;候捷&lt;/author&gt;&nbsp;<BR>&lt;price&gt;58.3&lt;/price&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;/bookstore&gt;&nbsp;</P>
<P>2、修改节点：将genre属性值为“李赞红“的节点的genre值改为“update李赞红”，将该节点的子节点&lt;author&gt;的文本修改为“亚胜”。&nbsp;<BR>XmlNodeList&nbsp;nodeList=xmlDoc.SelectSingleNode("bookstore").ChildNodes;//获取bookstore节点的所有子节点&nbsp;<BR>foreach(XmlNode&nbsp;xn&nbsp;in&nbsp;nodeList)//遍历所有子节点&nbsp;<BR>{&nbsp;<BR>XmlElement&nbsp;xe=(XmlElement)xn;//将子节点类型转换为XmlElement类型&nbsp;<BR>if(xe.GetAttribute("genre")=="李赞红")//如果genre属性值为“李赞红”&nbsp;<BR>{&nbsp;<BR>xe.SetAttribute("genre","update李赞红");//则修改该属性为“update李赞红”&nbsp;</P>
<P>XmlNodeList&nbsp;nls=xe.ChildNodes;//继续获取xe子节点的所有子节点&nbsp;<BR>foreach(XmlNode&nbsp;xn1&nbsp;in&nbsp;nls)//遍历&nbsp;<BR>{&nbsp;<BR>XmlElement&nbsp;xe2=(XmlElement)xn1;//转换类型&nbsp;<BR>if(xe2.Name=="author")//如果找到&nbsp;<BR>{&nbsp;<BR>xe2.InnerText="亚胜";//则修改&nbsp;<BR>break;//找到退出来就可以了&nbsp;<BR>}&nbsp;<BR>}&nbsp;<BR>break;&nbsp;<BR>}&nbsp;<BR>}&nbsp;</P>
<P>xmlDoc.Save("bookstore.xml");//保存。&nbsp;<BR>//==================================================&nbsp;<BR>最后结果为：&nbsp;<BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="gb2312"?&gt;&nbsp;<BR>&lt;bookstore&gt;&nbsp;<BR>&lt;book&nbsp;genre="fantasy"&nbsp;ISBN="2-3631-4"&gt;&nbsp;<BR>&lt;title&gt;Oberon's&nbsp;Legacy&lt;/title&gt;&nbsp;<BR>&lt;author&gt;Corets,&nbsp;Eva&lt;/author&gt;&nbsp;<BR>&lt;price&gt;5.95&lt;/price&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;book&nbsp;genre="update李赞红"&nbsp;ISBN="2-3631-4"&gt;&nbsp;<BR>&lt;title&gt;CS从入门到精通&lt;/title&gt;&nbsp;<BR>&lt;author&gt;亚胜&lt;/author&gt;&nbsp;<BR>&lt;price&gt;58.3&lt;/price&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;/bookstore&gt;&nbsp;</P>
<P>3、删除&nbsp;&lt;book&nbsp;genre="fantasy"&nbsp;ISBN="2-3631-4"&gt;节点的genre属性，删除&nbsp;&lt;book&nbsp;genre="update李赞红"&nbsp;ISBN="2-3631-4"&gt;节点。&nbsp;<BR>XmlNodeList&nbsp;xnl=xmlDoc.SelectSingleNode("bookstore").ChildNodes;&nbsp;</P>
<P>foreach(XmlNode&nbsp;xn&nbsp;in&nbsp;xnl)&nbsp;<BR>{&nbsp;<BR>XmlElement&nbsp;xe=(XmlElement)xn;&nbsp;<BR>if(xe.GetAttribute("genre")=="fantasy")&nbsp;<BR>{&nbsp;<BR>xe.RemoveAttribute("genre");//删除genre属性&nbsp;<BR>}&nbsp;<BR>else&nbsp;if(xe.GetAttribute("genre")=="update李赞红")&nbsp;<BR>{&nbsp;<BR>xe.RemoveAll();//删除该节点的全部内容&nbsp;<BR>}&nbsp;<BR>}&nbsp;<BR>xmlDoc.Save("bookstore.xml");&nbsp;<BR>//===========================================&nbsp;<BR>最后结果为：&nbsp;<BR>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="gb2312"?&gt;&nbsp;<BR>&lt;bookstore&gt;&nbsp;<BR>&lt;book&nbsp;ISBN="2-3631-4"&gt;&nbsp;<BR>&lt;title&gt;Oberon's&nbsp;Legacy&lt;/title&gt;&nbsp;<BR>&lt;author&gt;Corets,&nbsp;Eva&lt;/author&gt;&nbsp;<BR>&lt;price&gt;5.95&lt;/price&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;book&gt;&nbsp;<BR>&lt;/book&gt;&nbsp;<BR>&lt;/bookstore&gt;&nbsp;</P>
<P>4、显示所有数据。&nbsp;<BR>XmlNode&nbsp;xn=xmlDoc.SelectSingleNode("bookstore");&nbsp;</P>
<P>XmlNodeList&nbsp;xnl=xn.ChildNodes;&nbsp;</P>
<P>foreach(XmlNode&nbsp;xnf&nbsp;in&nbsp;xnl)&nbsp;<BR>{&nbsp;<BR>XmlElement&nbsp;xe=(XmlElement)xnf;&nbsp;<BR>Console.WriteLine(xe.GetAttribute("genre"));//显示属性值&nbsp;<BR>Console.WriteLine(xe.GetAttribute("ISBN"));&nbsp;</P>
<P>XmlNodeList&nbsp;xnf1=xe.ChildNodes;&nbsp;<BR>foreach(XmlNode&nbsp;xn2&nbsp;in&nbsp;xnf1)&nbsp;<BR>{&nbsp;<BR>Console.WriteLine(xn2.InnerText);//显示子节点点文本&nbsp;<BR>}&nbsp;<BR>}&nbsp;</P></A>]]></description>
</item><item>
<title><![CDATA[基本知识--价格]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=5391</link>
<author>angle800</author>
<pubDate>2005/4/29 10:12:36</pubDate>
<description><![CDATA[<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">均价是指将各单位的销售价格相加之后的和数除以单位建筑面积的和数，即得出每平方米的均价。均价一般不是销售价，但也有例外，前段时期某高层物业推出的<SPAN lang=EN-US>"</SPAN>不计楼层、朝向，以<SPAN lang=EN-US>2800</SPAN>元／平方米统一价销售<SPAN lang=EN-US>"</SPAN>，即以均价作销售价，也不失为引人瞩目的营销策略。</SPAN></SPAN></P>
<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">基价也叫基础价，是指经过核算而确定的每平方米商品房基本价格。商品房的销售价一般以基价为基数增减楼层，朝向差价后而得出。</SPAN></SPAN></SPAN></P>
<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">起价也叫起步价，是指某物业各楼层销售价格中的最低价格，即是起价。多层住宅，不带花园的，一般以一楼或顶楼的销售价为起价；带花园的住宅，一般以二楼或五楼做为销售的起价。高层物业，以最低层的销售价为起步价。房产广告中常表<SPAN lang=EN-US>?quot;</SPAN>×××元／平方米起售<SPAN lang=EN-US>"</SPAN>，以较低的起价来引起消费者的注意</SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">预售价也是商品房预（销）售合同中的专用术语；预售价不是正式价格，在商品房交付使用时，应按有批准权限部问核定的价格为准。</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">一次性买断价是指买方与卖方商定的一次性定价。一次性买断价属房产销售合同中的专用价格术语，确定之后，买方或卖方必须按此履行付款或交房的义务，不得随意变更。</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed11><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">定金是指当事人约定由一方向对方给付的，作为债权担保的一定数额的货币，它属于一种法律上的担保方式，目的在于促使债务人履行债务，保障债权人的债权得以实现。根据我国发法通则和《担保法》八十九条规定，定金应当以书面形式约定，当事人在定金合同中应约定交付定金的期限。定金合同从实际交付定金之日起生效，定金的数额由当事人约定，但不得超出合同标的额的<SPAN lang=EN-US>20%</SPAN>。如果购房者交了定金之后改变主意决定不买，开发商有权以购房者违约为由不退定金；如果开发商将房屋卖给他人，应当向购房者双倍返还定金。</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed2><SPAN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed11><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><SPAN class=unnamed11><SPAN style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">违约金是指违约方按照法律规定和合同的约定，应该付给对方的一定数量的货币。违约金是对违约方的一种经济制裁，具有惩罚性和补偿性，但主要体现惩罚性。只要当事人有违约行为且在主观上有过错，无论是否给对方造成损失，都要支付违约金。</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>]]></description>
</item><item>
<title><![CDATA[javascript函数集合[转]]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3558</link>
<author>angle800</author>
<pubDate>2005/3/12 11:07:39</pubDate>
<description><![CDATA[-------------- 函数检索 --------------<BR>trim函数:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trim() lTrim() rTrim()<BR>校验字符串是否为空:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIsNotEmpty(str)<BR>校验字符串是否为整型:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIsInteger(str)<BR>校验整型最小值:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIntegerMinValue(str,val)<BR>校验整型最大值:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIntegerMaxValue(str,val) <BR>校验整型是否为非负数:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isNotNegativeInteger(str)<BR>校验字符串是否为浮点型:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIsDouble(str) <BR>校验浮点型最小值:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkDoubleMinValue(str,val)<BR>校验浮点型最大值:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkDoubleMaxValue(str,val)<BR>校验浮点型是否为非负数:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isNotNegativeDouble(str)<BR>校验字符串是否为日期型:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIsValidDate(str)<BR>校验两个日期的先后:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkDateEarlier(strStart,strEnd)<BR>校验字符串是否为email型:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkEmail(str)<BR><BR>校验字符串是否为中文:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; checkIsChinese(str)<BR>计算字符串的长度，一个汉字两个字符:&nbsp;&nbsp; realLength()<BR>校验字符串是否符合自定义正则表达式:&nbsp;&nbsp; checkMask(str,pat)<BR>得到文件的后缀名:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getFilePostfix(oFile)&nbsp; <BR>-------------- 函数检索 --------------<BR>*/<BR><BR>/**<BR>* added by LxcJie 2004.6.25<BR>* 去除多余空格函数<BR>* trim:去除两边空格 lTrim:去除左空格 rTrim: 去除右空格<BR>* 用法：<BR>*&nbsp;&nbsp;&nbsp;&nbsp; var str = "&nbsp; hello ";<BR>*&nbsp;&nbsp;&nbsp;&nbsp; str = str.trim();<BR>*/<BR>String.prototype.trim = function()<BR>{<BR>&nbsp;&nbsp;&nbsp; return this.replace(/(^[\s]*)|([\s]*$)/g, "");<BR>}<BR>String.prototype.lTrim = function()<BR>{<BR>&nbsp;&nbsp;&nbsp; return this.replace(/(^[\s]*)/g, "");<BR>}<BR>String.prototype.rTrim = function()<BR>{<BR>&nbsp;&nbsp;&nbsp; return this.replace(/([\s]*$)/g, "");<BR>}<BR>/********************************** Empty **************************************/<BR>/**<BR>*校验字符串是否为空<BR>*返回值：<BR>*如果不为空，定义校验通过，返回true<BR>*如果为空，校验不通过，返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入域不能为空！<BR>*/<BR>function checkIsNotEmpty(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; if(str.trim() == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>}//~~~<BR>/*--------------------------------- Empty --------------------------------------*/<BR>/********************************** Integer *************************************/<BR>/**<BR>*校验字符串是否为整型<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串全部为数字，校验通过，返回true<BR>*如果校验不通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入域必须为数字！<BR>*/<BR>function checkIsInteger(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(/^(\-?)(\d+)$/.test(str))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>*校验整型最小值<BR>*str：要校验的串。&nbsp; val：比较的值<BR>*<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果满足条件，大于等于给定值，校验通过，返回true<BR>*如果小于给定值，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入域不能小于给定值！<BR>*/<BR>function checkIntegerMinValue(str,val)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(typeof(val) != "string")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val = val + "";<BR>&nbsp;&nbsp;&nbsp; if(checkIsInteger(str) == true)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(parseInt(str,10)&gt;=parseInt(val,10))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>*校验整型最大值<BR>*str：要校验的串。&nbsp; val：比较的值<BR>*<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果满足条件，小于等于给定值，校验通过，返回true<BR>*如果大于给定值，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入值不能大于给定值！<BR>*/<BR>function checkIntegerMaxValue(str,val)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(typeof(val) != "string")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val = val + "";<BR>&nbsp;&nbsp;&nbsp; if(checkIsInteger(str) == true)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(parseInt(str,10)&lt;=parseInt(val,10))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>*校验整型是否为非负数<BR>*str：要校验的串。<BR>*<BR>*返回值：<BR>*如果为空，定义校验通过，返回true<BR>*如果非负数，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果是负数，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入值不能是负数！<BR>*/<BR>function isNotNegativeInteger(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(checkIsInteger(str) == true)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(parseInt(str,10) &lt; 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/*--------------------------------- Integer --------------------------------------*/<BR>/********************************** Double ****************************************/<BR>/**<BR>*校验字符串是否为浮点型<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串为浮点型，校验通过，&nbsp; 返回true<BR>*如果校验不通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入域不是合法的浮点数！<BR>*/<BR>function checkIsDouble(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; //如果是整数，则校验整数的有效性<BR>&nbsp;&nbsp;&nbsp; if(str.indexOf(".") == -1)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(checkIsInteger(str) == true)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(/^(\-?)(\d+)(.{1})(\d+)$/g.test(str))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; }<BR>}//~~~<BR>/**<BR>*校验浮点型最小值<BR>*str：要校验的串。&nbsp; val：比较的值<BR>*<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果满足条件，大于等于给定值，校验通过，返回true<BR>*如果小于给定值，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入域不能小于给定值！<BR>*/<BR>function checkDoubleMinValue(str,val)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(typeof(val) != "string")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val = val + "";<BR>&nbsp;&nbsp;&nbsp; if(checkIsDouble(str) == true)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(parseFloat(str)&gt;=parseFloat(val))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>*校验浮点型最大值<BR>*str：要校验的串。&nbsp; val：比较的值<BR>*<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果满足条件，小于等于给定值，校验通过，返回true<BR>*如果大于给定值，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入值不能大于给定值！<BR>*/<BR>function checkDoubleMaxValue(str,val)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(typeof(val) != "string")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val = val + "";<BR>&nbsp;&nbsp;&nbsp; if(checkIsDouble(str) == true)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(parseFloat(str)&lt;=parseFloat(val))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>*校验浮点型是否为非负数<BR>*str：要校验的串。<BR>*<BR>*返回值：<BR>*如果为空，定义校验通过，返回true<BR>*如果非负数，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果是负数，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参考提示信息：输入值不能是负数！<BR>*/<BR>function isNotNegativeDouble(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if(checkIsDouble(str) == true)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(parseFloat(str) &lt; 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/*--------------------------------- Double ---------------------------------------*/<BR>/********************************** date ******************************************/<BR>/**<BR>*校验字符串是否为日期型<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串为日期型，校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果日期不合法，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp; 参考提示信息：输入域的时间不合法！（yyyy-MM-dd）<BR>*/<BR>function checkIsValidDate(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; var pattern = /^((\d{4})|(\d{2}))-(\d{1,2})-(\d{1,2})$/g;<BR>&nbsp;&nbsp;&nbsp; if(!pattern.test(str))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; var arrDate = str.split("-");<BR>&nbsp;&nbsp;&nbsp; if(parseInt(arrDate[0],10) &lt; 100)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arrDate[0] = 2000 + parseInt(arrDate[0],10) + "";<BR>&nbsp;&nbsp;&nbsp; var date =&nbsp; new Date(arrDate[0],(parseInt(arrDate[1],10) -1)+"",arrDate[2]);<BR>&nbsp;&nbsp;&nbsp; if(date.getYear() == arrDate[0]<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; date.getMonth() == (parseInt(arrDate[1],10) -1)+""<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; date.getDate() == arrDate[2])<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>*校验两个日期的先后<BR>*返回值：<BR>*如果其中有一个日期为空，校验通过,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果起始日期早于等于终止日期，校验通过，&nbsp;&nbsp; 返回true<BR>*如果起始日期晚于终止日期，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp; 参考提示信息： 起始日期不能晚于结束日期。<BR>*/<BR>function checkDateEarlier(strStart,strEnd)<BR>{<BR>&nbsp;&nbsp;&nbsp; if(checkIsValidDate(strStart) == false || checkIsValidDate(strEnd) == false)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; //如果有一个输入为空，则通过检验<BR>&nbsp;&nbsp;&nbsp; if (( strStart == "" ) || ( strEnd == "" ))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; var arr1 = strStart.split("-");<BR>&nbsp;&nbsp;&nbsp; var arr2 = strEnd.split("-");<BR>&nbsp;&nbsp;&nbsp; var date1 = new Date(arr1[0],parseInt(arr1[1].replace(/^0/,""),10) - 1,arr1[2]);<BR>&nbsp;&nbsp;&nbsp; var date2 = new Date(arr2[0],parseInt(arr2[1].replace(/^0/,""),10) - 1,arr2[2]);<BR>&nbsp;&nbsp;&nbsp; if(arr1[1].length == 1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arr1[1] = "0" + arr1[1];<BR>&nbsp;&nbsp;&nbsp; if(arr1[2].length == 1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arr1[2] = "0" + arr1[2];<BR>&nbsp;&nbsp;&nbsp; if(arr2[1].length == 1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arr2[1] = "0" + arr2[1];<BR>&nbsp;&nbsp;&nbsp; if(arr2[2].length == 1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arr2[2]="0" + arr2[2];<BR>&nbsp;&nbsp;&nbsp; var d1 = arr1[0] + arr1[1] + arr1[2];<BR>&nbsp;&nbsp;&nbsp; var d2 = arr2[0] + arr2[1] + arr2[2];<BR>&nbsp;&nbsp;&nbsp; if(parseInt(d1,10) &gt; parseInt(d2,10))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>}//~~~<BR>/*--------------------------------- date -----------------------------------------*/<BR>/********************************** email *****************************************/<BR>/**<BR>*校验字符串是否为email型<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串为email型，校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果email不合法，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp; 参考提示信息：Email的格式不正確！<BR>*/<BR>function checkEmail(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果为空，则通过校验<BR>&nbsp;&nbsp;&nbsp; if(str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; if (str.charAt(0) == "." || str.charAt(0) == "@" || str.indexOf('@', 0) == -1<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; || str.indexOf('.', 0) == -1 || str.lastIndexOf("@") == str.length-1 || str.lastIndexOf(".") == str.length-1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>}//~~~<BR>/*--------------------------------- email ----------------------------------------*/<BR>/********************************** chinese ***************************************/<BR>/**<BR>*校验字符串是否为中文<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串为中文，校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串为非中文，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp; 参考提示信息：必须为中文！<BR>*/<BR>function checkIsChinese(str)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果值为空，通过校验<BR>&nbsp;&nbsp;&nbsp; if (str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; var pattern = /^([\u4E00-\u9FA5]|[\uFE30-\uFFA0])*$/gi;<BR>&nbsp;&nbsp;&nbsp; if (pattern.test(str))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/**<BR>* 计算字符串的长度，一个汉字两个字符<BR>*/<BR>String.prototype.realLength = function()<BR>{<BR>&nbsp; return this.replace(/[^\x00-\xff]/g,"**").length;<BR>}<BR>/*--------------------------------- chinese --------------------------------------*/<BR>/********************************** mask ***************************************/<BR>/**<BR>*校验字符串是否符合自定义正则表达式<BR>*str 要校验的字串&nbsp; pat 自定义的正则表达式<BR>*返回值：<BR>*如果为空，定义校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串符合，校验通过，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回true<BR>*如果字串不符合，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回false&nbsp;&nbsp;&nbsp; 参考提示信息：必须满足***模式<BR>*/<BR>function checkMask(str,pat)<BR>{<BR>&nbsp;&nbsp;&nbsp; //如果值为空，通过校验<BR>&nbsp;&nbsp;&nbsp; if (str == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; var pattern = new RegExp(pat,"gi")<BR>&nbsp;&nbsp;&nbsp; if (pattern.test(str))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<BR>}//~~~<BR>/*--------------------------------- mask --------------------------------------*/<BR>/********************************** file ***************************************/<BR>/**<BR>* added by LxcJie 2004.6.25<BR>* 得到文件的后缀名<BR>* oFile为file控件对象<BR>*/<BR>function getFilePostfix(oFile)<BR>{<BR>&nbsp;&nbsp;&nbsp; if(oFile == null)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp; var pattern = /(.*)\.(.*)$/gi;<BR>&nbsp;&nbsp;&nbsp; if(typeof(oFile) == "object")<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(oFile.value == null || oFile.value == "")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var arr = pattern.exec(oFile.value);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return RegExp.$2;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else if(typeof(oFile) == "string")<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var arr = pattern.exec(oFile);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return RegExp.$2;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>}//~~~<BR>/*--------------------------------- file --------------------------------------*/<BR>
<DIV class=postText>window.close关闭窗口，如何可以不弹出系统提示，直接关闭<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;private void btnClose_Click(object sender, System.EventArgs e)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("&lt;script language=javascript&gt;window.opener=null;window.close() ;&lt;/script&gt;");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>如果是通过子窗体关闭父窗体时怎么做呢, 子窗体（弹出窗体）：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Write("&lt;script&gt;window.opener.top.opener=null;window.opener.top.close()&lt;/script&gt;")</DIV>]]></description>
</item><item>
<title><![CDATA[关于南北创业的不同之处，很有道理的，也很值得思考]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3556</link>
<author>angle800</author>
<pubDate>2005/3/12 10:44:18</pubDate>
<description><![CDATA[<P>有人把北方人和南方人的创业形式作了比较，从中发现一个规律：北方人创业以经商开店居多，一说下海，十有八九在经商开店上动脑筋，寻思着如何开个商店或租个门脸做买卖，开个小饭店甚至摆个小摊卖冰棍、烤羊肉串等，就连北京娱乐界的明星们也都竞相下海开饭馆，试图以大腕的派头招徕追星族食客；却很少有人像南方人那样办家庭作坊或合资工厂，从事制造业。 </P>
<P>&nbsp;&nbsp;&nbsp; 在南方，譬如广东顺德、福建晋江、浙江温州、江苏无锡等地，家庭工厂星罗棋布，民营企业遍地开花，制造业十分红火，小到钮扣、酒瓶盖，大到电冰箱、摩托车，甚至高科技产品都生产，包罗万象，无所不造。现在又建起了现代化的工业园区，形成了大规模制造产业带和产业区，生产的商品规模在全国、甚至全球都名列前茅。 </P>
<P>&nbsp;&nbsp;&nbsp; 单纯地把北方人和南方人的创业形式用办厂和开店作区分，似乎不太公允，南方的工厂也洋溢着关东大汉的豪爽，折射着齐鲁精英的睿智，飘逸着京津名流的风韵，而北方的商铺也闪烁江浙富豪的机敏，显露着粤桂商贾的精明，也张扬闽赣巨头的霸气。 </P>
<P>&nbsp;&nbsp;&nbsp; 我们姑且不去议论北方人和南方人的创业形式之异，单就办厂和开店两者之间在创业之初的区别而言，确确实实有风险之分，有效益之分，有财富之分。 </P>
<P>&nbsp;&nbsp;&nbsp; 风险之分。开店是小本经营，坐地行商，倘若是开个馄饨店，两千元就能开张，不担什么市场风险，即使赔了也不会倾家荡产；办厂则需要巨额投资，少则十多万，多则数百万，要承受巨大的市场风险，有时产品还在设计之中就遭到市场封杀而胎死腹中。 </P>
<P>&nbsp;&nbsp;&nbsp; 效益之分。开店本小利微，只是解决基本生计，即使是卖电脑，一台电脑也只能赚一捆大葱的钱；而开办工厂风险大利润也大，有的当年投资当年见效，立马就发了。2003年，东北一位姓赵的下岗工人集资200万元建造了一座化工厂，专门从菜籽油的油渣中提炼一种化学物质，产品十分抢手，春天盖厂房，秋天就坐桑塔纳，在亲友面前十分风光。 </P>
<P>&nbsp;&nbsp;&nbsp; 财富之分。开店只是在服务和流通的中间环节上赚钱，多一个批发层次就多一道盘剥，再到小店铺就没有什么赚头，不会产生多少社会财富；办厂是在产品的制造工序上赚钱，在产品的使用价值上赚钱，越是科技含量高的越是赚大钱，可创造巨大的社会财富。 </P>
<P>&nbsp;&nbsp;&nbsp; 所以有人说，办工厂比开商店，创业层次高，赚钱又多，要多办工厂少开店。 </P>
<P>&nbsp;&nbsp;&nbsp; 但话又说回来，不管你是南方人还是北方人，无论是办工厂还是开店铺，一定要因人而异，如果你没有较强的风险意识，没有雄厚的资金实力，没有独特的经营理念，别打肿脸充胖子去办工厂，还是先找个合适的地段开个小店铺。待经过一段时间的原始积累，打造了风险意识，开拓了经营理念，练硬了翅膀，再去办工厂赚大钱，进行二次创业。 </P>]]></description>
</item><item>
<title><![CDATA[别人看不到的就是商机]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3555</link>
<author>angle800</author>
<pubDate>2005/3/12 10:43:42</pubDate>
<description><![CDATA[<P>市场最艰难的时刻就是最佳的投资时机，1999年，正是上海房地产经历最萧条沉寂的岁月，正当所有投资商决策犹豫，持币观望的时候，中融集团负责人倪召兴却坚信，这是一个绝佳的投资机遇，决不能错过。 </P>
<P>&nbsp;&nbsp;&nbsp; 大笔一挥，倪召兴一口吞下了陆家嘴3块地，于是就有了中融城市建筑交响乐上海乐章的开头乐章“中融·国际商城”，紧接着华丽篇章“中融·碧玉蓝天”也应声响起。今年4月25日，中融·国际商城正式开张，中融集团也正式在上海设立了总部，10月18日，中融·恒瑞国际大厦结顶，目前正在销售中。“今后的目标是，立足浦东，走向海外”，和其他迁往上海的浙江商人一样，对倪召兴来说，上海也许只是通往国际市场的一个窗口……东部浙商发言人：上海浙商协会成员上海地理位置优越，人才密集、机遇众多，来上海这个大都市历练胆魄，掌握国际市场的游戏技巧是浙江商人的心愿，杉杉集团到上海后，利用这里的人才条件，发展高新技术产业和资本运作都取得了成效，之后不少企业纷纷把总部迁往上海。 </P>
<P>&nbsp;&nbsp;&nbsp; 浙江开发商之所以瞩目上海滩，还离不开浙商整体的特性和文化底蕴———浙江式的儒雅、务实、尊重历史和与时俱进。在上海的浙江开发商大多比较低调，不聒噪，埋头做产品。像南都、绿城、赞成其实都已在上海进行了不少的土地储备，但在他们眼里，产品依然是最好的说话者。 </P>
<P>&nbsp;&nbsp;&nbsp; 如今浙江在上海兴办的企业，从联营合作或租赁摊位开设“窗口”，到创办商贸企业、专业市场，创办私人企业和股份制企业，数目和规模都在进一步扩大。 </P>
<P>&nbsp;&nbsp;&nbsp; 用勤奋开拓出的市场 </P>
<P>&nbsp;&nbsp;&nbsp; 12000只缙云麻鸭、两条狼狗，丽水人周勤富用三辆10吨大卡车带着这些家当，走了四天三夜，在1985年的一天踏上了海南的土地。 </P>
<P>&nbsp;&nbsp;&nbsp; 当时的海南在周勤富眼里和荒岛没有太大区别，“当地居民大多是*种植热带水果过日子。”于是周勤富*着12000只鸭子在海南掘到了第一桶金。 </P>
<P>&nbsp;&nbsp;&nbsp; 周勤富说，在家乡村子里，自己的父母是最勤劳的人，因为勤劳，也是村子里最富的人。显然，浙江人的这种勤劳后来被周勤富带到了海南。1990年，海南的鸭蛋市场几乎近饱和状态时，周勤富用最原始的养鱼方法，*人工撒鱼苗，起早摸黑一点点做大他的“罗非鱼”事业。从1992年起，周勤富的罗非鱼养殖基地以每年100亩、200亩的规模扩大，如今拥有了2000亩的养殖面积。现在海南勤富实业有限公司占据了80％的海南罗非鱼市场，年产值达到6000万元左右。而由他带到海南的浙江老乡达到了2000余人。 </P>
<P>&nbsp;&nbsp;&nbsp; 南部浙商发言人：海南浙江商会会长 </P>
<P>&nbsp;&nbsp;&nbsp; 海南亚洲制药有限公司总经理郑志勇才成立3个多月的海南浙江商会，现在已有150家正式会员企业，按浙江人从小本经营开始创业的一贯传统，在海南创业的浙商远远不止这个数。而这些南下的浙商给当地人第一印象便是勤劳，认真做事。浙商不爱张扬，然而低调的浙商却用务实，好好打造浙江人诚信形象的共识，在海南各行业中都做出了成绩。 </P>
<P>&nbsp;&nbsp;&nbsp; 当年抓住海南大开发机会“走出去”的浙商，现在也正积极回报着自己的家乡，在海南诸如养生堂、海南亚洲制药有限公司等企业将多个基地设回了浙江，至今亚洲制药反哺回浙江的资金已不少于2亿元。从针眼里发现的机遇在一声声吆喝中，丁德松度过了最初来到云南那段摆摊创业的日子。而如今依旧骑着自行车、穿戴不起眼的他，已经占领了云南袜子市场60～70%的份额。 </P>
<P>&nbsp;&nbsp;&nbsp; 摆摊人每天看得最多的是来往行人的脚，但和别的生意人不同，当初丁德松在眼前那窄窄的视野发现了一个被别人忽视的市唱——由于昆明四季如春，那里的人几乎一年四季都穿袜子，“这个市场可不小埃”从此，到云南闯荡的他开始转行卖起了袜子，生意果然红火起来。 </P>
<P>&nbsp;&nbsp;&nbsp; 1984年，积累了些许财富的丁德松在螺蛳湾创办了“袜子世界”。奋斗至今，昆明所有超市卖的几乎都是“袜子世界”的袜子，对于成功，丁德松总是这么一句话：“以质量求发展,以诚信扩市常”转眼，丁德松由初来乍到时的愣头小伙进入了中年，最近他又忙起了云南云县的旧城改造，开始向多元化经营迈进。 </P>
<P>&nbsp;&nbsp;&nbsp; 西部浙商发言人：云南浙商协会会长 </P>
<P>&nbsp;&nbsp;&nbsp; 云南恒信屋业有限公司总经理何永贯 </P>
<P>&nbsp;&nbsp;&nbsp; 丁德松可谓是西进第一代人，而如今，西进的浙商已发展到第三代了。上世纪80年代初，云南本地人对浙江人并无好感，称浙江人卖的是“伪货”，第一代来云南的浙江人几乎都是白手起家。在这样恶劣的环境中，浙商用自己不怕苦、敢闯荡的精神和诚实守信的态度改变了当地人的观点，使他们认同了浙江商人和他们的商品。 </P>
<P>&nbsp;&nbsp;&nbsp; 可能跟云南的地域环境有关，有4000多公里边境线、交通也方便，从事贸易的浙商占了来滇浙商的60%，螺蛳湾市场里70%的经营者是浙江人。无论哪一代浙商，他们的一个显著特点都是容易发现商机，第一代人流传下来的诚信精神也影响着第二代、第三代浙商。 </P>
<P>&nbsp;&nbsp;&nbsp; 以独到的眼光闯进国企 </P>
<P>&nbsp;&nbsp;&nbsp; 从租柜台卖阀门、电器，到如今投资的边贸城已立项投建，在20多年的时间里，黑龙江奔马实业集团有限公司董事长蒋贤云从事过边贸生意、房地产，卖过化工原料，也承接过电力工程……很难想象，一个商人可以在这么多行业里都闯出一番成绩。 </P>
<P>&nbsp;&nbsp;&nbsp; 现在，哈尔滨最繁华的中央大街上，一座哈尔滨妇孺皆知的青灰色优美的哥特式建筑正在整修迎接它的新生，2003年，浙江商人蒋贤云又用他的闯劲，收购了当地百年商业老字号———秋林公司，当时，这一消息如同重磅炸弹般震荡了整个黑龙江。事后蒋贤云坦言，作为一家老字号国有企业，“秋林”经营有些困难，但他更看重秋林作为百年品牌的价值，而且自己也有信心破解“秋林”的经营困局。 </P>
<P>&nbsp;&nbsp;&nbsp; 北部浙商发言人：黑龙江浙商协会娄秘书长上个世纪90年代末，浙江商人来北方，大多做的是贸易生意，把浙江的货物拿到北方卖。辽宁的五爱、海城的西柳、吉林的公主林等都是浙商盘踞的有名的批发市场，之后又在当地建了义乌小商品批发城，温州商城等专业市场，直到今天，从事百货业的浙商还是占到当地浙商60%的比例。 </P>
<P>&nbsp;&nbsp;&nbsp; 经过几年的原始积累，现在浙江商人在东北投资实业的越来越多，投资额也在不断增加，今年光在哈尔滨的投资就达到了12亿元。在蒋贤云参与国企改造后，有不少企业也紧跟着参与国企改制。 </P>
<P>&nbsp;&nbsp;&nbsp; 浙商不仅带动了当地经济的发展，更重要的是在自觉不自觉中，把先进的经营理念、管理经验传授给了当地商人，在东北成了最好的社会主义市场经济的实例教材。 </P>
<P>&nbsp;&nbsp;&nbsp; 造浙江人的奔驰 </P>
<P>&nbsp;&nbsp;&nbsp; 提起浙江民企造汽车，人们首先想到的是有“汽车鲶鱼”之称的吉利。而在前不久的西博会重点展览项目第五届中国杭州国际汽车展览会上，萧山一家民营企业中誉集团远赴湖北武汉生产的中誉商务用车首次在家门口亮相，吸引了众多看客的眼球，最大的卖点就是这里有浙江人造的“奔驰”。 </P>
<P>&nbsp;&nbsp;&nbsp; 这家*照明设备起家的民营企业董事长童江亮一直有着造车梦想。去年初，他听说武汉市政府将对当地一家面临困境的老牌国有企业东风武汉轻型汽车厂实施重组改造。童江亮和武汉当地有关方面经过几轮谈判，终于把这家老牌企业吃了下来，一跃成为投身造车大潮的浙商。 </P>
<P>&nbsp;&nbsp;&nbsp; 2003年5月，武汉中誉汽车公司正式成立，成为该市继神龙、东风本田之后的第3家汽车整车生产企业。而童江亮还有更大的野心———打造国内的顶级汽车。今年年初中誉与德国奔驰汽车公司建立了战略合作伙伴关系，拥有了奔驰旗下Sprinter和NewVito系列车型在亚洲区的商务车改装权，同奔驰公司联手，开发中高档商务用车。童江亮说，中誉汽车这个品牌，能跟奔驰公司合作生产商务房车，主要就是想学习奔驰的造车技术和文化，共享品牌效果。 </P>
<P>&nbsp;&nbsp;&nbsp; 华中浙商发言人：湖北浙江企业联合会会长湖北舜杰房地产开发有限公司董事长任雪涛浙江商人肯吃苦，在外省创业有个很大特点就是渗透性强。目前在湖北，有28万浙江人，创办了2000多家企业，企业盈利面高达90％以上。近年来，随着长三角区域经济向西部辐射，浙江商人把湖北作为向西部发展支点的意识更加强烈。很多温州、台州、绍兴的商人来到湖北，尤其集中在武汉，涉及的领域也很广泛，除了创办各类市场外，在汽车、房产、水电方面都很突出。武汉中誉汽车公司与奔驰携手更是提高了它的知名度，是做得很成功的一家企业。 </P>
<P>&nbsp;&nbsp;&nbsp; 观点 </P>
<P>&nbsp;&nbsp;&nbsp; 他们很善于把握机会 </P>
<P>&nbsp;&nbsp;&nbsp; 浙江大学管理学院EMBA中心主任吴晓波 </P>
<P>&nbsp;&nbsp;&nbsp; 新浙商的出现是一个必然现象，从企业发展角度及自然演化规律看，浙商都会自觉不自觉地经历优胜劣汰过程。进入新阶段的浙商，从他们身上表现出的与老一辈不同的能力和素质，可以判断出，这些新浙商将改写以往“肯吃苦、勤劳苦干”等以描写静态方面为主的老浙商精神。 </P>
<P>&nbsp;&nbsp;&nbsp; 在面对市场环境改变带来的竞争压力，以及第二代、第三代浙商在继承了大笔家族财产，面对怎么花这个问题时，新浙商利用自己善于学习的典型特点，去寻找新方法新模式，让自己跑在别人前面。抢先一步掌握金融等多种资本工具，在资本运作中获取更大价值。 </P>
<P>&nbsp;&nbsp;&nbsp; 企业发展过程中，所依存的资源在本省得不到支持，也促成了新浙商将眼光向外看，通过大规模运作使得浙商优势在外得到了更大的发展。 </P>
<P>&nbsp;&nbsp;&nbsp; 总而言之，市场变化中会出现很多机会，浙商敏感地抓住了这些机会，但新机会需要新能力和素质去完成，因此新浙商也表现出属于他们的浙江人经济的独特气质。 </P>]]></description>
</item><item>
<title><![CDATA[35岁前必须做好的十件事情]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3554</link>
<author>angle800</author>
<pubDate>2005/3/12 10:43:09</pubDate>
<description><![CDATA[35岁是青春的后期， <BR>　　35岁以后是收获的季节， <BR>　　如果你没有资格说这句话，你将会憎恨自己。 <BR>　　所以在35岁以前， <BR>　　在烂漫蓬勃的青春年华里， <BR>　　你最好把下面十件事做好！ <BR>　　 <BR>　　第一，学会本行业所需要的一切知识并有所发展。已故零件大王布鲁丹在他35岁时，已经成为零件行业的领袖，并且组建了年收入达千万美元的海湾与西部工业公司。每个人在年轻时都可能有过彻夜不眠、刻苦攻读，这在20岁甚或30岁都没有问题，但到了35岁，就不应该再为学习基本技能而大伤脑筋了。35岁之前是一个人从事原始积累的阶段，35岁之后就应该勃发了。 <BR>　　 <BR>　　第二，养成个人风格。在35岁以前，找出你所喜欢的，不论是衣着或是爱好，哪怕是与众不同的小习惯也好。20岁、30岁时你可以不断尝试、不断改变，但是到了35岁，你便要明确地建立个人风格。一位男士或女士在事业中途改变自己的形象，就会让人觉得很不可靠。你喜欢穿西装吗？好！就把西装当作你的商标吧！办公桌上摆些鲜花会令你工作更有效率吗？那就每天都摆些鲜花吧！ <BR>　　 <BR>　　第三，在感情生活方面平和安定。在攀登事业的高峰时，如果私人生活不愉快，陷入感情危机，对你会产生很大的干扰，甚至会逐渐令你对别的事物失去兴趣。那些在35岁之前私人生活已经平和安定的人，一般都比生活动荡不安的人有更大的机会获得成功。因此，如果你想结束一段没有结果的恋情，或者你想和女友结婚，那就赶快行动吧，免得把问题拖到生命的第35个春秋。在35岁以后，你应该专注地看着你对事业的投资开始获利。 <BR>　　 <BR>　　第四，明白自己的短处。承认有些事情你的确做不好，或者不愿做。如果你讨厌数字而喜欢创作，那就不要因为待遇高或顺从别人的期望而强迫自己做数字工作。在 35岁之前，一定要投入你所喜爱、所擅长的那种工作。否则，35岁之后必然会有一段郁郁不乐的日子。而且，真正的成功可能因为活力的消退而丧失。 <BR>　　 <BR>　　第五，知道自己的长处。你应该知道自己擅长什么，并且清楚你所喜欢做而又做得比别人好的事情。不管你目前担任什么样的角色，知道自己的长处对成功都很重要。 <BR>　　 <BR>　　第六，储备辞职另谋生路的钱。在这个多变的职业世界里，你也许不会永远在一个地方工作，或者永远在一个位置上淋漓尽致地发挥自己，当你感到无法施展时，你很可能会想到辞职，或者开辟第二职业，如果你事先储蓄了足够的钱，你便有了一个安全的后盾。 <BR>　　 <BR>　　第七，建立人际关系网。如果到了35岁你仍未建立起牢固的人际关系网，那你就有麻烦了。这个人际关系网包括你的朋友、亲人，最低限度包括所有可以互相帮助的人。这些人有的是你的同事，有的受过你的恩惠，有的你倾听过他们的问题，有的你和他有着相同的爱好。人际关系网不是一朝一夕就能建立起来的，它需要几年甚至十几年的培养。一个人在事业上、生活上的成功其实如同一个政党的成功，你要有许多人散布在适当的地方，你可以依赖他们，他们也可以依赖你。 <BR>　　 <BR>　　第八，学会授权他人。许多人不肯或不能这样做，因此始终被钉在从属的职位上。授权他人是成功的一半，一个事无巨细，不能将工作授权别人的人，注定会遇到极大的障碍。到了35岁，你最好已成为这方面的专家。换言之，你懂得挑选合适的人并信任他们。 <BR>　　 <BR>　　第九，学会在什么时候三缄其口。因说话不小心而自毁前程的人，比因为任何其他原因丧失成功的人都多。要学会保持沉默而且看起来机智--别人自然以为你知道的比实际还多。别讲别人的闲话，别谈论你自己的大计，守口如瓶所赢得的声誉，远比讲人闲话所带来的东西更加珍贵。你在事业上越成功，这一点就越重要。 <BR>　　 <BR>　　第十，对人要忠诚。如果你到了35岁仍未能建立起坚如磐石的忠诚信誉，这一缺点将会困扰你一生。不忠诚的恶名必然会使你在事业上到处不受欢迎。你不能靠暗箭伤人爬到事业的顶峰，而要靠在早期树立起来的真诚刚直和不可动摇的声誉。35岁以前，忠诚只是投资；35岁以后，你会作为一个可以信赖的人收到忠诚的回报。 <BR>　　 <BR>　　不要因为我收藏这篇文章就认为我接近那个年龄了^_*]]></description>
</item><item>
<title><![CDATA[想要创业者须知 企业注册商标6大步]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3552</link>
<author>angle800</author>
<pubDate>2005/3/12 10:42:44</pubDate>
<description><![CDATA[<P>注册商标大致分为六个步骤，准备的资料不繁杂，费用也才1000元，但耗时却要1年，所以需要您准备的是耐心。 </P>
<P>&nbsp;&nbsp;&nbsp; 注册准备 </P>
<P>&nbsp;&nbsp;&nbsp; 选择注册方式 </P>
<P>&nbsp;&nbsp;&nbsp; 一种是自己到所在地政府工商行政管理局商标局申请注册；另一种是委托一家经验丰富的商标代理组织代理服务。 </P>
<P>&nbsp;&nbsp;&nbsp; 注：如果您没有注册商标的经验，本身又不懂相关的法律法规，那么劝您还是委托代理机构帮忙，这样会节省您大量的时间和精力。笔者以前就曾委托过类似机构帮我注册，委托费才1000元，可先预付30％。 </P>
<P>&nbsp;&nbsp;&nbsp; 查询 </P>
<P>&nbsp;&nbsp;&nbsp; 在注册前，最好先找一家比较权威的查询公司，因为你的商标有可能和其他注册人的相同或相近，所以注册前的查询可以大大减少商标注册的风险，提高商标注册的把握性。 </P>
<P>&nbsp;&nbsp;&nbsp; 注：因为负责商标查询和审查工作由不同人员承担，他们在审查观点上可能出现不同的意见，所以，商标查询的结果不能当作最后的法律依据。 </P>
<P>&nbsp;&nbsp;&nbsp; 准备资料 </P>
<P>&nbsp;&nbsp;&nbsp; 准备商标图样10张（指定颜色的彩色商标，应交着色图样10张，黑白墨稿1张），长和宽不大于10厘米，不小于5厘米，商标图样方向不清的，应用箭头标明上下方；如果是个人提出申请，需出示身份证并递交复印件；若是企业申请，则出示企业《营业执照》副本并递交复印件；盖有单位公章及个人签字的填写完整的商标注册申请书。 </P>
<P>&nbsp;&nbsp;&nbsp; 开始申请 </P>
<P>&nbsp;&nbsp;&nbsp; 申请人的身份 </P>
<P>&nbsp;&nbsp;&nbsp; 商标注册申请人必须是依法成立的企事业单位、社会团体、个体工商户、个人合伙、与中国签订协议或与中国共同参加国际条约或按对等原则办理的国家的外国人、外国企业。 </P>
<P>&nbsp;&nbsp;&nbsp; 注：如果能取得海外投资商的身份，注册手续可就简单多了。 </P>
<P>&nbsp;&nbsp;&nbsp; 按商品与服务分类提出申请 </P>
<P>&nbsp;&nbsp;&nbsp; 目前，商品和服务项目共分为42类，其中商品34类，服务项目8类。申请注册时，应按商品与服务分类表的分类确定使用商标的商品或服务类别；同一申请人在不同类别的商品上使用同一商标的，应按不同类别提出注册申请。 </P>
<P>&nbsp;&nbsp;&nbsp; 申请日的确定 </P>
<P>&nbsp;&nbsp;&nbsp; 这是最重要的一点：由于我国商标注册采用申请在先原则，一旦您和其他企业发生商标权的纠纷，申请日在先的企业将受法律保护。所以，确立申请日十分重要，申请日以商标局收到申请书的日期为准。 </P>
<P>&nbsp;&nbsp;&nbsp; 接下来就是商标审查、初审公告、注册公告三个程序。需要强调的是，经过商标局初审通过的商标，要在刊登公告三个月后误认提出异议才可以注册完成，该商标即受法律保护。已注册商标的有效期为十年，自核准注册之日起计算。有效期满，需要继续使用的，可以申请商标续展注册。 </P>
<P>&nbsp;&nbsp;&nbsp; 领取商标注册证 </P>
<P>&nbsp;&nbsp;&nbsp; 商标完成注册后，商标局向注册人颁发证书。 </P>
<P>&nbsp;&nbsp;&nbsp; 若是通过代理组织的由代理人向注册人发送《商标注册证》；直接办理注册的，注册人应在接到《领取商标注册证通知书》后三个月内到商标局领证，同时还应携带：领取商标注册证的介绍信、领证人身份证及复印件、营业执照副本原件和加盖当地工商部门的章戳的复印件、领取商标注册证通知书、商标注册人名义变更的需附送工商部门出具的变更证明。 </P>
<P>&nbsp;&nbsp;&nbsp; 注：一件新申请商标从申请到发证一般需要一年到一年半左右时间，其中申请受理和形式审查约需一个月，实质审查约需四到五个月，异议期三个月，核准公告到发证约三个月。 </P>]]></description>
</item><item>
<title><![CDATA[人脉对职业生涯最重要]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3551</link>
<author>angle800</author>
<pubDate>2005/3/12 10:42:06</pubDate>
<description><![CDATA[<P>很多人没有特别背景，自身能力也一般，过着看老板脸色的日子，有时不免做做梦，盼望一朝得到贵人提携，从此飞黄腾达。其实只要你留意建立好人脉关系，你会发现，生活中从来不缺贵人，他们可能就是你的朋友、同事，甚至是萍水相逢的人。在前程无忧近日所做的一次“职场处处皆贵人”的调查中显示，良好的人脉关系对职业生涯发展影响甚深。 </P>
<P><BR>　　17.35%的人认为人脉对职业生涯最重要 </P>
<P>　　有人讲30岁以前靠专业赚钱，30岁以后靠人脉赚钱，可见人脉的重要。在关于哪类因素对职业生涯影响最大的调查问题中，“个人能力”被公认为第一要素；其次是“机遇”，有30.77%的受访者认为“机遇”起决定性作用；人脉关系的因素被排在第三位，有17.35%的受访者感受到人脉的重要性。 </P>
<P>　　调查发现，男性比女性更关注人脉关系对职场生涯的影响，同时随着工作时间的增加，人们对于人脉在职场中的作用也愈加看重，国企职员对人脉的关注度高于其他企业。 </P>
<P>　　另外，不同学历的人对于“机遇”、“人脉关系”、“个人能力”的重视程度大相径庭——— </P>
<P>　　本科学历者对于三要素的关注度为：28.92%、17.46%、36.89% </P>
<P>　　博士学历者对于三要素的关注度为：18.42%、13.16%、63.16% </P>
<P>　　显然，“个人能力”在博士人群中受到绝对优势的肯定，相对而言，“机遇”和“人脉关系”的作用被弱化了。 </P>
<P><BR>　　四成人没注重与人结缘 </P>
<P>　　调查显示，只有48.36%的人是主动出击建立自己的人脉关系，有34.22%的人是通过朋友介绍增长人脉，只有一小部分人(9.82%)是被动等待别人找上门。外企工作的人主动结识朋友的意识比较强烈，占了50.8%；国企工作者朋友介绍与主动认识的得票率非常接近，分别为40.49%和43.67%。 </P>
<P>　　尽管大多数人认同“人脉关系”的重要性，但仍有45.56%的人仅仅局限于职场中，认为除了8小时工作以外就不必太在意了。另外54.44%人群则表示，寻找贵人与人交往并不能清楚地把界线划分在职场内，只有做个有心人，更多机会展示自己的优势，才更有可能得到贵人的赏识与帮助。 </P>
<P>　　调查发现，男性比女性更注重在职场之外的人缘修行，有61.70%的男性受访者认为职场之外仍是结识贵人的好时机，而持相同观点的女性朋友仅占49.39%。同时受访者中随着工作经验的增长，对职场之外的人际交往也越来越重视。 </P>
<P>　　前程无忧专家认为，人脉的积累是长年累月的，是一种在工作和生活中养成的习惯，并不是一件要刻意定时完成的项目。不管是一条人脉，或是由人脉伸展出去的人脉，都需要长期的付出与关怀，这样才能在看似不经意间逐步建立起自己的人脉网。 </P>
<P>　　65.62%的人乐于“君子之交” </P>
<P>　　调查发现，65.62%的受访者认为，与人交往应保持“君子之交淡如水”的心态，保持朋友间的距离同时尊重个人相对的空间；有14.08%的人是无事不登三宝殿型；有11.16%的人选择了“亲密无间型”；9.13%的人是“心血来潮”型，完全依性格行事。 </P>
<P>　　 专家建议，朋友之间的关系同样需要维护和经营，平时要多与朋友联系，同时适当拜访，这样可以培养感情。交朋友有功利目的，但并不是朋友间的每一次来往都以利益来估价。友谊的培养需要累积，这样的人脉关系不但能持久稳固，而且会更光亮。 </P>
<P>　　近四成人认为良好人脉能增加职业机会 </P>
<P>　　良好的人脉究竟对个人会带来怎样的帮助？本次调查发现，34.57%的人认为人脉能给自己增加职业机会，名列第一。根据人力资源管理协会与《华尔街日报》共同针对人力资源主管与求职者所进行的一项调查显示：95%的人力资源主管或求职者透过人脉关系找到适合的人才或工作，而且61%的人力资源主管及78%的求职者认为，这是最有效的方式。前程无忧也曾经做过“最有效的求职途径”调查，其中“熟人介绍”被列为第二大有效方法。 </P>
<P>　　此外，对于人脉关系的作用，27.8%的人认为有助于业务发展，15.89%的人认为对个人职业指导起重大作用；6.94%的人认为有助于专业技术上的交流与沟通。 </P>
<P>　　在职场的不同阶段，人脉关系的作用也不一样——— </P>
<P>　　毕业生更倾向于人脉对个人职业指导的作用，而随着工作经验的丰富，人们也看到了人脉关系对于工作业务发展以及跳槽晋升等机会的影响； </P>
<P>　　刚毕业的学生在“个人职业导师”这个选项的得票率有21.35%； </P>
<P>　　对于已工作3年的受访者来讲，此选项的得票率下降为16.99%； </P>
<P>　　工作8年的受访者在此选项的认同率只有9.17%。 </P>
<P>　　与此相反，人脉关系对于个人的“职业机会（跳槽、晋升）”作用却是随着年龄的增长而变大。有42.08%的8年工作经验者认为人脉关系对“职业机会（跳槽、晋升）”作用最大，3年工作经验者选择此项的为38.58%，毕业生在此选项的得票率为29.72%。 </P>
<P>　　谁是职场贵人？ </P>
<P>　　谁是职场上的贵人？师长？上司……还是擦肩而过的陌生人？调查结果显示，大部分人(33.61%)认为，周围处处皆贵人。另外，朋友(19.13%)、上司(17.63%)、工作上的合作伙伴(11.95%)。 </P>
<P>　　 </P>
<P>另外，虽然大部分人认同职场处处皆贵人的理念，但大多数男性认为朋友中存在贵人的可能性比较大，而更多的女性朋友则把上司作为潜在的贵人人选。 </P>
<P>　　从地域看，北京人似乎更倾向于在朋友中得到贵人缘，而上海人认为贵人缘的机遇在上司老板更容易找到，南方的深圳、广州一带更把上司、朋友一网打尽，两者的得票率非常接近。 </P>
<P>　　从学历上看，大专本科的受访者认为朋友与上司中的贵人缘几率均等，但硕士和博士学历者却更看重自己与老板的关系，认为老板更有可能在未来对自己的职业发展产生重大影响。 </P>
<P>　　相关链接 人际网好比八爪鱼 </P>
<P>　　有研究表明：你和世界上的任何一个人之间只隔着四个人，不管你和对方身处何处，哪个国家，哪类人种，何种肤色。不用惊奇，你和布什或拉登之间也只有四个人，而且构成这个奇妙六人链中的第二个人，竟是你认识的人，也许是你的父母，也许是你大学同学，更可能是办公室里每天帮你抹桌子做清洁的阿姨……仔细想想，通过做清洁的阿姨的人际网竟可以让你联系到布什，这是不是很奇妙？ </P>
<P>　　人际网好比一个八脚章鱼，每一个八脚章鱼在每一天每一分里都在不停地集合、交错着，只是我们自己常常不自知、不在意，常常和贵人擦身而过！不要只看着人脉中的显贵，太看重显贵而忽视其他更多的普通人。在适当的时机，任何一个普通人都可以扭转乾坤，成为你的大贵人！但也要注意，毫无诚意的点头之交等于零，人脉需长时间的积累和沉淀。 </P>
<P>　　机遇和贵人是在适当时候出现的适当的人、事、物的组合体。我们无法控制这种完美的巧合何时出现，惟一能做的就是通过控制自己的人脉来给自己创造更多的可能。 </P>]]></description>
</item><item>
<title><![CDATA[实战SOHO接单的全过程]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3550</link>
<author>angle800</author>
<pubDate>2005/3/12 10:41:33</pubDate>
<description><![CDATA[<P>前段时间，非常多的网友在问我的同一个问题：如何找客户？如何谈价格？如何进行合作？如何进行业务拓展？我不由的想起用我最近做的一个小项目的一个全过程，来展示这一切是如何进行的，我也希望这可能给大家一点启发： </P>
<P>SOHO日志：用友　ERP　U852的打印程序 </P>
<P>项目时间：2005－1－7至2005－1－15 </P>
<P>项目金额：1000RMB </P>
<P>客户来源：在QQ的一个名叫“软件商务频道”群中认识的朋友，因为问了几个相关的有关U8　ERP中的打印问题，便大家熟悉起来。进一步了解到其为河北某个代理用友U8　ERP的软件公司的销售；大学毕业一年，学习的是企业管理，不懂编程； </P>
<P>客户需求：在用友ERP　U8中根据销售订单、发货单打印类似于银行存折的单据。估计该程序的工作量为5 人/天，按200RMB　人/天计算，项目金额为1000RMB； </P>
<P>项目过程说明：由于客户一开始提的需求只是给了一个报表打印结果的样式，但并没有说明数据来源是从销售订单以及发货单中进行提取的，导致我根据客户、部门、职员、物料信息做了一个信息编辑的窗口，让用户进行类似于订单编辑的功能；还做了相关的报表，直到提交给用户的时候，用户才又提出来需要数据源是从销售订单以及发货单的数据的；程序预期需要进行返工，但因为客户不愿意支付更多的费用，此功能留待下次合作时完成。 </P>
<P>项目中碰到的一些问题以及解决的办法： <BR>1、需求不准确的问题：前面也提到过，虽然是一个很简单的需求，但由于需求不准确，导致软件的功能还是有偏差，但是通过与对方的协商，要不是加钱实现新的需求；要不就是该功能待有新的客户的时候再实现，毕竟“羊毛出在羊身上”嘛； <BR>2、对U8软件的熟悉问题：由于在这之前，虽然做过KINGDEE的软件的数据库数据写入，但是由于并没有接触过U8；而且没有安装盘；没有U8的数据字典，想要进行开发的难度可想而知；还好，这一切都由客户方的技术人员提供了相关的资料以及程序，很快就进入状态； <BR>3、付款安全的问题：由于很多人担心没有预付款就开始写程序，我们的风险太大，的确如此，所以我在软件开始之前，就已经收了30%的定金，在程序做完之后，用了一个软件使用次数以及时间相关的加密，这样我就不担心客户在收到DEMO程序之后就不再付钱了；当然，碰上最坏的情况是：你收不到尾款。幸好，这个客户非常大方，没有出现这样的问题；而且这是一个小项目，不需要什么实施以及维护，这也是我前面有提到过，为什么SOHO只适合做小项目的原因了。 </P>
<P>结果： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、用户按3/4/3分三次进行付款，分别在软件编写之前、软件DEMO提交、软件测试运行正常之后； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、由于该公司自己不具备软件开发能力，所以我们建立了一个长期合作的关系，虽然此次业务的金额非常小，但由于U8软件中需要进行二次开发的功能比较多，故以后进行合作开发的机会非常多； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、通过本次开发，对U8软件有了一个比较深入的了解，而且也通过U8软件的数据字典学习了一些U8数据库设计的理念，为解决我们在软件开发中的一些问题起到了非常好的作用； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、这个程序通过进一步完善，已经与对方建立了长期的合作关系，确定以200元/套的价格卖给对方，这样可以做为一个小型的软件来卖； </P>
<P>思路拓展： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、下一步的思路是将这个软件提供给本地用友分公司，让其使用，以便通过这个软件与本地的用友软件分公司建立长期的合作； <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、由于这个软件本身其实并无多大价值，但是因为这样我认识了一个软件销售人员，这样我就可以通过这个软件销售人员，将我自己具有特色的，与U8软件并不冲突并且最好有互补的软件产品提供给对方，让其为我们做义务软件销售人员； </P>]]></description>
</item><item>
<title><![CDATA[如何让企业网站发挥出应用的功能？]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3549</link>
<author>angle800</author>
<pubDate>2005/3/12 10:40:56</pubDate>
<description><![CDATA[<P><A>　我在给中小企业提供网站服务的三年时间里，看到一个非常普遍的现象：很多企业的网站做是做了，但根本没有发挥出效果，或者起到的作用很小！这种现象是如何造成的呢？搜集、整理、分析其中的原因，至少有以下几点吧： </A></P>
<P>1、网站建成万事大吉！ <BR>现象：企业望站建成以后，企业认为大功告成，等着收获效益；而服务商呢，忙着收款，收款以后完事大吉。 </P>
<P>实质：我们知道，网站本身是没有价值的，只有当它传播出去了，将它融入到企业的经营活动中去了，网站才能发挥出它的价值。这就好比，产品没有交换出去它就没有价值！又好比，花儿开在深山无人识，酒在深巷无人知一样，虽然存在，但如果没有人欣赏，没有人品尝，它们的价值就无从体现。因此，网站建设完了，整个的网站运营工作才迈出了第一步，不把以后的每一步走好，网站运营就收不到应有的效果。 </P>
<P>出现这种现象的原因：为什么会出现这种现象，最主要还是服务提供商的问题。大多数中小型企业的决策者并不能理解或者全面地理解网站在它经营活动中的意义和角色。因此，需要专业的服务提供商告诉他们怎么用。但大多数服务提供商一方面自身员工的水平有限，另外一方面是少一事不如多一事，着眼点往往在于怎样赶快签单赶快收钱，所以对于企业网站的“死活”就睁一只眼睛闭一只眼。 </P>
<P>2、没有充分了解企业状况就开单下药 <BR>现象：服务提供商的做法往往是要么提供几个套餐，套用一些不同的服务的让你选择；要么就是问你要做多少钱的，然后再去搭配内容。很少有专业的人士提出真正符合企业实际需求的解决方案。 </P>
<P>实质：其实我们知道，在软件开发中，在企业网站建设中，需求分析是做好项目的首要条件。需求分析没有做好，就等于不看病或者没有看准病就开药，不但收不到好的效果，还有可能回医死人的。 </P>
<P>出现这种现象的原因：一方面企业的领导人对互联网不是很了解，在心理上就有一种排斥感，或者他们是为做网站而做网站，甚至有老板是抱着好玩的心态或者人家做了我也做一个充充面子，所以很难让他们能够静下心来进行讨论做需求分析，这就是病人的不配合；另外一方面，服务提供商的业务代表们水平也是参差不齐，有些是刚刚毕业的学生，不论是对企业运作情况，就是对自己的专业也不了解，所以很难给出合适的解决方案。这是医生的问题。 </P>
<P>PS：这里把企业比做病人，好象很不妥当，不过我想不出更好的比喻了。所以企业老总们，抱歉了。呵呵 </P>
<P>下面，我想来谈一谈有关于我的一些想法： </P>
<P>&nbsp;&nbsp;&nbsp; 我觉的上面所造成的问题，应该来说，是没有很好的回答以下的一些问题，才导致网站才会有这样的问题的，那么，如果我们在为一个企业开发一个网站的时候，我们应该向企业了解哪些内容，同时需要让企业通过回答我们的问题时明白哪里内容呢？ <BR>&nbsp;&nbsp; 我觉的相关的问题如下： <BR>1、你建网站的目的是什么？&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp; 建网站不是为了过家家，但有些企业老总还真就是不当一回事，有一次，一位企业老板跟我说：“听朋友说，建个网站能顶几个业务员用呢!”，我听了就想，网站竟然比人还要厉害了，总的来说，应该有以下几个目的： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1). 做业务、产品、品牌的广告 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2). 产品、服务的在线销售 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)、公益性服务的网站，如：联合国网站&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4)、 为一种思想、观念、事业做宣传 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5)、提供交友或者是娱乐、视频的服务性网站 <BR>2、你希望是独立域名的呢？还是只在你公司的局域网呢用的呢？或者是申请一个免费的域名以及空间呢？ <BR>3、你主要把这个网站给谁看的呢？工商业的、男的、女的、老的、少的、学生、客户，等等 <BR>4、你的网站想做的有多大？怎么来比喻呢：像SOHO、像易趣？、还只是只说一个网页的像张名片？ <BR>5、你想这个网站有什么样的设计特色？颜色、LOGO、网页的浏览速度、视觉设计的要求如何？登录速度重要还是美观重要？等等，这些都是根据你的需求的优先度进行排名的不是吗？ <BR>6、你的网站做完了，是不是需要推广？如何推广的问题？推广的方案就包括：更新你们公司的名片，打上你的网站地址，搜索引擎注册、付费广告、新闻、邮件、印刷以及其它的办法 <BR>7、网站制作是需要投入的？你的这个网站大概准备多少投放呢？或者按照客户前面的一些想法，可能的大概预算是多少？与客户的预期相差多少？如何平衡这两个点？ <BR>8、有了投入，你当然想这个网站有产出了是吗？那客户的期望产出是什么呢？如：品牌宣传、零售、在线订购、在线业务洽谈、页眉广告等收入。或者这只是一个宣传品牌的网站，那预计的用户点击量是多少呢？ </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 我想，如果很好的回答了上面的问题，我觉的网站以后的思路也就比较清晰了，上面的问题我觉的也可以做为一个网站需求分析的大纲吧。 </P>]]></description>
</item><item>
<title><![CDATA[创业流程]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3548</link>
<author>angle800</author>
<pubDate>2005/3/12 10:40:09</pubDate>
<description><![CDATA[<P>从做程序员到软件工程师，有一个最大的不同是什么呢？就是需要去做需求分析的事情，而需求分析的时候自然而然的就会接触到“流程”了，时下软件业最火爆的名词之一是什么呢？－－“工作流”。从需求分析的一系列过程当中，我们接触到了企业的各个流程，如：生产流程、采购流程、分销流程等。而且我原来所在的一家公司花了100多万RMB从一家咨询公司引进了SSP企业管理体系，管理的是什么呢？管理的就是企业流程，我们进行ERP软件开发、实施的时候，这个就是我们进行工作的一个蓝本，这也可以说是一个企业进行流程再造的过程，而在这个过程结束了之后，我们再接手，在这个基础上进行ERP软件实施，自然而然，这样的一个过程也使得我们的ERP实施水到渠成吧。 <BR>　　回到主题，我原来也有说过，创业也跟做软件一样的，是需要进行“可行性分析”、“需求分析”等一系列的过程的，那么，我们可以来看看，创业的一个流程是什么样的呢？有了这个流程，我们就可以结合我们自身的情况，进行相关的“可行性分析”、“需求分析”、“创业进度计划并实践”的环节了。 <BR>-------------------------------------------------------------------------------- <BR>　　　　　　　　　　　　　　创业流程 </P>
<P>　　1.产生创业灵感。一个新企业的诞生往往是伴随一种灵感或创意而开始的。诺兰.布什内尔在兔岛游艺场工作过，在犹他大学玩过电子游戏机，这使他预见到电子游戏未来巨大的市场潜力，因此他开办了阿塔里公司。美国著名的联邦快递(Federal ExPress)的发起人当时只是脑子里有一个想法，这是个有很大风险却孕育着希望的想法。风险投资专家非常欣赏隔夜传递的想法，因此投入了大量的资金，在经历了连续29个月每月损失1百万美元的痛苦过程后，联邦快递终于宣告成立。 <BR>＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝ <BR>每月损失1百万美元，我想在CSDN上的兄弟没有哪位能受的了吧，如果受的了的话，我估计也不会坐在这里看到我这篇文章了。不过话说回来，创业，有灵感这是最主要的，程序员的灵感是来自于代码、将代码做为商品来的，我们需要付出的更多的可能只是我们的时间而已。 </P>
<P>　　2.建立合作班子。企业的创办者不可能万事皆通，他可能是技术方面的天才，但对管理、财务和销售可能是外行；他也可能是管理方面的专家，但对技术却一窍不通。因此，建立一个由各方面的专家组成的合作班子，对创办风险企业是十分必要的。一个平衡的和有能力的班子，应当包括有管理和技术经验的经理和财务、销售、工程以及软件开发、产品设计等其它领域的专家。为了建立一个精诚合作、具有献身精神的班子，这位创业家必须使其他人相信跟他一起干是有甜头的。当电子游戏公司"活影"1979年开张时，他的主要创业家是来自唱片工业的吉姆.利维。他很快招来另外四个创办人合伙搞，他们是被阿塔里公司解雇的电子游戏设计师。活影公司得到了70万美元的风险资本，搞出了一种影像游艺机，风靡一时，在1981年，其销售额迅速达到6000万美元。利维说，如果他的班子里没有那四个合伙创办人，他很难得到能确保活影公司开张的风险资本。 <BR>＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝ <BR>合伙人，前几天，写了一篇文章，是说做SOHO得像狼一样的，但有许多网友都说，做SOHO的人更多的是独狼，而没有群狼。我想，如果要做独狼的话，解决温饱问题都会成问题的，只能吃一些小动物（小单子），而且风险高，容易被更大更凶猛的动物吃掉。但如果你有一个狼群的话那就不一样了。呵呵，顺便说一句，昨天我在跟一家平面设计公司谈合作事情，就是把我们手里有的平面设计师跟他们合作进行平面设计，而让他们原本打算招全职的平面设计师就不再招人了。希望这个合作能够谈成功，如果能够谈成的话，我们也就多了一个固定的收入来源了。 </P>
<P>　　3.企业初步定型。通过获得现有的关于顾客需要和潜在市场的信息，一班人马着手开发某种新产品。在硅谷，这个阶段的工作通常是在某人的家里或汽车房里完成的。如普卡特和惠利特开发音频振荡器就是在他们公寓后边的车库里开始其创业生涯的，苹果公司的乔布斯和沃兹尼克也是在其汽车库里开始其创业生涯的。当Sequoia的合伙人麦克.莫利茨第一次造访Yahoo工作间时，只见"杨致远和他的同伴坐在狭小的房间里，服务器不停地散发热量，电话应答机每隔一分钟响一下，地板上散放着比萨饼盒，到处乱扔着脏衣服。"在这个阶段，创业者们一般每天工作10-14小时，每周工作6-7天。这期间，创业者往往没有任何报酬，主要靠自己的积蓄过活。风险资本公司很少在这个阶段就向该企业投资（这种最原始的创业资本叫"种子"资金），在这个阶段，支撑创业者奋斗的主要动力是创业者的创业冲动和对未来的美好向往。 <BR>＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝ <BR>有想法，最初的想法还是需要自己去实现的，找风险投资，这是需要的，但是，你的想法还是在你的脑袋里的时候，你找投资的可能性就会更小，毕竟投资人还是愿意看到你已经初步成型了，他可以预见你们的前景的时候，他才会来做这样的投资不是吗？当然，这一个过程是一个艰辛的过程，而且是需要毅力与耐力去支持它的，因为这一段时间可能你们什么回报也看不到。 </P>
<P>　　4.制定企业计划。一份企业计划书，既是开办一个新公司的发展计划，也是风险资本家评估一个新公司的主要依据。一份有吸引力的企业计划书要能使一个创业家认识到潜在的障碍，并制订克服这些障碍的战略对策。在硅谷，有些公司的计划书带有传奇色彩。例如，坦德姆公司在1974年制订的企业计划书中所做的销售额预测，与该公司1982年实现的销售额（2亿多美元）惊人的接近。而罗伯特.诺伊斯起草的INTEL公司计划书，仅用了一页纸。 <BR>＝＝＝＝＝＝＝＝＝＝＝ <BR>企业计划，就算你现在是自己一个人做SOHO，你做了2005年的财务收支计划了吗？你做了你自己的SOHO行动计划了吗？ </P>
<P>　　5.寻找资本支持。大多数创业班子没有足够的资本创办一个新企业，他们必须从外部寻求风险资本的支持。创业家往往通过朋友或业务伙伴把企业计划书送给一家或更多的风险资本公司。如果风险家认为企业计划书有前途，就与这个企业班子举行会谈。同时，风险资本家还通过各种正式或非正式渠道，了解这些创业家以及他们的发明情况。风险资本公司往往是2～5家进行联合投资，在硅谷，风险资本界就象一个乡村俱乐部，如果一项特别有吸引力的投资只由一个风险资本家单干，那会被认为是贪婪自私的行为。 <BR>＝＝＝＝＝＝＝＝＝＝＝＝＝＝ <BR>当你有详细并具有足够吸引力的企业计划书的时候，你就可以找投资了，虽然国内的风险投资感觉还不是很成熟，但是，如果当你的企业走到一定的程度的时候，你就得考虑为企业找个奶瓶了。 </P>
<P>　　6.企业开张。如果创业家的企业计划书（一般是经过某种修正之后）被风险资本家所认可，风险投资家就会向该创业者投资，这时，创业者和风险投资者的"真正"联合就开始了，一个新的企业也就诞生了。之所以说创业者和风险投资家的联合是"真正"的联合，是因为风险资本家不仅是这个新成立公司董事会的成员，而且要参与新企业的经营管理。帕洛阿尔托的财产经营公司经理皮彻.约翰逊说："风险资本家的作用就象牧师，对创业家起了一种心理按摩师的作用。"旧金山的风险投资家比尔.汉布雷克特是37个风险企业董事会的成员，他说："我们不仅把骰子投出去，我们还吹它们，使劲地吹。"</P>
<P>　　当新公司的规模和销售额扩大时，创业家往往要求风险资本家进一步提供资金，以便壮大自己，在竞争中占上风。随着时间的推移，风险减少，常规的资金来源（如银行）就会大举进军高技术公司。这时，风险资本家开始考虑撤退。 <BR>＝＝＝＝＝＝＝＝＝＝＝＝ <BR>呵呵，这可是做成我们成功的第一步了，这绝对算是一个里程碑式的成功；因为你现在就可以摆脱原来那种捉襟见肘的动作方式了，各种资源也相对充足，整个公司的动作开始进入正轨，盈利模块也比较可靠了，这时候你就可考虑企业的进一步发展与进步了，当然，做为你本身，更是从这一系列的过程中从一名技术人员彻底的转变为创业者了。 </P>
<P>　　7.上市。在这家公司开办五、六年后，如果获得成功，风险资本家就会帮助它"走向社会"，办法是将它的股票广为销售。这时，风险资本家往往收起装满了的钱袋回家，到另一个有风险的新创企业去投资。大多数风险资本家都希望在五年内能得到相当于初始投资的10倍收益。当然，这种希望并不总是能够实现的。在新创办的企业中，大约有20-30%会夭折，60-70%会获得一定程度的成功，只有5%的新企业大发其财。 <BR>＝＝＝＝＝＝＝＝＝＝＝ <BR>看一看上面的统计数字吧，我不知道这个统计数据来源是哪里，不知道是在国内还是国外的，20－30%的企业会夭折，呵呵，那说明我们成功的机率还是很高的嘛。既然如此，为什么不去试一试呢？ </P>]]></description>
</item><item>
<title><![CDATA[如何奔向程序员打工的出头之日？]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3547</link>
<author>angle800</author>
<pubDate>2005/3/12 10:38:35</pubDate>
<description><![CDATA[<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <A>现在，谁都在说：打工不是一辈子的事，是永远没有出头之路的！&nbsp;干程序员的更是如此，“吃青春饭的”已经是我们这类人的一个共识。而且我还是一个在非IT专营企业里干程序员的，可以这么说，我在我们企业里只能算是“下人”，是为业务部门服务的，是一个不会创造利润的人，我的利润价值是需要由业务部门来体现的，这也就是说，业务部门就是我们的“爷”，所以，如何能够走出我的打工之路？我觉的这是我在2005年最需要考虑的一件事情了。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在前几天的BLOG中，我写了一篇程序如何做SOHO的，现在，我觉的，如果打工的话，这是一个学习、成长的过程，同时也是一个创业准备的过程。其实，我这个贴子的题目中的这个问号是谁都知道答案的了，如果想不打工的话，最好的办法就是自己当老板。当然，我觉的在这里需要声明的一点是：也不是每个人都适合做老板的，人生的路有很多种：从政、从教、做研究、做专业技术人员、做管理。关于人生的路如何走，我想各人各异，没有一个定论，从我自身的角度来说，从一名教师走到一名程序员，这也是一个人生角度的转变，现在，我将再次考虑一个新的突破，一个新的转变。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我觉的，如果需要创业，这并不是一日可成的事情，这是一个渐进的过程，是一个需要培养能力和创造性的过程。那我们在做程序员的时候，如果考虑到以后需要进行创业，我们现在应该做一些什么呢？应该先考虑一些什么样的问题呢？ <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、寻找一个创业模式。软件开发讲究“模式”，那创业也是有模式的，不是吗？这个模式应该就是你的公司以后的灵魂，只有先有了公司的灵魂，才能慢慢的构造公司的骨架－－组建团队；然后就是填充血肉－－进行业务运作。这个创业模式我觉的可以是一个构想，甚至是一个平时你在工作中碰到的一个灵感，这个灵感可以来自于你的工作、你的学习、你的生活。但是，这一切，要求你要有一颗时刻准备着的心，准备着这个灵感突然在你的脑海里降临。如果你在工作中把你的这个信念放在心底的话，那么你就会发现，机会其实就是在身边的。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、在工作中做到“有所有，有所不为”。不能因为我们有了创业的想法，　就把公司的事情扔到一边，甚至利用自己工作上的便利抢公司的业务，或者是在工作时间做私活。我觉的这是一个做人的原则问题，特别是做为一个未来的创业者，你现在就必须为你自己的信誉进行投资，也许在35岁之前，你维护良好的信誉只是投入而没有产出的；但是当你到了35岁之后，你就能够从你的信誉投资中得到丰厚的回报的，我非常相信这一点。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、学会“夹缝中生存”。当你有了创业的冲动的想法的时候，也许有很多的事情需要你去实现的，不管是做什么，你总是需要在周六、周日来回的跑，为你的客户做分析　、做实施；周一到周五每天工作到12点；每天在你坐车的时候做着你的工作上的计划；每天上班的时候又要换一付脑袋来做你本职工作上的事情，需要有多点思维。当然　，这一切，一开始肯定是很难的，我也承认，我原来就有这样做过，但我做不到，所以我放弃了做SOHO了，　但我现在第二次开始做的时候，我坚持下来了，所以我个人在本职工作上非常出色的完成了各种任务。现在还要应付各种繁重的SOHO工作，但我觉的，我很快乐，因为我很充实。而且我觉的这样的一个工作方式也许是很累，但只有这样，当你真正做老板的时候，你才能够应付的来复杂的业务、往来、开发等事务。这也是你在积累当老板经验的时候，请千万不要放弃！也许你做一段时间，觉的累了，可以，放下一切，休息一段时间吧！休整好了，你可以重新再来。毕竟，你现在还有一份工作可以　做为你避风的港湾。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、确定一个创业的期限。世界在不断的快速变化，市场也是，人也是，所以，要不断的跟踪市场，不断的进行技术与能力更新，给自己确定一个里程碑，一般来说，你要做一个项目或者一个产品，最好不要超过6个月 ，最多是一年，否则到时候市场离你的创意已经很远了。 <BR>　　5、找合适的人做适当的事。团队非常重要，找能够跟你合适的人更是重要，“不求最好，好用就行”！ </A></P>
<P>　　当然，这是一个我们蜕变的过程，这也是一个非常痛苦的过程，寂寞、压力、疲劳会时刻伴随着我们，但如果你明白，我们做为一个打工人，我们在这个时期是没有退路可言的，只有一咱向前，才能看到阳光、蓝天、白云！ <BR>　　祝：大家2005年好运！ </P>]]></description>
</item><item>
<title><![CDATA[创业的成功之路]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3546</link>
<author>angle800</author>
<pubDate>2005/3/12 10:37:32</pubDate>
<description><![CDATA[<P><A>　一个新企业的诞生往往是伴随一种开始的。诺兰·布什内尔在兔岛游艺场工作过，在犹他大学玩过电子游戏机，这使他预见到电子游戏未来巨大的市场潜力，因此他开办了阿塔里公司。 </A></P>
<P>&nbsp;&nbsp;&nbsp; 美国著名的联邦快递(FederalExPress)的发起人当时只是脑子里有一个想法，这是个有很大风险却孕育着希望的想法。风险投资专家非常欣赏隔夜传递的想法，因此投入了大量的资金，在经历了连续29个月每月损失1百万美元的痛苦过程后，联邦快递终于宣告成立。 </P>
<P>&nbsp;&nbsp;&nbsp; 建立合作班子 </P>
<P>&nbsp;&nbsp;&nbsp; 企业的创办者不可能万事皆通，他可能是技术方面的天才，但对管理、财务和销售可能是外行；他也可能是管理方面的专家，但对技术却一窍不通。因此，建立一个由各方面的专家组成的合作班子，对创办风险企业是十分必要的。一个平衡的和有能力的班子，应当包括有管理和技术经验的经理和财务、销售、工程以及软件开发、产品设计等其它领域的专家。为了建立一个精诚合作、具有献身精神的班子，这位创业家必须使其他人相信跟他一起干是有甜头的。当电子游戏公司“活影”1979年开张时，他的主要创业家是来自唱片工业的吉姆·利维。他很快招来另外四个创办人合伙搞，他们是被阿塔里公司解雇的电子游戏设计师。活影公司得到了70万美元的风险资本，搞出了一种影像游艺机，风靡一时，在1981年，其销售额迅速达到6000万美元。利维说，如果他的班子里没有那四个合伙创办人，他很难得到能确保活影公司开张的风险资本。 </P>
<P>&nbsp;&nbsp;&nbsp; 企业初步定型 </P>
<P>&nbsp;&nbsp;&nbsp; 通过获得现有的关于顾客需要和潜在市场的信息，一班人马着手开发某种新产品。在硅谷，这个阶段的工作通常是在某人的家里或汽车房里完成的。如普卡特和惠利特开发音频振荡器就是在他们公寓后边的车库里开始其创业生涯的，苹果公司的乔布斯和沃兹尼克也是在其汽车库里开始其创业生涯的。当Sequoia的合伙人麦克·莫利茨第一次造访Yahoo工作间时，只见“杨致远和他的同伴坐在狭小的房间里，服务器不停地散发热量，电话应答机每隔一分钟响一下，地板上散放着比萨饼盒，到处乱扔着脏衣服。”在这个阶段，创业者们一般每天工作10-14小时，每周工作6-7天。这期间，创业者往往没有任何报酬，主要*自己的积蓄过活。风险资本公司很少在这个阶段就向该企业投资（这种最原始的创业资本叫“种子”资金），在这个阶段，支撑创业者奋斗的主要动力是创业者的创业冲动和对未来的美好向往。 </P>
<P>&nbsp;&nbsp;&nbsp; 制定企业计划 </P>
<P>&nbsp;&nbsp;&nbsp; 一份企业计划书，既是开办一个新公司的发展计划，也是风险资本家评估一个新公司的主要依据。一份有吸引力的企业计划书要能使一个创业家认识到潜在的障碍，并制订克服这些障碍的战略对策。在硅谷，有些公司的计划书带有传奇色彩。例如，坦德姆公司在1974年制订的企业计划书中所做的销售额预测，与该公司1982年实现的销售额（2亿多美元）惊人的接近。而罗伯特.诺伊斯起草的INTEL公司计划书，仅用了一页纸。 </P>
<P>&nbsp;&nbsp;&nbsp; 寻找资本支持 </P>
<P>&nbsp;&nbsp;&nbsp; 大多数创业班子没有足够的资本创办一个新企业，他们必须从外部寻求风险资本的支持。创业家往往通过朋友或业务伙伴把企业计划书送给一家或更多的风险资本公司。如果风险家认为企业计划书有前途，就与这个企业班子举行会谈。同时，风险资本家还通过各种正式或非正式渠道，了解这些创业家以及他们的发明情况。风险资本公司往往是2～5家进行联合投资，在硅谷，风险资本界就像一个乡村俱乐部，如果一项特别有吸引力的投资只由一个风险资本家单干，那会被认为是贪婪自私的行为。 </P>
<P>&nbsp;&nbsp;&nbsp; 企业开张 </P>
<P>&nbsp;&nbsp;&nbsp; 如果创业家的企业计划书（一般是经过某种修正之后）被风险资本家所认可，风险投资家就会向该创业者投资，这时，创业者和风险投资者的“真正”联合就开始了，一个新的企业也就诞生了。之所以说创业者和风险投资家的联合是“真正”的联合，是因为风险资本家不仅是这个新成立公司董事会的成员，而且要参与新企业的经营管理。帕洛阿尔托的财产经营公司经理皮彻·约翰逊说：“风险资本家的作用就像牧师，对创业家起了一种心理按摩师的作用。”旧金山的风险投资家比尔·汉布雷克特是37个风险企业董事会的成员，他说：“我们不仅把骰子投出去，我们还吹它们，使劲地吹。”当新公司的规模和销售额扩大时，创业家往往要求风险资本家进一步提供资金，以便壮大自己，在竞争中占上风。随着时间的推移，风险减少，常规的资金来源（如银行）就会大举进军高技术公司。这时，风险资本家开始考虑撤退。 </P>
<P>&nbsp;&nbsp;&nbsp; 上市 </P>
<P>&nbsp;&nbsp;&nbsp; 在这家公司开办五、六年后，如果获得成功，风险资本家就会帮助它“走向社会”，办法是将它的股票广为销售。这时，风险资本家往往收起装满了的钱袋回家，到另一个有风险的新创企业去投资。大多数风险资本家都希望在五年内能得到相当于初始投资的10倍收益。当然，这种希望并不总是能够实现的。在新创办的企业中，大约有20-30%会夭折，60-70%会获得一定程度的成功，只有5%的新企业大发其财。 </P>]]></description>
</item><item>
<title><![CDATA[创业小常识]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3545</link>
<author>angle800</author>
<pubDate>2005/3/12 10:32:08</pubDate>
<description><![CDATA[<P>问：现在社会鼓励个人创业，我也想利用自己一技之长创业，但听说公司注册资本最低要十万元，我手头一时没那么多现钱，请问有何办法实现自己的创业愿望，法律对出资有什么规定？&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp; 答：以我国现行法律，个人创业的法律途径主要有：申请登记从事个体工商业，设立有限责任公司，设立合伙企业，设立个人独资企业。&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 如果您从事的创业活动主要以您本人或家庭成员的劳动为基础的小商品零售及餐饮、理发、洗烫、花店、报刊零售等社会服务业，建议您申请登记成为个体工商户。个体工商户资金没有法定要求，其经营收入归公民个人或家庭所有。但个体工商户不属于经济组织，不具有法人资格，要对自身债务负无限连带责任；其中，个人经营的，以个人财产偿还，家庭经营的，以家庭财产偿还。&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp; 如果您欲设立有限责任公司，按《公司法》股东人数须二个以上五十个以下，其注册资本不得少于下列最低限额：以生产经营为主或以商品批发为主的公司五十万元，以商业零售为主的公司三十万元，科技开发、咨询、服务性公司十万元，股东可以用货币出资，也可以用实物、工业产权、非专利技术、土地使用权作价出资。对作为出资的实物、工业产权、非专利技术或者土地使用权，必须进行评估作价、核实财产，不得高估或者低估作价。以工业产权（主要是专利、商标）、非专利技术作价出资的金额不得超过公司注册资本的百分之二十，但经国家有关部门认定的高新技术成果可占注册资本的百分之三十五。因此，您如果采用有限责任形式创业，除了其余股东出资及可作为出资的非货币财产，您实际以现金货币作为出资可能大大低于十万元。有限公司股东须在公司名称核准后，公司营业执照颁布前而由法定验资单位对股东出资进行验证。有限责任公司本身以其资产对公司债务承担责任，公司股东以其出资额为限对公司承担责任。创业总有风险，如有可能建议您尽量按《公司法》采用有限责任公司形式进行创业。&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp; 如果您欲设立合伙企业，根据《合伙法》必须有两个以上合伙人。法律对合伙企业的注册资金没有最低限度要求和需要由法定机构强制验资的要求，但要求合伙人应当按照合伙协议约定的出资方式、数额和缴付出资的期限，履行出资义务。合伙人可以以货币、实物、土地使用权、知识产权、其他财产权利及劳务出资。以货币出资的，应在合伙协议中载明或出具全体合伙人认定的书面文件；以实物出资的，应出具实物的所有权或许可用于合伙企业投资的使用证明；以土地使用权出资的，应出具土地使用权证明；以知识产权出资的，应出具知识产权的所有权或使用证明；不能取得所有权和使用权证明的，应当有全体合伙人认定的书面文件；以劳务出资的，应在合伙协议中载明或出具经全体合伙人认定的书面文件。合伙企业与有限责任公司不同，其对企业债务先用合伙企业财产抵偿，在抵偿不足时，由合伙人以其财产承担无限连带责任。合伙企业设立时虽无最低限度出资要求，但由于合伙人对合伙企业债务承担无限连带责任，故风险较大。若您采用合伙形式创业，请谨慎选择合伙对象。&nbsp;&nbsp; </P>
<P>&nbsp;&nbsp;&nbsp; 此外，最近实施的《个人独资企业法》规定一个自然人可以设立个人独资企业。该法亦没有规定投资人出资的最低限度和须法定验资机构验资的规定，只规定须由投资人申报的出资。投资人申报的出资包括投资人的出资额和出资方式，出资额指投资人以货币出资的数额，以及采取实物、土地使用权、知识产权或其他财产权利的作价数额。投资人申报的出资额应当与企业的生产规模相适应。出资方式指投资人一个人财物出资，或者以家庭共有财产作为个人出资。以个人财产作为个人出资的，应当依法以家庭共有财产对企业债务承担无限责任。值得注意的是，个人独资企业解散后，原投资人对个人独资企业存续期间的债务仍应承担偿还责任，但债权人在五年内未向债务人提出偿债请示的，该责任消灭。相对有限公司和合伙企业而言，个人独资企业更能满足资金缺乏、又不愿与人合股或合伙的个人进行创业。如您选择个人独资企业进行创业，则尤需注意在无人帮助监督情况下加强控制企业的各类风险。&nbsp; </P>]]></description>
</item><item>
<title><![CDATA[B/S开发常用JavaScript技术[转载]]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=angle800&amp;id=3544</link>
<author>angle800</author>
<pubDate>2005/3/12 10:29:55</pubDate>
<description><![CDATA[在b/s开发中经常用到的javascript技术 <BR>一、验证类<BR>1、数字验证内<BR>1.1 整数<BR>1.2 大于0的整数 （用于传来的ID的验证)<BR>1.3 负整数的验证<BR>1.4 整数不能大于iMax<BR>1.5 整数不能小于iMin<BR>2、时间类<BR>2.1 短时间，形如 (13:04:06)<BR>2.2 短日期，形如 (2003-12-05)<BR>2.3 长时间，形如 (2003-12-05 13:04:06)<BR>2.4 只有年和月。形如(2003-05,或者2003-5)<BR>2.5 只有小时和分钟,形如(12:03)<BR>3、表单类<BR>3.1 所有的表单的值都不能为空<BR>3.2 多行文本框的值不能为空。<BR>3.3 多行文本框的值不能超过sMaxStrleng<BR>3.4 多行文本框的值不能少于sMixStrleng<BR>3.5 判断单选框是否选择。<BR>3.6 判断复选框是否选择.<BR>3.7 复选框的全选，多选，全不选，反选<BR>3.8 文件上传过程中判断文件类型<BR>4、字符类<BR>4.1 判断字符全部由a-Z或者是A-Z的字字母组成<BR>4.2 判断字符由字母和数字组成。<BR>4.3 判断字符由字母和数字，下划线,点号组成.且开头的只能是下划线和字母<BR>4.4 字符串替换函数.Replace();<BR>5、浏览器类<BR>5.1 判断浏览器的类型<BR>5.2 判断ie的版本<BR>5.3 判断客户端的分辨率<BR><BR>6、结合类<BR>6.1 email的判断。<BR>6.2 手机号码的验证<BR>6.3 身份证的验证<BR><BR><BR>二、功能类<BR><BR>1、时间与相关控件类<BR>1.1 日历<BR>1.2 时间控件<BR>1.3 万年历<BR>1.4 显示动态显示时钟效果（文本，如OA中时间）<BR>1.5 显示动态显示时钟效果 (图像，像手表) <BR>2、表单类<BR>2.1 自动生成表单<BR>2.2 动态添加，修改，删除下拉框中的元素<BR>2.3 可以输入内容的下拉框<BR>2.4 多行文本框中只能输入iMax文字。如果多输入了，自动减少到iMax个文字（多用于短信发送)<BR><BR>3、打印类<BR>3.1 打印控件<BR>4、事件类<BR>4.1 屏蔽右键<BR>4.2 屏蔽所有功能键<BR>4.3 --&gt; 和&lt;-- F5 F11,F9,F1<BR>4.4 屏蔽组合键ctrl+N<BR>5、网页设计类<BR>5.1 连续滚动的文字，图片（注意是连续的，两段文字和图片中没有空白出现）<BR>5.2 html编辑控件类<BR>5.3 颜色选取框控件<BR>5.4 下拉菜单<BR>5.5 两层或多层次的下拉菜单<BR>5.6 仿IE菜单的按钮。（效果如rongshuxa.com的导航栏目)<BR>5.7 状态栏，title栏的动态效果（例子很多，可以研究一下）<BR>5.8 双击后，网页自动滚屏<BR>6、树型结构。<BR>6.1 asp+SQL版<BR>6.2 asp+xml+sql版<BR>6.3 java+sql或者java+sql+xml<BR>7、无边框效果的制作<BR>8、连动下拉框技术<BR>9、文本排序<BR><BR><BR>一、验证类<BR>1、数字验证内<BR>1.1 整数<BR>/^(-|\+)?\d+$/.test(str)<BR>1.2 大于0的整数 （用于传来的ID的验证)<BR>/^\d+$/.test(str)<BR>1.3 负整数的验证<BR>/^-\d+$/.test(str)<BR>2、时间类<BR>2.1 短时间，形如 (13:04:06)<BR>function isTime(str)<BR>{<BR>var a = str.match(/^(\d{1,2})(:)?(\d{1,2})\2(\d{1,2})$/);<BR>if (a == null) {alert('输入的参数不是时间格式'); return false;}<BR>if (a[1]&gt;24 || a[3]&gt;60 || a[4]&gt;60)<BR>{<BR>alert("时间格式不对");<BR>return false<BR>}<BR>return true;<BR>}<BR>2.2 短日期，形如 (2003-12-05)<BR>function strDateTime(str)<BR>{<BR> var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/); <BR> if(r==null)return false; <BR> var d= new Date(r[1], r[3]-1, r[4]); <BR> return (d.getFullYear()==r[1]&amp;&amp;(d.getMonth()+1)==r[3]&amp;&amp;d.getDate()==r[4]);<BR>}<BR>2.3 长时间，形如 (2003-12-05 13:04:06)<BR>function strDateTime(str)<BR>{<BR>var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/; <BR>var r = str.match(reg); <BR>if(r==null)return false; <BR>var d= new Date(r[1], r[3]-1,r[4],r[5],r[6],r[7]); <BR>return (d.getFullYear()==r[1]&amp;&amp;(d.getMonth()+1)==r[3]&amp;&amp;d.getDate()==r[4]&amp;&amp;d.getHours()==r[5]&amp;&amp;d.getMinutes()==r[6]&amp;&amp;d.getSeconds()==r[7]);<BR>}<BR>2.4 只有年和月。形如(2003-05,或者2003-5)<BR>2.5 只有小时和分钟,形如(12:03)<BR>3、表单类<BR>3.1 所有的表单的值都不能为空<BR>&lt;input onblur="if(this.value.replace(/^\s+|\s+$/g,'')=='')alert('不能为空!')"&gt;<BR>3.2 多行文本框的值不能为空。<BR>3.3 多行文本框的值不能超过sMaxStrleng<BR>3.4 多行文本框的值不能少于sMixStrleng<BR>3.5 判断单选框是否选择。<BR>3.6 判断复选框是否选择.<BR>3.7 复选框的全选，多选，全不选，反选<BR>3.8 文件上传过程中判断文件类型<BR>4、字符类<BR>4.1 判断字符全部由a-Z或者是A-Z的字字母组成<BR>&lt;input onblur="if(/[^a-zA-Z]/g.test(this.value))alert('有错')"&gt;<BR>4.2 判断字符由字母和数字组成。<BR>&lt;input onblur="if(/[^0-9a-zA-Z]/g.test(this.value))alert('有错')"&gt;<BR>4.3 判断字符由字母和数字，下划线,点号组成.且开头的只能是下划线和字母<BR>/^([a-zA-z_]{1})([\w]*)$/g.test(str)<BR>4.4 字符串替换函数.Replace();<BR>5、浏览器类<BR>5.1 判断浏览器的类型<BR>window.navigat or.appName<BR>5.2 判断ie的版本<BR>window.navigat or.appVersion<BR>5.3 判断客户端的分辨率<BR>window.screen.height;window.screen.width;<BR><BR>6、结合类<BR>6.1 email的判断。<BR>function ismail(mail)<BR>{<BR>return(new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(mail));<BR>}<BR>6.2 手机号码的验证<BR>6.3 身份证的验证<BR>function isIdCardNo(num)<BR>{<BR>if (isNaN(num)) {alert("输入的不是数字！"); return false;}<BR>var len = num.length, re; <BR>if (len == 15)<BR>re = new RegExp(/^(\d{6})()?(\d{2})(\d{2})(\d{2})(\d{3})$/);<BR>else if (len == 18)<BR>re = new RegExp(/^(\d{6})()?(\d{4})(\d{2})(\d{2})(\d{3})(\d)$/);<BR>else {alert("输入的数字位数不对！"); return false;}<BR>var a = num.match(re);<BR>if (a != null)<BR>{<BR>if (len==15)<BR>{<BR>var D = new Date("19"+a[3]+"/"+a[4]+"/"+a[5]);<BR>var B = D.getYear()==a[3]&amp;&amp;(D.getMonth()+1)==a[4]&amp;&amp;D.getDate()==a[5];<BR>}<BR>else<BR>{<BR>var D = new Date(a[3]+"/"+a[4]+"/"+a[5]);<BR>var B = D.getFullYear()==a[3]&amp;&amp;(D.getMonth()+1)==a[4]&amp;&amp;D.getDate()==a[5];<BR>}<BR>if (!B) {alert("输入的身份证号 "+ a[0] +" 里出生日期不对！"); return false;}<BR>}<BR>return true;<BR>}<BR><BR>3.7 复选框的全选，多选，全不选，反选<BR>&lt;f orm name=hrong&gt;<BR>&lt;input type=checkbox name=All onclick="checkAll('mm')"&gt;全选&lt;br/&gt;<BR>&lt;input type=checkbox name=mm onclick="checkItem('All')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm onclick="checkItem('All')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm onclick="checkItem('All')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm onclick="checkItem('All')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm onclick="checkItem('All')"&gt;&lt;br/&gt;&lt;br/&gt;<BR><BR><BR>&lt;input type=checkbox name=All2 onclick="checkAll('mm2')"&gt;全选&lt;br/&gt;<BR>&lt;input type=checkbox name=mm2 onclick="checkItem('All2')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm2 onclick="checkItem('All2')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm2 onclick="checkItem('All2')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm2 onclick="checkItem('All2')"&gt;&lt;br/&gt;<BR>&lt;input type=checkbox name=mm2 onclick="checkItem('All2')"&gt;&lt;br/&gt;<BR><BR>&lt;/f orm&gt;<BR><BR>&lt;SCRIPT LANGUAGE="java script"&gt;<BR>function checkAll(str)<BR>{<BR>var a = document．getElementsByName(str);<BR>var n = a.length;<BR>f or (var i=0; i&lt;n; i++)<BR>a[i].checked = window.event.srcElement.checked;<BR>}<BR>function checkItem(str)<BR>{<BR>var e = window.event.srcElement;<BR>var all = eval("document．hrong."+ str);<BR>if (e.checked)<BR>{<BR>var a = document．getElementsByName(e.name);<BR>all.checked = true;<BR>f or (var i=0; i&lt;a.length; i++)<BR>{<BR>if (!a[i].checked){ all.checked = false; break;}<BR>}<BR>}<BR>else all.checked = false;<BR>}<BR>&lt;/SCRIPT&gt;<BR><BR>3.8 文件上传过程中判断文件类型<BR>&lt;input type=file onchange="alert(this.value.match(/^(.*)(\.)(.{1,8})$/)[3])"&gt;<BR><BR>画图:<BR>&lt;OBJECT <BR>id=S <BR>style="LEFT: 0px; WIDTH: 392px; TOP: 0px; HEIGHT: 240px" <BR>height=240 <BR>width=392 <BR>classid="clsid:369303C2-D7AC-11D0-89D5-00A0C90833E6"&gt;<BR>&lt;/OBJECT&gt;<BR>&lt;SCRIPT&gt;<BR>S.DrawingSurface.ArcDegrees(0,0,0,30,50,60);<BR>S.DrawingSurface.ArcRadians(30,0,0,30,50,60);<BR>S.DrawingSurface.Line(10,10,100,100);<BR>&lt;/SCRIPT&gt;<BR><BR>写注册表：<BR>&lt;SCRIPT&gt;<BR>var WshShell = WScript.CreateObject("WScript.Shell");<BR>WshShell.RegWrite ("HKCU\\Software\\ACME\\F ortuneTeller\\", 1, "REG_BINARY");<BR>WshShell.RegWrite ("HKCU\\Software\\ACME\\F ortuneTeller\\MindReader", "Goocher!", "REG_SZ");<BR>var bKey =WshShell.RegRead ("HKCU\\Software\\ACME\\F ortuneTeller\\");<BR>WScript.Echo (WshShell.RegRead ("HKCU\\Software\\ACME\\F ortuneTeller\\MindReader"));<BR>WshShell.RegDelete ("HKCU\\Software\\ACME\\F ortuneTeller\\MindReader");<BR>WshShell.RegDelete ("HKCU\\Software\\ACME\\F ortuneTeller\\");<BR>WshShell.RegDelete ("HKCU\\Software\\ACME\\");<BR>&lt;/SCRIPT&gt;<BR><BR>TABLAE相关(客户端动态增加行列）<BR>&lt;HTML&gt;<BR>&lt;SCRIPT LANGUAGE="JScript"&gt;<BR>function numberCells() {<BR>var count=0;<BR>f or (i=0; i &lt; document．all.mytable.rows.length; i++) {<BR>f or (j=0; j &lt; document．all.mytable.rows(i).cells.length; j++) {<BR>document．all.mytable.rows(i).cells(j).innerText = count;<BR>count++;<BR>}<BR>}<BR>}<BR>&lt;/SCRIPT&gt;<BR>&lt;BODY onload="numberCells()"&gt;<BR>&lt;TABLE id=mytable b order=1&gt;<BR>&lt;TR&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;TH&gt;&nbsp;&lt;/TH&gt;&lt;/TR&gt;<BR>&lt;TR&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;/TR&gt;<BR>&lt;TR&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;TD&gt;&nbsp;&lt;/TD&gt;&lt;/TR&gt;<BR>&lt;/TABLE&gt;<BR>&lt;/BODY&gt;<BR>&lt;/HTML&gt; <BR><BR>１．身份证严格验证：<BR><BR>&lt;script&gt;<BR>var aCity={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"}<BR><BR>function cidInfo(sId){<BR>var iSum=0<BR>var info=""<BR>if(!/^\d{17}(\d|x)$/i.test(sId))return false;<BR>sId=sId.replace(/x$/i,"a");<BR>if(aCity[parseInt(sId.substr(0,2))]==null)return "Err or:非法地区";<BR>sBirthday=sId.substr(6,4)+"-"+Number(sId.substr(10,2))+"-"+Number(sId.substr(12,2));<BR>var d=new Date(sBirthday.replace(/-/g,"/"))<BR>if(sBirthday!=(d.getFullYear()+"-"+ (d.getMonth()+1) + "-" + d.getDate()))return "Err or:非法生日";<BR>f or(var i = 17;i&gt;=0;i --) iSum += (Math.pow(2,i) % 11) * parseInt(sId.charAt(17 - i),11)<BR>if(iSum%11!=1)return "Err or:非法证号";<BR>return aCity[parseInt(sId.substr(0,2))]+","+sBirthday+","+(sId.substr(16,1)%2?"男":"女")<BR>}<BR><BR>document．write(cidInfo("380524198002300016"),"&lt;br/&gt;");<BR>document．write(cidInfo("340524198002300019"),"&lt;br/&gt;")<BR>document．write(cidInfo("340524197711111111"),"&lt;br/&gt;")<BR>document．write(cidInfo("34052419800101001x"),"&lt;br/&gt;");<BR>&lt;/script&gt;<BR><BR>２．验证ＩＰ地址<BR>&lt;SCRIPT LANGUAGE="java script"&gt;<BR>function isip(s){<BR>var check=function(v){try{return (v&lt;=255 &amp;&amp; v&gt;=0)}catch(x){return false}};<BR>var re=s.split(".")<BR>return (re.length==4)?(check(re[0]) &amp;&amp; check(re[1]) &amp;&amp; check(re[2]) &amp;&amp; check(re[3])):false<BR>}<BR><BR>var s="202.197.78.129";<BR>alert(isip(s))<BR>&lt;/SCRIPT&gt;<BR><BR><BR><BR>３．加sp1后还能用的无边框窗口！！<BR>&lt;HTML XMLNS:IE&gt;<BR>&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;IE:Download ID="include" STYLE="behavi or:url(#default#download)" /&gt;<BR>&lt;title&gt;Chromeless Window&lt;/title&gt;<BR><BR>&lt;SCRIPT LANGUAGE="JScript"&gt;<BR>/*--- Special Thanks F or andot ---*/<BR><BR>/*<BR>This following code are designed and writen by Windy_sk &lt;seasonx@163.net&gt;<BR>You can use it freely, but u must held all the copyright items!<BR>*/<BR><BR>/*--- Thanks F or andot Again ---*/<BR><BR>var CW_width = 400;<BR>var CW_height = 300;<BR>var CW_top = 100;<BR>var CW_left = 100;<BR>var CW_url = "/";<BR>var New_CW = window.createPopup();<BR>var CW_Body = New_CW.document．body;<BR>var content = "";<BR>var CSStext = "margin:1px;col or:black; b order:2px outset;b order-style:expression(onmouseout=onmouseup=function(){this.style.b orderStyle='outset'}, onmousedown=function(){if(event.button!=2)this.style.b orderStyle='inset'});background-col or:buttonface;width:16px;height:14px;font-size:12px;line-height:11px;curs or:Default;";<BR><BR>//Build Window<BR>include.startDownload(CW_url, function(source){content=source});<BR><BR>function insert_content(){<BR>var temp = "";<BR>CW_Body.style.overflow= "hidden";<BR>CW_Body.style.backgroundCol or = "white";<BR>CW_Body.style.b order="solid black 1px";<BR>content = content.replace(/&lt;a ([^&gt;]*)&gt;/g,"&lt;a onclick='parent.open(this.href);return false' $1&gt;");<BR>temp += "&lt;table width=100% height=100% cellpadding=0 cellspacing=0 b order=0&gt;";<BR>temp += "&lt;tr style=';font-size:12px;background:#0099CC;height:20;curs or:default' ondblclick=\"Max.innerText=Max.innerText=='1'?'2':'1';parent.if_max=!parent.if_max;parent.show_CW();\" onmouseup='parent.drag_up(event)' onmousemove='parent.drag_move(event)' onmousedown='parent.drag_down(event)' onselectstart='return false' oncontextmenu='return false'&gt;";<BR>temp += "&lt;td style='col or:#ffffff;padding-left:5px'&gt;Chromeless Window F or IE6 SP1&lt;/td&gt;";<BR>temp += "&lt;td style='col or:#ffffff;padding-right:5px;' align=right&gt;";<BR>temp += "&lt;span id=Helponclick=\"alert('Chromeless Window F or IE6 SP1-Ver 1.0\\n\\nCode By Windy_sk\\n\\nSpecial Thanks F or andot')\" style=\""+CSStext+"font-family:System;padding-right:2px;\"&gt;?&lt;/span&gt;";<BR>temp += "&lt;span id=Min onclick='parent.New_CW.hide();parent.blur()' style=\""+CSStext+"font-family:Webdings;\" title='Minimum'&gt;0&lt;/span&gt;";<BR>temp += "&lt;span id=Max onclick=\"this.innerText=this.innerText=='1'?'2':'1';parent.if_max=!parent.if_max;parent.show_CW();\" style=\""+CSStext+"font-family:Webdings;\" title='Maximum'&gt;1&lt;/span&gt;";<BR>temp += "&lt;span id=Close onclick='parent.opener=null;parent.close()' style=\""+CSStext+"font-family:System;padding-right:2px;\" title='Close'&gt;x&lt;/span&gt;";<BR>temp += "&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=2&gt;";<BR>temp += "&lt;div id=include style='overflow:scroll;overflow-x:hidden;overflow-y:auto; HEIGHT: 100%; width:"+CW_width+"'&gt;";<BR>temp += content;<BR>temp += "&lt;/div&gt;";<BR>temp += "&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;";<BR>CW_Body.innerHTML = temp;<BR>}<BR><BR>setTimeout("insert_content()",1000);<BR><BR>var if_max = true;<BR>function show_CW(){<BR>window.moveTo(10000, 10000);<BR>if(if_max){<BR>New_CW.show(CW_top, CW_left, CW_width, CW_height);<BR>if(typeof(New_CW.document．all.include)!="undefined"){<BR> New_CW.document．all.include.style.width = CW_width;<BR> New_CW.document．all.Max.innerText = "1";<BR>}<BR><BR>}else{<BR>New_CW.show(0, 0, screen.width, screen.height);<BR>New_CW.document．all.include.style.width = screen.width;<BR>}<BR>}<BR><BR>window.onfocus= show_CW;<BR>window.onresize = show_CW;<BR><BR>// Move Window<BR>var drag_x,drag_y,draging=false<BR><BR>function drag_move(e){<BR>if (draging){<BR>New_CW.show(e.screenX-drag_x, e.screenY-drag_y, CW_width, CW_height);<BR>return false;<BR>}<BR>}<BR><BR>function drag_down(e){<BR>if(e.button==2)return;<BR>if(New_CW.document．body.offsetWidth==screen.width &amp;&amp; New_CW.document．body.offsetHeight==screen.height)return;<BR>drag_x=e.clientX;<BR>drag_y=e.clientY;<BR>draging=true;<BR>e.srcElement.setCapture();<BR>}<BR><BR>function drag_up(e){<BR>draging=false;<BR>e.srcElement.releaseCapture();<BR>if(New_CW.document．body.offsetWidth==screen.width &amp;&amp; New_CW.document．body.offsetHeight==screen.height) return;<BR>CW_top= e.screenX-drag_x;<BR>CW_left = e.screenY-drag_y;<BR>}<BR><BR>&lt;/SCRIPT&gt;<BR>&lt;/HTML&gt;<BR><BR>电话号码的验证<BR><BR>要求：<BR>　　(1)电话号码由数字、"("、")"和"-"构成<BR>　　(2)电话号码为3到8位<BR>　　(3)如果电话号码中包含有区号，那么区号为三位或四位<BR>　　(4)区号用"("、")"或"-"和其他部分隔开<BR>　　(5)移动电话号码为11或12位，如果为12位,那么第一位为0<BR>　　(6)11位移动电话号码的第一位和第二位为"13"<BR>　　(7)12位移动电话号码的第二位和第三位为"13"<BR>　　根据这几条规则，可以与出以下正则表达式：<BR>　　(^[0-9]{3,4}\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\([0-9]{3,4}\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)<BR><BR><BR>&lt;script language="java script"&gt;<BR>function PhoneCheck(s) {<BR>var str=s;<BR>var reg=/(^[0-9]{3,4}\-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^\([0-9]{3,4}\)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)/<BR>alert(reg.test(str));<BR>}<BR>&lt;/script&gt;<BR>&lt;input type=text name="iphone"&gt;<BR>&lt;input type=button onclick="PhoneCheck(document．all.iphone.value)" value="Check"&gt;<BR><BR>具有在输入非数字字符不回显的效果，即对非数字字符的输入不作反应。<BR>function numbersonly(field,event){<BR>var key,keychar;<BR>if(window.event){<BR>key = window.event.keyCode;<BR>}<BR>else if (event){<BR>key = event.which;<BR>}<BR>else{<BR>return true<BR>}<BR>keychar = String.fromCharCode(key);<BR>if((key == null)||(key == 0)||(key == 8)||(key == 9)||(key == 13)||(key == 27)){<BR>return true;<BR>}<BR>else if(("0123456789.").indexOf(keychar)&gt;-1){<BR>window.status = "";<BR>return true;<BR>}<BR>else {<BR>window.status = "Field excepts numbers only";<BR>return false;<BR>}<BR>}<BR><BR>验证ip <BR><BR>str=document．RegExpDemo.txtIP.value;<BR>if(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.test(str)==false)<BR>{<BR>window.alert('错误的IP地址格式');<BR>document．RegExpDemo.txtIP.select();<BR>document．RegExpDemo.txtIP.focus();<BR>return;<BR>}<BR>if(RegExp.$1&lt;1 || RegExp.$1&gt;254||RegExp.$2&lt;0||RegExp.$2&gt;254||RegExp.$3&lt;0||RegExp.$3&gt;254||RegExp.$4&lt;1||RegExp.$4&gt;254)<BR>{<BR>window.alert('错误的IP地址');<BR>document．RegExpDemo.txtIP.select();<BR>document．RegExpDemo.txtIP.focus();<BR>return;<BR>}<BR>//剔除 如010.020.020.03 前面 的0 <BR>var str=str.replace(/0(\d)/g,"$1");<BR>str=str.replace(/0(\d)/g,"$1");<BR>window.alert(str);<BR><BR><BR>//一下是取数据的类<BR>//Obj参数指定数据的来源(限定Table),默认第一行为字段名称行<BR>//GetTableData类提供MoveNext方法,参数是表的行向上或向下移动的位数,正数向下移动,负数向上.<BR>//GetFieldData方法获得指定的列名的数据<BR>//S ort_desc方法对指定的列按降序排列<BR>//S ort_asc方法对指定的列按升序排列<BR>//GetData方法返回字段值为特定值的数据数组,提供数据,可以在外部进行其他处理<BR>//Delete方法删除当前记录,数组减少一行<BR>//初始化,Obj:table的名字,Leftlen:左面多余数据长度,Rightlen:右面多余数据长度,<BR>function GetTableData(Obj,LeftLen,RightLen){<BR>var MyObj=document．all(Obj);<BR>var iRow=MyObj.rows.length;<BR>var iLen=MyObj.rows[0].cells.length;<BR>var i,j;<BR><BR>TableData=new Array();<BR>f or (i=0;i&lt; iRow;i++){<BR> TableData[i]=new Array();<BR> f or (j=0;j&lt;iLen;j++){<BR> TableStr=MyObj.rows(i).cells(j).innerText;<BR> TableStr=TableStr.substring(LeftLen, TableStr.length-RightLen).Trim();<BR> TableStr=TableStr.replace(/ /gi,"").replace(/\r\n/ig,"");<BR> TableData[i][j]=TableStr;<BR> }<BR> }<BR><BR>this.TableData=TableData; <BR>this.cols=this.TableData[0].length;<BR>this.rows=this.TableData.length;<BR>this.rowindex=0;<BR>}<BR><BR><BR>function movenext(Step){<BR>if (this.rowindex&gt;=this.rows){<BR>return<BR>}<BR><BR>if (Step=="" || typeof(Step)=="undefined") {<BR>if (this.rowindex&lt;this.rows-1)<BR>this.rowindex++;<BR>return;<BR><BR>}<BR>else{<BR>if (this.rowindex + Step&lt;=this.rows-1 &amp;&amp; this.rowindex + Step&gt;=0 ){<BR>this.rowindex=this.rowindex + Step;<BR>}<BR>else<BR>{<BR>if (this.rowindex + Step&lt;0){<BR> this.rowindex= 0;<BR> return;<BR> }<BR>if (this.rowindex + Step&gt;this.rows-1){<BR> this.rowindex= this.rows-1;<BR> return;<BR> }<BR>}<BR>}<BR>}<BR><BR><BR>function getfielddata(Field){<BR>var colindex=-1;<BR>var i=0;<BR>if (typeof(Field) == "number"){<BR> colindex=Field;<BR>}<BR>else<BR>{<BR>f or (i=0;i&lt;this.cols &amp;&amp; this.rowindex&lt;this.rows ;i++){<BR> if (this.TableData[0][i]==Field){<BR> colindex=i;<BR> break;<BR> }<BR>}<BR>}<BR>if (colindex!=-1) {<BR>return this.TableData[this.rowindex][colindex];<BR>}<BR><BR>}<BR><BR><BR><BR>function s ort_desc(){//降序<BR>var colindex=-1;<BR>var highindex=-1;<BR>desc_array=new Array();<BR>var i,j;<BR>f or (n=0; n&lt;arguments.length; n++){<BR>Field=arguments[arguments.length-1-n];<BR>f or (i=0;i&lt;this.cols;i++){<BR>if (this.TableData[0][i]==Field){<BR>colindex=i;<BR>break;<BR>}<BR>}<BR> if ( colindex==-1 )<BR>return;<BR> else<BR>{<BR>desc_array[0]=this.TableData[0];<BR>f or(i=1;i&lt;this.rows;i++){<BR>desc_array[i]=this.TableData[1];<BR>highindex=1;<BR> f or(j=1;j&lt;this.TableData.length;j++){<BR>if(desc_array[i][colindex]&lt;this.TableData[j][colindex]){ <BR>desc_array[i]=this.TableData[j]; <BR>highindex=j;<BR>}<BR><BR> }<BR> if (highindex!=-1)<BR> this.TableData=this.TableData.slice(0,highindex).concat(this.TableData.slice(highindex+1,this.TableData.length));<BR>}<BR>}<BR><BR><BR>this.TableData=desc_array;<BR>}<BR>return;<BR>}<BR><BR><BR><BR>function s ort_asc(){//升序<BR>var colindex=-1;<BR>var highindex=-1;<BR>var i,j;<BR>f or (n=0; n&lt;arguments.length; n++){<BR> asc_array=new Array();<BR> Field=arguments[arguments.length-1-n];<BR> f or (i=0;i&lt;this.cols;i++){<BR>if (this.TableData[0][i]==Field){<BR>colindex=i;<BR>break;<BR>}<BR> }<BR> if ( colindex==-1 )<BR> return;<BR> else<BR> {<BR> asc_array[0]=this.TableData[0];<BR> f or(i=1;i&lt;this.rows;i++){<BR> asc_array[i]=this.TableData[1];<BR> highindex=1;<BR>f or(j=1;j&lt;this.TableData.length;j++){//找出最小的列值<BR> if(asc_array[i][colindex]&gt;this.TableData[j][colindex]){ <BR> asc_array[i]=this.TableData[j]; <BR> highindex=j;<BR><BR>}<BR><BR> }<BR> if (highindex!=-1)<BR> this.TableData=this.TableData.slice(0,highindex).concat(this.TableData.slice(highindex+1,this.TableData.length));<BR> <BR>}<BR> }<BR><BR><BR>this.TableData=asc_array;<BR>}<BR>return;<BR>}<BR><BR><BR><BR>function getData(Field,Fieldvalue){<BR>var colindex=-1;<BR>var i,j;<BR><BR>GetData=new Array();<BR>if (typeof(Field)=="undefined" || typeof(Fieldvalue)=="undefined" ){<BR>return this.TableData;<BR>}<BR><BR> f or(j=0;j&lt;this.cols;j++){<BR>if(this.TableData[0][j]==Field){<BR> colindex=j;<BR> }<BR> }<BR> if (colindex!=-1){<BR> <BR> f or(i=1;i&lt;this.rows;i++){<BR>if(this.TableData[i][colindex]==Fieldvalue){<BR> GetData[i]=new Array();<BR> GetData[i]=this.TableData[i]; <BR> }<BR> }<BR> }<BR> return GetData;<BR>}<BR>function DeletE(){<BR>this.TableData=this.TableData.slice(0,this.rowindex).concat(this.TableData.slice(this.rowindex+1,this.TableData.length));<BR>this.rows=this.TableData.length;<BR>return;<BR>}<BR>function updateField(Field,Fieldvalue){<BR>var colindex=-1;<BR>var i=0;<BR>if (typeof(Field) == "number"){<BR> colindex=Field;<BR>}<BR>else<BR>{<BR>f or (i=0;i&lt;this.cols &amp;&amp; this.rowindex&lt;this.rows ;i++){<BR> if (this.TableData[0][i]==Field){<BR> colindex=i;<BR> break;<BR> }<BR>}<BR>}<BR>if (colindex!=-1) {<BR>this.TableData[this.rowindex][colindex]=Fieldvalue;<BR>}<BR><BR><BR>}<BR>function movefirst(){<BR>this.rowindex=0;<BR>}<BR>function movelast(){<BR>this.rowindex=this.rows-1;<BR>}<BR>function String.prototype.Trim() {return this.replace(/(^\s*)|(\s*$)/g,"");}<BR>GetTableData.prototype.MoveNext = movenext;<BR>GetTableData.prototype.GetFieldData = getfielddata;<BR>GetTableData.prototype.S ort_asc = s ort_asc;<BR>GetTableData.prototype.S ort_desc = s ort_desc;<BR>GetTableData.prototype.GetData = getData;<BR>GetTableData.prototype.Delete = DeletE;<BR>GetTableData.prototype.UpdateField = updateField;<BR>GetTableData.prototype.MoveFirst = movefirst;<BR><BR>具体的例子：http://202.119.73.208/NetEAn/com/test/jsprint.htm<BR><BR>在每个文本框的onblur事件中调用校验代码,并且每个文本框中onKeyDown事件中写一个enter转tab函数<BR><BR>//回车键换为tab<BR>function enterToTab()<BR>{<BR>if(event.srcElement.type != 'button' &amp;&amp; event.srcElement.type != 'textarea'<BR> &amp;&amp; event.keyCode == 13)<BR>{<BR>event.keyCode = 9;<BR>}<BR>}<BR><BR>有时候还需要自由编辑表格---<BR>给大家一个自由编辑表格的小例子,写的有点乱,呵呵:）<BR><BR>//===============================start================================<BR><BR><BR>&lt;HTML&gt;<BR>&lt;HEAD&gt;<BR>&lt;META http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;<BR>&lt;TITLE&gt;测试修改表格&lt;/TITLE&gt;<BR>&lt;STYLE&gt;<BR>/*提示层的样式*/<BR>div<BR>{<BR>BORDER-RIGHT: #80c144 1px solid;<BR>BORDER-TOP: #80c144 1px solid;<BR>VISIBILITY: hidden;<BR>BORDER-LEFT: #80c144 1px solid;<BR>CURSOR: default;<BR>LINE-HEIGHT: 20px;<BR>BORDER-BOTTOM: #80c144 1px solid;<BR>FONT-FAMILY: 宋体;<BR>font-size:12px;<BR>POSITION: absolute;<BR>BACKGROUND-COLOR: #f6f6f6;<BR>TOP:30px;<BR>LEFT:30px;<BR>}<BR>/*tr的样式*/<BR>tr<BR>{<BR>font-family: "宋体";<BR>col or: #000000;<BR>background-col or: #C1DBF5;<BR>font-size: 12px<BR>}<BR>/*table脚注样式*/<BR>.TrFoot<BR>{<BR>FONT-SIZE: 12px;<BR>font-family:"宋体", "Verdana", "Arial";<BR>BACKGROUND-COLOR: #6699CC;<BR>COLOR:#FFFFFF;<BR>height: 25;<BR>}<BR>/*trhead属性*/<BR>.TrHead<BR>{<BR>FONT-SIZE: 13px;<BR>font-family:"宋体", "Verdana", "Arial";<BR>BACKGROUND-COLOR: #77AADD;<BR>COLOR:#FFFFFF;<BR>height: 25;<BR>}<BR>/*文本框样式*/<BR>INPUT<BR>{<BR>BORDER-COLOR: #AACEF7 #AACEF7 #AACEF7 #AACEF7;<BR>BORDER-RIGHT: 1px solid;<BR>BORDER-TOP: 1px solid;<BR>BORDER-LEFT: 1px solid;<BR>BORDER-BOTTOM: 1px solid;<BR>FONT-SIZE: 12px;<BR>FONT-FAMILY: "宋体","Verdana";<BR>col or: #000000;<BR>BACKGROUND-COLOR: #E9EFF5;<BR>}<BR>/*button样式*/<BR>button<BR>{<BR>BORDER-COLOR: #AACEF7 #AACEF7 #AACEF7 #AACEF7;<BR>BACKGROUND-COLOR: #D5E4F3;<BR>CURSOR: hand;<BR>FONT-SIZE:12px;<BR>BORDER-RIGHT: 1px solid;<BR>BORDER-TOP: 1px solid;<BR>BORDER-LEFT: 1px solid;<BR>BORDER-BOTTOM: 1px solid;<BR>COLOR: #000000;<BR>}<BR>&lt;/STYLE&gt;<BR>&lt;/HEAD&gt;<BR>&lt;BODY&gt;<BR>&lt;SCRIPT language = "java script"&gt;<BR>&lt;!--全局变量<BR>//标志位,值为false代表未打开一个编辑框,值为true为已经打开一个编辑框开始编辑<BR>var editer_table_cell_tag = false;<BR>//开启编辑功能标志,值为true时为允许编辑<BR>var run_edit_flag = false;<BR>//--&gt;<BR>&lt;/SCRIPT&gt;<BR><BR>&lt;SCRIPT language = "java script"&gt;<BR>&lt;!--<BR>/**<BR>* 编辑表格函数<BR>* 单击某个单元格可以对里面的内容进行自由编辑<BR>* @para tableID 为要编辑的table的id<BR>* @para noEdiID 为不要编辑的td的ID,比如说table的标题<BR>* 可以写为&lt;TD id="no_editer"&gt;自由编辑表格&lt;/TD&gt;<BR>* 此时该td不可编辑<BR>*/<BR>function editerTableCell(tableId,noEdiId)<BR>{<BR>var tdObject = event.srcElement;<BR>var tObject = ((tdObject.parentNode).parentNode).parentNode;<BR>if(tObject.id == tableId &amp;&amp;tdObject.id != noEdiId&amp;&amp;editer_table_cell_tag == false &amp;&amp; run_edit_flag == true)<BR>{<BR>tdObject.innerHTML = "&lt;input type=text id=edit_table_txt name=edit_table_txt value="+tdObject.innerText+" size='15' onKeyDown='enterToTab()'&gt;&lt;input type=button value=' 确定 ' onclick='certainEdit()'&gt;";<BR>edit_table_txt.focus();<BR>edit_table_txt.select();<BR>editer_table_cell_tag = true;<BR>//修改按钮提示信息<BR>editTip.innerText = "请先点确定按钮确认修改!";<BR>}<BR>else<BR>{<BR>return false;<BR>}<BR>}<BR><BR>/**<BR>* 确定修改<BR>*/<BR>function certainEdit()<BR>{<BR>var bObject = event.srcElement;<BR>var tdObject = bObject.parentNode; <BR>var txtObject = tdObject.firstChild;<BR>tdObject.innerHTML = txtObject.value;<BR>//代表编辑框已经关闭<BR>editer_table_cell_tag = false;<BR>//修改按钮提示信息<BR>editTip.innerText = "请单击某个单元格进行编辑!";<BR>}<BR><BR>function enterToTab()<BR>{<BR>if(event.srcElement.type != 'button' &amp;&amp; event.srcElement.type != 'textarea'<BR> &amp;&amp; event.keyCode == 13)<BR>{<BR>event.keyCode = 9;<BR>}<BR>}<BR><BR>/**<BR>* 控制是否编辑<BR>*/<BR>function editStart()<BR>{<BR>if(event.srcElement.value == "开始编辑")<BR>{<BR>event.srcElement.value = "编辑完成";<BR>run_edit_flag = true;<BR>}<BR>else<BR>{<BR>//如果当前没有编辑框,则编辑成功,否则,无法提交<BR>//必须按确定按钮后才能正常提交<BR>if(editer_table_cell_tag == false)<BR>{<BR> alert("编辑成功结束!");<BR> event.srcElement.value = "开始编辑";<BR> run_edit_flag = false;<BR>}<BR>}<BR>}<BR><BR>/**<BR>* 根据不同的按钮提供不同的提示信息<BR>*/<BR>function showTip()<BR>{<BR>if(event.srcElement.value == "编辑完成")<BR>{<BR>editTip.style.top = event.y + 15;<BR>editTip.style.left = event.x + 12;<BR>editTip.style.visibility = "visible";<BR>}<BR>else<BR>{<BR>editTip.style.visibility = "hidden"; <BR>} <BR>}<BR>--&gt;<BR>&lt;/SCRIPT&gt;<BR>&lt;TABLE id="editer_table" width="100%" align="center" <BR>onclick="editerTableCell('editer_table','no_editer')"&gt;<BR>&lt;TR class="TrHead"&gt;<BR>&lt;TD colspan="3" align="center" id="no_editer"&gt;自由编辑表格&lt;/TD&gt;<BR>&lt;/TR&gt;<BR>&lt;TR&gt;<BR>&lt;TD width="33%"&gt;单击开始编辑按钮,然后点击各单元格编辑&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;2&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;3&lt;/TD&gt;<BR>&lt;/TR&gt;<BR>&lt;TR&gt;<BR>&lt;TD width="33%"&gt;4&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;5&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;6&lt;/TD&gt;<BR>&lt;/TR&gt;<BR>&lt;TR&gt;<BR>&lt;TD width="33%"&gt;one&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;two&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;three&lt;/TD&gt;<BR>&lt;/TR&gt;<BR>&lt;TR&gt;<BR>&lt;TD width="33%"&gt;four&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;five&lt;/TD&gt;<BR>&lt;TD width="33%"&gt;six&lt;/TD&gt;<BR>&lt;/TR&gt;<BR>&lt;TR class="TrFoot"&gt;<BR>&lt;TD colspan="3" align="center" id="no_editer"&gt;<BR> &lt;INPUT type="button" class="bt" value="开始编辑" onClick="editStart()" onMouseOver="showTip()" onMouseMove="showTip()" onMouseOut="editTip.style.visibility = 'hidden';"&gt;<BR>&lt;/TD&gt;<BR>&lt;/TR&gt; <BR>&lt;/TABLE&gt;<BR>&lt;/BODY&gt;<BR>&lt;DIV id="editTip"&gt;请单击某个单元格进行编辑!&lt;/DIV&gt; <BR>&lt;/HTML&gt;]]></description>
</item>
</channel>
</rss>