一个能防止改名木马漏洞的无组件上传类

现在流行的asp上传组件除了无惧的化境之外,最多的可能就是ewebEditor 和Fckeditor的上传是,但是经过测试都很难防止改名为gif和asp文件上传,在FckEditor中改名后的asp木马不能直接上传,系统会检测到 <%等字符而拒绝,但是经过修改后的asp木马再改名为gif后却可以顺利上传,如在文件前端加上许多空行,或对木马进行加密处理。当然有人会认为木马传到服务器后会被杀掉,但是做过免杀的木马却会漏网。基于这些原因,本人开发了一个可以从根本上解决这个问题的无组件上传类。经过测试常用的文件格式均可通过。做法是对上传的文件进行格式分析,不符合的格式不允许上传,这样就从根本上解决了这个问题。现贴上来请大家指教。

1、文件upfile.asp

'************************************************************************** 
'*  类文件名称:upfile.asp 
'*  作者:马如风(Melon) 
'*  邮箱:mqmelon0@163.com 
'*  版权:=====筱风工作室(R)2004.1-2004.3===== 
'*  内容:不用组件上传文件类 
'*  用法:在接收表单内容的文件中定义UpFileClass类对象,用GetData方法 
'*      读取文件内容,并使用FileInfo类的SaveToFile方法存入指定文件 
'*  例子:set FileUP=new UpFileClass 
'* FileUp.GetData 
'*      set file1=FileUP.upFile("表单元素名") 
'* filename=path&filename 
'*      file1.SaveToFile(server.mappath(filename)) 
'*      set FileUp=nothing 
'************************************************************************** 
%> 
<% 
response.charset="gb2312" 

Dim BinaStream '全局变量 
'dim FileSavePath    

Class UpFileClass  '类别名称 
'定义Dictionary变量,用于保存上传的信息 
Dim upForm,upFile 

' 类初始化过程 
private sub Class_Initialize 
'判断传递的数据,如无,则退出 
if Request.TotalBytes <1 Then 
Exit sub 
End if 
'FileSavePath=""  '全局变量负值 
set BinaStream=Server.CreateObject("adodb.stream") 
set upForm=New DictionaryClass 
set upFile=New DictionaryClass 
End sub 

'类清除过程 
Private sub Class_Terminate 
upFile.RemoveAll 
upForm.RemoveAll 
set upFile=nothing 
set upForm=nothing 
BinaStream.Close 
set BinaStream=nothing 
FileSavePath="" 
End sub 

'获取数据过程 
Public sub GetData 
Dim oFileInfo '用于保存文件信息的类对象 
Dim oDataSeprator '用于保存分隔符信息,为二进制字符串 
Dim oFindStart,oFindEnd '寻找指针 
Dim oCrLf ' CHRB(13)&CHRB(10), 分隔数字 
Dim oFormData ' 表单数据描述信息,文本串 
Dim oFileStart ' 文件开始位置 
Dim otmpStream ' 临时Stream 对象,用于中间周转字符串 
Dim otmpBinaData ' 临时二进制字符串,用于中间周转 
Dim oDataAllSize ' 所有二进制数值大小 
Dim oFormName ' 表单元素名称 
Dim oFormContent ' 表单元素内容 
Dim oFormStart ' 表单元素开始位置 
Dim oFormEnd ' 表单元素结束位置 
Dim oFileFullName ' 带路径文件名 

'变量初始化 
set oFileInfo=new FileInfo 
oDataSeprator="" 
oFindStart=Clng(0) 
oFindEnd=Clng(0) 
oCrLf=chrB(13)&chrB(10) 
oFormData="" 
oFileStart=Clng(0) 
set otmpStream=Server.CreateObject("adodb.stream") 
otmpBinaData="" 
oDataAllSize=Clng(0) 
oFormName="" 
oFormcontent="" 
oFormStart=Clng(0) 
oFormEnd=Clng(0) 
oFileFullName="" 
' 获得传递过来的二进制数据 
if Request.TotalBytes <1 then 
Error_Msg("发生数据错误,传递数据空或丢失!") 
Exit sub 
End if 
BinaStream.Type=1 '二进制 
BinaStream.Mode=3 '读写模式,1-读,2-写,3-读写 
BinaStream.Open  '打开对象,准备读写 
'开始读取所有上传的数据 
'Thankful long(yrl031715@163.com) 
'Fix upload large file. 
'********************************************** 
' 修正作者:long 
' 联系邮件: yrl031715@163.com 
' 修正时间:2007年5月6日 
' 修正说明:由于iis6的Content-Length 头信息中包含的请求长度超过了 AspMaxRequestEntityAllowed 的值(默认200K), IIS 将返回一个 403 错误信息. 
'          直接导致在iis6下调试FCKeditor上传功能时,一旦文件超过200K,上传文件时文件管理器失去响应,受此影响,文件的快速上传功能也存在在缺陷。 
'          在参考 宝玉 的 Asp无组件上传带进度条 演示程序后作出如下修改,以修正在iis6下的错误。 

