收录查询

多线程脑袋

博客园 首页 联系 订阅 管理
  19 Posts :: 421 Stories :: 29 Comments :: 0 Trackbacks

置顶随笔 #

摘要: The Code Project is constantly growing, with hundreds of new articles added monthly and more sections created to house them. Below is a quick guide to help you find the sections that most interest you...阅读全文
posted @ 2006-08-18 21:25 -> 阅读(299) 评论(0) 编辑

摘要: The Microsoft Foundation Class Library can be divided into two major sections: (1) the MFC classes and (2) macros and globals. If a function or variable is not a member of a class, it is a global func...阅读全文
posted @ 2006-08-18 21:19 -> 阅读(167) 评论(0) 编辑

2009年5月7日 #

摘要: 随机函数的定义和使用到的DS和函数:1. 实现在rand.c文件中:[代码]2. 用到了一个DS定义在MTDLL.H头文件中:[代码]3. 用到了一个function实现在tidtable.c文件中:[代码] /***2*_ptiddata_getptd(void)-getper-threaddatastructureforthecurrentthread3*4*Purpose:5*6*Entry...阅读全文
posted @ 2009-05-07 19:47 -> 阅读(147) 评论(0)  编辑

原文地址:http://alexclark.itpub.net/post/670/482058

实际上,在web开发中,cookie仅仅是一个文本文件,当用户访问站点时,它就被存储在用户使用的计算机上,其中,保存了一些信息,当用户日后再次访问这个站点时,web可以将这些信息提取出来。

尽管现在听起来cookie没有什么激动人心的,但实际上利用它,你能实现许多有意义的功能!比如说:你可以在站点上放置一个调查问答表,询问访问者最喜 欢的颜色和字体,然后根据这些定制用户的web界面。并且,你还可以保存访问者的登录密码,这样,当访问者再次访问这个站点时,不用再输入密码进行登录。




当然,cookie也有一些不足。首先,由于利用cookie的功能可以编程实现一些不良企图,所以大多数的浏览器中都有安全设
定,其中可以设置是否允许或者接受cookie,因此这就不能保证随时能使用cookie。再者,访问者可能有意或者无意地删除
cookie。当访问者的机器遇到“蓝屏”死机时,或者重新格式化硬盘、安装系统后,原来保存的cookie将全部丢失。最后一点,有
一些最初始的浏览器并不能支持cookie。

利用cooklie能做什么?

有2种使用cookie的基本方式:
1、将cookie写入访问者的计算机(使用 RESPONSE 命令)
2、从访问者的计算机中取回cookie(使用 REQUEST 命令)

创建cookie的基本语法

Response.Cookies("CookieName")=value

执行下面的代码将会在访问者的计算机中创建一个cookie,名字=VisitorName,值=Ken
Response.Cookies("VisitorName")="Ken"

执行下面的代码将会在访问者的计算机中创建一个cookie,名字=VisitorName,值=表单中UserName的值
Response.Cookies("VisitorName")=Request.Form("UserName")

读取cookie的基本语法

Request.Cookies("CookieName")

可以将Request值当作一个变量看待,执行下面的代码,将取回名字为KensCookie的cookie值,并存入变量MyVar:
MyVar=Request.Cookies("KensCookie")

执行下面的代码,将判断名字为KensCookie的cookie值是否为“Yes”:
If Request.Cookies("KensCookie")="Yes" then

功能丰富的cookie

你可以扩展上面的代码成为Cookie子关键值(CookieSubName),代码如下:
Response.Cookies("VisitorName")("FirstName")="Ken"
Response.Cookies("VisitorName")("LastName")="Baumbach"

讲解例子前,最后讨论2个概念:命令约定和使用到期时间。

命名约定

同其他变量的命名一样,合适地、独特地命名cookie,有利于在程序中前后连贯地使用它。你可以使用下面的1个或者2个
cookie属性进行cookie变量的命名:

域属性(Domain):域属性表明cookie由哪个网站产生或者读取,默认情况下,cookie的域属性设置为产生它的网站,但你
也可以根据需要改变它。相关代码如下:Response.Cookies("CookieName").Domain = "www.mydomain.com"

路径属性(Path):路径属性可以实现更多的安全要求,通过设置网站上精确的路径,就能限制cookie的使用范围。例如:
Response.Cookies("CookieName").Path = "/maindir/subdir/path"

使用到期时间

通常情况下,当浏览器关闭时,一个cookie就不存在了。但是在许多时候,比如下面将要讨论的web站点例子,我们希望能更
长时间地在访问者的计算机上保存cookie。很幸运,有这样的实现方法。下面的代码,就可以设置cookie的使用到期时间为2010年
1月1日:
Response.Cookies("CookieName").Expires=#January 01, 2010#

执行下面的代码,将设定cookie的过期时间为“cookie的创建时间+365日”:
Response.Cookies("CookieName")=Date+365

使用cookie的实际例子(非常精彩)

现在开始讨论实际的例子。假设:你想做一个调查,每个人初次访问时需要填写好信息,但是当日后再访问时,就不需要再那
么做。利用cookie,就可以非常圆满地解决这个问题,而大可不必用到数据库。

< %@ LANGUAGE="VBSCRIPT" % >
< %
Survey=Request.Cookies("KensSurvey")
If Survey ="" then
Response.Cookies("KensSurvey")="x"
Response.Cookies("KensSurvey").Expires=#January 01, 2010#
Response.Redirect "survey.asp"
Else
'rest of the page
End if
% >
好,下面开始从头讨论上面的代码。

首先,初始设置页面,并读取名字为KensSurvey的cookie值:


< %@ LANGUAGE="VBSCRIPT" % >
< %
Survey=Request.Cookies("KensSurvey")
然后,判断是否已经存在cookie值:

If Survey ="" then
如果不存在, 就创建并设置cookie,并转到页面survey.asp。 当下一次访问时,因为存在cookie值,就不会再转到
survey.asp 页面。

Response.Cookies("KensSurvey")="x"
Response.Cookies("KensSurvey").Expires=#January 01, 2010#
Response.Redirect "survey.asp"
如果cookie已经存在,那么访问者将执行页面中剩余的代码:

'rest of the page

End if
% >
例子2

这里有另外一个简单的例子:当访问者第1次浏览某个站点时,向他们显示欢迎信息。代码如下:

< %@ LANGUAGE="VBSCRIPT" % >
< %
RequestName = Request.Form("Name")
RequestLeaveMeAlone = Request.Form("LeaveMeAlone")
If RequestName < >"" or RequestLeaveMeAlone < >"" then
Response.Cookies("MySiteVisitorName") = RequestName
Response.Cookies("MySiteVisitorName").Expires = #January 01, 2010#
Response.Cookies("MySiteLeaveMeAlone") = RequestLeaveMeAlone
Response.Cookies("MySiteLeaveMeAlone").Expires = #January 01, 2010#
End if
VisitorName = request.cookies("MySiteVisitorName")
LeaveMeAlone = request.cookies("MySiteLeaveMeAlone")

If VisitorName ="" and LeaveMeAlone ="" then
% >
< HTML > < HEAD > < /HEAD >
< body bgcolor="#ccffff" text="black" link="navy" vlink="purple" >
< DIV ALIGN="CENTER" >
< form action="index.asp" method="POST" >
< H2 >Let's be friends< /H2 >
What's your name (leave blank and hit the Submit button if you don't want us to
know)?
< input type="text" name="name" >< BR >< BR >
< input type="hidden" name="LeaveMeAlone" value="x" >
< input type="submit" value="Submit" >
< /FORM >
< /DIV >
< /BODY >
< %
End if
If VisitorName < > "" then
Response.write "Hi, " & VisitorName & "! I hope you are having a great day!"
End if
'rest of the page
% >
好,现在来看看上面的代码实现执行了什么。首先,设置页面。然后,检查表单变量(在同一个页面中)。如果表单变量存
在,就创建cookie,并设置到期时间。

< %@ LANGUAGE="VBSCRIPT" % >
< %
RequestName = Request.Form("Name")
RequestLeaveMeAlone = Request.Form("LeaveMeAlone")
If RequestName < >"" or RequestLeaveMeAlone < >"" then
Response.Cookies("MySiteVisitorName") = RequestName
Response.Cookies("MySiteVisitorName").Expires = #January 01, 2010#
Response.Cookies("MySiteLeaveMeAlone") = RequestLeaveMeAlone
Response.Cookies("MySiteLeaveMeAlone").Expires = #January 01, 2010#
End if

接着,读取cookie:

VisitorName = request.cookies("MySiteVisitorName")
LeaveMeAlone = request.cookies("MySiteLeaveMeAlone")
如果cookie在访问者的计算机上不存在,就创建一个表单,询问相关信息:

If VisitorName ="" and LeaveMeAlone ="" then
% >
< HTML >
< HEAD >
< /HEAD >
< body bgcolor="#ccffff" text="black" link="navy" vlink="purple" >
< DIV ALIGN="CENTER" >
< form action="index.asp" method="POST" >
< H2 >Let's be friends< /H2 >
What's your name (leave blank and hit the Submit button if you don't want us to
know)?
< input type="text" name="name" >< br >< br >
< input type="hidden" name="LeaveMeAlone" value="x" >
< input type="submit" value="Submit" >
< /FORM >
< /DIV >
< /BODY >
< %
End if
如果cookie已经存在,并且用户名字存在,就显示给访问者一个欢迎界面,然后执行其余的代码。

If VisitorName < > "" then
Response.write "Hi, " & VisitorName & "! I hope you are having a great day!"
End if
'rest of the page
% >
尽管上面的这个例子很简单,但可以从中扩展许多富有创造力的应用。你可以在表单中加入许多功能,以便定制化web站点。
你还可以让访问者定制网站的色彩、字体,以至于其他web元素。有可能的话,你可以询问访问者的生日,当访问者在那一天来访
时,你就可以显示“生日快乐”的信息给他。

如你所见,cookie的扩展性是无穷的,这篇文章仅仅是抛砖引玉。

如你所见,cookie的扩展性是无穷的,这篇文章仅仅是抛砖引玉。

资料引用:http://www.knowsky.com/301480.html

VBScript code
<%
'得到当前页面的地址
if request.Cookies("Username")="" then
response.Cookies("GetUrl")=GetUrl()
response.Redirect("/Company/admin/Login.asp")
response.end
end if

Function GetUrl()
On Error Resume Next
Dim strTemp
If LCase(Request.ServerVariables("HTTPS")) = "off" Then
strTemp = "http://"
Else
strTemp = "https://"
End If
strTemp = strTemp & Request.ServerVariables("SERVER_NAME")
If Request.ServerVariables("SERVER_PORT") <> 80 Then strTemp = strTemp & ":" & Request.ServerVariables("SERVER_PORT")
strTemp = strTemp & Request.ServerVariables("URL")
If Trim(Request.QueryString) <> "" Then strTemp = strTemp & "?" & Trim(Request.QueryString)
GetUrl = strTemp
End Function
%>


posted @ 2009-05-07 18:45 -> 阅读(6) 评论(0)  编辑

 

Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。

  简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

  HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系

  了解了hash基本定义,就不能不提到一些著名的hash算法,MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。那么他们都是什么意思呢?

  这里简单说一下:

  1) MD4

  MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位操作数的位操作来实现的。

  2) MD5

  MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好

  3) SHA1 及其他

  SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

  那么这些Hash算法到底有什么用呢?

  Hash算法在信息安全方面的应用主要体现在以下的3个方面:

  1) 文件校验

  我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。

  MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。

  2) 数字签名

  Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。 对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。

  3) 鉴权协议

  如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。

用hash算法加密用户名对应的密码,存入数据库中,使密码不能直观可见,增强密码的安全性能。哈希算法是单向的,可以将字符串转换成某个某个输出,但无法从输出确定输入值,确保即使加密后的字符泄漏,也无法获得原输入值。本系统中使用的hash算法是MD5.

  /// <summary>
        /// 对字符串进行md5哈希算法加密。
        /// </summary>
        /// <param name="unencryptPassword">待加密的字符串</param>
        /// <returns>返回一个包含哈希密码的字符串</returns>
        public string Encrypt(string unencryptPassword)
        {
            //添加对应加密算法
            string hashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(unencryptPassword, "md5");
            return hashedPassword;
        }


  /// <summary>
        /// 检查密码是否正确
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool CheckUserPassword(decimal userID, string password)
        {
            return iL.CheckUserPassword(userID,Encrypt(password));
        }

 

  /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public int UpdateUserPassword(decimal userID, string password)
        {
            return iL.UpdateUserPassword(userID, Encrypt(password));
        }

===================================================================
best way to handle user id hash common to all rails requests

Q:
Each client is identified by a hash, passed along with every request to the server. What's the best way to handle tracking a users session in this case?

I'm using restful_authentication for user accounts etc. A large percentage of requests are expected to originate without a user account but just the unique hash.

My understanding of the way handles sessions is limited so please bear that in mind. :)

A:
Using this hash in the URL means that you don't have Rails built-in session. The point of the session is to provide some sense of state between requests. You're already providing this state, seeing that you are passing this hash, so in my opinion you could remove the restful_authentication plugin and do something like this instead:

class ApplicationController < ActionController::Base
def require_login
  if params[:access_key]
  @current_user = User.find_by_access_key(params[:access_key]) || restrict_access
  else
    restrict_access
  end
end

def restrict_access
  flash[:error] = "You have to log in to access that."
  redirect_to root_path
  end
end
Then, do a before_filter :require_login in the controllers where login is required for access.
=====================================================================================
Hash表和TList的结合使用
试想一下,如果在游戏中如果突然有哪个玩家断线,那么即便是我们知道这个玩家的Socket,但是要从所有玩家中检索出他的信息,
也不是一件容易的事。
那我们为什么不能将Hash表和Tlist结合使用呢。在我开发的游戏中,我就是将Hash表和Tlist同时使用,来对玩家断线做相关的处理。
今天我就简单的写一下我是如何处理的。

假定有一个Tlist中(UserList)保存着游戏中某房间的所有玩家信息。玩家的信息结构如下:
RuserInfo = record
Socket;Tsocket;
UserID:String[20];
Face:Byte;
Sex:Boolean;
Socre:Integer;
CurrStatus:Integer;
End;
PuserInfo = ^ RuserInfo;

我们来创建一个Hash表和一个Tlist表:
ScHash:= THashedStringlist.Create;
UserList:=Tlist.Create;
当某一玩家加入游戏时这样处理。
New(P_User)
P_User.Socket:=3500;
P_User.UserID:=’fxh7622’;
P_User.Face:=3;
P_User.Sex:=true;
P_User.Socre:=1000;
P_User.CurrStatus:=0;
Index:=ScHash.IndexOf(IntToStr(p_User.Socket));
if Index=-1 then
begin
ScHash.AddObject(IntToStr(p_User^.Socket),TObject(Integer(p_User)));
end;

//这里将玩家的信息以Socket作为KEY来放入Hash表中。
UserList.Add(P_User);

//在这里将玩家的信息保存在一个Tlist表中。通过前面我的文章中介绍,大家可以知道在HASH表中和在Tlist表中保存的是
//同一个内容,也就是说:如果修改了某玩家在Tlist中保存的信息那么他在Hash表中保存的信息也将随着修改。
这样当玩家断线以后,我们可以快速的使用Hash表来检索出是哪个玩家断线。
function TUserBaseControl.Sel_Hash(sc:TSOCKET;var p_User:PUserSocket): Boolean;

var
t_User:PUserSocket;
t_Object:TObject;
Index:Integer;

begin
Result:=false;
Index:=ScHash.IndexOf(IntToStr(sc));
if Index<>-1 then
begin
t_Object:=ScHash.Objects[Index];
p_User:=PUserSocket(t_Object);
Result:=true;
end;
end;
检索出玩家信息以后可以将玩家信息中的相关信息进行修改。

例如:p_User.CurrStatus:=5;
以上的例子只是对Hash表和Tlist使用的一个小小的窍门,但是的确可以加快服务器的处理速度。希望也对大家有一个帮助。
posted @ 2009-05-07 15:40 -> 阅读(68) 评论(0)  编辑

2009年5月6日 #

摘要: 原文地址:http://www.blueidea.com/tech/web/2006/3330_3.asp[代码]阅读全文
posted @ 2009-05-06 01:21 -> 阅读(107) 评论(0)  编辑

原文地址:http://devcenter.infragistics.com/Articles/ArticleTemplate.Aspx?ArticleID=2183

Applies To:


  • ASP.NET
  • .NET Framework
  • JavaScript

Summary:

Your pages need JavaScript, both for logic and UI. But debugging JavaScript code can be a pain, unless you know a few tricks.

ASP.NET has many advantages over classic ASP in the area of debugging. You can now easily debug your server-side code using the full power of a modern debugger such as Visual Studio .NET. This, along with the introduction of server controls and a postback architecture, has simplified Web-based development. But what about the other half of a Web application, the client-side script?

Although server controls and postbacks have reduced the need for Web developers to interact with JavaScript in an ASP.NET application, many developers are learning that they cannot forget about client-side scripting altogether.
 
Developers creating Web pages designed to display even a moderate amount of data know the cost of posting back to the server. Using JavaScript to perform simple tasks minimizes the number of roundtrips to the server, potentially avoiding unnecessary queries to the database and reducing the number of times the ViewState is pushed over the wire.

Besides reducing the amount of network traffic, the use of client-side JavaScript enables ASP.NET developers to provide a richer and more interactive experience to the end-user. By moving appropriate functionality from the server to the client you provide the user with instant responsiveness and feedback without the latency implicit in a postback. Balancing functionality between both the client and the server helps reduce some of the load on the Web server, which in turn yields better server response times.

A substantial roadblock to using JavaScript, though, is that it can be difficult to write and debug.

First, IntelliSense for JavaScript is limited at best, which leads to errors in the initial coding stage. Because JavaScript is case-sensitive, the lack of IntelliSense can be aggravating - particularly for developers turning to ASP.NET from a case-insensitive language like Visual Basic.

Also, when a browser's JavaScript error message provides a line number to look at, it often doesn't match the line numbers indicated in the code. The line number will get you in the right area, but after that, it often becomes a guessing game.

Furthermore, if you try putting a breakpoint in the JavaScript in your ASPX, you'll find that when running the project, control will not stop on it and, at best, you may get the not-so-helpful message, "Breakpoint will not be hit, symbols have not been loaded for this document."

 

Tap into HTML


With Internet Explorer 6 and VS .NET, Microsoft has provided a way to tap into the HTML and JavaScript that Internet Explorer is running, thereby closing the loop in the debugging cycle. By closing this hole developers can now debug their entire application in a single IDE - from client-side script to server-side code, and possibly right through to the database.

Unfortunately for most developers, this won't work without some basic set up. To verify that Internet Explorer is set up correctly, open Internet Explorer, choose Tools | Internet Options. Click the Advanced tab and find Disable script debugging about halfway down the list. Make sure there is no check in the box next to this option. Click OK and close Internet Explorer. The browser is now ready to work with Visual Studio .NET to debug your application.

To begin exploring the basic functions of the debugger, start a new WebForms project and run it without adding any controls or code. When the empty project loads in Internet Explorer, return to Visual Studio and open the Running Documents window by selecting Debug | Windows | Running Documents from the Debug menu.

The Running Documents window will appear docked on the right edge of the IDE. The name of the page, "WebForm1.aspx", will appear in the window. Double-click the page and the HTML rendered to the browser when the ASPX page was evaluated by the server will be shown in a code window on the left. The HTML rendered by the ASPX page can be seen by double-clicking the page in the Running Documents window.

The code provided by the Running Documents window is where a developer can set breakpoints and step through the code, just like in server-side code. Stop the project and bring up the form designer.

As an example, a developer might need to create a custom validator that ensures the user has selected a valid item from a dropdown list. Often times a developer does not want users to be able to choose the first item in the list, as this might be a prompt such as "Select an item." (If you are not familiar with custom validators, check out the .NET Framework General Reference for the CustomValidator control at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconcustomvalidatorcontrol.asp.)

In this example, create two dropdown lists, one prompting users to "Choose your favorite animal..." (and list various animals). The other should ask the user to "Choose your favorite color..." (and list a few colors).

After configuring a new custom validator on the page to validate the first dropdown, set its ClientValidationFunction to clientvalidate and insert the following validation code into the page's header section (this code will be called by the ASP.NET custom validator control):

 

<script>
function clientvalidate(source, args){
   var dropdown =
  document.getElementById(source.controltovalidate);
  if (dropdown.selectedindex == 0){
   args.IsValid = false;
  }   else {
  args.IsValid = true;
  }
 }
</script>

 

The ClientValidationFunction will be called by the CustomValidator each time the value of the dropdown changes.

In the HtmlView, add an OnServerValidation event like this:

 

<asp:CustomValidator OnServerValidate="ServerValidation"/>

 

Then add the following code, which adds an event handler for ServerValidation. The server-side code is added to the code behind. This code will be called by the ASP.NET custom validator control on browsers that do not support client-side script:

 

Sub ServerValidation(ByVal source As Object,
  ByVal args As ServerValidateEventArgs)
Dim dl As DropDownList = _
  FindControl(CType(source, CustomValidator) _
  .ControlToValidate)
 
 If dl.SelectedIndex = 0 Then
  args.IsValid = False
 Else
  args.IsValid = True
 End If
End Sub

 

Another validator will need to be added and configured in the same way for the second dropdown list. Both validators can point to the same client-side script and server-side event.

After adding a new button labeled Submit.

Start the project and choose an animal from the animal dropdown. Correctly, the validation error message doesn't appear. Select the first item in the list again and notice that the error message is still not displayed. This is not the expected functionality. The validation function is called each time the value of the dropdown changes. Because the first item in the list is chosen, the error message should be visible.

To find out what is happening in our custom JavaScript code, double-click the Web page in the Running Documents window and put a breakpoint on the first line of code, where we assign the dropdown list. Switch back to Internet Explorer and select another animal name. Execution of the page will break on the line of code selected. From here, a developer can walk through the code as if it were server code. Press F10 to step through the code and into the else statement. This is correct behavior. Press F5 to continue running the code.

Now select the first item in the same dropdown list so that execution stops at the breakpoint again. This time, however, examine the value of dropdown.selectedindex. Highlight the words "dropdown.selectedindex" and hit Ctrl-Alt-Q or drag the text to a watch window. The watch window shows that dropdown.seletectedindex is undefined. The one major ramification of this is that the comparison will never return true, and args.IsValid will never be set to false. That is, regardless of the dropdown's value, validation will never fail.

Change the text in the Quick Watch window to "dropdown" and hit Enter. The watch window now lists all the members of the "dropdown" object. Scrolling to the bottom, you can see the problem: "selectedindex" is not a property of the dropdown. It should really be "selectedIndex", with a capital "I".

Now that the problem is known the code must be updated. Don't try to update the code here, though, because this view of the code is not editable. Remember, this is what the browser sees; switch back to the ASPX HtmlView to change the code.

Make the change and run the project again; this time it works as expected.

 

Debug Startup Code


Unfortunately, the technique described above breaks down when you try to debug code that executes on start up, such as from a server-side Page.RegisterStartUpScriptBlock method in the page load event. Because the JavaScript code runs as the page loads, you have no opportunity to return to the IDE to set a breakpoint.

Debugging startup script code requires a different method for debugging. There are three ways to debug startup script. First, start your project with F10. Pressing F10 will load your default startup page in the browser and immediately put you in break mode on the first line of JavaScript. You can then set another breakpoint elsewhere in your code, or you can step through line by line until you reach the line of interest.

Next, run the page, let the error occur, then set the breakpoint and hit F5. This method comes in handy when you receive an unexpected error. After the page has loaded in your browser and you get an error or incorrect behavior, open the appropriate Running Documents window and place a breakpoint where you would have wanted execution to stop. Return to the browser and hit F5. Visual Studio .NET will recognize that this is the same page you loaded before and will keep your breakpoint in place. When execution reaches the breakpoint, control will return to the IDE.

Finally, use the debugger keyword. The debugger keyword works just like a breakpoint. When the JavaScript interpreter reaches this keyword, it halts execution and returns control to the IDE.

To demonstrate the power of the debugger keyword, insert the code shown in Figure 3 behind the click event of our Submit button.

 

Private Sub Button1_Click(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles Button1.Click
    If Page.IsValid Then                            
      Dim sb As New System.Text.StringBuilder()
      sb.Append("<script>" & vbCrLf)
      sb.Append("dropdown1 = document" _
        & ".getElementById('DropDownList1');" & vbCrLf)
      sb.Append("color = dropdown1." _
  & "value.toLowerCase();" & vbCrLf)
      sb.Append("dropdown2 = document." _
  & "getElementById('DropDownList2');" & vbCrLf)
      sb.Append("animal = dropdown2." _
  & "value.toLowerCase;" & vbCrLf)
      sb.Append("alert('Would you like a" _
  & " ' + color + ' ' + animal + '?');" & vbCrLf)
      sb.Append("</script>")
      Page.RegisterStartupScript("MyStartupScript", _
  sb.ToString())
   End If
End Sub


Figure 3. The code behind the Submit button uses the Page.RegisterStartupScript method to add code that will execute after the page loads in the browser.

Run the project, select values from the dropdown, and click the Submit button. No error message is displayed, but the value in our alert box is not quite what would be expected. Add a "debugger" line and step through the code line-by-line. Add this line after the initial <script> tag illustrated above:

 

sb.Append("debugger;" & vbCrLf)

 

Run the project, select values from our dropdowns, and click the Submit button again. This time the page reloads and stops on the word "debugger" Hit F10 to move to the next line and continue stepping through the startup code.

Examining each line of code and the resulting values, notice that the offending line is:

 

animal = dropdown2.value.toLowerCase;


When a developer is unable to diagnose the problem from a quick glance, the watch window can help out. Bring up Quick Watch again with Ctrl-Alt-Q and enter "dropdown2.value", then add ".toLowerCase". By verifying that the value exists, but that toLowerCase does not, the scope of the problem has been narrowed. The solution is now evident: "toLowerCase" is a method, not a field, and as such, requires parentheses.

Return to the button's click event and fix the code by adding parentheses after ".toLowerCase". Execute the page again. When you are satisfied that the bug has been worked out, remove or comment out the line containing "debugger;".

Note that if the browser executes the debugger statement while not connected to a debugger, it will throw an error and ask you if you would like to debug. As a result, be sure you remove the keyword when you have finished debugging so your end users never see it.

Debugging startup script is a little more difficult than debugging script behind a button click or a validation routine because it is hard to insert a breakpoint at the right place. Starting the page with F10 or using the debugger keyword can help break into the code. From that point, a developer can find the errors in his logic using the same powerful tools he is accustomed to using with server-side code.

Visual Studio .NET provides the same powerful and flexible tools for debugging your client-side code as it does for server-side code. Get the most out of Visual Studio .NET by using the techniques described here to close the loop and debug your entire ASP.NET application in one IDE.

Brian Clark, a developer on leave from Infragistics, is currently pursuing a Master's degree in Computer Science and Systems Engineering at Cornell University. He welcomes your comments and questions at BrianC@infragistics.com.

posted @ 2009-05-06 00:29 -> 阅读(47) 评论(0)  编辑

原文地址:http://support.microsoft.com/default.aspx?kbid=317699

本文分步介绍了如何通过使用 Visual Basic.NET 或 Visual Basic 2005 和 Microsoft 脚本调试器调试 Microsoft ASP.NET 应用程序中的客户端脚本。

Visual Basic.NET 或 Visual Basic 2005 提供了许多新的调试功能,使您能够更轻松地确定和诊断代码中的问题。

要求

以下列表概述了推荐使用的硬件、 软件、 网络的基础结构和所需的 Service Pack:
  • Microsoft Visual Studio.NET 或 Microsoft Visual Studio 2005
  • Microsoft Internet Information Services (IIS) 5.0 或更高版本
  • Microsoft 脚本调试器
本文假定您熟悉下列主题:
  • Web 应用程序
  • ASP.NET
  • Visual Basic.NET 或 Visual Basic 2005

    调试客户端-脚本在 Visual Basic.NET 或 Visual Basic 2005

    在早期版本 Microsoft Active Server Pages (ASP) 中, 应用程序很难进行调试,尤其在客户端脚本代码中出现的错误。 Visual Studio.NET 可以更好地控制在调试客户端脚本通过集成的调试器和该局部变量时窗口。

    创建应用程序

    在本节,您可以创建一个显示和与计算输入的 按钮 控件的三个 HTML 文本框 控件的 ASP.NET Web 应用程序 (在 Visual Studio 2005 中的 ASP.NET Web 站点)。 此示例使用 JavaScript 进行编程 Button 控件。
    1. 客户端 JavaScript 使用调试器,您必须首先启用脚本调试为浏览器。 要这样做,请按下列步骤操作:
      1. 打开 Microsoft Internet Explorer。
      2. 工具 菜单上单击 Internet 选项
      3. 高级 选项卡上找到 浏览 部分,清除 禁用脚本调试 复选框,然后单击 确定
      4. 关闭 Internet Explorer。
    2. 在 Visual Basic.NET (在 Visual Studio 2005 中的 ASP.NET Web 站点) 中创建新的 ASP.NET Web 应用程序,请按照下列步骤操作:
      1. 打开 Visual Studio.NET 或 Visual Studio 2005。
      2. 文件 菜单上指向 新建 ,然后单击 项目

        请注意 在 Visual 的 Studio 2005 中指向 文件 菜单上的 新建 ,然后单击 网站
      3. 在, 新建项目 对话框中单击 项目类型 下的 Visual Basic 项目 ,然后单击 模板 下的 ASP.NET Web 应用程序

        请注意 在 Visual 的 Studio 2005 中单击 模板 下的 ASP.NET Web 站点
      4. 名称 文本框中,键入 ScriptDebuggingExample
    3. 切换到 HTML 视图,WebForm 1.aspx 的文件。

      请注意 在 Visual 的 Studio 2005 切换到 Default.aspx 文件的 HTML 视图。
    4. 复制并粘贴下面的代码在 <form> 内部标记:
      <table>
              <tr>
              <td width="100">
              <asp:label id="lblFirstNumber" runat="server" Width="125">
              First Number:
              </asp:label>
              </td>
              <td width="50">
              <input id="txtNumber1" type="text" maxLength="3"
              size="5" name="txtNumber1">
              </td>
              </tr>
              <tr>
              <td width="100">
              <asp:label id="lblSecondNumber" runat="server" Width="125">
              Second Number:
              </asp:label>
              </td>
              <td width="50">
              <input id="txtNumber2" type="text" maxLength="3"
              size="5" name="txtNumber2">
              </td>
              </tr>
              <tr>
              <td width="100">
              <asp:Label id="lblResult" runat="server" Width="125">
              Result:
              </asp:Label>
              </td>
              <td width="50">
              <input id="txtResult" type="text" size="5" maxlength="5"
              NAME="txtResult" readonly>
              </td>
              </tr>
              </table>
              <br>
              <table>
              <tr>
              <td width="150" align="center">
              <input id="btnDivide" onclick="return btnDivide_Clicked()"
              type="submit" value=" Divide " name="btnDivide">
              </td>
              </tr>
              </table>
              
    1. 此代码将创建两个输入的文本框、 一个计算按钮以及一个显示结果的第三个文本框。
    1. 复制并将以下代码粘贴到您的页 ; 确保要将代码块放置在第一个 <body> 标记之前:
    2. <SCRIPT language="javascript">
              function btnDivide_Clicked()
              {    var intNumber1 = 0;
              var intNumber2 = 0;
              var intResult = 0;
              intNumber1 = document.all('txtNumber1').value;
              intNumber2 = document.all('txtNumber1').value;
              intResult = intNumber1/intNumber2;
              document.all('txtResult').value = intResult;
              return false;
              }
              </SCRIPT>
              
    3. 此代码程序按钮,以便单击按钮时发生的以下功能:
    4. 检索输入的值。
    • 计算输入。
    • 显示结果。

    1. 单击 保存
    2. 要测试项目,请按照下列步骤操作:
    3. 调试 菜单中上, 单击 开始 生成并运行该应用程序。 WebForm 1 在浏览器中打开,并显示两个输入的文本框、 结果文本框和按钮。
    4. 在将 第一个号码 文本框中,键入 16
    5. 第二个号码 文本框中,键入 2
    6. 单击 。 请注意 结果 文本框不显示 8 正如您所期望的那样。
    7. 关闭 Internet Explorer。

    调试应用程序

    Microsoft 脚本调试程序可用于调试在 ASP.NET 应用程序中的客户端脚本。 您可以使用"调试器"关键字来调用 Microsoft 脚本调试器以编程方式在脚本代码。
    1. 与第一个代码 btnDivide_Clicked 过程中添加以下代码:
         debugger
              
      此关键字指示脚本调试器应在此停止执行和启动调试器。 此关键字允许您跟踪在例程的其余部分变量的值。
    2. 单击 保存
    3. 要运行该项目,请按下列步骤操作:
      1. 调试 菜单中上, 单击 开始 生成并运行该应用程序。
      2. 当页打开在浏览器类型 16 第一个号码 文本框中。
      3. 第二个号码 文本框中,键入 2
      4. 单击 。 请注意执行停止在该调试器关键字和该控制将转到 Visual Studio.NET 或 Visual Studio 2005 集成开发环境 (IDE)。
      5. 关闭 Internet Explorer。
    4. 右键单击下面的代码行:
         intResult = intNumber1/intNumber2;
              
      然后单击 插入断点
    5. 调试 菜单中上, 单击 继续
    6. 调试 菜单上指向 Windows ,然后单击 局部变量 。 请注意这为 16 设置 intNumber 1 的值按预期方式。 但是,请注意这也设置的值 intNumber 2 为 16,它不对应于您键入的值。 intNumber 2 变量已赋值相同 intNumber 1 的值。
    7. 调试 菜单中上, 单击以关闭调试器和浏览器窗口的 停止调试 。 在控制返回到 IDE。

    修改代码

    1. 将代码
         intNumber2 = document.all('txtNumber1').value;
              
      使用下面的代码向 intNumber 2 变量分配正确的值:
         intNumber2 = document.all('txtNumber2').value;
              
    2. 单击 保存
    3. 要再次测试项目,请请按照下列步骤操作:
      1. 调试 菜单中上, 单击 开始 生成并运行该应用程序。
      2. 当页打开在浏览器类型 16 第一个号码 文本框中。
      3. 第二个号码 文本框中,键入 2
      4. 单击 。 请注意执行将在 btnDivide_Clicked 例程的开头处停止。
      5. 确保局部变量窗口是打开状态。 在 调试 菜单中上, 单击 逐语句 逐句通过代码行的行,直到到达 返回 语句。 请注意 intNumber 1 intNumber 2 变量显示正确的值。
      6. 调试 菜单中上, 单击 继续 。 控制返回到浏览器,并在 结果 文本框显示正确结果。
  •            g. 关闭 Internet Explorer。

    完整代码列表

    创建应用程序

    <%@ Page Language="vb" AutoEventWireup="false" Codebehind = "WebForm1.aspx.vb"
        Inherits="ScriptDebuggingExample.WebForm1"%>
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
        <HTML>
        <HEAD>
        <title>WebForm1</title>
        <meta content="Microsoft Visual Studio.NET 7.0" name="GENERATOR">
        <meta content="Visual Basic 7.0" name="CODE_LANGUAGE">
        <meta content="JavaScript" name="vs_defaultClientScript">
        <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
        <SCRIPT language="javascript">
        function btnDivide_Clicked()
        {  var intNumber1 = 0;
        var intNumber2 = 0;
        var intResult = 0;
        intNumber1 = document.all('txtNumber1').value;
        intNumber2 = document.all('txtNumber1').value;
        intResult = intNumber1/intNumber2;
        document.all('txtResult').value = intResult;
        return false;
        }
        </SCRIPT>
        </HEAD>
        <body MS_POSITIONING="GridLayout">
        <form id="Form1" method="post">
        <table>
        <tr>
        <td width="100">
        <asp:label id="lblFirstNumber" runat="server" Width="125">
        First Number:
        </asp:label>
        </td>
        <td width="50">
        <input id="txtNumber1" type="text" maxLength="3"
        size="5" name="txtNumber1">
        </td>
        </tr>
        <tr>
        <td width="100">
        <asp:label id="lblSecondNumber" runat="server" <BR/>
        Width="125">
        Second Number:
        </asp:label>
        </td>
        <td width="50">
        <input id="txtNumber2" type="text" maxLength="3"
        size="5" name="txtNumber2">
        </td>
        </tr>
        <tr>
        <td width="100">
        <asp:Label id="lblResult" runat="server" Width="125">
        Result:
        </asp:Label>
        </td>
        <td width="50">
        <input id="txtResult" type="text" size="5" maxlength="5"
        NAME="txtResult" readonly>
        </td>
        </tr>
        </table>
        <table>
        <tr>
        <td width="75" align="center">
        <input id="btnDivide" value=" Divide "
        onclick="return btnDivide_Clicked()"
        type="submit" size="50" name="btnDivide">
        </td>
        </tr>
        </table>
        </form>
        </body>
        </HTML>
        

    调试应用程序

    <%@ Page Language="vb" AutoEventWireup="false" Codebehind = "WebForm1.aspx.vb"
        Inherits="ScriptDebuggingExample.WebForm1"%>
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
        <HTML>
        <HEAD>
        <title>WebForm1</title>
        <meta content="Microsoft Visual Studio.NET 7.0" name="GENERATOR">
        <meta content="Visual Basic 7.0" name="CODE_LANGUAGE">
        <meta content="JavaScript" name="vs_defaultClientScript">
        <meta content="http://schemas.microsoft.com/intellisense/ie5"
        name="vs_targetSchema">
        <SCRIPT language="javascript">
        function btnDivide_Clicked()
        {  debugger
        var intNumber1 = 0;
        var intNumber2 = 0;
        var intResult = 0;
        intNumber1 = document.all('txtNumber1').value;
        intNumber2 = document.all('txtNumber1').value;
        intResult = intNumber1/intNumber2;
        document.all('txtResult').value = intResult;
        return false;
        }
        </SCRIPT>
        </HEAD>
        <body MS_POSITIONING="GridLayout">
        <form id="Form1" method="post">
        <table>
        <tr>
        <td width="100">
        <asp:label id="lblFirstNumber" runat="server"
        Width="125">
        First Number:
        </asp:label>
        </td>
        <td width="50">
        <input id="txtNumber1" type="text" maxLength="3"
        size="5" name="txtNumber1">
        </td>
        </tr>
        <tr>
        <td width="100">
        <asp:label id="lblSecondNumber" runat="server"
        Width="125">
        Second Number:
        </asp:label>
        </td>
        <td width="50">
        <input id="txtNumber2" type="text" maxLength="3"
        size="5" name="txtNumber2">
        </td>
        </tr>
        <tr>
        <td width="100">
        <asp:Label id="lblResult" runat="server" Width="125">
        Result:
        </asp:Label>
        </td>
        <td width="50">
        <input id="txtResult" type="text" size="5" maxlength="5"
        NAME="txtResult" readonly>
        </td>
        </tr>
        </table>
        <br>
        <table>
        <tr>
        <td width="75" align="center">
        <input id="btnDivide" value=" Divide "
        onclick="return btnDivide_Clicked()"
        type="submit" size="50" name="btnDivide">
        </td>
        </tr>
        </table>
        </form>
        </body>
        </HTML>
        

    修改代码

    <%@ Page Language="vb" AutoEventWireup="false" Codebehind = "WebForm1.aspx.vb"
        Inherits="ScriptDebuggingExample.WebForm1"%>
        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
        <HTML>
        <HEAD>
        <title>WebForm1</title>
        <meta content="Microsoft Visual Studio.NET 7.0" name="GENERATOR">
        <meta content="Visual Basic 7.0" name="CODE_LANGUAGE">
        <meta content="JavaScript" name="vs_defaultClientScript">
        <meta content="http://schemas.microsoft.com/intellisense/ie5"
        name="vs_targetSchema">
        <SCRIPT language="javascript">
        function btnDivide_Clicked()
        {  debugger
        var intNumber1 = 0;
        var intNumber2 = 0;
        var intResult = 0;
        intNumber1 = document.all('txtNumber1').value;
        intNumber2 = document.all('txtNumber2').value;
        intResult = intNumber1/intNumber2;
        document.all('txtResult').value = intResult;
        return false;
        }
        </SCRIPT>
        </HEAD>
        <body MS_POSITIONING="GridLayout">
        <form id="Form1" method="post">
        <table>
        <tr>
        <td width="100">
        <asp:label id="lblFirstNumber" runat="server"
        Width="125">
        First Number:
        </asp:label>
        </td>
        <td width="50">
        <input id="txtNumber1" type="text" maxLength="3"
        size="5" name="txtNumber1">
        </td>
        </tr>
        <tr>
        <td width="100">
        <asp:label id="lblSecondNumber" runat="server"
        Width="125">
        Second Number:
        </asp:label>
        </td>
        <td width="50">
        <input id="txtNumber2" type="text" maxLength="3"
        size="5" name="txtNumber2">
        </td>
        </tr>
        <tr>
        <td width="100">
        <asp:Label id="lblResult" runat="server" Width="125">
        Result:
        </asp:Label>
        </td>
        <td width="50">
        <input id="txtResult" type="text" size="5" maxlength="5"
        NAME="txtResult" readonly>
        </td>
        </tr>
        </table>
        <br>
        <table>
        <tr>
        <td width="75" align="center">
        <input id="btnDivide" value=" Divide "
        onclick="return btnDivide_Clicked()"
        type="submit" size="50" name="btnDivide">
        </td>
        </tr>
        </table>
        </form>
        </body>
        </HTML>
        
posted @ 2009-05-06 00:27 -> 阅读(14) 评论(0)  编辑

2009年4月27日 #

posted @ 2009-04-27 23:05 -> 阅读(74) 评论(0)  编辑

原文地址:http://www.codeguru.com/cpp/misc/misc/stack/article.php/c3875/

Chavdar Dimitrov (view profile)
November 14, 2002

Environment: MSVC6, Borland C++ 5.02, Borland C++ Builder 6, NT4, Win2000

In this essay, I am going to show you how the most commonly used C++ compilers (MSVC and Borland) use the stack. Beginners will learn how the stack is used, what the function stack frame is, what the stack frame pointer is, and how to use this information to get a function stack trace. I hope that the more advanced readers will find some interesting information, too.


(continued)



As an example, a simple class named StackDumper is described. The class StackDumper has a method that browses the thread's stack and allows you to save in a text file the names (or addresses in the worst case) of all functions executed before the foo is called. As a side effect of this functionality, you will be able to ask the StackDumper whether foo is called from foo1.

The task became a little bit complicated by my intention to create a class that is not dependent on any particular compiler. If you download the article demo, you will find three projects—for MSVC++ 6, for Borland C++ 5.02, and for Borland C++ Builder 6.

If you are using the VC++ compiler, there is an easy and already described way to implement this functionality. John Panzer has published in the C/C++ Users Journal, January 1999, his essay "Automatic Code Instrumentation." Shortly, he uses the /Gh compiler switch to force the compiler to generate a call to a _penter function at the start of each client function. From inside _penter, the address of the caller is retrieved and stored in a parallel stack. It also records the function entry time. Afterwards, the original return address of the caller is replaced by the address of a user function. This function is used for profiling purposes. When it is called, it records the function exit time and restores the original return address of the caller.

This is the main idea. You can download the essay from here. Obviously, this approach uses a Microsoft-specific compiler switch. Due to the parallel stack support, special attention should be paid to the case when an exception occurs in one of the profiled functions.

The compiler generates a hidden call to the _penter function in all user functions; this is not very flexible because you may not want to collect information about every function.

The same functionality can be implemented by the well-known concept of stack backtrace. The idea is to use the stack frame that each function builds on the stack to trace the calling sequence. This approach is compiler independent (at least it works with both MSVC and Borland compilers), but it also imposes some limitations. Most compilers provide options to compile a function without prolog and epilog code. For example, functions declared with the __declspec(naked) attribute will be compiled by MSVC++ and Borland C++ compilers without prolog and epilog code. The same effect can be reached by specifying some compiler options for optimizations. For example, the /Oy switch of the Microsoft compiler suppresses the creation of frame pointers on the call stack.

In this essay, I take for granted that the program is compiled without any optimisations or "special" compiler switches.

1. How the Stack Is Used

1.1. Stack Frame and Frame Pointer

Here is a brief explanation for those of you who are not familiar with the way the stack is used during function calls.
The more advanced readers can skip this section. When a function is called, its arguments are pushed first on the stack, depending on the calling convention.

Then, the call instruction is executed. It pushes the return address on the stack. The first instruction of the function is push ebp—the base pointer is pushed. The stack pointer is moved in the ebp, than esp is decremented to make room on the stack for the local variables of the function. So, for every called function, the following information is built on the stack:

Figure 1.

This information is called the "stack frame." The register ebp has a special meaning. It is called the "frame pointer." The frame pointer is initialized at the function start by the standard prolog code and stays unchanged during function execution.

The value of the previous function frame pointer is restored when the current function exits (epilog). How is the frame pointer used? The compiler uses the frame pointer to refer to local variables and parameters of a function (if any).

  1. *(ebp) is the value of the frame pointer of the caller;
  2. *(ebp+4) is the return address (the place in the caller body where execution will continue after the callee returns);
  3. *(ebp+4+4*i) is the value of i-th function argument (1 based, assuming that each argument takes 4 bytes);
  4. *(ebp-offset) refers to local variables.

You can see this operation in the following simple example:

int func(int nArg1, int nArg2)
{
int n[3];
return nArg1;
}

int main()
{
func(0,1);

return 1;
}

The Borland C++ 5.02 compiler generates the following assembly code(__cdecl calling convention—the arguments are pushed on the stack from right to left, the caller cleans the stack. More information about calling convention can be found here):

Dissassembly of main:
00401110 55 push ebp store the ebp register on the stack
00401111 8B EC mov ebp, esp current stack pointer in ebp
00401113 6A 01 push 1 the arguments of func are pushed on the stack from right to left
00401115 6A 00 push 0  
00401117 E8 EC FF FF FF call func this call pushes the return address (0040111C) on the stack
0040111C 83 C4 08 add esp, 8 __cdecl calling convention; caller has to clean the space that arguments used on the stack. Every push decrements the stack pointer and every pop increments it by the size of the operand. Two ints are pushed on the stack => the stack pointer has to be increased by 8.
0040111F B8 01 00 00 00 mov eax, 1 the return value of main goes in eax
00401124 5D pop ebp ebp is restored
00401125 C3 ret    
Dissassembly of func:
00401108 55 push ebp | prolog
00401109 8B EC mov ebp, esp |
0040110B 83 C4 F4 add esp, -0x0c make room for 3*4 bytes for the local variable n on the stack

add esp, -0x0c make room for 3*4 bytes for the local variable n on the stack
0040110E 8B 45 08 mov eax, [ebp+0x08] move the return value (nArg1) in eax
00401111 8B E5 mov esp, ebp | epilog. epb contains the caller frame ptr
00401113 5D pop ebp |
00401114 C3 ret    

1.2. Callstack

It is not very hard to see how the stack frame of a function can be used to get the caller address of this function. As I have mentioned before, *(ebp+4) points to the return address of the function. This address is inside the body of the caller.

1.2.1. How to Get the Starting Address of the Caller

Approach 1: Prolog searching

We supposed that all functions are compiled with a prolog and an epilog. Having an address inside the function, we just have to search for the byte sequence 55 8B EC. As you can see from the dissassembly above, these are the opcodes of the prolog. Let's call them the "prolog signature."

Unfortunately, there is a problem. The same sequence of bytes could appear in an instruction encoding. For example, the instruction mov eax, EC8B55h has the following instruction encoding: B8 55 8B EC 00.

Obviously, when we are searching the prolog signature byte by byte we will find the signature somewhere inside the mov instruction.

Note: In my experience, the method of searching the prolog signature in most cases works fine. To keep things simple, you can skip the next section.

Well, I don't have an elegant solution to the above described problem. For that reason, I am going to kill a mosquito with a nuclear bomb.

Approach 2: Backwards disassembling

Given an address inside the body of a function, it is quite enough to find the address of the previous instruction. This task cannot be solved without knowing the instruction format. We need a disassembler to do this. You can find in the source a function called FindAddressOfPrevInstruction:

#define  MAX_INTEL_INSTRUCTION_LEN 15
DWORD FindAddressOfPrevInstruction(DWORD EIP, PUCHAR instr)
{
DWORD Addr = EIP-MAX_INTEL_INSTRUCTION_LEN;
DWORD PrevAddr;
unsigned long res;

do
{
PrevAddr=Addr;
res = Disasm32(&Addr, instr);
} while(Addr < EIP);

EIP=PrevAddr;

return EIP;
}

I think this function is straightforward. Having this function, it is easy to find the prolog signature in a more precise way—you just have to disassemble backwards until you find the prolog signature.

1.2.2. Tracing the Stack

As you can see from Figure 1, every function stack frame contains a pointer to the caller's frame that contains a pointer to its caller frame, and so on. In fact, we have a list of stack frames which can be used to find the callstack of every called function. But still there is an important question: When do we have to stop stack browsing, or, in other words, when does this list begin?

I think we can find the answer if we take a look at the process and thread starting routines which resides in kernel32.dll. When Windows creates a process and its main thread, it performs an internal call to the CreateProcess API. CreateProcess, on the other hand, invokes an internal routine in kernel32.dll named BaseProcessStart. Here is the disassembly (under the condition that you have kernel32.pdb):

KERNEL32!BaseProcessStartThunk:
77e8d2e4 xor ebp,ebp Look here!
77e8d2e6 push eax  
77e8d2e7 push 0x0 This can be interpreted as a return address
KERNEL32!BaseProcessStart:
77e8d2e9 push ebp This is a normal stack frame. But the previous frame ptr is zeroed a few lines above
77e8d2ea mov ebp,esp  
77e8d2ec push 0xff  
...snip...
77e8d323 call dword ptr [ebp+0x8] call the entry point of our process (for example, mainCRTStartup)
77e8d326 jmp KERNEL32!BaseProcessStart+0x3d (77eb6624)  

Similar things are happening in each call to the CreateThread API:

KERNEL32!BaseThreadStartThunk:
77e964cb xor ebp,ebp  
77e964cd push ebx  
77e964ce push eax  
77e964cf push 0x0  
KERNEL32!BaseThreadStart:
77e964d1 55 push ebp  
77e964d2 8bec mov ebp,esp  
77e964d4 6aff push 0xff  
...snip...
77e9651d ff750c push dword ptr [ebp+0xc] push the argument to ThreadFunc
77e96520 ff5508 call dword ptr [ebp+0x8] DWORD WINAPI ThreadFunc( LPVOID );
77e96523 50 push eax  
77e96524 e805000000 call KERNEL32!ExitThread (77e9652e)  
77e96529 e923f10000 jmp KERNEL32!BaseThreadStart+0x81 (77ea5651)  

Judging from the examples above, I think we can conclude that stack frames tracing can stop when either the return address or the old ebp turns to zero.

1.3. "Called from" Functionality

Up to now, we know how to create a callstack list (a list of addresses of functions). I would like to say a few words about the following question: Is it possible to implement a method that will allow the following C++ functionality?

retType foo(arguments)
{
if (foo_is_called_from_functionX)
doThings
else
doOtherThings

return whateverHasToBeReturned
}

Two additional questions arise here:

1.3.1 Do We Need Such a Functionality?

This functionality could be considered as a new type of C++ runtime information. Because it is not implemented in the C++ standard, it is probably useless.... In my opinion, this is a theoretical question and it should be the subject of a separate discussion.

1.3.2. How to Implement This Functionality

Because we know the call stack of foo, it may seems trivial to browse the caller addresses searching for the address of functionX. Unfortunately, things are not so simple. The main difficulty is how to get the address of functionX. functionX can be a class member (virtual or nonvirtual) function.

There is no way to get the "real" address of a function from inside a C++ program. By "real address," I mean the relative virtual address where the compiler placed the function body. In most cases, when you get a function address from inside a C++ program, it does not appear to be a real address, but rather an address in some virtual or thunking table.

On the other hand, it is definitely clear that callstack addresses are real addresses. So, what can we do in this case? The only simple solution I have found is to use function names instead of their addresses. This is because there is a relatively easy way(s) to find the address of a function, having been given its name. This will allow us to implement the above function as follows:

retType foo(arguments)
{
if (IsCalledFrom("functionX") || IsCalledFrom("A::member1"))
doThings
else
doOtherThings

return whateverHasToBeReturned
}

Now the question is how to find the address of a function given its name. There are two common ways to do this:

1. The development environment provides libraries that allow working with symbolic information.

For example, Microsoft provides the debug help library named DbgHelp (prior to Windows 2000, the library was known as the Image Help Library). The library contains functions for working with symbolic information; for example SymGetSymFromName, SymFromName, and so forth. As an example of using the DbgHelp library, here is the function getFuncInfo you can find in the source. As far as I know, Borland provides a similar library named Borland Debug Hook Library, that can be used to extract information from Borland debug symbol (.tds) files. Unfortunately, there is not much information on the Net about how to use this library. You can download it from here.

2. Working with .map files

Both the Microsoft VC++ and Borland C++ compilers are able to generate .map files. Generally speaking, .map files are text files that contain information about functions (and variables) in a module and their addresses. For example, here is a snippet of a .map file generated by the Borland C++ 5.02 compiler:

 0001:000006F5      StackDumper::DumpStack(unsigned int)
0001:00000694 StackDumper::GetCallerAddr(long)
0001:000006C5 StackDumper::GetFuncAddr(unsigned long)
0001:000005FC StackDumper::StackDumper()
0001:00000639 StackDumper::~StackDumper()

The important thing here is that the addresses are logical addresses. For example, 0001:00000639 means that the destructor StackDumper::~StackDumper() resides in the first section in the PE file at offset 0x639 in that section. In the source, you can find a simple function (written by Matt Pietrek) that converts linear addresses to logical addresses. Using this function, you can convert the addresses from the stack trace into logical addresses that can be found in the .map file. Having the logical address you just have to parse the .map file to find the function name.

As a conclusion, I have to say that I don't have any idea about how to implement the IsCalledFrom functionality in your release builds—when you have neither debug information nor a .map file generated (or you don't want to distribute such information with your program).

2. Exit Thunks

In this section, I will describe how to use the stack frame information in order to implement exit thunks. An exit thunk is a function that is invoked immediately after the ret instruction of the function for which the thunk is installed. Exit thunks can be used, for example, in profiling applications. Here they are implemented just as another example of how to use the stack frame information. The idea is very simple—to install an exit thunk we just have to declare a local variable: StackDumper varName(true) (true means "use exit thunk") in the body of the function for which we want to install the thunk. The destructor StackDumper::~StackDumper() first saves the original return address of the function(for example, foo) where StackDumper is declared in a static local variable in StackDumper.

Afterwards, it replaces the return address of foo with the address of the ExitThunk. This causes the ret instruction of foo to pass the control to the beginning of the ExitThunk. (Note that the destructor is the right place to perform this replacement. If we replace the function return address in the constructor (for instance), subsequent calls to the DumpStack function will generate erroneous stack trace information.) This is not a common function call—the ret instruction has popped the return address from the stack (which is now the address of ExitThunk) and a jump is performed. So, if ExitThunk builds a standard stack frame, this frame will not contain a return address.

Another problem is that ExitThunk has to be "invisible"—it should not touch the registers, especially eax—where the foo has placed its return value (if any). If ExitThunk is a standard function, it will have something like this at the beginning(MSVC, Debug):

50:   void main()
51: {
004010F2 55 push ebp
004010F3 8B EC mov ebp,esp
004010F5 6A FF push 0FFh
004010F7 68 F0 30 41 00 push offset $L49591 (004130f0)
004010FC 64 A1 00 00 00 00 mov eax,fs:[00000000]
// Look here: The eax register is changed and there is nothing you
// can do!!!
00401102 50 push eax
00401103 64 89 25 00 00 00 00 mov dword ptr fs:[0],esp
...

You see that ExitThunk could not be a normal function. This is the reason for which this function must be declared naked. From MSDN: "For functions declared with the naked attribute, the compiler generates code without prolog and epilog code. You can use this feature to write your own prolog/epilog code using inline assembler code." Fortunately, the three compilers I have tested the examples with (BC++ 5.02, BCB6, MSVC6) support naked function calls. (For Borland C++ 5.02 users, this is probably a surprise. This was not documented. ;-))).

This is the solution of the above-mentioned problems. So, the implementation of ExitThunk could be the following:

/* static  */
void __declspec(naked) StackDumper::ExitThunk()
{
__asm
{
push ebp
mov ebp, esp
sub esp, 4 //make room for one local variable
pushad
}

DoTheWork();

long temp;
temp = origRetAddr;
__asm{
popad
mov esi, temp
mov esp,ebp
pop ebp
jmp esi //I don't have return value on the stack
//-> can not use ret here.
}
}

