Подтвердить что ты не робот

Загрузка файла в классическом asp

Я всегда использовал следующий script для загрузки файлов в классическом asp, но он переставал работать, давая мне эту ошибку

ошибка времени выполнения vbscript 800a01a8
object required 'Item (...)'

Я немного исследовал, и я думаю, что проблема заключается в файле upload.asp с функцией BuildUploadRequest, но я действительно не могу понять, почему

Форма

<form method="POST" action="landing-page.asp" ENCTYPE="multipart/form-data">
    <input type="file" name="file">
    <input type="hidden" name="key" value="0">
    <input type="submit" name="send" value="1">
</form>

страница, где область формы

byteCount = Request.TotalBytes
RequestBin = Request.BinaryRead(byteCount)

Dim UploadRequest
Set UploadRequest = CreateObject("Scripting.Dictionary")
BuildUploadRequest(RequestBin)  '//function defined in upload.asp
if UploadRequest.Item("key").Item("Value")="0" then  '//this is the line giving the error
    '//code here...
end if

upload.asp

Sub BuildUploadRequest(RequestBin)
    PosBeg = 1  
    PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
    boundary = MidB(RequestBin,PosBeg,PosEnd-PosBeg)    
    boundaryPos = InstrB(1,RequestBin,boundary)

    '//Get all data inside the boundaries
    Do until (boundaryPos=InstrB(RequestBin,boundary & getByteString("--")))
        '//Members variable of objects are put in a dictionary object
        Dim UploadControl
        Set UploadControl = CreateObject("Scripting.Dictionary")
        '//Get an object name
        Pos = InstrB(BoundaryPos,RequestBin,getByteString("Content-Disposition"))
        Pos = InstrB(Pos,RequestBin,getByteString("name="))
        PosBeg = Pos+6
        PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(34)))
        Name = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
        PosFile = InstrB(BoundaryPos,RequestBin,getByteString("filename="))
        PosBound = InstrB(PosEnd,RequestBin,boundary)
        '//Test if object is of file type
        If  PosFile<>0 AND (PosFile<PosBound) Then
            '//Get Filename, content-type and content of file
            PosBeg = PosFile + 10
            PosEnd =  InstrB(PosBeg,RequestBin,getByteString(chr(34)))
            FileName = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
            '//Add filename to dictionary object
            UploadControl.Add "FileName", FileName
            Pos = InstrB(PosEnd,RequestBin,getByteString("Content-Type:"))
            PosBeg = Pos+14
            PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
            '//Add content-type to dictionary object
            ContentType = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
            UploadControl.Add "ContentType",ContentType
            '//Get content of object
            PosBeg = PosEnd+4
            PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
            Value = MidB(RequestBin,PosBeg,PosEnd-PosBeg)
        Else
            '//Get content of object
            Pos = InstrB(Pos,RequestBin,getByteString(chr(13)))
            PosBeg = Pos+4
            PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
            Value = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
        End If
        '//Add content to dictionary object
        UploadControl.Add "Value" , Value   
        '//Add dictionary object to main dictionary
        '//response.write name & "<br>"
        UploadRequest.Add name, UploadControl   
        '//Loop to next object
        BoundaryPos=InstrB(BoundaryPos+LenB(boundary),RequestBin,boundary)
    Loop
End Sub

'//String to byte string conversion
Function getByteString(StringStr)
  For i = 1 to Len(StringStr)
    charx = Mid(StringStr,i,1)
    getByteString = getByteString & chrB(AscB(charx))
  Next
End Function

'//Byte string to string conversion
Function getString(StringBin)
 getString =""
 For intCount = 1 to LenB(StringBin)
    getString = getString & chr(AscB(MidB(StringBin,intCount,1))) 
 Next
End Function

Этот код всегда работал правильно в каждом проекте, но теперь он не работает повсюду. Поэтому я не могу просто редактировать и использовать другую функцию, мне нужно понять, почему она больше не работает

