zoukankan      html  css  js  c++  java
  • 一个能防止改名木马漏洞的无组件上传类

    现在流行的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组件

  • 相关阅读:
    ARM标准汇编与GNU汇编
    使用友元,编译出错fatal error C1001: INTERNAL COMPILER ERROR (compiler file 'msc1.cpp', line 1786) 的解决
    C++中值传递,引用传递,指针传递
    C++命名空间的用法
    关于初始化C++类成员
    vivi的配置与编译
    C++ 容器
    vivi分区问题,及移植时需要修改的地方(转)
    基于S3C2410的VIVI移植
    拷贝构造函数什么时候调用?
  • 原文地址:https://www.cnblogs.com/mqmelon/p/4757545.html
Copyright © 2011-2022 走看看