Well, that's all, folks!

Acknowledgements

I would like to thank mamaich for his help on disassembling issues!

Note about the source compilation. To compile inline assembler source code with the Borland C++ 5.02, you will need the Turbo Assembler (tasm32.exe). The tasm32.exe is not included in Borland C++ 5.02 distribution. If you have BC++ Builder, you will find the tasm32.exe in the bin folder.

Downloads

Download source InstallDemo.zip - 108Kb
posted @ 2009-04-27 23:02 -> 阅读(72) 评论(0)  编辑

posted @ 2009-04-27 21:26 -> 阅读(326) 评论(0)  编辑

2009年4月25日 #

原文地址:http://www.joecodegood.net/tread/


Tread is a map editor for Quake 1/2/3 based on MFC and OpenGL that runs on Windows XP and Vista. (If anyone has the chance, let me know if it works under Wine or anything similiar just curious...).

This version of the editor is completely new, and is in no way similar or based on the older versions of the editor that have been around since the late 90's.

Forums

1.13.09 9:30 p.m.

I've added forums, the link is on the top left. Please feel free to post comments and questions.

Alpha 2 - Prelim Quake3 Support, Fixed Bugs

7.16.08 11:15 p.m.

I spent this last weekend fixing various bugs and adding preliminary Quake 3 support. Currently the editor does not read or write the brushDef style map files so you will most likely not be able to import maps built in other editors yet. There is also no patch support.