4b9b3361

Ответ 1

Исправить # 1 - Удалить "KB3104002 Накопительное обновление для системы безопасности для IE11"

Исправить # 2. Скопировать все байтовые массивы в строку байтовых значений и работать против этого или предоставить замену instrb, которая выполняет свою собственную итерацию по массиву.

Function InstrBNew(startPos, inputArray, searchChar)

  if LenB(searchChar) = 1 Then
    Dim loc
    For loc = startPos to Lenb(inputArray)
      if MidB(inputArray, loc, 1) = searchChar then Exit For
    Next
    InstrBNew = loc
  Else
    InstrBNew = InstrB(startPos, inputArray, searchChar)
  End If
End Function

Исправить # 3. Корпорация Майкрософт выпустила исправление. Это выйдет всем в январе 2016 года. Вы можете получить его здесь рано. https://support.microsoft.com/en-us/kb/3125446

Проблема заключается в том, что функция InstrB в vbScript теперь возвращает значение 1 при следующих условиях.

  • Если вы ищете массив байтов (например, Response.BinaryRead). Это не очень распространено в ASP или VBScript, но загрузка файлов - это одно из тех случаев, когда вы это делаете.
  • Когда вы ищете один байт

Если вы ищете строку или ищете многобайтовый шаблон, то InstrB работает правильно.

PosEnd = InstrB(PosBeg, ByteArray, chrb(13))

В моих сломанных системах эта функция всегда возвращает 1, даже если в позиции 1 нет значения байта 13. Оно возвращает 1 для любого значения при поиске массива байтов. Классические компоненты загрузки ASP файлов, поэтому мы все в этом потоке, сталкиваются с этой ситуацией, потому что они анализируют массив байтов, ищущий разделители.

PosEnd = InstrB(PosBeg,ByteArray,getByteString("FormBoundary"))
PosEnd = InstrB(PosBeg,ByteArray,getByteString(vbCRLF))
PosEnd = InstrB(PosBeg,"Normal string", chrb(103)) ' Search for letter g in a string

Эти строки работают нормально и, как ожидалось. Ожидается, что многобайтовые поиски и сопоставления с строкой будут работать.

Эта проблема ударила меня одновременно на нескольких серверах прошлой ночью. Я видел, что обновления системы Windows также были запущены прошлой ночью. Сужая его, я обнаружил, что MS15-124 (KB3104002 накопительное обновление для системы безопасности для IE11) содержит обновление для vbscript.dll. Я удалил это обновление, и теперь код возвращается к нормальной работе.

Я зарегистрировал проблему в своей системе "IE Connect", так как она была включена в обновление IE, но я не уверен, что это место.

Я приложил тестовый пример. На сломанных системах он вернет "5, 1, 5". На рабочих системах он вернет "5, 5, 5"

Надеемся на исправление. Некоторые из этого старого кода работают в системах, к которым у меня нет доступа.

' Test.vbs
Dim byteArray, byteArray2, byteArray3, bPosition
Dim responseText

' byte string
' "hello hello"
byteArray = chrb(104) & chrb(101) & chrb(108) & chrb(108) & chrb(111) & chrb(32) & chrb(104) & chrb(101) & chrb(108) & chrb(108) & chrb(111) & chrb(0)

' byte array - What Response.BinaryRead is
byteArray2 = TextToBytes(byteArray)

' Vartype: http://stackoverflow.com/questions/3281355/get-the-type-of-a-variable-in-vbscript
ResponseText = ResponseText + "blen: " & lenb(byteArray) & vbCRLF
ResponseText = ResponseText + "type: " & vartype(byteArray) & vbCRLF

ResponseText = ResponseText + "blen: " & lenb(byteArray2) & vbCRLF
ResponseText = ResponseText + "type: " & vartype(byteArray2) & vbCRLF

