Как я могу использовать zlib на японском компьютере? - PullRequest
0 голосов
/ 27 августа 2009

Я пытаюсь сжать строку с помощью zlib (я пробовал этот код с текущей версией 1.2.3 zlib и с zlib 1.1.3). Мой код работает правильно, если только он не запущен на японском компьютере . После сжатия файла я шифрую его. Расшифровка успешна, но вызов uncompress возвращает -3 (Z_DATA_ERROR, что означает, что входные данные были повреждены). Поскольку в журнале нет ошибок, я знаю, что не генерируются исключения, и что функция сжатия возвращает 0 (Z_OK, что означает, что это сработало).

Таким образом, я подозреваю, что проблема в том, что строка sCompressed теряет целостность либо в строке "sCompressed = Left(sCompressed, lcompressedlen)", либо в строке "encryptedData.Content = sCompressed". В качестве альтернативы VB6 может делать что-то глупое полезное для содержимого sCompressed во время вызова compress. Я знаю, что возвращаемое значение этой функции не будет повреждено позже, потому что это нарушило бы дешифрование, которое работает нормально.

Public Function EncryptString(ByVal Definition As String) As String
On Error GoTo ErrorHandler
    Dim encryptedData As New CAPICOM.encryptedData
    encryptedData.SetSecret KEY_CONST
    Dim lStringLen As Long
    Dim lcompressedlen As Long
    Dim sCompressed As String
    Dim lReturn As Long
    Dim tstpost As String
    lStringLen = Len(Definition)
    lcompressedlen = (lStringLen * 1.01) + 13
    sCompressed = Space(lcompressedlen)
    lReturn = compress(sCompressed, lcompressedlen, Definition, lStringLen)
    If lReturn <> 0 Then
        sCompressed = "Error: " & CStr(lReturn)
        '<LOG ERROR>'
    Else
        sCompressed = Left(sCompressed, lcompressedlen)
    End If
    encryptedData.Content = sCompressed
    encryptedData.Algorithm.Name = CAPICOM_ENCRYPTION_ALGORITHM_3DES
    EncryptXmlString = encryptedData.Encrypt
Exit Function
ErrorHandler:
    '<LOG ERROR>'
    Resume Next
End Function

Вывод:
Я закончил тем, что заставил программу выдать сообщение об ошибке и завершить работу при запуске на машине с подозрительным набором символов. Вполне вероятно, что эта ошибка все еще существует в некоторых настройках, а также, вероятно, что она не существует в некоторых настройках, которые вызывают ошибку. Однако, поскольку целевой аудиторией являются носители английского языка, прохождение теста Турции не является достаточно важным, чтобы оправдать фактическое уделение этому времени больше времени.

Ответы [ 2 ]

2 голосов
/ 27 августа 2009

Прекратить использование строки, когда вы хотите передать массив байтов?

Конечно вы получите автоматическое преобразование ANSI и повторное копирование данных при использовании строк, как здесь.

0 голосов
/ 02 сентября 2009

Боб прав .Это только мои сноски к его ответу.Имейте в виду, что я совершенно незнаком с zlib - я предполагаю, что вы вызываете DLL, используя Declare для compress.

Использование строки вместо массива байтов не означает, что вы избегаете преобразования ANSI.Часто это просто означает, что VB6 выполняет преобразование неявно , и вы не можете управлять им - например, когда вы вызываете DLL с оператором Declare и передаете строку.

Возможно, магическая последовательность байтов, возвращаемых при сжатии, не является допустимой строкой "ANSI" на японской кодовой странице.Некоторые последовательности символов не определены в таблице MSDN для этой кодовой страницы.Если вы вызываете DLL с оператором Declare и ожидаете, что строка будет возвращена в sCompressed, эта DLL лучше записать правильную строку «ANSI» в соответствующий буфер.Если он записывает неверную последовательность байтов, может произойти все что угодно.У вас также будут проблемы с китайским (936 и 950) и корейским (949).

То, что вы описываете, вполне может произойти: когда compress возвращает неверную последовательность байтов, она может быть преобразована в "Unicode"msgstr "строка без сообщений об ошибках - возможно, усечённая строка Unicode, соответствующая первой части вашей последовательности байтов.Затем, когда вы позже попытаетесь распаковать, эта строка Unicode преобразуется обратно в строку ANSI, и она не соответствует исходной последовательности байтов, с которой вы начали.Это не может совпадать.На кодовой странице 932 нет возможной строки Unicode, которая преобразуется в строку «ANSI» в виде последовательности байтов, которая не является допустимой строкой.

Вот еще немного информации об ужасной путанице, которая представляет собой реализацию Unicode на VB6: бесплатная глава из превосходной книги Майкла Каплана Интернационализация с Visual Basic

Я также подозреваю, что вы можете путать количество символов в строке с количеством байтов, которое оно занимает в представлении ANSI (я с подозрением отношусь к lStringLen и lcompressedlen).Опять же, японский является двухбайтовым набором символов, поэтому строка ANSI может занять до 2 * N байтов для N символов.

...