I also removed a bunch of crap from the source tree, so the source download for this new version is less than half the size of the old one.

Some people may notice that right now the editor doesn't work out of anything except pak files. I realize that this is limiting for people who have custom content and don't want to make pak files for it during development. I'll be adding that at some point down the line.

For the less hardcore, Tread does some work for you to extract the necessary files for the compiler tools so you don't have to extract any pak files for any of the Quake games. The goal is for it to work "out of the box" .

Installation

Tread does not need to be installed (there is no installer). Simply unzip the binaries wherever you want and run the Tread executable. Currently the editor supports Quake 1, 2, and 3. The configuration of the editor should be straightforward.

Steam

If you purchased Quake 1, 2 or 3 from Steam, then there are a couple tricks you need to do to get your maps to build and run in an integrated fashion with the editor.

For Quake, I recommend you download GLQuake and put it into your Quake folder, and point the editor to that. If you don't want to do that then point the editor to your Steam.exe and add the following in your game command line in the editor minus the quotes: "-applaunch 2310"

For Quake2, point the editor to your Steam.exe and add "-applaunch 2320" minus the quotes to your game command line in the editor.

For Quake3, point the editor to your Steam.exe and add "-applaunch 2200 +sv_pure 0".

In all cases make sure that you set the game directory to the correct spot.