bPosition = instrb(1, byteArray, chrb(111))
ResponseText = ResponseText + "Position in string: " & bPosition & vbCRLF

bPosition = instrb(1, byteArray2, chrb(111))
ResponseText = ResponseText + "Position in byte array: " & bPosition & vbCRLF

bPosition = instrb(1, byteArray2, chrb(111) & chrb(32))
ResponseText = ResponseText + "Position in byte array: " & bPosition & vbCRLF

WScript.Echo ResponseText

' Converts a string (8) to a vbArray of bytes (8192 + 17)
' I'm not sure how else to create a vbArray of bytes. It does not seem to be a common data type in vbscript
Private Function TextToBytes(ByRef pbinBinaryData)
    Dim lobjRs
    Dim llngLength
    Dim lbinBuffer
    CONST adLongVarBinary = 205
    llngLength = LenB(pbinBinaryData)
    Set lobjRs = CreateObject("ADODB.Recordset")
    Call lobjRs.Fields.Append("BinaryData", adLongVarBinary, llngLength)
    Call lobjRs.Open()
    Call lobjRs.AddNew()
    Call lobjRs.Fields("BinaryData").AppendChunk(pbinBinaryData)
    Call lobjRs.Update()
    lbinBuffer = lobjRs.Fields("BinaryData").GetChunk(llngLength)
    Call lobjRs.Close()
    Set lobjRs = Nothing
    TextToBytes = lbinBuffer
End Function

Ответ 2

У меня была такая же проблема в классическом ASP, InStrB внезапно возвращал 1, даже когда я проверял в отладчике, что он не должен, то есть персонаж, о котором идет речь, находился в позиции 17.

Я написал следующую функцию замены для InStrB (только для использования при поиске 1 char). Я дерьмовый программист VBS, поэтому, не стесняйтесь чистить это. Но, похоже, он работает...

Private Function findCharInStrB(startPos, inputArray, searchChar)
  Dim loc
  For loc = startPos to Len(inputArray)
    if MidB(inputArray, loc, 1) = searchChar then Exit For
  Next
  findCharInStrB = loc
End Function

Ответ 4

Попробуйте этот код загрузки (кредит для Льюиса Мотена): http://planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=8525&lngWId=4

Недавно я столкнулся с той же проблемой при переносе сайта на более новую версию Windows Server. Использование кода загрузки Льюиса Модена вместо этого устранило проблему.

В случае, если ссылка замирает, код также отправляется в этот ответ.

Ответ 5

Я не могу ответить на исходный комментарий из-за низкой репутации, но в случае, если вы не можете удалить обновление, используя обычные методы панели управления, как я не мог (он не отображался в списке удалений ) вот как вы это делаете с Powershell и командной строкой:

Временное обходное решение для удаления "KB3104002 Накопительное обновление для системы безопасности для IE11":

Выполните следующие действия, чтобы проверить, установлено ли обновление:

  • Нажмите на клавишу Windows (или щелкните правой кнопкой мыши на кнопке Windows и т.д.) и введите `cmd` и нажмите enter.
  • Введите `powershell` и нажмите enter.
  • Используйте команду `get-hotfix -id KB3104002`, чтобы узнать, установлено ли обновление. Вы увидите список, возвращенный с датой установки этого обновления, если он есть.

Если обновление установлено, продолжайте:

  • Если вы все еще находитесь в powershell, выходите из `exit`.
  • Используйте команду `wusa/uninstall/kb: 3104002` для удаления патча
  • Reboot!

Предостережение: KB3104002 указано как "Критическое обновление безопасности" согласно для Microsoft, поэтому я бы не рекомендовал игнорировать это обновление навсегда, но в качестве временного решения проблем, вызванных этим обновлением, я решил это сделать. Я думаю, что Microsoft выпустит обновление для этого обновления, которое касается резни, которая, по-видимому, вызывает использование кода ASP, который все еще используется.