博文
客户端Cookie中文编程(上)(2006-05-24 16:33:00)
摘要:客户端Cookie中文编程(转自yesky.com) Cookie的使用中,我们发现这样一个问题:如果写入Cookie的内容是中文(如用户称呼),用服务器端程序(如ASP或PHP)读出完全正确,但是用一般的JavaScript或VBScript的读Cookie函数取出的却是一堆乱码。这是一个棘手的问题,因为在有些情况下,Cookie的内容需要在客户机端用脚本语言读取。如果你写入了中文,得到了一堆乱码,是不是感觉很别扭呢?解决这个问题,还要从Cookie的存取方式说起。 我们知道,写入Cookie内容前需要进行escape(十六进制编码),编码时又是以字节为单位的,这就是问题的关键所在:任何一个汉字都会被拆成两个字节分别编码;而在读Cookie时,unescape又以字节单位解码,因此最后每个汉字都变成了两个字节的乱码。怎么办呢?ASP或PHP方式能够正确读出,应该是在unescape解码后,又按照unicode编码把其中的汉字拼了出来。如果这样的话,能不能找到一种变通的方法解决这个问题呢?仔细研究后发现,只要在十六进制codec(编解码)过程中能够保存汉字信息就行了,因而我们需要再外包一层codec过程,方案如下: 1.在escape编码前,把Cookie字符串中的每个字符转换为unicode码的字符串形式(用一特殊字符作为字串的分隔符)。 2.在unescape解码后,先把所有unicode字串提取出来,再用对应的函数转换为原字符。<SCRIPT LANGUAGE=javascript><!--//编码程序:function CodeCookie(str){ var strRtn=""; for (var i=str.length-1;i>=0;i--) { strRtn+=str.charCodeAt(i); if (i) strRtn+="a"; //用a作分隔符 } return strRtn;}//解码程序:function DecodeCookie(str){ var strArr; var strRtn=""; strArr=str.split("a"); for (var i=strArr.length-1;i>=0;i--) strRtn+=String.fromCharCode(eval(strArr[i......
献丑啦--正则表达式练习器(2006-05-24 16:31:00)
摘要:正则表达式的用途很广泛,但要熟练掌握就不是一件容易的事情了。为此,我编写了这个练习器用来帮助学习。 请多指教!*********将以下代码复制到 RegExp.htm 即可 **********<HTML><HEAD><TITLE>正则表达式练习器</TITLE><meta name = 安徽 池州 统计局 徐祖宁 e-mail:czjsz@stats.gov.cn><script language="JavaScript">function OnMove() {window.status = "("+window.event.clientX+","+window.event.clientY+")" + " :: "+document.location}</script><SCRIPT LANGUAGE="JavaScript1.2">var re = new RegExp() //建立正则表达式对象var nextpoint = 0 //匹配时的偏移量//设置正则表达式function setPattern(form) { var mode if(form.chkmode.checked) mode = "gi" //i:不分大小写 g:全局,好象没什么作用 else mode = "g" re.compile(form.regexp.value,mode) nextpoint = 0 form.reglist.value = ""}//检查是否有匹配function findIt(form) { setPattern(form) var input = form.main.value if (input.search(re) != -1) { form.output[0]......
对正则表达式练习器的改进(2006-05-24 16:31:00)
摘要:覆盖原execIt函数修改后的execIt函数允许对多个正则表达式进行匹配(每个正则表达式一行),并对每一个匹配成分显示出是第几个正则表达式匹配的。这可视为语法分析的雏形,只要对匹配产生相应的动作。function execIt(form) { var mode if(form.chkmode.checked) mode = "gi" else mode = "g" var regexpArray = form.regexp.value.split("\r\n") //获取正则表达式到数组 if(nextpoint == 0) form.reglist.value = "" var key = true if(form.scankmode.checked) key = false else nextpoint = 0 do { var offs = 9999999999 var pos = -1 var input = form.main.value.substr(nextpoint) //对每个正则表达式进行匹配 for(var i=0;i<regexpArray.length;i++) { re.compile(regexpArray[i],mode) var matchArray = re.exec(input) if(matchArray) { if(offs > matchArray.index) {&n......
实现UBB代码(2006-05-24 16:29:00)
摘要:上一次,我们谈到在ASP中如何利用“正则表达式”对象来实现各种数据的校验,文中描述了正则表达式对象的强大功能,接下来, 我们来看看有关“正则表达式”对象的其他功能。当我们在网上冲浪的时候,尤其是浏览各类论坛的时候,经常会见到“UBB代码” 这个词语。什么是UBB代码呢?UBB代码是HTML的一个变种,是Ultimate Bulletin Board (国外一个BBS程序,国内也有不少地方 使用这个程序)采用的一种特殊的TAG。为了避免用户无意或者有意的HTML代码对论坛的攻击,各种论坛基本上都屏蔽了HTM L代码,但是为了使得论坛更加“多姿多彩”,论坛都会相应的开放一些自定义的Tag标签,类似于HTML中的Tag,比如 “[URL],[/URL],[RED],[/RED]”,这样,可以提供一些等同于HTML代码的功能,又避免了论坛受到恶意攻击,这些自定义的 各种Tag就是俗称的UBB代码。眼下时髦的论坛均支持UBB代码,比如:http://www。chinaasp。com(动 感技术网络)的论坛就很好的支持UBB代码。现在,我们一同使用“正则表达式”对象来实现我们自己的丰富多彩的UBB代码吧。 首先,你的服务器端(IIS或者PWS)要有VBScript5.0的支持环境,一般指要安装了IE5.X就已经可以支持“正则表达式”对 象了。 关于“正则表达式”对象的常见方法、属性的使用方法,我在本刊的“在ASP中利用“正则表达式”对象实现数据的校验”一文中已 经有详细介绍了,可以参见那一篇文章,在这里,我主要介绍一下实现“UBB代码”的主要正则表达式对象方法:Replace()方 法。 Replace方法语法如下: 描述 替换在正则表达式查找中找到的文本。 语法 object.Replace(string1, string2) Replace 方法的语法包含以下几个部分: 部分 描述 object 必需的。总是一个 RegExp 对象的名称。 string1 必需的。string1 是将要进行文本替换的字符串。 string2 必需的。 string2 是替换文本字符串。 说明 被替换的文本的实际模式是通过 RegExp 对象的 Pattern 属性设置的。 Replace 方法返回 string1 的副本,其中的 RegExp......
一个正则表达式的类(2006-05-24 16:27:00)
摘要:using System; namespace Regexlib { /// /// Class1 的摘要说明。 public class Regexlib { public Regexlib() { // // TODO: 在此处添加构造函数逻辑 // } //搜索输入字符串并返回所有 href=“...”值 string DumpHrefs(String inputString) { Regex r; Match m; r = new Regex("href\\s*=\\s*(?:\"(?<1>[^\"]*)\"|(?<1>\\S+))", RegexOptions.IgnoreCase|RegexOptions.Compiled); for (m = r.Match(inputString); m.Success; m = m.NextMatch()) { Return("Found href " + m.Groups[1]); } } //验证Email地址 bool IsValidEmail(string strIn) { // Return true if strIn is in valid e-mail format. return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"); } //dd-mm-yy 的日期形式代替 mm/dd/yy 的日期形式。 string MDYToDMY(String input) { return Regex.Replace(input,"\\b(?\\d{1,2})/(?\\d{1,2})/(?\\d{2,4})\\b","${day}-${month}-${year}"); } //验证是否为小数 bool IsValidDecimal(string strIn) { return Regex.IsMatch(strIn,@"[0].\d{1,2}|[1]"); } //验证是否为电话号码 bool IsValidTel(string strIn) { return Regex.IsMatc......
.NET多线程编程(1):多任务和多线程(2006-05-22 09:52:00)
摘要:在.NET多线程编程这个系列我们讲一起来探讨多线程编程的各个方面。首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述。NET平台上多线程编程的知识,诸如System.Threading命名空间的重要类以及方法,并就一些例子程序来作说明。 引言 早期的计算硬件十分复杂,但是操作系统执行的功能确十分的简单。那个时候的操作系统在任一时间点只能执行一个任务,也就是同一时间只能执行一个程序。多个任务的执行必须得轮流执行,在系统里面进行排队等候。由于计算机的发展,要求系统功能越来越强大,这个时候出现了分时操作的概念:每个运行的程序占有一定的处理机时间,当这个占有时间结束后,在等待队列等待处理器资源的下一个程序就开始投入运行。注意这里的程序在占有一定的处理器时间后并没有运行完毕,可能需要再一次或多次分配处理器时间。那么从这里可以看出,这样的执行方式显然是多个程序的并行执行,但是在宏观上,我们感觉到多个任务是同时执行的,因此多任务的概念就诞生了。每个运行的程序都有自己的内存空间,自己的堆栈和环境变量设置。每一个程序对应一个进程,代表着执行一个大的任务。一个进程可以启动另外一个进程,这个被启动的进程称为子进程。父进程和子进程的执行只有逻辑上的先后关系,并没有其他的关系,也就是说他们的执行是独立的。但是,可能一个大的程序(代表着一个大的任务),可以分割成很多的小任务,为了功能上的需要也有可能是为了加快运行的速度,可能需要同一时间执行多个任务(每个任务分配一个多线程来执行相应的任务)。举个例子来说,你正在通过你的web浏览器查看一些精彩的文章,你需要把好的文章给下载下来,可能有些非常精彩的文章你需要收藏起来,你就用你的打印机打印这些在线的文章。在这里,浏览器一边下载HTML格式的文章,一边还要打印文章。这就是一个程序同时执行多个任务,每个任务分配一个线程来完成。因此我们可以看出一个程序同时执行多个任务的能力是通过多线程来实现的。多线程VS多任务 正如上面所说的,多任务是相对与操作系统而言,指的是同一时间执行多个程序的能力,虽然这么说,但是实际上在只有一个CPU的条件下不可能同时执行两个以上的程序。CPU在程序之间做高速的切换,使得所有的程序在很短的时间之内可以得到更小的CPU时间,这样从用户的角度来看就好象是同时在执行多个程序。......
c#.net多线程编程教学(2):Thread类(2006-05-22 09:43:00)
摘要:这章将向大家介绍.NET中的线程API,怎么样用C#创建线程,启动和停止线程,设置优先级和状态. 在.NET中编写的程序将被自动的分配一个线程.让我们来看看用C#编程语言创建线程并且继续学习线程的知识。我们都知道.NET的运行时环境的主线程由Main ()方法来启动应用程序,而且.NET的编译语言有自动的垃圾收集功能,这个垃圾收集发生在另外一个线程里面,所有的这些都是后台发生的,让我们无法感觉到发生了什么事情.在这里默认的是只有一个线程来完成所有的程序任务,但是正如我们在第一篇文章讨论过的一样,有可能我们根据需要自己添加更多的线程让程序更好的协调工作。比如说我们的例子中,一个有用户输入的同时需要绘制图形或者完成大量的运算的程序,我们必须得增加一个线程,让用户的输入能够得到及时的响应,因为输入对时间和响应的要求是紧迫的,而另外一个线程负责图形绘制或者大量的运算。 .NET 基础类库的System.Threading命名空间提供了大量的类和接口支持多线程。这个命名空间有很多的类,我们将在这里着重讨论Thread这个类。 System.Threading.Thread类是创建并控制线程,设置其优先级并获取其状态最为常用的类。他有很多的方法,在这里我们将就比较常用和重要的方法做一下介绍: Thread.Start():启动线程的执行; Thread.Suspend():挂起线程,或者如果线程已挂起,则不起作用; Thread.Resume():继续已挂起的线程; Thread.Interrupt():中止处于 Wait或者Sleep或者Join 线程状态的线程; Thread.Join():阻塞调用线程,直到某个线程终止时为止 Thread.Sleep():将当前线程阻塞指定的毫秒数; Thread.Abort():以开始终止此线程的过程。如果线程已经在终止,则不能通过Thread.Start()来启动线程。 通过调用Thread.Sleep,Thread.Suspend或者Thread.Join可以暂停/阻塞线程。调用Sleep()和Suspend()方法意味着线程将不再得到CPU时间。这两种暂停线程的方法是有区别的,Sleep()使得线程立即停止执行,但是在调用Suspend()方法之前,公共语言运行时必须到达一个安全点。一个线程不能对另外一个线程......
C#多线程应用技术面对面探讨(2006-05-22 09:22:00)
摘要:实例程序说明 本文的实例程序包括一个列表框、三个按钮。程序使用一个新的线程来运行一个后台处理,结果在列表框中显示。按钮button1启动一个计算平方的线程。按钮button2停止后台处理线程。按钮button3退出程序。程序运行情况如图1所示。 使用线程 首先创建运行在新线程上的后台任务。表1所示的代码执行一个相当长的运行处理----一个无限循环。 表1、后台处理程序 private void BackgroundProcess() { int i= 1; while(true) { // 向列表框增加一个项目 listBox1.Items.Add("Iterations: " + i.ToString ()); i ++; Thread.Sleep(2000); // 指定线程休眠的时间 } } 这段代码无限循环,每次执行时在列表框中加入一个项目。 在规定好一个工作的处理代码以后,就需要将这段代码分配给一个线程,并且启动它。为此需要使用线程对象(Thread object),它是.NET架构类中System.Threading命名空间的一部分。在实例化一个新的线程类时,需要把在线程类构造器中执行的代码块的一个引用传送给该实例。表2所示的代码创建一个新的线程对象,并且将BackgroundProcess的一个引用传送给该对象。 表2、线程的使用 Thread t1,t2; // 说明为窗体类成员 t1 = new Thread(new ThreadStart(BackgroundProcess)); t1.Start(); // 以上2行放置在窗体的load事件中 ThreadStart表示在线程上执行的方法,这里是一个到BackgroundProcess方法的委派对象。在C#中,一个委派是一个类型安全、面向对象的函数指针。在实例化该线程后,可以通过调用线程的Start()方法来开始执行代码。 控制线程 在线程启动以后,可以通过调用线程对象的方法来控制线程的状态。可以通过调用Thread.Sleep方法来暂停一个线程的执行,这个方法可以接收一个整型值,用来决定线程休眠的时间。对于本文的实例程序,为了让列表项目增加的速度变慢,在其中放入了一个Sleep方法的调用。 可以通过调用Threa......
如何将论坛附件直接以文件形式保存,并读取照片文件的Exif信息(2006-05-19 11:42:00)
摘要:废话少说,直接进入主题: 准备工作:下载PhotoProperties类库(http://www.codeproject.com/cs/media/photoproperties.asp),用于读取Exif信息,在Components中引用该类库1、修改web.config配置文件,在forums/forums下增加一个配置项 uploadFilesPath="/Upload/" 值可以自行修改,用来保存用户上传的文件;2、修改数据库 forums_PostAttachments表增加如下字段 DiskFileName nvarchar(256), 保存附件在硬盘上的文件名 Exif nvarchar(200), 用于保存照片附件的Exif信息 CheckGuid nvarchar(50) 用于保存检测的Guid 注意:我们修改的最终方案是会删除原有的Content字段的
修改存储过程:create procedure forums_PostAttachment_Add ( @PostID int, @UserID int, @ForumID int, @Filename nvarchar(256), @DiskFileName&......
利用WSE 加密SOAP报文(2006-05-18 17:41:00)
摘要:给收到的报文解密 当收到一个由X.509证书加密后的报文后,SoapInputFilter会自动尝试使用用户密钥储存室的私有密钥来进行解密,当然,这个需要告诉WSE运行时哪里可以找到这个证书的额外配置信息。这个信息由应用程序配置文件的Security元素所指定,这个例子在客户端上的应用程序配置文件是App.config。对于 X.509加密,你只需要添加一个x509子节点,内容和下面一样就可以了 <x509 storeLocation="CurrentUser" verifyTrust="true" allowTestRoot="false" /> 在我的例子中,我将x509节点的storeLocation属性设为CurrentUser,假设证书在当前用户的证书储存室里,当我使用了来自CA的受信任证书之后,我也将verifyTrust设为true了。这些属性还能够用WSE的设置工具来修改。利用这些信息,WSE能够得到报文中证书的私有密钥,还能用这个来给对称性会话密钥解密,解密后的内容到头来还要给报文正文解密。 选择用于解密的报文元素 当整个消息正文由默认设置给加密后,WSE能被用来给SOAP报文内的特定元素加密;唯一的问题是,在Security头元素那的元素不能被加密。你还可以加密嵌套的元素, 在这个例子服务中,我修改了GetXmlDocument方法用的X.509版本,用一个基于X.509的安全Token来同时给EncryptedSubResponse和它的EncryptedResponse父节点进行数字化加密,返回的XML文档如下: <Response> <NotEncrypted> 回应报文的这里没有必要被加密 </NotEncrypted> <EncryptedResponse> <EncryptedSubResponse> 这里是敏感数据. </EncryptedSubResponse> </EncryptedResponse> </Response> 为了加密一个元素,它需要一个wsu:Id属性,以便当XML被序列化后引用可以加到该节点上了。命名空间wsu被定义为: xmlns:wsu="http://schemas.xmlsoap.org/ws/......