Basic Navigation and Shortcut Keys

This new version of Tread is totally different from the older versions. People that have used the older versions won't find anything familiar here. This version of the editor is focused towards a fast workflow, and more intuitive and fluid editing (there are no "modes" like in WorldCraft and Tread3D2).

  • Probably the most unique feature of the editor is that the undo history saves with the map (up to 64 levels) .
  • ALT + right click creates the currently selected creation type (located on the right hand side).
  • The gizmos to drag and scale only respond to moving the mouse up and down.
  • The middle mouse button is used to navigate and zoom. Holding it down in any of the views will pan you around. Scrolling will zoom in or out. This applies to the texture view as well.
  • The 3D navigation is based on the 3DS MAX interface. Holding middle mouse + ALT will rotate you around your selection. If you have no selection you will rotate in place. If you have a selection and don't want to rotate around it then middle mouse + ALT + SHIFT will rotate you in place.
  • Press the Escape key to deselect.
  • Most objects have a right-click context menu which is the primary way you edit them.
  • You can nudge objects using the arrow keys (the nudge factor is on the right dock bar).
  • SHIFT + Drag duplicates the selection
  • Holding CTRL while dragging one of the translate gizmos will rotate the object in 15 degree increments. Holding CTRL + SHIFT will rotate in a fine control mode.
  • In face mode, the faces you are editing are not highlighted red (done so you can see what you're doing to it).
  • In face mode, left drag shifts the texture on the x axis, SHIFT + left drag shifts on the y axis, CTRL + left drag scales, and ALT + left drag rotates the texture.
  • Bounding box selection works in all views. Hold CTRL to add to the selection, hold ALT to remove from it (including in vertex mode).
  • You can't delete vertices you can collapse them and the editor will merge them.
  • SHIFT + left click in vertex mode in a 2D view will not select vertices on top of each other, only the closest one will be selected.
  • Press W while hovering over any view to maximize it. Press W again to restore it.
  • Press M while hovering over any view to turn it into a texture view, press M again to restore it.
  • Right click in the upper left hand corner of any view to see its options.
  • License

    Tread and its source are released under a free software license, and can be used for commercial and non-commercial purposes free of charge. Refer to the licensing terms in the source code for source licensing terms.

    Building the source code.

    The code should build without problems under Visual Studio 2005. Open the Tread.sln file and you should be good to go.

    The plugin architecture should give people the ability to do most things they need (all the Quake/Quake2 support is isolated in a plugin). Developers should be able to easily write plugins to export their own map files. The full source code is released for people to completely redo the entire application or make large changes if they want to.

    I don't stand by the code in this editor (although it is better than the predecessor versions of Tread). It was built quickly (over about 8 weeks if I recall correctly), and has some fairly odd things in it, like the lack of STL where it would have been really useful. The code is manageable enough. At one point I was considering resurrecting it for a modern project but the tool chain for my currently technology is too .NET centric for it to be worth the trouble to effectively interface.

    ----------------------------------------------------------------------------------------------
    posted @ 2009-04-25 22:26 -> 阅读(98) 评论(0)  编辑

    2009年4月24日 #

    腾讯官方绿茶活动--Head(头部)的第1段JavaScript脚本代码(带行号)
    地址:http://act.qzone.qq.com/uni-greentea/index.html

    <script src="http://qzone.qq.com/js/login.js" type="text/javascript">
    1var g_init = null;
    2var g_myBodyInstance = null;
    3var g_myBodyInstanceString = null;
    4var isMinNS4 = null;
    5var isMinNS5 = null;
    6var isMinIE4 = null;
    7var isMinIE5 = null;
    8var isMacIE = null;
    9var getFFVersion = null;
    10var FFextraHeight = null;
    11var isOpera = null;
    12
    13var w_rs = null;
    14var w_sc = null;
    15
    16var encjs = "http://qzone.qq.com/js/ps.js";
    17var dflt_css = "http://qzone.qq.com/js/login.css";
    18var css_obj = null;
    19var css_rel = null;
    20var login_window = null;
    21var mask_layer = null;
    22var drag_div = null;
    23var fix_div = null;
    24var module_div = null;
    25var timer = null;
    26
    27function qq_login_form(aid)
    28{
    29 if ( !g_init )
    30 {
    31 // initialize global variables
    32 g_myBodyInstance = document.body;
    33 g_myBodyInstanceString = "document.body";
    34 isMinNS4 = (navigator.appName.indexOf("Netscape") >= 0 && parseFloat(navigator.appVersion) >= 4) ? 1 : 0;
    35 isMinNS5 = (navigator.appName.indexOf("Netscape") >= 0 && parseFloat(navigator.appVersion) >= 5) ? 1 : 0;
    36 isMinIE4 = (document.all) ? 1 : 0;
    37 isMinIE5 = (isMinIE4 && navigator.appVersion.indexOf("5.") >= 0) ? 1 : 0;
    38 isMacIE = (isMinIE4 && navigator.userAgent.indexOf("Mac") >= 0) ? 1 : 0;
    39 getFFVersion = navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1];
    40 //extra height in px to add to iframe in FireFox 1.0+ browsers
    41 FFextraHeight = getFFVersion < 1.5 ? 16 : 0;
    42 isOpera = (navigator.appName.indexOf("Opera") >= 0) ? 1 : 0;
    43
    44 if ( document.compatMode != "BackCompat" && !isOpera )
    45 {
    46 // for looser.dtd
    47 g_myBodyInstance = document.documentElement;
    48 g_myBodyInstanceString = "document.documentElement";
    49 }
    50
    51 g_init = true;
    52 // initialize done
    53 }
    54
    55 var aid_pt = /\d+/;
    56
    57 // get APPID
    58 if ( !aid_pt.test(aid) )
    59 {
    60 return;
    61 }
    62
    63 // get all arguments
    64 var argv = qq_login_form.arguments;
    65
    66 // get redirect url
    67 if ( argv[1] )
    68 {
    69 redirect_url = argv[1];
    70 }
    71 else
    72 {
    73 redirect_url = window.location;
    74 }
    75
    76 // get err_callback url
    77 if ( argv[2] )
    78 {
    79 fp_val = argv[2];
    80 }
    81 else
    82 {
    83 fp_val = 'loginerroralert';
    84 }
    85
    86 // get target window
    87 if ( argv[3] )
    88 {
    89 target_win = argv[3];
    90 }
    91 else
    92 {
    93 target_win = "_self";
    94 }
    95
    96 // get css url
    97 if ( argv[4] )
    98 {
    99 css_url = argv[4];
    100 }
    101 else
    102 {
    103 css_url = dflt_css;
    104 }
    105
    106 if ( !css_obj || (css_rel != css_url) )
    107 {
    108 css_obj = document.getElementById('login_css');
    109
    110 if ( !css_obj )
    111 {
    112 // add login css
    113 var login_css = document.createElement('link');
    114 login_css.id = 'login_css';
    115 login_css.rel = 'stylesheet';
    116 login_css.type = 'text/css';
    117 login_css.media = 'screen';
    118 login_css.href = css_url;
    119 document.body.appendChild(login_css);
    120
    121 css_obj = login_css;
    122 }
    123 else
    124 {
    125 css_obj.href = css_url;
    126 }
    127
    128 css_rel = css_url;
    129 }
    130
    131 if ( !login_window )
    132 {
    133 // add encrypt js
    134 var encScript = document.createElement('script');
    135 encScript.src = encjs;
    136 encScript.type = "text/javascript";
    137 document.body.appendChild(encScript);
    138
    139 // add div element
    140 var divE = document.createElement('div');
    141 divE.id = 'login_container';
    142 //divE.style.display = 'none';
    143 divE.style.visibility = 'hidden';
    144 //divE.style.filter = 'Alpha(opacity=0)';
    145 divE.style.opacity = 0;
    146
    147 var login_HTML = "";
    148
    149 if ( navigator.userAgent.indexOf('MSIE') != -1 )
    150 {
    151 login_HTML += "<iframe id=\"mask_iframe\" src=\"\"></iframe>";
    152 }
    153
    154 login_HTML += " <div id=\"login_header\">";
    155 login_HTML += " <h4>请您登录</h4>";
    156 login_HTML += " <span id=\"close\" onclick=\"javascript:setLoginFormVisible('hide');\"><span class=\"none\">关闭

    </span></span>";
    157 login_HTML += " </div>";
    158 login_HTML += " <div id=\"login_form\">";
    159 login_HTML += " <form id=\"user_login\" name=\"user_login\" action=\"http://ptlogin2.qq.com/login\" method=\"post\"

    enctype=\"application/x-www-form-urlencoded\" target=\"" + target_win + "\" autocomplete=\"off\" onSubmit=\"javascript:return

    process(user_login);\">";
    160 //login_HTML += " <form id=\"user_login\" name=\"user_login\" action=\"http://ptlogin.qq.com/login\" method=\"post\"

    enctype=\"application/x-www-form-urlencoded\" target=\"" + target_win + "\" autocomplete=\"off\" onSubmit=\"javascript:return

    process(user_login);\">";
    161 login_HTML += " <input type=\"hidden\" name=\"h\" value=\"1\" />";
    162 login_HTML += " <input type=\"hidden\" name=\"u1\" value=\"" + redirect_url + "\" />";
    163 login_HTML += " <input type=\"hidden\" name=\"ep\" value=\"\" />";
    164 login_HTML += " <input type=\"hidden\" name=\"fp\" value=\"" + fp_val + "\" />";
    165 login_HTML += " <input type=\"hidden\" name=\"tm\" value=\"31313437373631393337\" />";
    166 login_HTML += " <input type=\"hidden\" name=\"type\" value=\"\" />";
    167 login_HTML += " <input type=\"hidden\" name=\"aid\" value=\"" + aid + "\" />";
    168 login_HTML += " <ul>";
    169 login_HTML += " <li>";
    170 //login_HTML += " <span>QQ帐号:</span>";
    171 login_HTML += " <span>登录名:</span>";
    172 login_HTML += " <label accesskey=\"u\" for=\"u\">";
    173 login_HTML += " <input id=\"u\" name=\"u\" tabindex=\"u\" type=\"text\" style=\"font-size:12px;color:#bcbcbc;ime-

    mode:disabled;\" value=\"QQ号码或Email帐号\" onfocus=\"javascript:swapUserInput();\" onblur=\"javascript:swapUserInput();\"

    />*";
    174 login_HTML += " </label>";
    175 login_HTML += " </li>";
    176 login_HTML += " <li>";
    177 //login_HTML += " <span>QQ密码:</span>";
    178 login_HTML += " <span>密 码:</span>";
    179 login_HTML += " <label accesskey=\"p\" for=\"p\">";
    180 login_HTML += " <input id=\"p\" name=\"p\" tabindex=\"p\" type=\"password\" />*";
    181 login_HTML += " </label>";
    182 login_HTML += " <p><a href=\"http://service.qq.com/psw/mo.shtml?psw_cs.htm\" target=\"_blank\" tabindex=\"-1\" >忘了密码

    ?</a></p>";
    183 login_HTML += " </li>";
    184 login_HTML += " <li>";
    185 login_HTML += " <span class=\"code_span\">验证图片:</span>";
    186 login_HTML += " <img id=\"loginVerifyImg\" src=\"http://ptlogin2.qq.com/getimage?aid=" + aid + "&" + Math.random() + "\"

    width=\"130\" height=\"53\" />";
    187 //login_HTML += " <img id=\"loginVerifyImg\" src=\"http://nverify.qq.com/getimage?" + Math.random() + "\" width=\"130\"

    height=\"53\" />";
    188 login_HTML += " <p><a href=\"javascript:_nchangeImg(" + aid + ");\" tabindex=\"-1\">看不清,换一张</a></p>";
    189 login_HTML += " </li>";
    190 login_HTML += " <li>";
    191 login_HTML += " <span>附加字符:</span>";
    192 login_HTML += " <label accesskey=\"v\" for=\"vrfycode\">";
    193 login_HTML += " <input id=\"vrfycode\" name=\"verifycode\" type=\"text\" class=\"verifycode\" maxlength=\"4\"

    style=\"ime-mode:disabled;\" />*";
    194 login_HTML += " </label>";
    195 login_HTML += " <p>请输入上图中字符,大小写忽略</p>";
    196 login_HTML += " </li>";
    197 login_HTML += " <li>";
    198 login_HTML += " <input name=\"imageField\" type=\"submit\" class=\"bt_login\" value=\"登  录\" border=\"0\">";
    199 login_HTML += " </li>";
    200 login_HTML += " </ul>";
    201 login_HTML += " </form>";
    202 login_HTML += " </div>";
    203
    204 divE.innerHTML = login_HTML;
    205
    206 document.body.appendChild(divE);
    207
    208 login_window = document.getElementById('login_container');
    209
    210 timer = setTimeout("setLoginFormVisible('show')", 500);
    211 }
    212 else
    213 {
    214 _nchangeImg(aid);
    215 timer = null;
    216 }
    217
    218 // Miscellaneous Functions ...
    219 // get drag flag
    220 if ( argv[5] !== undefined )
    221 {
    222 drag = argv[5];
    223 }
    224 else
    225 {
    226 drag = true;
    227 }
    228
    229 // get fix flag
    230 if ( argv[6] !== undefined )
    231 {
    232 fix = argv[6];
    233 }
    234 else
    235 {
    236 fix = false;
    237 }
    238
    239 // get module_div flag
    240 if ( argv[7] !== undefined )
    241 {
    242 l_b = argv[7];
    243 }
    244 else
    245 {
    246 l_b = false;
    247 }
    248
    249 drag_div = drag;
    250 fix_div = fix;
    251 module_div = l_b;
    252
    253 if ( fix || l_b )
    254 {
    255 if ( l_b )
    256 {
    257 makeMaskLayer();
    258 }
    259
    260 attachWinAct();
    261 }
    262
    263 //login_window.style.display == 'none';
    264 //if (login_window && login_window.style.display == 'none')
    265 //{
    266 //setLoginFormVisible('show');
    267 //}
    268
    269 if ( !timer )
    270 {
    271 setLoginFormVisible('show');
    272 }
    273
    274 try {
    275 var useruin = getCookie('saveduin');
    276
    277 if (useruin)
    278 {
    279 target_win.document.user_login.u.value = useruin;
    280 }
    281
    282 //setFocus('u');
    283 } catch(er) {}
    284
    285 document.user_login.p.value = '';
    286 document.user_login.verifycode.value = '';
    287 document.user_login.imageField.disabled = false;
    288
    289 var l_h = document.getElementById("login_header");
    290
    291 if ( drag_div )
    292 {
    293 l_h.onmousedown = startMove;
    294 }
    295 else
    296 {
    297 l_h.onmousedown = null;
    298 }
    299}
    300
    301function swapUserInput()
    302{
    303 var uipt = document.getElementById('u');
    304
    305 if( uipt.value == 'QQ号码或Email帐号' )
    306 {
    307 uipt.value = '';
    308 uipt.style.fontSize = '14px';
    309 uipt.style.color = '#666666';
    310 }
    311 else if ( uipt.value == '' )
    312 {
    313 uipt.value = 'QQ号码或Email帐号';
    314 uipt.style.fontSize = '12px';
    315 uipt.style.color = '#bcbcbc';
    316 }
    317}
    318
    319function _nchangeImg(aid)
    320{
    321 var img = document.getElementById("loginVerifyImg");
    322 //img.src = "http://nverify.qq.com/getimage?" + Math.random();
    323 img.src = "http://ptlogin2.qq.com/getimage?aid=" + aid + "&" + Math.random();
    324 var ctrl = document.getElementById("code");
    325 if (ctrl != null)
    326 {
    327 ctrl.focus();
    328 }
    329}
    330
    331function setCookie(key,value)
    332{
    333 document.cookie = key + "=" + escape(value);
    334}
    335
    336function getCookie(name)
    337{
    338 var pt_str = "(^|.*;)\\s*" + name + "=([^;]*)(;.*|$)";
    339 var pt_obj = new RegExp(pt_str);
    340 var rs = document.cookie.match(pt_obj);
    341 if (rs)
    342 {
    343 return rs[2];
    344 }
    345 return '';
    346}
    347
    348function CheckForm()
    349{
    350 var u_ipt = document.getElementById('u');
    351 var str = u_ipt.value;
    352 var upt1 = /^[1-9]{1}\d{4,9}$/;
    353 var upt2 = /^[a-z0-9_\-]+(\.[_a-z0-9\-]+)*@([_a-z0-9\-]+\.)+([a-z]{2}

    |aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)$/i;
    354 if ( !upt1.test(str) && !upt2.test(str))
    355 {
    356 alert("登录名必须为QQ号码或Email帐号");
    357 u_ipt.focus();
    358 u_ipt.select();
    359 return false;
    360 }
    361 setCookie("saveduin", u_ipt.value);
    362 var p_ipt = document.getElementById('p');
    363 if (p_ipt.value == "")
    364 {
    365 alert("您还没有输入密码!");
    366 p_ipt.focus();
    367 p_ipt.select();
    368 return false;
    369 }
    370 var vcode = document.getElementById('vrfycode');
    371 if (vcode.value.length != 4)
    372 {
    373 alert("请正确填写验证字符!");
    374 vcode.focus();
    375 vcode.select();
    376 return false;
    377 }
    378 return true;
    379}
    380
    381function process(form)
    382{
    383 if (!CheckForm())
    384 {
    385 return false;
    386 }
    387 preprocess(form);
    388 document.user_login.imageField.disabled = true;
    389 return true;
    390}
    391
    392function setLoginFormVisible(vis)
    393{
    394 if (vis != 'hide')
    395 {
    396 login_window.style.display = '';
    397 login_window.style.visibility = 'visible';
    398 //login_window.style.filter = 'Alpha(opacity=100)';
    399 login_window.style.opacity = 1;
    400
    401 if ( getWindowWidth() != getWidth(login_window) )
    402 {
    403 moveLayerTo(login_window,(getWindowWidth()-getWidth(login_window))/2,getPageScrollY()+(getWindowHeight()-getHeight

    (login_window))/2);
    404 }
    405
    406 if ( module_div )
    407 {
    408 mask_layer.style.display = '';
    409 //mask_layer.style.visibility = 'visible';
    410 //mask_layer.style.width = getWindowWidth();
    411 //mask_layer.style.height = getWindowHeight();
    412
    413 //moveLayerTo(mask_layer,(getWindowWidth()-getWidth(mask_layer))/2,getPageScrollY()+(getWindowHeight()-getHeight

    (mask_layer))/2);
    414 }
    415 }
    416 else
    417 {
    418 login_window.style.display = 'none';
    419 //login_window.style.visibility = 'hidden';
    420
    421 if ( module_div )
    422 {
    423 mask_layer.style.display = 'none';
    424 //mask_layer.style.visibility = 'hidden';
    425 }
    426
    427 detacheWinAct();
    428 }
    429}
    430
    431// make module_div mask layer
    432function makeMaskLayer()
    433{
    434 if ( mask_layer )
    435 {
    436 return;
    437 }
    438 else
    439 {
    440 var w = target_win.document.body.scrollWidth; //getWindowWidth();
    441 var h = target_win.document.body.scrollHeight; //getWindowHeight();
    442 var m_layer = document.createElement('div');
    443
    444 m_layer.style.width = w + 'px';
    445 m_layer.style.height = h + 'px';
    446 m_layer.style.background = '#DFE0E1';
    447 m_layer.style.position = 'absolute';
    448 m_layer.style.top = 0;
    449 m_layer.style.left = 0;
    450 m_layer.style.zIndex = 900;
    451 m_layer.style.filter = 'alpha(opacity=50)';
    452 m_layer.style.opacity = 0.5;
    453
    454 var in_HTML = '';
    455
    456 if ( navigator.userAgent.indexOf('MSIE') != -1 )
    457 {
    458 in_HTML = "<iframe id=\"module_iframe\" src=\"\"></iframe>";
    459 m_layer.innerHTML = in_HTML;
    460 }
    461
    462 document.body.appendChild(m_layer);
    463
    464 mask_layer = m_layer;
    465 }
    466}
    467
    468function reposDiv()
    469{
    470 try {
    471 if ( module_div )
    472 {
    473 mask_layer.style.width = target_win.document.body.scrollWidth; //getWindowWidth();
    474 //mask_layer.style.height = getWindowHeight();
    475 //moveLayerTo(mask_layer,(getWindowWidth()-getWidth(mask_layer))/2,getPageScrollY()+(getWindowHeight()-getHeight

    (mask_layer))/2);
    476 }
    477
    478 if ( fix_div )
    479 {
    480 if ( drag_div )
    481 {
    482 moveLayerTo(login_window,login_window.offsetLeft,getPageScrollY()+(getWindowHeight()-login_window.offsetTop));
    483 }
    484 else
    485 {
    486 moveLayerTo(login_window,(getWindowWidth()-getWidth(login_window))/2,getPageScrollY()+(getWindowHeight()-getHeight

    (login_window))/2);
    487 }
    488 }
    489 } catch (e) {}
    490}
    491
    492function attachWinAct()
    493{
    494 if ( w_rs || w_sc )
    495 {
    496 return;
    497 }
    498
    499 var f_rs = window.onresize;
    500 var f_sc = window.onscroll;
    501
    502 if ( typeof(f_rs) == 'function' )
    503 {
    504 w_rs = f_rs;
    505 window.onresize = function (){f_rs();reposDiv();};
    506 }
    507 else
    508 {
    509 window.onresize = reposDiv;
    510 }
    511
    512 if ( typeof(f_sc) == 'function' )
    513 {
    514 w_sc = f_sc;
    515 window.onscroll = function (){f_sc();reposDiv();};
    516 }
    517 else
    518 {
    519 window.onscroll = reposDiv;
    520 }
    521}
    522
    523function detacheWinAct()
    524{
    525 if ( typeof(w_rs) == 'function' )
    526 {
    527 window.onresize = w_rs;
    528 }
    529 else
    530 {
    531 window.onresize = null;
    532 }
    533
    534 if ( typeof(w_sc) == 'function' )
    535 {
    536 window.onscroll = w_sc;
    537 }
    538 else
    539 {
    540 window.onscroll = null;
    541 }
    542
    543 w_rs = null;
    544 w_sc = null;
    545}
    546
    547// drag functions
    548function startMove(evt)
    549{
    550 evt = getCurrentEvent(evt);
    551
    552 if ( !isLeftKeyDown(evt) )
    553 return;
    554
    555 var alertDlg = document.getElementById("login_header");
    556 var loginCtnr = document.getElementById("login_container");
    557 setEventCapture(alertDlg);
    558 stopEventTransfer(evt);
    559 //alertDlg.$clientX = evt.clientX;
    560 //alertDlg.$clientY = evt.clientY;
    561 loginCtnr.$clientX = evt.clientX;
    562 loginCtnr.$clientY = evt.clientY;
    563 alertDlg.onmousemove = MoveIt;
    564 alertDlg.onmouseup = stopMove;
    565}
    566
    567function MoveIt(evt)
    568{
    569 evt = getCurrentEvent(evt);
    570
    571 if ( !isLeftKeyDown(evt) )
    572 return;
    573
    574 var alertDlg = document.getElementById("login_container");//login_container
    575
    576 var w_wid = document.body.scrollWidth;
    577 var w_hgt = document.body.scrollHeight;
    578 var xoffset = alertDlg.offsetLeft + (evt.clientX - alertDlg.$clientX);
    579 var yoffset = alertDlg.offsetTop + (evt.clientY - alertDlg.$clientY);
    580
    581 if ( xoffset + getWidth(alertDlg) > w_wid )
    582 {
    583 alertDlg.style.left = w_wid - getWidth(alertDlg) - 4 + 'px';
    584 return;
    585 }
    586 else if ( yoffset + getHeight(alertDlg) > w_hgt )
    587 {
    588 alertDlg.style.top = w_hgt - getHeight(alertDlg) - 4 + 'px';
    589 return;
    590 }
    591
    592 alertDlg.style.left = xoffset + "px";
    593 alertDlg.style.top = yoffset + "px";
    594 alertDlg.$clientX = evt.clientX;
    595 alertDlg.$clientY = evt.clientY;
    596}
    597
    598function stopMove(evt)
    599{
    600 evt = getCurrentEvent(evt);
    601
    602 if ( !isLeftKeyDown(evt) )
    603 return;
    604
    605 var alertDlg = document.getElementById("login_header");
    606 alertDlg.onmousemove = null;
    607 alertDlg.onmouseup = null;
    608 releaseEventCapture(alertDlg);
    609}
    610
    611function getElementPageOffset(x,y)
    612{
    613 return {x: x + document.body.scrollLeft - 2, y: y + document.body.scrollTop - 2};
    614}
    615
    616function getPageOffset(element)
    617{
    618 var left = 0,top = 0;
    619
    620 do {
    621 top += element.offsetTop || 0;
    622 left += element.offsetLeft || 0;
    623 element = element.offsetParent;
    624 } while(element);
    625
    626 return {x: left, y: top};
    627}
    628
    629function getCurrentEvent(evt)
    630{
    631 return (!evt) ? window.event : evt;
    632}
    633
    634function getEventTarget(evt)
    635{
    636 evt = ( (!evt) ? window.event : evt );
    637 return evt.target || event.srcElement;
    638}
    639
    640function isLeftKeyDown(evt)
    641{
    642 return ( ( (evt.which) && (evt.which==1) ) || ( (evt.button) && (evt.button==1) ) );
    643}
    644
    645function stopEventTransfer(evt)
    646{
    647 if (evt.preventDefault)
    648 {
    649 evt.preventDefault();
    650 evt.stopPropagation();
    651 }
    652 else
    653 {
    654 evt.returnValue = false;
    655 evt.cancelBubble = true;
    656 }
    657}
    658
    659function setEventCapture(target)
    660{
    661 if (target.setCapture)
    662 target.setCapture();
    663 else if (window.captureEvents)
    664 window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP|Event.MOUSEDOWN);
    665}
    666
    667function releaseEventCapture(target)
    668{
    669 if (target.releaseCapture)
    670 target.releaseCapture();
    671 else if (window.releaseEvents)
    672 window.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP|Event.MOUSEDOWN);
    673}
    674
    675function isNULL(e)
    676{
    677 if (e==undefined || e==null)
    678 return true;
    679
    680 return false;
    681}
    682
    683// layer fix functions
    684function getLayer(name)
    685{
    686 if (isMinNS5)
    687 return document.getElementById(name);
    688 else if (isMinIE4)
    689 return eval('document.all.' + name);
    690 else if (isMinNS4)
    691 return findLayer(name, document);
    692
    693 return null;
    694}
    695
    696function findLayer(name, doc)
    697{
    698 var i, layer;
    699
    700 for (i = 0; i < doc.layers.length; i++)
    701 {
    702 layer = doc.layers[i];
    703 if (layer.name == name)
    704 return layer;
    705 if (layer.document.layers.length > 0)
    706 {
    707 layer = findLayer(name, layer.document);
    708 if (layer != null)
    709 return layer;
    710 }
    711 }
    712
    713 return null;
    714}
    715
    716function moveLayerTo(layer, x, y)
    717{
    718 if (isMinIE4)
    719 {
    720 layer.style.left = x;
    721 layer.style.top = y;
    722 }
    723 else if (isMinNS5)
    724 {
    725 layer.style.left = x+'px';
    726 layer.style.top = y+'px';
    727 }
    728 else if (isMinNS4)
    729 layer.moveTo(x, y);
    730}
    731
    732function getPageLeft(layer)
    733{
    734 if (isMinIE4||isMinNS5)
    735 return (layer.offsetLeft);
    736 else if (isMinNS4)
    737 return (layer.pageX);
    738
    739 return (-1);
    740}
    741
    742function getPageTop(layer)
    743{
    744 if (isMinIE4||isMinNS5)
    745 return (layer.offsetTop);
    746 else if (isMinNS4)
    747 return (layer.pageY);
    748
    749 return (-1);
    750}
    751
    752function getPageScrollX()
    753{
    754 if (isMinIE4||isMinNS5)
    755 return (g_myBodyInstance.scrollLeft);
    756 else if (isMinNS4)
    757 return (window.pageXOffset);
    758
    759 return (-1);
    760}
    761
    762function getPageScrollY()
    763{
    764 if (isMinIE4||isMinNS5)
    765 return (g_myBodyInstance.scrollTop);
    766 else if (isMinNS4)
    767 return (window.pageYOffset);
    768
    769 return (-1);
    770}
    771
    772function getWidth(layer)
    773{
    774 if (isMinIE4||isMinNS5)
    775 {
    776 if (layer.style.pixelWidth)
    777 return (layer.style.pixelWidth);
    778 else
    779 return (layer.clientWidth);
    780 }
    781 else if (isMinNS4)
    782 {
    783 if (layer.document.width)
    784 return (layer.document.width);
    785 else
    786 return (layer.clip.right - layer.clip.left);
    787 }
    788
    789 return (-1);
    790}
    791
    792function getHeight(layer)
    793{
    794 if (isMinIE4||isMinNS5)
    795 {
    796 if (false && layer.style.pixelHeight)
    797 return (layer.style.pixelHeight);
    798 else
    799 return (layer.clientHeight);
    800 }
    801 else if (isMinNS4)
    802 {
    803 if (layer.document.height)
    804 return (layer.document.height);
    805 else
    806 return (layer.clip.bottom - layer.clip.top);
    807 }
    808
    809 return(-1);
    810}
    811
    812function getWindowWidth()
    813{
    814 if (isMinIE4||isMinNS5)
    815 return (g_myBodyInstance.clientWidth);
    816 else if (isMinNS4)
    817 return (window.innerWidth);
    818
    819 return (-1);
    820}
    821
    822function getWindowHeight()
    823{
    824 if (isMinIE4||isMinNS5)
    825 return (g_myBodyInstance.clientHeight);
    826 else if (isMinNS4)
    827 return(window.innerHeight);
    828
    829 return(-1);
    830}
    831
    </script>
    posted @ 2009-04-24 09:53 -> 阅读(230) 评论(0)  编辑

    腾讯官方绿茶活动--Head(头部)第2段JavaScript代码(不带行号)
    地址:http://act.qzone.qq.com/uni-greentea/index.html

    <script src="load_brand_js.js" type="text/javascript">
    document.write('<script type="text/javascript" src="http://imgcache.qq.com/qzone/biz/comm/js/brand_release.js"><\/script>');
    </script>
    posted @ 2009-04-24 09:51 -> 阅读(2) 评论(0)  编辑

    posted @ 2009-04-24 09:49 -> 阅读(482) 评论(0)  编辑

    posted @ 2009-04-24 09:44 -> 阅读(728) 评论(0)  编辑

    腾讯官方绿茶活动--Head(头部)第5段JavaScript代码(带行号)
    地址:http://act.qzone.qq.com/uni-greentea/index.html

    <script type="text/javascript">
    1
    2 var zuanshi = ['红','黄','蓝','紫','粉','绿'];
    3 /*
    4 function newSize(datoX,datoY) {
    5 if(document.all && !document.getElementById) {
    6 document.all['main'].style.pixelWidth = datoX;
    7 document.all['main'].style.pixelHeight = datoY;
    8 }else{
    9 document.getElementById('main').style.width = datoX;
    10 document.getElementById('main').style.height = datoY;
    11 }
    12 }*/
    13 function newSize(datoX,datoY) {
    14 if(document.all && !document.getElementById) {
    15 document.all['main'].style.width = datoX+"px";
    16 document.all['main'].style.height = datoY+"px";
    17 }else{
    18 document.getElementById('main').style.width = datoX+"px";
    19 document.getElementById('main').style.height = datoY+"px";
    20 }
    21 }
    22 function show_zero(obj)
    23 {
    24 var m1 = MSG2.create('温馨提示','您目前没有玩转盘游戏的机会', null);
    25 m1.setIcon(2);
    26 m1.setButton([3]);
    27 m1.onunload = function(){
    28 window.location.href="user.html";
    29 }
    30 m1.show();
    31 }
    32 function show_err(obj){
    33 obj=eval('obj='+obj);
    34 switch(obj.err){
    35 case 4501:
    36 showLogin();
    37 break;
    38 case 4506:
    39 getPopUp('reg.html','',500,350);
    40 break;
    41 default :
    42 var m1 = MSG2.create('温馨提示', obj.msg, null);
    43 m1.setIcon(2);
    44 m1.setButton([3]);
    45 m1.onunload = function(){
    46 window.location.href="index.html";
    47 }
    48 m1.show();
    49 break;
    50 }
    51 }
    52
    53 function show_exchange(arg){
    54 var obj = eval('obj='+arg);
    55 if(obj.data){
    56 var m1 = MSG2.create('温馨提示','恭喜您获得一颗'+zuanshi[obj.data.type-1]+'钻,我们将会记录您的兑奖情况,活动结束后将会有

    专人给您赠送奖品', null);
    57 m1.setIcon(1);
    58 m1.setButton([1]);
    59 m1.onunload = function(){
    60 window.location.href="user.html";
    61 }
    62
    63 m1.show();
    64
    65 }
    66 else
    67 {
    68 var m1 = MSG2.create('温馨提示', obj.msg, null);
    69 m1.setIcon(2);
    70 m1.setButton([3]);
    71 m1.onunload = function(){
    72 window.location.href="index.html";
    73 }
    74
    75 m1.show();
    76
    77 }
    78 }
    79
    80
    81 function show_info(arg){
    82 var obj=eval('obj='+arg);
    83 if(obj.data){
    84 var leftTips = '您还剩下' + obj.data.left + '次转盘机会。';
    85 var m1 = MSG2.create('温馨提示','恭喜您获得了' + obj.data.score + '分', leftTips);
    86 m1.setIcon(1);
    87 m1.setButton([1]);
    88 m1.onunload = function(){
    89 window.location.href="user.html";
    90 }
    91 m1.show();
    92 }
    93 else
    94 {
    95 var m1 = MSG2.create('温馨提示', obj.msg, null);
    96 m1.setIcon(2);
    97 m1.setButton([3]);
    98 m1.onunload = function(){
    99 window.location.href="index.html";
    100 }
    101
    102 m1.show();
    103 }
    104 }
    105
    106 function show_succ(obj){
    107 if(!obj.error){
    108 var msg1 = '您已经注册过了';
    109 var msg2 = '3秒钟后将跳转到您的个人主页。';
    110 var m1 = MSG2.create(null, msg1, msg2);
    111 m1.setIcon(1);
    112 m1.setButton([1]);
    113 m1.onconfirm = function(){location.href = 'user.html'};
    114 setTimeout(function(){m1.onconfirm()},3000)
    115 m1.show();
    116 }
    117 }
    118
    119 //-->
    120
    </script>
    posted @ 2009-04-24 09:41 -> 阅读(8) 评论(0)  编辑

    腾讯官方绿茶活动body部分的JavaScript代码(body-1)
    地址:http://act.qzone.qq.com/uni-greentea/index.html

    body(体部),第1段JavaScript代码(带行号)
    <script type="text/javascript">
    1
    2//<![CDATA[
    3
    4function notice(){
    5 if(!getCookie('gtnotice')){
    6 var msg = '为了保证活动的公平性,我们将通过后台数据检查用户非正常途径取得积分的行为,一旦发现用户有违背活动规则的用户,例如使用外挂,刷分等(不限于此)不公平竞争、对其他用户造成伤害的行为,核实后将取消参与资格!'
    7 var m1 = MSG2.create('公告', msg, null);
    8 var expires = new Date();
    9 timeout=10*12*30*24*3600*1000;
    10 expires.setTime(expires.getTime()+timeout);
    11 m1.setIcon(1);
    12 m1.setButton([1]);
    13 m1.show();
    14 setFileCookie('gtnotice','1',null,'act.qzone.qq.com');
    15 }
    16
    17}
    18
    19setTimeout(notice, 1500)
    20//]]>
    21
    </script>
    posted @ 2009-04-24 09:38 -> 阅读(9) 评论(0)  编辑

    腾讯绿茶活动官方页面的http://act.qzone.qq.com/uni-greentea/index.html
    body(体部)第2段JavaScript代码(不带行号)


    <script src="http://pingjs.qq.com/ping.js">
    var pvCurDomain="";

    var pvCurUrl="";

    var pvCurParam="";

    var pvRefDomain="";

    var pvRefUrl="";

    var

    pvRealDomain="";

    var pvRefParam="";

    var pvRealDomainToSet="qq.com";

    var

    pvGifUrl="http://pingfore.";

    var pvHotUrl="http://pinghot.";

    var pvDoc=document;

    var pgvImage;

    var

    sendUrl;

    function pgvCircleQueue(size){

    this.initialize(size);

    } pgvCircleQueue.prototype=

    {

    initialize: function(size){

    this.list=[];

    this.capacity=size+1;

    this.head=0;

    this.tail=0;

    } ,push:

    function(e){

    if(e=="undefined"||e==""){

    return;

    } var pos=this.find(e);

    if(pos==-1){

    this.list

    [this.head]=e;

    this.head=(this.head+1)% this.capacity;

    if(this.head==this.tail){

    this.tail=

    (this.tail+1)% this.capacity;

    }

    } else{

    var next=(pos+1)% this.capacity;

    while(next!=this.head)

    {

    this.list[pos]=this.list[next];

    pos=next;

    next=(next+1)% this.capacity;

    } this.list[pos]

    =e;

    }

    } ,join: function(spliter){

    if(this.head==this.tail){

    return new String();

    } var

    pos=this.tail;

    var str=new String(this.list[pos]);

    pos=(pos+1)% this.capacity;

    while(pos!

    =this.head){

    str+=spliter+new String(this.list[pos]);

    pos=(pos+1)% this.capacity;

    } return

    str;

    } ,size: function(){

    if(this.head>=this.tail){

    return this.head-this.tail;

    } else{

    return

    this.head-this.tail+this.capacity;

    }

    } ,set: function(str, spliter){

    var ar=str.split(spliter);

    for

    (var i=0;

    i<ar.length;

    ++i){

    this.push(ar[i]);

    }

    } ,find: function(str){

    var pos=this.tail;

    while

    (pos!=this.head){

    if(this.list[pos]==str){

    return pos;

    } else{

    pos=(pos+1)% this.capacity;

    }

    } return-

    1;

    }

    } ;

    if(window!=top){

    try{

    pvDoc=top.document;

    } catch(e){

    }

    } var pvLoc=pvDoc.location;

    var

    pvBody=pvDoc.body;

    var pvNone="-";

    var pvVersion="3.1";

    if(typeof(pvRepeatCount)=='undefined'){

    var

    pvRepeatCount=1;

    } function pgvGetParameter(name,src){

    if(!name||name==""||!src||src==""){

    return

    "";

    } var r=new RegExp("(\\?|&)*"+name+"=([^&]*)(&|$)");

    var m=src.match(r);

    return(!m?"":m[2]);

    }

    function pgvVoid(){

    return;

    } function pgvGetCookieByName(search){

    var value=pvNone;

    var

    offset=pvDoc.cookie.indexOf(search);

    var end=0, end2=0;

    if(offset!=-1)

    {

    offset+=search.length;

    end=pvDoc.cookie.indexOf(";", offset);

    if(end==-1)

    {

    end=pvDoc.cookie.length;

    } end2=pvDoc.cookie.indexOf("&", offset);

    if(end2!=-1){

    end=Math.min(end,

    end2);

    } value=unescape(pvDoc.cookie.substring(offset, end));

    } return value;

    } function

    pgvRealSetCookie(cookie_str)

    {

    pvDoc.cookie=cookie_str+";path=/;domain="+pvRealDomainToSet+";expires=Sun, 18 Jan 2038  00:00:00 GMT;";

    } function pgvRealDelCookie(cookie_str)

    {

    pvDoc.cookie=cookie_str+";path=/;domain=minisite.qq.com;expires=Sun, 18 Jan 1970 00:00:00  GMT;";

    } function pgvGetCookieSetDomain(){

    var aDot=new Array();

    var domainToSet,j=0;

    for(var

    i=0;

    i<pvRealDomain.length;

    i++){

    if(pvRealDomain.charAt(i)=='.'){

    aDot[j]=i;

    j++;

    }

    } var

    pos=pvRealDomain.indexOf(".cn");

    if(pos!=-1){

    aDot.length--;

    } if(aDot.length<1)

    {

    domainToSet="qq.com";

    } else if(aDot.length==1){

    domainToSet=pvRealDomain;

    } else

    {

    domainToSet=pvRealDomain.substring(aDot[aDot.length-2]+1,pvRealDomain.length);

    } return

    domainToSet;

    } function pgvGetDomainByUrl(){

    var dm=pvDoc.domain;

    if(pgvVirtualDomain!

    =pvNone&&pgvVirtualDomain!=""){

    dm=pgvVirtualDomain;

    } else{

    var pos=pvDoc.URL.indexOf("://");

    if

    (pos!=-1){

    var strUrl=pvDoc.URL.substr(pos+3,pvDoc.URL.length-pos-3);

    var pos2=strUrl.indexOf

    ("/");

    if(pos2!=-1){

    dm=strUrl.substr(0,pos2);

    }

    }

    } return dm;

    } function pgvGetDomainInfo(needtitle,

    hot){

    var dm="",url="",title="";

    dm=pvCurDomain;

    if(pvCurDomain==""){

    dm=pgvGetDomainByUrl();

    }

    pvRealDomain=pvCurDomain=dm;

    if(pgvVirtualURL!=pvNone&&pgvVirtualURL!=""){

    url=pgvVirtualURL;

    }

    else{

    url=escape(pvCurUrl);

    if(pvCurUrl==""&&pvLoc.pathname){

    pvCurUrl=url=escape

    (pvLoc.pathname);

    pvCurParam=escape(pvLoc.search.substr(1));

    } if(pgvSenseParam!

    =pvNone&&pgvSenseParam!=""){

    var value=pgvGetParameter(pgvSenseParam, pvDoc.URL);

    if(value!

    =pvNone&&value!=''){

    url+="_"+value;

    }

    }

    } title=pvNone;

    if(pgvVirtualTitle!

    =pvNone&&pgvVirtualTitle!=""){

    title=pgvVirtualTitle;

    } else if(pvDoc.title){

    title=pvDoc.title;

    }

    if(hot){

    dm+=".hot";

    } if(needtitle&&needtitle=="title"){

    return("dm="+dm+"&url="+escape(url));

    }

    else{

    return("dm="+dm+"&url="+escape(url)+"&tt="+escape(title));

    }

    } function pgvGetRefInfo(){

    var

    refdm=refurl=pvNone,refStr=pvDoc.referrer;

    if(pgvStatIframe){

    refStr=pgvGetCookieByName

    ("pgvReferrer=");

    var newRef=pvDoc.URL;

    var paraPos=newRef.indexOf("?");

    if(paraPos!=-1)

    newRef=newRef.substr(0, paraPos);

    pgvSetSessionCookie("pgvReferrer", newRef);

    } var

    tagParamName="ADTAG";

    if(pgvTagParamName!=""&&pgvTagParamName!=pvNone)

    {

    tagParamName=pgvTagParamName;

    } var adtag=pgvGetParameter(tagParamName,pvDoc.URL);

    if(adtag!

    =pvNone&&adtag!=""){

    refdm="ADTAG";

    refurl=adtag;

    } var pos=refStr.indexOf("://");

    if(pos!=-

    1&&refdm==pvNone){

    var refStr2=refStr.substr(pos+3,refStr.length);

    refdm=refStr2;

    var

    pos=refStr2.indexOf("/");

    if(pos!=-1){

    refdm=refStr2.substr(0,pos);

    var refStr3=refStr2.substr

    (pos,refStr2.length);

    refurl=refStr3;

    pos=refStr3.indexOf("?");

    if(pos!=-1){

    pvRefParam=escape

    (refStr3.substr(pos+1));

    var dmReg2=new RegExp("^(.*)(\\?.*)$");

    var dmMatch2=refStr3.match

    (dmReg2);

    if(dmMatch2){

    refurl=dmMatch2[1];

    }

    } pos=refurl.indexOf("#");

    if(pos!=-1){

    var urlReg=new

    RegExp("^(.*)(\\#.*)$");

    var urlMatch=refurl.match(urlReg);

    if(urlMatch){

    refurl=urlMatch[1];

    }

    }

    }

    }

    if(pvRefDomain!="")refdm=pvRefDomain;

    if(pvRefUrl!="")

    refurl=pvRefUrl;

    pvRealReferInfo=refdm;

    pvRefDomain=refdm;

    pvRefUrl=escape(refurl);

    return

    ("&rdm="+refdm+"&rurl="+escape(refurl));

    } function pgvGetUserInfo(){

    try{

    if(!

    navigator.cookieEnabled)return "&pvid=NoCookie";

    } catch(e){

    return "&pvid=NoCookie";

    } var

    pvid=pgvGetCookieByName("pvid=");

    pgvSetCookies(pvid);

    pvRealPvid=pvid;

    pvUserid=(pvUserid=='')?

    pvRealPvid:pvUserid;

    return "&pvid="+pvid;

    } function pgvSetCookies(pvid){

    var pvidtmp=pvid;

    if

    (pvid==pvNone){

    var curDate=new Date();

    var curMs=curDate.getUTCMilliseconds();

    pvidtmp=

    (Math.round(Math.random()* 2147483647)*curMs)%10000000000;

    pvUserid=pvidtmp;

    pvNewUser=1;

    }

    pvRealDomainToSet=pgvGetCookieSetDomain();

    pgvRealSetCookie("pvid="+pvidtmp);

    } function

    pgvGetMainEnvInfo(){

    var ret="";

    try{

    var scr=scl=lang=flash=cpuc=pf=ce=tz=pvNone,java=0;

    var

    n=navigator;

    if(self.screen){

    scr=screen.width+"x"+screen.height;

    scl=screen.colorDepth+"-bit";

    }

    if(n.language){

    lang=n.language.toLowerCase();

    } else if(n.browserLanguage)

    {

    lang=n.browserLanguage.toLowerCase();

    } java=n.javaEnabled()?

    1:0;

    cpuc=n.cpuClass;

    pf=n.platform;

    var now=new Date();

    tz=now.getTimezoneOffset

    ()/60;

    ret="&scr="+scr+"&scl="+scl+"&lang="+lang+"&java="+java+"&cc="+cpuc+"&pf="+pf+"&tz="+tz;

    }

    catch(e){

    } finally{

    return ret;

    }

    } function pgvGetExtendEnvInfo(){

    var ret="";

    try{

    var

    flash=pgvGetCookieByName("flv=");

    if(flash==pvNone){

    ret+="&flash="+pgvFlashInfo();

    } var

    currentUrl=pvLoc.href;

    var isHp="N";

    if(pvBody.addBehavior&&pvBody.isHomePage)

    {

    pvBody.addBehavior("#default#homePage");

    isHp=pvBody.isHomePage(currentUrl)?"Y":"N";

    } if

    (isHp=="Y")ret+="&hp=Y";

    var connectType=pvNone;

    if(pvBody.addBehavior){

    pvBody.addBehavior

    ("#default#clientCaps");

    var connectType=pvBody.connectionType;

    } ret+="&ct="+connectType;

    } catch

    (e){

    } finally{

    return ret;

    }

    } function pgvGetEnvInfo(){

    return(pgvGetMainEnvInfo()

    +pgvGetExtendEnvInfo());

    } function pgvFlashInfo(){

    var f=pvNone,n=navigator;

    try{

    if

    (n.plugins&&n.plugins.length){

    for(var i=0;

    i<n.plugins.length;

    i++){

    if(n.plugins[i].name.indexOf

    ('Shockwave Flash')!=-1){

    f=n.plugins[i].description.split('Shockwave Flash ')[1];

    break;

    }

    }

    } else

    if(window.ActiveXObject){

    for(var i=10;

    i>=2;

    i--){

    try{

    var fl=eval("new ActiveXObject ('ShockwaveFlash.ShockwaveFlash."+i+"');");

    if(fl){

    f=i+'.0';

    break;

    }

    } catch(e){

    }

    }

    }

    pgvRealSetCookie("flv="+f);

    } catch(e){

    } return f;

    } function pgvSendInfo(_url){

    pgvImage=new Image

    (1,1);

    pgvImage.src=_url;

    } function pgvGenImageUrl(){

    var Url=pgvGetDomainInfo();

    Url+=pgvGetRefInfo();

    Url+=pgvGetUserInfo();

    Url+=pgvGetEnvInfo

    ();

    Url+="&vs="+pvVersion;

    Url=pvGifUrl+pgvGetCookieSetDomain()+"/pingd?"+Url;

    return Url;

    }

    function pgvGetCstm(){

    var dm=pvDoc.domain;

    if(pvCurDomain!=""){

    dm=pvCurDomain;

    } return

    "&cstm="+dm.replace(/\./g,"_")+"_"+pvCSTM;

    } var

    pvSpecialGifUrl="http://219.133.51.97/pingd?";

    var pvSpecialTimeSpan=300;

    var

    pvRealReferInfo=pvNone;

    var pvRealChannel=pvNone;

    var pvCSTM="";

    var pvRealPvid=pvNone;

    var

    pvUserid='';

    var pvNewUser=0;

    function pgvSpecialInfo(){

    var

    SpecialUrl=pvSpecialGifUrl;

    SpecialUrl+=pgvGetDomainInfo("title");

    SpecialUrl+=pgvGetRefInfo

    ();

    SpecialUrl+=pgvGetUserInfo();

    var now=new Date();

    nowtime=parseInt(now.getTime

    ()/1000);

    SpecialUrl+="&vtime="+nowtime;

    SpecialUrl+="&pvch="+pvRealChannel;

    SpecialUrl+="&rand="+

    Math.round(Math.random()*100000);

    pgvSendInfo(SpecialUrl);

    } function pgvSetSpecialCookie(){

    var

    now=new Date();

    var minitime=parseInt(now.getTime()/1000);

    pgvRealSetCookie

    ("minitime="+minitime);

    } function pgvCheckSpecialCookie(){

    var newtime,timespan;

    var

    minitime=parseInt(pgvGetCookieByName("minitime="));

    minitime=minitime?minitime:0;

    var now=new

    Date();

    newtime=parseInt(now.getTime()/1000);

    timespan=newtime-minitime;

    if

    (timespan>pvSpecialTimeSpan){

    timespan=0;

    pgvRealSetCookie("minitime=0");

    } else{

    pgvRealSetCookie

    ("minitime="+newtime);

    } return timespan;

    } function pgvMinisiteSpecial(){

    if

    (pvRealDomain=="minisite.qq.com"){

    pgvSetSpecialCookie();

    } else if(pvRealDomainToSet=="qq.com")

    {

    var timespan=pgvCheckSpecialCookie();

    if(pvRealReferInfo!=pvNone)

    {

    pvRealChannel=timespan>0?'MINI':'OTHER';

    }

    } pgvSpecialInfo();

    } function getNavVer(){

    var

    verArr=navigator.appVersion.match('MSIE(.*?);');

    if(verArr){

    return verArr[1];

    } else{

    return

    6.0;

    }

    } function initGlobalVariable(pgv_bhv_value){

    if(pgv_bhv_value){

    if

    (pgv_bhv_value.statIframe){

    pgvStatIframe=pgv_bhv_value.statIframe;

    pgvInitStatIframe

    (pgv_bhv_value.statIframe);

    } if(pgv_bhv_value.senseParam)

    {

    pgvSenseParam=pgv_bhv_value.senseParam;

    } if(pgv_bhv_value.tagParamName)

    {

    pgvTagParamName=pgv_bhv_value.tagParamName;

    } if(pgv_bhv_value.virtualURL)

    {

    pgvVirtualURL=pgv_bhv_value.virtualURL;

    } if(pgv_bhv_value.virtualDomain)

    {

    pgvVirtualDomain=pgv_bhv_value.virtualDomain;

    } if(pgv_bhv_value.virtualTitle)

    {

    pgvVirtualTitle=escape(pgv_bhv_value.virtualTitle);

    } if(pgv_bhv_value.sessionSpan)

    {

    pgvSessionSpan=pgv_bhv_value.sessionSpan;

    } if(pgv_bhv_value.originalReferer)

    {

    pgvOriginalReferer=pgv_bhv_value.originalReferer;

    }

    }

    } function pgvMain(pgv_bhv_type,

    pgv_bhv_value){

    try{

    initGlobalVariable(pgv_bhv_value);

    if(pvRepeatCount==1){

    pvRepeatCount=2;

    }

    else{

    return;

    } pgvInitSessionCookie();

    var Url=pgvGenImageUrl();

    if(pvCSTM&&pvCSTM!="")

    {

    Url+=pgvGetCstm();

    } if(pgv_bhv_type&&pgv_bhv_type=="return_url"){

    return Url;

    } pgvSetSsIdCookie

    ();

    Url+=pgvPathTrace(pgv_bhv_type, pgv_bhv_value);

    pgvFlushSessionCookies();

    if

    (pgvOriginalReferer!=""){

    Url+="&or="+pgvOriginalReferer;

    } Url+="&rand="+Math.round(Math.random

    ()*100000);

    pgvSendInfo(Url);

    tracert();

    if(parseInt(pvRealPvid)%1000==123)pgvMinisiteSpecial();

    }

    catch(e){

    var v=ScriptEngineMajorVersion()+"."+ScriptEngineMinorVersion();

    var

    Url=pvSpecialGifUrl+"err="+escape(e.message)+"&jsv="+v+"&url="+escape

    (pvDoc.URL);

    Url+="&rand="+Math.round(Math.random()*100000);

    pgvSendInfo(Url);

    }

    } function

    getuinstr(){

    try{

    var axObj;

    axObj=new ActiveXObject("TimwpDll.TimwpCheck");

    if(typeof(axObj)

    =='object'){

    if(axObj.CheckValid()&&(axObj.GetVersion()>=3.4)){

    var s=document.createElement

    ("SCRIPT");

    document.getElementsByTagName("HEAD")[0].appendChild

    (s);

    s.src="http://trace.qq.com:8080/q?"+axObj.GetQQInfo();

    }

    } return true;

    } catch(e){

    return

    false;

    }

    } function _callback(d){

    if(typeof(d)=='string'){

    pgvRealSetCookie("icache="+d);

    }

    } function

    pgvGetColumn(){

    var ret="&column=";

    if(typeof(vsPgvCol)!='undefined'&&vsPgvCol!="")

    {

    ret+=vsPgvCol;

    } return ret;

    } function pgvGetNewRand(){

    var uin=pgvGetCookieByName

    ("uin_cookie=");

    var ouin=pgvGetCookieByName("o_cookie=");

    var ruin=pgvGetCookieByName

    ("r_cookie=");

    if(ruin==pvNone){

    var pvDate=new Date();

    pgvRealSetCookie

    ("r_cookie="+pvDate.getYear()%100+(pvDate.getUTCMonth()+1)+pvDate.getUTCDate()

    +pvDate.getUTCMilliseconds()+Math.round(Math.random()*100000));

    ruin=pgvGetCookieByName

    ("r_cookie=");

    } if(uin!=pvNone){

    pgvRealSetCookie("o_cookie="+uin);

    return "&nrnd="+uin;

    } if(ouin!

    =pvNone){

    return "&nrnd="+ouin;

    } if(ruin!=pvNone){

    return "&nrnd="+"F"+ruin;

    } return "&nrnd=-";

    }

    function pgvGetTopic(){

    var ret="&subject=";

    if(typeof(pvCSTM)!='undefined'&&pvCSTM!="")

    {

    ret+=pvCSTM;

    } return ret;

    } function tracert(){

    var ol=0;

    var icache=pgvGetCookieByName

    ("uin_cookie=");

    if(!(/(qzone)|(cache)|(ossweb-img)|(ring)|(im)|(fo)|(shuqian)|(photo)|(pet)| (r2)|(bar)|(client)|(music)|(pay)|(paipai)|(sg)|(vip)|(show)|(qqtang)|(safe)|(service)| (love)/.test(pvRealDomain))){

    sendUrl=new Image(1,1);

    var loc=escape

    (window.location.href);

    urlstr='pj=1990&dm='+pvRealDomain+'&url='+(pvCurUrl=='-'?'':escape

    (pvCurUrl))+'&arg='+escape(pvCurParam)+'&rdm='+(pvRefDomain=='-'?'':pvRefDomain)+'&rurl='+

    (pvRefUrl=='-'?'':escape(pvRefUrl))+'&rarg='+escape(pvRefParam)

    +'&icache='+icache+'&uv='+pvUserid+'&nu='+pvNewUser+'&ol='+ol+'&loc='+loc+pgvGetColumn()

    +pgvGetTopic()+pgvGetNewRand()+'&rnd='+Math.round(Math.random()

    *100000);

    sendUrl.src='http://trace.qq.com:80/collect?'+urlstr;

    }

    } var pgvStatIframe=false;

    var

    pgvSenseParam=pvNone;

    var pgvTagParamName=pvNone;

    var pgvVirtualURL=pvNone;

    var

    pgvVirtualDomain=pvNone;

    var pgvVirtualTitle=pvNone;

    var pgvSessionSpan=0;

    var

    pgvOriginalReferer="";

    function pgvInitStatIframe(statIframe){

    if(statIframe&&statIframe==true)

    {

    pvDoc=document;

    pvLoc=pvDoc.location;

    pvBody=pvDoc.body;

    } else{

    pvDoc=document;

    if(window!=top)

    {

    try{

    pvDoc=top.document;

    } catch(e){

    } ;

    } pvLoc=pvDoc.location;

    pvBody=pvDoc.body;

    }

    } var

    pvSCA=null;

    var pvSCO=null;

    function pgvInitSessionCookie(){

    pvSCA=new Array();

    pvSCO=new Object

    ();

    var start=pvDoc.cookie.indexOf("pgv=");

    if(start==-1){

    return;

    } start+=4;

    var

    end=pvDoc.cookie.indexOf(";", start);

    if(end==-1){

    end=pvDoc.cookie.length;

    } var value=unescape

    (pvDoc.cookie.substring(start, end));

    var arr=value.split('&');

    for(var i=0;

     i<arr.length;

    i++)

    {

    var arr2=arr[i].split('=');

    pvSCO[arr2[0]]=arr2[1];

    }

    } function pgvSetSessionCookie(key, value)

    {

    pvSCO[key]=value;

    } function pgvFlushSessionCookies(){

    if(pgvSessionSpan&&pgvSessionSpan!=0){

    var

    expires=new Date();

    expires.setTime(expires.getTime()+(pgvSessionSpan*60*1000));

    } var

    index=0;

    for(var key in pvSCO){

    pvSCA[index]=key+"="+pvSCO[key];

    index++;

    } var pvCookies="";

    for(var

    i=0;

    i<pvSCA.length;

     i++){

    pvCookies+=pvSCA[i];

    if(i!=pvSCA.length-1){

    pvCookies+="&";

    }

    } var

    cookie2Set="pgv="+pvCookies;

    if(expires){

    cookie2Set+="; expires="+expires.toGMTString();

    }

    cookie2Set+="; path=/; domain="+pgvGetCookieSetDomain()+";";

    pvDoc.cookie=cookie2Set;

    } function

    pgvSetSsIdCookie(){

    var ssid=pgvGetCookieByName("ssid=");

    if(ssid==pvNone){

    var curDate=new Date

    ();

    var curMs=curDate.getUTCMilliseconds();

    ssid="s"+(Math.round(Math.random()* 2147483647)

    *curMs)%10000000000;

    } pgvSetSessionCookie("ssid", ssid);

    return ssid;

    } function pgvPathTrace

    (pgv_bhv_type, pgv_bhv_value){

    var Url="";

    if(pgv_bhv_type!="pathtrace"){

    return Url;

    } if

    (pgv_bhv_value){

    if(pgv_bhv_value.pathStart){

    var oldpathtag=pgvGetCookieByName("SPATHTAG=");

    var

    pathtag="";

    var qlen=1;

    var queue;

    if(pgv_bhv_value.spQueueLen!=null){

    qlen=Math.max(1,

    pgv_bhv_value.spQueueLen);

    } queue=new pgvCircleQueue(qlen);

    if(oldpathtag=="-"){

    oldpathtag="";

    }

    queue.set(oldpathtag, "!");

    if

    (oldpathtag==""||oldpathtag==pvNone||oldpathtag==pvNone+pvNone||typeof(pgv_bhv_value.override)

    =="undefined"||pgv_bhv_value.override==true){

    var rptSpt=true;

    if(pvRefDomain=="ADTAG")

    {

    pathtag=pvRefUrl;

    } else if(pgv_bhv_value.useRefUrl){

    if

    (pgv_bhv_value.careSameDomainRef||pvCurDomain!=pvRefDomain){

    pathtag=pvRefDomain+pvRefUrl;

    } else

    {

    rptSpt=false;

    }

    } if(rptSpt){

    if(pathtag==""||pathtag==pvNone||pathtag==pvNone+pvNone)

    {

    pathtag="NONE_REF";

    } if(pgv_bhv_value.spreadPathTag)

    {

    pathtag=pgv_bhv_value.spreadPathTag+"|"+pathtag;

    } if(pathtag!=null&&pathtag!=""&&pathtag!

    =pvNone){

    var newtag;

    queue.push(pathtag);

    newtag=queue.join("!");

    pgvSetSessionCookie("SPATHTAG",

    newtag);

    Url+="&spt="+pathtag;

    }

    }

    }

    } if(pgv_bhv_value.keyPathTag&&pgv_bhv_value.nodeIndex){

    var

    keyPathTag=pvNone;

    var

    nodeIndex=pvNone;

    keyPathTag=pgv_bhv_value.keyPathTag;

    nodeIndex=pgv_bhv_value.nodeIndex;

    Url+="&k pt="+keyPathTag+"&ni="+nodeIndex;

    pgvSetSessionCookie("KEYPATHTAG", keyPathTag);

    } if

    (pgv_bhv_value.endPath){

    Url+="&ep=true";

    }

    } return Url;

    } function pgvWatchClick(params){

    try

    {

    initGlobalVariable(params);

    var srcElement=window.event.srcElement;

    if

    (srcElement.tagName=="A"||srcElement.tagName=="IMG"||srcElement.tagName=="INPUT"||srcElement.ta

    gName=="SELECT"){

    var hottag="";

    switch(srcElement.tagName){

    case "A": hottag="<A  href="+srcElement.href+">"+srcElement.innerHTML+"</a>";

    break;

    case "IMG" : hottag="<IMG  src="+srcElement.src+">";

    break;

    case "INPUT" : hottag="<INPUT type="+srcElement.type+"  value="+srcElement.value+">";

    break;

    case "SELECT" : hottag="SELECT";

    break;

    } var

    pos=pgvGetElementPos(srcElement);

    if(params&&params.coordinateId){

    var

    coordinatePos=pgvGetElementPos(document.getElementById(params.coordinateId));

    pos.x-

    =coordinatePos.x;

    } var url=pgvGetDomainInfo("", true);

    url+="&hottag="+escape

    (hottag);

    url+="&hotx="+pos.x;

    url+="&hoty="+pos.y;

    url+="&rand="+Math.round(Math.random()

    *100000);

    url=pvHotUrl+pgvGetCookieSetDomain()+"/pingd?"+url;

    pgvSendInfo(url);

    }

    } catch(e){

    }

    }

    function pgvSendClick(params){

    if(params&&params.hottag){

    initGlobalVariable(params);

    var

    url=pgvGetDomainInfo("", true);

    url+="&hottag="+escape

    (params.hottag);

    url+="&hotx=9999";

    url+="&hoty=9999";

    url+="&rand="+Math.round(Math.random()

    *100000);

    url=pvHotUrl+pgvGetCookieSetDomain()+"/pingd?"+url;

    pgvSendInfo(url);

    }

    } function

    pgvGetElementPos(el){

    var ua=navigator.userAgent.toLowerCase();

    var isOpera=(ua.indexOf

    ('opera')!=-1);

    var isIE=(ua.indexOf('msie')!=-1&&!isOpera);

    if

    (el.parentNode===null||el.style.display=='none'){

    return false;

    } var parent=null;

    var pos=[];

    var box;

    if(el.getBoundingClientRect){

    box=el.getBoundingClientRect();

    var scrollTop=Math.max

    (document.documentElement.scrollTop, document.body.scrollTop);

     var scrollLeft=Math.max

    (document.documentElement.scrollLeft, document.body.scrollLeft);

    var

    clientTop=document.body.clientTop;

    var clientLeft=document.body.clientLeft;

    return

    {

    x:box.left+scrollLeft-clientLeft, y:box.top+scrollTop-clientTop

    } ;

     

    } else if

    (document.getBoxObjectFor){

    box=document.getBoxObjectFor(el);

    var borderLeft=

    (el.style.borderLeftWidth)?parseInt(el.style.borderLeftWidth):0;

    var borderTop=

    (el.style.borderTopWidth)?parseInt(el.style.borderTopWidth):0;

     pos=[box.x-borderLeft, box.y-

    borderTop];

    } else {

    pos=[el.offsetLeft, el.offsetTop];

    parent=el.offsetParent;

    if(parent!=el)

    {

    while(parent){

    pos[0]+=parent.offsetLeft;

    pos[1]+=parent.offsetTop;

    parent=parent.offsetParent;

     

    }

    } if(ua.indexOf('opera')!=-1 ||(ua.indexOf('safari')!=-1&&el.style.position=='absolute')){

    pos

    [0]-=document.body.offsetLeft;

    pos[1]-=document.body.offsetTop;

    }

    } if(el.parentNode)

    {

    parent=el.parentNode;

    } else{

    parent=null;

    } while(parent&&parent.tagName!='BODY'&&parent.tagName!

    ='HTML'){

    pos[0]-=parent.scrollLeft;

    pos[1]-=parent.scrollTop;

    if(parent.parentNode)

    {

    parent=parent.parentNode;

    } else{

    parent=null;

    }

    } return{

    x:pos[0], y:pos[1]

    } ;

    } /*  |xGv00|578f89b9f2cd5e5faca55d77aa8a7c19 */
    </script>
    posted @ 2009-04-24 09:35 -> 阅读(107) 评论(0)  编辑

    原文地址:http://bbs.pediy.com/showthread.php?threadid=20078

    首先
    1 从od里加载文件(就直接把进程启动起来了),再按F12 暂停;
    2 View菜单中选击Windows项,在打开的窗口中可以从Title栏看到目标按钮,从而找到它的Handle(xxxxxxxx) ;

    对不同平台生成的程序,分别处理:

    一、VB, Delphi, CBuilder 程序:
    3 在CallWindowProcA入口下条件断点: [esp+8]==xxxxxxxx && [esp+0c]==202;
    4 F9继续程序,点击目标按钮,程序中断;
    5 Alt+F4,在代码段(.text)上下访问断点;
    6 F9执行程序,程序中断,
       1). VB程序中断在下面代码
         PUSH DWORD PTR DS:[EAX+EBX]              ; yyyyyyy
         上面[EAX+EBX]的值(yyyyyy)就是我们要找的位置。

       2). Delphi, CBuilder 的程序
         程序直接断在我们要找的位置。

    借moon一句,这姑妄称作CallWindowProcA条件断点加上code段内存断点法吧。 

    二、VC程序
    又分MFC和Win32两种情况,二者相同之处:
    3 在IsDialogMessageW入口下条件断点: [[esp+8]]==xxxxxxxx && [[esp+8]+4]==202
    4 F9继续程序,点击目标按钮,程序中断;
    5 Alt+F4,在代码段上下访问断点;
    6 F9执行程序,程序中断, 注意这里虽然中断在code段,但却不是处理Button点击事件的代码处
      这时:
      对Win32程序,只需要按几下F7,当回到User32.dll领空后再重复一次第 5、6步就可以了;
      而对于MFC程序,我们不得不多次重复这样的操作:单步回到MFC领空,再第 5、6步。好在已经看到大陆啦!

    类比,这就叫IsDialogMessageW条件断点加上code段内存断点法了。 

    敬请各位指正。
    posted @ 2009-04-24 04:37 -> 阅读(47) 评论(0)  编辑

    2009年4月23日 #

    posted @ 2009-04-23 18:19 -> 阅读(129) 评论(0)  编辑

    posted @ 2009-04-23 03:01 -> 阅读(135) 评论(0)  编辑

    2009年4月22日 #

    posted @ 2009-04-22 23:49 -> 阅读(49) 评论(0)  编辑

    posted @ 2009-04-22 23:48 -> 阅读(42) 评论(0)  编辑

    2009年4月21日 #

    posted @ 2009-04-21 06:03 -> 阅读(49) 评论(0)  编辑

    2009年4月20日 #

    posted @ 2009-04-20 01:16 -> 阅读(387) 评论(0)  编辑

    posted @ 2009-04-20 00:33 -> 阅读(212) 评论(0)  编辑

    posted @ 2009-04-20 00:21 -> 阅读(211) 评论(0)  编辑

    posted @ 2009-04-20 00:02 -> 阅读(389) 评论(0)  编辑

    2009年4月19日 #

    posted @ 2009-04-19 23:50 -> 阅读(13) 评论(0)  编辑

    2009年4月17日 #

    posted @ 2009-04-17 17:36 -> 阅读(49) 评论(0)  编辑

    2009年4月15日 #

    posted @ 2009-04-15 16:04 -> 阅读(17) 评论(0)  编辑

    posted @ 2009-04-15 01:25 -> 阅读(14) 评论(0)  编辑

    2009年4月5日 #

    posted @ 2009-04-05 11:27 -> 阅读(120) 评论(0)  编辑

    2009年3月30日 #

    posted @ 2009-03-30 07:46 -> 阅读(60) 评论(0)  编辑

    2009年3月9日 #

    posted @ 2009-03-09 13:06 -> 阅读(61) 评论(0)  编辑

    2009年3月2日 #

    posted @ 2009-03-02 00:08 -> 阅读(263) 评论(0)  编辑

    2009年3月1日 #

    posted @ 2009-03-01 23:36 -> 阅读(57) 评论(0)  编辑

    posted @ 2009-03-01 07:39 -> 阅读(25) 评论(0)  编辑

    2009年2月28日 #

    posted @ 2009-02-28 05:25 -> 阅读(16) 评论(0)  编辑

    posted @ 2009-02-28 04:36 -> 阅读(138) 评论(0)  编辑

    posted @ 2009-02-28 01:30 -> 阅读(183) 评论(0)  编辑