Dim nTotalBytes, nPartBytes, ReadBytes 
ReadBytes = 0 
nTotalBytes = Request.TotalBytes 
'循环分块读取 
Do While ReadBytes < nTotalBytes 
'分块读取 
nPartBytes = 64 * 1024 '分成每块64k 
If nPartBytes + ReadBytes > nTotalBytes Then 
nPartBytes = nTotalBytes - ReadBytes 
End If 
BinaStream.Write Request.BinaryRead(nPartBytes) 
ReadBytes = ReadBytes + nPartBytes 
Loop 
'读取完毕 
BinaStream.Position=0 
otmpBinaData=BinaStream.Read 
oDataAllSize=BinaStream.Size 
'获得分隔符 
oDataSeprator=MidB(otmpBinaData,1,InstrB(1,otmpBinaData,oCrLf)-1) 
'给寻找指针付值 
oFindStart=Lenb(oDataSeprator)+2 
oFindEnd=oFindStart 
'分解名项目,且保存其值 
While oFindStart+2 <oDataAllSize 
otmpStream.Type=1 
otmpStream.MOde=3 
otmpStream.Open 
oFindEnd=InstrB(oFindStart,otmpBinaData,oCrLf&oCrLf)+3 
'此时,oFindEnd指向内容,oFindStart指向描述 
BinaStream.Position=oFindStart 
BinaStream.CopyTo otmpStream,oFindEnd-oFindStart 
'把表单描述存入oFormData 
otmpStream.Position=0 
otmpStream.Type=2 '设为文本类型数据 
otmpStream.Charset="gb2312" '设字符集为中文 
oFormData=otmpStream.ReadText '保存数据为文本 
'查找表单项目名称 
oFormStart=Instr(1,oFormData,"name=",1)+len("name=")+1 
oFormEnd=Instr(oFormStart,oFormData,"""",1) 
oFormName=Mid(oFormData,oFormStart,oFormEnd-oFormStart) 
'调试开始 
'open_appe_txt "debug.txt","oFormData="&chr(13)&chr(10)&oFormData 
'open_appe_txt "debug.txt","判断前:"&chr(13)&chr(10)&"oFormStart="&oFormStart&"oFormEnd="&oFormEnd&"oFormName="&oFormName 
'调试结束 
'判断是否为文件 
if Instr(oFormEnd,oFormData,"filename=",1)>0 Then 
'是文件,则取文件属性 
'找到文件名字 
oFormStart=Instr(oFormEnd,oFormData,"filename=",1)+len("filename=")+1 
'加1是为了去掉文件名字前面的引号 
oFormEnd=Instr(oFormStart,oFormData,"""",1) 
'此时,oFormEnd指向下一个描述的前一个位置,减1是为去掉引号 
'获得文件信息 
'获得带路径文件名称 
oFileFullName=Mid(oFormData,oFormStart,oFormEnd-oFormStart) 
'分解文件名称 
oFileInfo.FileName=GetFileName(oFileFullName) 
oFileInfo.FileExt=GetFileExt(oFileFullName) 
oFileInfo.FilePath=GetFilePath(oFileFullName) 
'获得文件类型 
oFormStart=Instr(oFormEnd,oFormData,"Content-Type:",1)+len("Content-Type:") 
oFormEnd=Instr(oFormStart,oFormData,chr(13)&chr(10),1) 
oFileInfo.FileType=Mid(oFormData,oFormStart,oFormEnd-oFormStart) 
'获得文件内容起始点 
oFileInfo.FileStart=oFindEnd 
oFindStart=InstrB(oFindEnd,otmpBinaData,oDataSeprator) 
'此时,oFindStart指向分隔符位置 
oFileInfo.FileSize=oFindStart-oFindEnd-3 
oFileInfo.FormName=oFormName 
'把数据加入到upFile[Dictionary对象]中保存 
'调试开始 
'open_appe_txt "debug.txt","循环中(文件):"&chr(13)&chr(10)&"oFindStart="&oFindStart&"oFormName="&oFormName 
'调试结束 
upFile.add oFormName,oFileInfo 
Else 
'如果是表单元素,则取元素值 
'关闭otmpStream对象,以便重新读取内容 
otmpStream.Close 
otmpStream.Type=1 
otmpStream.Mode=3 
otmpStream.Open 
'找到内容结束位置 
oFindStart=InstrB(oFindEnd,otmpBinaData,oDataSeprator) 
'读出内容 
BinaStream.Position=oFindEnd 
BinaStream.CopyTo otmpStream,oFindStart-oFindEnd-3 
otmpStream.Position=0 
otmpStream.Type=2 
otmpStream.Charset="gb2312" 
oFormContent=otmpStream.ReadText 
upForm.add oFormName,oFormContent 
End if 
'调整寻找指针位置 
oFindStart=oFindStart+LenB(oDataSeprator)+1 
'此时,寻找指针均指向下一描述 
otmpStream.Close 
WEnd '循环返回 
'变量清空 
otmpBinaData="" 
set otmpBinaData=nothing 
end sub '子程序到此结束

'获得文件路径程序 
Private Function GetFilePath(FullPath) 
if FullPath <>"" Then 
GetFilePath=Left(FullPath,InstrRev(FullPath,"/")) 
Else 
GetFilePath="" 
End if 
End Function 

'获得文件名程序 
Private Function GetFileName(FullPath) 
if FullPath <>"" Then 
GetfileName=Mid(FullPath,InstrRev(FullPath,"/")+1) 
Else 
GetFileName="" 
End if 
End Function 

'获得文件扩展名 
Private Function GetFileExt(FullPath) 
if FullPath <>"" Then 
GetFileExt=Mid(FullPath,InstrRev(FullPath,".")+1) 
Else 
GetFileExt="" 
End if 
End Function 

'类定义结束 
End Class 

'文件属性类定义开始 
Class FileInfo 
Dim FileName,FileSize,FileStart,FilePath,FileExt,FileType,FormName 
'Dim FileSaveName 

Private sub Class_Initialize 
FileName="" 
FileSize=0 
FileStart=0 
FilePath="" 
FileExt="" 
FileType="" 
FormName="" 
End sub 

Private sub Class_Terminate 
'空子程序 
End sub 


'把内容存入到服务器上指定位置和名称的文件 
Public Function SaveToFile(tmpFileName) 
Dim FileSaveStream,tmpStream,tmpReadStream,FullPath 
Dim filePath,FileFullName,SpcPosition 
'使用服务器路径 
tmpFileName=s_SavePath&tmpFileName 
FullPath=server.mappath(tmpFileName) 
'加入 
Dim mfileExt,tmpData 
mfileExt=Mid(FullPath,InstrRev(FullPath,".")+1,Len(FullPath)) 
'加入2009.3.27 

SaveFile=-1 
if FullPath="" or Right(FullPath,1)="/" Then 
Call Error_Msg("Error Occured when Save the file to appointed directory and fileName!:/n The fileName is not valid!") 
Exit Function 
Else 
'替换/为/ 
FullPath=Replace(FullPath,"/","/") 
'取出保存的目录 
SpcPosition=InStrrev(FullPath,"/") 
If spcposition=0 Then 
filePath=s_curPath '使用程序所在目录 
FileFullName=FullPath 
Else 
filePath=Mid(FullPath,1,SpcPosition-1) 
FileFullName=Mid(FullPath,spcPosition+1,Len(Fullpath)) 
End if 


If i_AutoRename=1 Then 
'如果存在同名,则自动更名 
tmpFileName=s_SavePath& autoRename(filePath,FileFullName) 
FullPath=server.mappath(tmpFileName) 
End if 
End if 

set FileSaveStream=Server.CreateObject("adodb.stream") 
FileSaveStream.Type=1 
FileSaveStream.Mode=3 
fileSaveStream.Open 
BinaStream.position=FileStart 
BinaStream.CopyTo FileSaveStream,FileSize 

BinaStream.position=FileStart 
tmpData=BinaStream.read(30) 

If mfileExt <>"" Then 
If SniffPic(mfileExt,tmpData)=False Then 
saveToFile=-1 
Exit function 
End if 
End If 

FileSaveStream.SaveToFile FullPath,2 
FileSaveStream.Close 
set FileSaveStream=nothing 

SaveToFile=0 

End Function 

'获得文件保存的内容,返回二进制数据,可以用来存入数据库中 
Public Function GetFileData() 
BinaStream.Position=FileStart 
GetFileData=BinaStream.Read(Filesize) 
End Function 

'测试一个文件是否存在 
function AutoRename(filePath,FileFullName) 
'如果一个文件存在,则自动更名 
Dim oFSO,testFileName,testFileExt,extPosition,iCounter,sFileName 
'返回值,默认直接返回 
AutoRename=fileFullName 
'取得文件名 
extPosition=InstrRev(FileFullName,".") 
If extPosition>0 Then 
testFileName=Mid(FileFullName,1,extPosition-1) 
testFileExt=Mid(FileFullName,extPosition+1,Len(FileFullName)) 
Else 
testFileName=FileFullName 
testFileExt="" 
End If 
sFileName=fileFullName 
Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" ) 
'测试指定目录是否存在 
if not (oFSO.FolderExists( filePath)) then 
'不存在,则生成目录,然后退出 
oFSO.CreateFolder(filePath) 
else 
iCounter = 0 

Do While ( True ) 
Dim sFilePath 
sFilePath = filePath & "/" & sFileName 

If ( oFSO.FileExists( sFilePath ) ) Then 
iCounter = iCounter + 1 
sFileName =  testFileName & "(" & iCounter & ")." & testFileExt 
Else 
Exit Do 
End If 
Loop 

If iCounter>0 Then 
AutoRename=sFileName 
End if 
end if 
End function 

End Class 
'FileInfo类定义结束 
%> 
<% 
function open_appe_txt(txt_name,txt_content) 
dim MyFileObject,MyTextFile 
set MyFileObject=server.CreateObject("Scripting.FileSystemObject") 
set MyTextFile=MyFileObject.OpenTextFile(server.MapPath(txt_name),8,true) 
MyTextFile.WriteLine(txt_content) 
MyTextFile.Close 
set MyTxtFile=nothing 
set MyFileObject=nothing 
end function 
%> 
<% 
'显示错误信息程序 
sub Error_Msg(eMsg,eUrl) 
%> 
<script> 
alert(' <%=eMsg%>'); 
if (""==' <%=eUrl%>') 
history.back(); 
else 
document.location=' <%=eUrl%>'; 
</script> 
<% 
End Sub 


'马如风2009.3.26 
Function Bin2Str(Bin) 
  Dim I, Str 
  For I=1 to LenB(Bin) 
    clow=MidB(Bin,I,1) 
    if AscB(clow) <128 then 
      Str = Str & Chr(ASCB(clow)) 
    Else 
      I=I+1 
      if I <= LenB(Bin) then Str = Str & Chr(ASCW(MidB(Bin,I,1)&clow)) 
    end If 
  Next 
  Bin2Str = Str 
End Function 

function binToNum(bin) 
    '二进制转为 Numeric 
        dim i:binToNum=0 
        for i=lenB(bin) to 1 step -1 
            binToNum=binToNum*256+ascB(midB(bin,i,1)) 
        next 'shawl.qiu code' 

end function 

Function SniffPic(sFileExt,sData) 
SniffPic=false 
If sfileExt="" Then 
Exit function 
End if 

Dim tmpExt,tmpData,tmpI,tmpSource 

tmpExt=UCase(sFileExt) 
If lenb(sData) <10 Then 
Exit Function 
End If 

Select Case tmpExt 
Case "GIF" 
For tmpI=1 To 3 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
Next 
tmpSource=Hex("&H47") & Hex("&H49") & Hex("&H46") 
If tmpData=tmpSource Then 
SniffPic=true 
End if 
Case "JPG" 
For tmpI=1 To 3 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&HFF")) & CStr(Hex("&HD8")) & CStr(Hex("&HFF")) 
If tmpData=tmpSource Then 
SniffPic=true 
End if 
Case "PNG" 
For tmpI=1 To 4 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&H89")) & CStr(Hex("&H50")) & CStr(Hex("&H4E")) & CStr(Hex("&H47")) 
If tmpData=tmpSource Then 
SniffPic=true 
End if 
Case "BMP" 
For tmpI=1 To 2 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&H42")) & CStr(Hex("&H4D")) 
If tmpData=tmpSource Then 
SniffPic=true 
End if 
Case "PCX" 
For tmpI=1 To 4 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&H0A")) & CStr(Hex("&H05")) & CStr(Hex("&H01")) & CStr(Hex("&H08")) 
If tmpData=tmpSource Then 
SniffPic=true 
End if 
Case "TIF" 
For tmpI=1 To 4 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&H49")) & CStr(Hex("&H49")) & CStr(Hex("&H2A")) & CStr(Hex("&H00")) 
If tmpData=tmpSource Then 
SniffPic=true 
End If 
Case "DOC" 
For tmpI=1 To 8 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&HD0")) & CStr(Hex("&HCF")) & CStr(Hex("&H11")) & CStr(Hex("&HE0")) & CStr(Hex("&HA1")) 
tmpSource=tmpSource & CStr(Hex("&HB1")) & CStr(Hex("&H1A")) & CStr(Hex("&HE1")) 
If tmpData=tmpSource Then 
SniffPic=true 
End If 
Case "XLS" 
For tmpI=1 To 8 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&HD0")) & CStr(Hex("&HCF")) & CStr(Hex("&H11")) & CStr(Hex("&HE0")) & CStr(Hex("&HA1")) 
tmpSource=tmpSource & CStr(Hex("&HB1")) & CStr(Hex("&H1A")) & CStr(Hex("&HE1")) 
If tmpData=tmpSource Then 
SniffPic=true 
End If 
Case "RAR" 
For tmpI=1 To 10 
tmpData=tmpData & Hex(binToNum(Midb(sData,tmpI,1))) 
next 
tmpSource=CStr(Hex("&H52")) & CStr(Hex("&H61")) & CStr(Hex("&H72")) & CStr(Hex("&H21")) & CStr(Hex("&H1A")) & CStr(Hex("&H07")) 
tmpSource=tmpSource & CStr(Hex("&H00")) & CStr(Hex("&HCF")) & CStr(Hex("&H90")) & CStr(Hex("&H73")) 
If tmpData=tmpSource Then 
SniffPic=true 
End If 
Case Else 
sniffpic=true 
End Select 
End function 
'马如风2009.3.26 
%> 
2、up.asp 
<%@codepage=936%> 
<html> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 
<body topmargin=0  rightmargin=0  leftmargin=0> 
<% 
'******************************************* 
'* 文件:up.asp 
'* 功能:上传文件 
'* 输入:无 
'* 输出:无 
'* 修改日期:2004.3.5 
'* 作者:马如风 
'* 版权声明:筱风工作室版权所有(2004-2005) 
'******************************************* 
%> 
<!--#include file="upfile.asp"--> 
<!--#include file="dic.asp"--> 
<!--#include file="setup.asp"--> 

<% 
fname=""&year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&"" 
if request("up_act")="up_files" then 

set FileUP=new upFileClass 
FileUP.GetData 

set file1=FileUP.upFile.item("file1") 
If i_rename=0 then 
'filename=s_SavePath&fname&"."&file1.FileExt 
filename=fname&"."&file1.FileExt 
else 
filename=file1.filename 
End if 

'对文件格式进行判断处理 
If InStr(S_FileExt,UCase(file1.fileExt))=0 then 
error_msg "Your File"&Chr(96)& "s Type is not allowed!/n","" 
response.End() 
end if 

if int(file1.filesize/1024)>i_upSize then 
Error_Msg "The FileSize is Exceed "&i_upSize&"KB!/n","" 
response.End() 
end if 

' 
Dim tmpResult 
'tmpResult=file1.SaveToFile(server.mappath(filename)) 
tmpResult=file1.SaveToFile(fileName) 
set FileUP=Nothing 

If tmpResult=0 then 

img=filename 
response.write (" <SCRIPT>parent.document.getElementById("""& s_inputName &""").value+='/n"&img&"';history.back(); </SCRIPT>") 

Else 

error_msg "Sorry!File"&Chr(96)& "s Type is not correct!/n","" 
response.End() 
End if 

Else 
If i_upfile=1 And i_Author=1 then 
%> 

<table cellpadding=0 cellspacing=0 border="0"> 
<tr> 
<form enctype=multipart/form-data method=post action=up.asp?up_act=up_files> 
<td> <input type=file style="FONT-SIZE:9pt;cursor:hand;" name=file1 size="20"> 
<input style="FONT-SIZE:9pt;cursor:hand;" type="submit" value=" 上 传 " name=Submit> 
</form> </td> </tr> </table> 
<% 
ElseIf i_Author=0 Then 

%> 
<table cellpadding=0 cellspacing=0 border="0"> 
<tr> <td style="font-size:12px;height:24px;" valign="middle">请登录后再使用上传功能。 </td> </tr> </table> 
<% 
else 
%> 
<table cellpadding=0 cellspacing=0 border="0"> 
<tr> <td style="font-size:12px;height:24px;" valign="middle">不允许上传文件. </td> </tr> </table> 
<% 
End if 
end if 
%>

3、dic.asp 
<% 
Class DictionaryClass 
Dim ArryObj()    '使用该二维数组来做存放数据的字典 
Dim MaxIndex      'MaxIndex则是ArryObj开始的最大上标 
Dim CurIndex      '字典指针,用来指向ArryObj的指针 
Dim C_ErrCode      '错误代码号 


Private Sub Class_Initialize 
CurIndex=0      '从下标0开始 
C_ErrCode=0      '0表示没有任何错误 
MaxIndex=100      '默认的大小 
Redim ArryObj(1,MaxIndex)  '定义一个二维的数组 
End Sub 

Private Sub Class_Terminate 
Erase ArryObj  '清除数组 
End Sub 

Public Property Get ErrCode '返回错误代码 
ErrCode=C_ErrCode 
End Property 

Public Property Get Count  '返回数据的总数,只返回CurIndex当前值-1即可. 
Count=CurIndex 
End Property 

Public Property Get Keys  '返回字典数据的全部Keys,返回数组. 
Dim KeyCount,ArryKey(),I 
KeyCount=CurIndex-1 
Redim ArryKey(KeyCount) 

For I=0 To KeyCount 
    ArryKey(I)=ArryObj(0,I) 
    Next 

Keys=ArryKey 
Erase ArryKey 
End Property 

Public Property Get Items  '返回字典数据的全部Values,返回数组. 
  Dim KeyCount,ArryItem(),I 
  KeyCount=CurIndex-1 
  Redim ArryItem(KeyCount) 

  For I=0 To KeyCount 
      If isObject(ArryObj(1,I)) Then 
      Set ArryItem(I)=ArryObj(1,I) 
  Else 
        ArryItem(I)=ArryObj(1,I) 
  End If 
  Next 

  Items=ArryItem 
  Erase ArryItem 
End Property 

Public Property Let Item(sKey,sVal) '取得sKey为Key的字典数据 
  If sIsEmpty(sKey) Then 
  Exit Property 
  End If 

  Dim i,iType 

  iType=GetType(sKey) 
  If iType=1 Then '如果sKey为数值型的则检查范围 
  If sKey>CurIndex Or sKey <1 Then 
  C_ErrCode=2 
Exit Property 
End If 
  End If 

  If iType=0 Then 
  For i=0 to CurIndex-1 
    If ArryObj(0,i)=sKey Then 
    If isObject(sVal) Then 
      Set ArryObj(1,i)=sVal 
  Else 
    ArryObj(1,i)=sVal 
  End If 
  Exit Property 
  End If 
  Next 
  ElseIf iType=1 Then 
      sKey=sKey-1 
    If isObject(sVal) Then 
      Set ArryObj(1,sKey)=sVal 
  Else 
    ArryObj(1,sKey)=sVal 
  End If 
  Exit Property 
  End If 
  C_ErrCode=2        'ErrCode为2则是替换或个为sKey的字典数据时找不到数据 
End Property 

Public Property Get Item(sKey) 
  If sIsEmpty(sKey) Then 
    Item=Null 
  Exit Property 
End If 
  
Dim i,iType 
  
iType=GetType(sKey) 
If iType=1 Then '如果sKey为数值型的则检查范围 
  If sKey>CurIndex Or sKey <1 Then 
    Item=Null 
  Exit Property 
End If 
  End If 

If iType=0 Then 
For i=0 to CurIndex-1 
    If ArryObj(0,i)=sKey Then 
    If isObject(ArryObj(1,i)) Then 
      Set Item=ArryObj(1,i) 
  Else 
    Item=ArryObj(1,i) 
  End If 
  Exit Property 
  End If 
  Next 
  ElseIf iType=1 Then 
    sKey=sKey-1 
    If isObject(ArryObj(1,sKey)) Then 
      Set Item=ArryObj(1,sKey) 
  Else 
    Item=ArryObj(1,sKey) 
  End If 
  Exit Property 
  End If 

  Item=Null 
End Property 

Public Sub Add(sKey,sVal) '添加字典 
  'On Error Resume Next 
  If Exists(sKey) Or C_ErrCode=9 Then 
  C_ErrCode=1          'Key值不唯一(空的Key值也不能添加数字) 
  Exit Sub 
End If 

  If CurIndex>MaxIndex Then 
  MaxIndex=MaxIndex+1      '每次增加一个标数,可以按场合需求改为所需量 
  Redim Preserve ArryObj(1,MaxIndex) 
End If 

ArryObj(0,CurIndex)=Cstr(sKey)    'sKey是标识值,将Key以字符串类型保存 
if isObject(sVal) Then 
  Set ArryObj(1,CurIndex)=sVal    'sVal是数据 
Else 
  ArryObj(1,CurIndex)=sVal    'sVal是数据 
End If 

CurIndex=CurIndex+1 
End Sub 

Public Sub Insert(sKey,nKey,nVal,sMethod) 
If Not Exists(sKey) Then 
C_ErrCode=4 
Exit Sub 
End If 

If Exists(nKey) Or C_ErrCode=9 Then 
C_ErrCode=4          'Key值不唯一(空的Key值也不能添加数字) 
Exit Sub 
End If 

sType=GetType(sKey)        '取得sKey的变量类型 

Dim ArryResult(),I,sType,subIndex,sAdd 

ReDim ArryResult(1,CurIndex)  '定义一个数组用来做临时存放地 

if sIsEmpty(sMethod) Then sMethod="b"  '为空的数据则默认是"b" 
sMethod=lcase(cstr(sMethod)) 
subIndex=CurIndex-1 
sAdd=0 
If sType=0 Then            '字符串类型比较 
If sMethod="1" Or sMethod="b" Or sMethod="back" Then '将数据插入sKey的后面 
For I=0 TO subIndex 
ArryResult(0,sAdd)=ArryObj(0,I) 

If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,sAdd)=ArryObj(1,I) 
Else 
ArryResult(1,sAdd)=ArryObj(1,I) 
End If 

If ArryObj(0,I)=sKey Then '插入数据 
sAdd=sAdd+1 
ArryResult(0,sAdd)=nKey 
If IsObject(nVal) Then 
Set ArryResult(1,sAdd)=nVal 
Else 
ArryResult(1,sAdd)=nVal 
End If 
End If 

sAdd=sAdd+1 
Next 

Else 
For I=0 TO subIndex 
If ArryObj(0,I)=sKey Then '插入数据 
ArryResult(0,sAdd)=nKey 
If IsObject(nVal) Then 
Set ArryResult(1,sAdd)=nVal 
Else 
ArryResult(1,sAdd)=nVal 
End If 
sAdd=sAdd+1 
End If 
ArryResult(0,sAdd)=ArryObj(0,I) 

If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,sAdd)=ArryObj(1,I) 
Else 
ArryResult(1,sAdd)=ArryObj(1,I) 
End If 

sAdd=sAdd+1 
Next 
End If 
ElseIf sType=1 Then 
sKey=sKey-1            '减1是为了符合日常习惯(从1开始) 

If sMethod="1" Or sMethod="b" Or sMethod="back" Then '将数据插入sKey的后面 
For I=0 TO sKey        '取sKey前面部分数据 
ArryResult(0,I)=ArryObj(0,I) 
If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,I)=ArryObj(1,I) 
Else 
ArryResult(1,I)=ArryObj(1,I) 
End If 
Next 
'插入新的数据 
ArryResult(0,sKey+1)=nKey 
If IsObject(nVal) Then 
Set ArryResult(1,sKey+1)=nVal 
Else 
ArryResult(1,sKey+1)=nVal 
End If 
'取sKey后面的数据 
For I=sKey+1 TO subIndex 
ArryResult(0,I+1)=ArryObj(0,I) 
If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,I+1)=ArryObj(1,I) 
Else 
ArryResult(1,I+1)=ArryObj(1,I) 
End If 
Next 
Else 
For I=0 TO sKey-1        '取sKey-1前面部分数据 
ArryResult(0,I)=ArryObj(0,I) 
If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,I)=ArryObj(1,I) 
Else 
ArryResult(1,I)=ArryObj(1,I) 
End If 
Next 
'插入新的数据 
ArryResult(0,sKey)=nKey 
If IsObject(nVal) Then 
Set ArryResult(1,sKey)=nVal 
Else 
ArryResult(1,sKey)=nVal 
End If 
'取sKey后面的数据 
For I=sKey TO subIndex 
ArryResult(0,I+1)=ArryObj(0,I) 
If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,I+1)=ArryObj(1,I) 
Else 
ArryResult(1,I+1)=ArryObj(1,I) 
End If 
Next 
End If 
Else 
C_ErrCode=3 
Exit Sub 
End If 

ReDim ArryObj(1,CurIndex) '重置数据 

For I=0 To CurIndex 
ArryObj(0,I)=ArryResult(0,I) 
If isObject(ArryResult(1,I)) Then 
Set ArryObj(1,I)=ArryResult(1,I) 
Else 
ArryObj(1,I)=ArryResult(1,I) 
End If 
Next 

MaxIndex=CurIndex 
Erase ArryResult 
CurIndex=CurIndex+1    'Insert后数据指针加一 
End Sub 

Public Function Exists(sKey)  '判断存不存在某个字典数据 
If sIsEmpty(sKey) Then 
Exists=False 
Exit Function 
End If 

Dim I,vType 
vType=GetType(sKey) 

If vType=0 Then 
For I=0 To CurIndex-1 
If ArryObj(0,I)=sKey Then 
Exists=True 
Exit Function 
End If 
Next 
ElseIf vType=1 Then 
If sKey <=CurIndex And sKey>0 Then 
Exists=True 
Exit Function 
End If 
End If 

Exists=False 
End Function 

Public Sub Remove(sKey)        '根据sKey的值Remove一条字典数据 
If Not Exists(sKey) Then 
C_ErrCode=3 
Exit Sub 
End If 

sType=GetType(sKey)        '取得sKey的变量类型 

Dim ArryResult(),I,sType,sAdd 

ReDim ArryResult(1,CurIndex-2)  '定义一个数组用来做临时存放地 
sAdd=0 
If sType=0 Then            '字符串类型比较 
For I=0 TO CurIndex-1 
If ArryObj(0,I) <>sKey Then 
    ArryResult(0,sAdd)=ArryObj(0,I) 

If IsObject(ArryObj(1,I)) Then 
    Set ArryResult(1,sAdd)=ArryObj(1,I) 
Else 
    ArryResult(1,sAdd)=ArryObj(1,I) 
End If 

sAdd=sAdd+1 
End If 
Next 

ElseIf sType=1 Then 
sKey=sKey-1            '减1是为了符合日常习惯(从1开始) 
For I=0 TO CurIndex-1 
If I <>sKey Then 
    ArryResult(0,sAdd)=ArryObj(0,I) 
If IsObject(ArryObj(1,I)) Then 
Set ArryResult(1,sAdd)=ArryObj(1,I) 
Else 
ArryResult(1,sAdd)=ArryObj(1,I) 
  End If 

sAdd=sAdd+1 
End If 
Next 
Else 
C_ErrCode=3 
Exit Sub 
End If 

MaxIndex=CurIndex-2 
ReDim ArryObj(1,MaxIndex) '重置数据 

For I=0 To MaxIndex 
ArryObj(0,I)=ArryResult(0,I) 
If isObject(ArryResult(1,I)) Then 
Set ArryObj(1,I)=ArryResult(1,I) 
Else 
ArryObj(1,I)=ArryResult(1,I) 
End If 
Next 

Erase ArryResult 
CurIndex=CurIndex-1    '减一是Remove后数据指针 
End Sub 

Public Sub RemoveAll '全部清空字典数据,只Redim一下就OK了 
Redim ArryObj(MaxIndex) 
CurIndex=0 
End Sub 

Public Sub ClearErr  '重置错误 
C_ErrCode=0 
End Sub 

Private Function sIsEmpty(sVal) '判断sVal是否为空值 
If IsEmpty(sVal) Then 
C_ErrCode=9          'Key值为空的错误代码 
sIsEmpty=True 
Exit Function 
End If 

If IsNull(sVal) Then 
C_ErrCode=9          'Key值为空的错误代码 
sIsEmpty=True 
Exit Function 
End If 

If Trim(sVal)="" Then 
C_ErrCode=9          'Key值为空的错误代码 
sIsEmpty=True 
Exit Function 
End If 

sIsEmpty=False 
End Function 

Private Function GetType(sVal)  '取得变量sVal的变量类型 
dim sType 
sType=TypeName(sVal) 
Select Case sType 
Case "String" 
GetType=0 
Case "Integer","Long","Single","Double" 
GetType=1 
Case Else 
GetType=-1 
End Select 

End Function 

End Class 

4、1.asp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
  <title> new document </title> 
  <meta name="generator" content="editplus" /> 
  <meta name="author" content="" /> 
  <meta name="keywords" content="" /> 
  <meta name="description" content="" /> 
</head> 

<body> 
  <table> 
  <form name="upfile"> 
  <tr> 
  <td> <input type="text" id="filePath" name="filePath" size="40"> </td> 
<td> <iframe height="30" width="320" frameborder="0" scrolling="no" src="up.asp"> </iframe> </td> </tr> </form> </table> </body> </html>

 
说明:upfile.asp为上传类,up.asp为调用文件,1.asp为演示文件,dic.asp为避免iis服务器dictonary组件不可用时的自写义dictonary组件也可以将其修改为iis的dictonary组件

原文地址:https://www.cnblogs.com/mqmelon/p/4757545.html