zLib с опцией Qt C ++ MCCP / Telnet Compress2

0

Я пытаюсь сжать/распаковать QStrings.

Как у меня такая настройка: существует модуль telnet/socket, который считывает информацию с сервера telnet. Затем эти строки отправляются в Javascript (это клиентский клиент, где пользовательский интерфейс реализован в HTML с использованием QWebView и т.д.). Это работает нормально.

Я хотел бы добавить поддержку MCCP (сжатие zlib ввода/вывода).

Я хотел бы, если вообще возможно, предоставить полную поддержку скриптов для приложения (только минимальный C++ код, все остальное реализовано плагинами.)

Я хочу реализовать две функции, compressString и decpressionString:

QString MainWindow::compressString(QString s) {

    QByteArray str = s.toLocal8Bit();

    int ret,flush;
    z_stream strm;
    unsigned char out[CHUNK];
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    ret = deflateInit(&strm,Z_DEFAULT_COMPRESSION);
    if ( ret != Z_OK ) {
        return "ERROR: Failed to init z_stream";
    }
    // do until end of string
    do {
       strm.avail_in = str.size();
       strm.next_in = (unsigned char*)str.data();
       strm.avail_out = CHUNK;
       strm.next_out = out;
       flush = Z_FINISH;
       ret = deflate(&strm,flush);
       if ( ret == Z_STREAM_ERROR) {
           return "ERROR: Z_STREAM_ERROR when deflating.";
       }
    } while ( flush != Z_FINISH );
    deflateEnd(&strm);
    return QString( (char *)out );
}
QString MainWindow::decompressString(QString s) {
    QByteArray str = s.toLocal8Bit();

    int ret,flush;
    z_stream strm;
    unsigned char out[CHUNK];
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    if ( ret != Z_OK ) {
        return "ERROR: Failed to init z_stream for inflate";
    }
    // do until end of string
    do {
       strm.avail_in = str.size();
       strm.next_in = (unsigned char*)str.data();
       strm.avail_out = CHUNK;
       strm.next_out = out;
       flush = Z_NO_FLUSH;
       ret = inflate(&strm,flush);
       if ( ret == Z_STREAM_ERROR) {
           return "ERROR: Z_STREAM_ERROR when inflating.";
       }
       switch( ret ) {
        case Z_NEED_DICT:
           inflateEnd(&strm);
           return "Error: Z_NEED_DICT";
           break;
        case Z_DATA_ERROR:
           inflateEnd(&strm);
           return "Error: Z_DATA_ERROR";
           break;
        case Z_MEM_ERROR:
           inflateEnd(&strm);
           return "Error: Z_MEM_ERROR";
           break;
        default:
           break;
       }
    } while ( ret != Z_STREAM_END );
    inflateEnd(&strm);

    return QString( (char *)out );
}

Речь идет о третьем/четвертом переписывании, которое я пробовал. Метод строки сжатия возвращает это: xóHÍÉÉWÏ/ÊIQ Возможно, это правильно, может быть, нет, не знаю.

Метод decapseString возвращает это: Ошибка: Z_NEED_DICT;

Независимо от того, что я делаю (я пробовал некоторые другие примеры, найденные в Интернете, и при переполнении стека).

Прямо сейчас я просто кормлю строки из JS, в конце концов, мне хотелось бы сжать/распаковать строки, отправленные с сервера telnet, используя telopt 86.

Любые подсказки/указатели будут оценены. Моя цель прямо сейчас состоит в том, чтобы выстроить простой тест на вход/выход.

ОБНОВИТЬ:

После прохождения кода расширения zlib моя проблема здесь:

state->mode = hold & 0x200 ? DICTID : TYPE;

Zlib ожидает какой-то заголовок строки. hold - это буфер, и DICTID отправит его, чтобы запросить Z_DICT_NEEDED. Это, скорее всего, потому, что заголовок не существует или теряется во время прохождения строки. Если я его взломаю и скажу state->mode = TYPE; то я получу ошибку данных.

Кроме того, я изменил функцию распаковки следующим образом:

QString MainWindow::decompressString(QString s) {
    QByteArray str = s.toLocal8Bit();

    unsigned char in[CHUNK];
    for ( int i = 0; i < str.size(); i++ ) {
        in[i] = (unsigned char)str.at(i);
    }
    fflush(stdout);
    int ret,flush;
    z_stream strm;
    unsigned char out[CHUNK];
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    if ( ret != Z_OK ) {
        return "ERROR: Failed to init z_stream for inflate";
    }
    // do until end of string
    do {
       strm.avail_in = str.size();
       strm.next_in = in;
       strm.avail_out = CHUNK;
       strm.next_out = out;
       flush = Z_NO_FLUSH;
       ret = inflate(&strm,flush);
       if ( ret == Z_STREAM_ERROR) {
           return "ERROR: Z_STREAM_ERROR when inflating.";
       }
       switch( ret ) {
        case Z_NEED_DICT:
           inflateEnd(&strm);
           return "Error: Z_NEED_DICT";
           break;
        case Z_DATA_ERROR:
           inflateEnd(&strm);
           return "Error: Z_DATA_ERROR";
           break;
        case Z_MEM_ERROR:
           inflateEnd(&strm);
           return "Error: Z_MEM_ERROR";
           break;
        default:
           break;
       }
    } while ( ret != Z_STREAM_END );
    inflateEnd(&strm);

    return QString( (char *)out );
}

Затем, используя printf как на выходе, создаваемом deflate, так и на том, что посылается для раздувания, и данные (шестнадцатеричные значения для каждого символа) кажутся одинаковыми.

  • 0
    Кажется, что проверка выходного буфера показывает, что после нулевого значения есть что-то вроде 4 байтов данных в том, что создается с помощью deflate. Возможно, мне придется реализовать это как QObject с методом toString, чтобы я мог поддерживать байтовый буфер, который я могу обойти? Не знаю, как это сделать только с QStrings.
  • 0
    В ваших (de)compressed функциях вы используете буферы out и in в цикле, не перемещая его. Это перезапишет любые предыдущие данные, если цикл повторяется более одного раза. Может быть, это делается для функции сжатия, и поэтому вы теряете словарь.
Показать ещё 2 комментария
Теги:
qt
telnet
zlib

1 ответ

0

По сути, вы не можете.

QStrings "потеряет" некоторые данные. Чтобы выполнить сжатие/декомпрессию с помощью zlib, вам нужно работать с QByteArray, на самом деле, это еще проще, если вы работаете только с строками STL и только конвертируете в QByteArrays, когда вам нужно. Решение, которое я нашел, работает с pantehma.net http://panthema.net/2007/0328-ZLibString.html

Поскольку я читаю сжатые строки из внешнего источника, я просто не конвертирую их в QStrings и обрабатываю сжатие/декомпрессию в слое C и не пытаюсь передать его javascript. Это просто не стоило усилий, чтобы заставить его работать.

Счастливого Рождества тому, кто голосовал по этому вопросу.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню