PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : iconv Konvertierung von UTF-8 nach UTF-16LE (c++)



undefined
09-01-2011, 10:08
Ich muss eine Passworteingabe nach UTF-16LE konvertieren bevor ich einen MD5 digest daraus machen kann. Aber Irgendwie habe ich ein Verständnis Problem was die Zeichenketten Konvertierung betrifft, Ich bekomme einen leeren Ausgabepuffer zurück.
Wo habe ich den hier den Fehler?


// Setze zunächst einmal wieder zu einem normalen Unicode-Zeichencode
// Mein System verwendet UTF-8
QTextCodec* codec = QTextCodec::codecForLocale ();
QByteArray realm = codec->toUnicode ( textValue().toAscii() ).toAscii();
// g++4* kompatible
size_t invalid = -1;
// initialisiere iconv
iconv_t cd = iconv_open ( "UTF-16LE", "UTF-8" );
// nehme die bytes von QByteArray
size_t inbytesleft = realm.size();
// convertiere QByteArray nach char*
char* inbuf = realm.data();
// setze den ausgabe Puffer von 8 auf 16 rauf und hänge den term an
size_t outbytesleft = ( realm.size() * 2 ) + 1;
// erstelle den ausgabe Puffer
char* outbuf = new char[outbytesleft];
// starte konvertieren
while ( inbytesleft > 0 )
{
if ( iconv ( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ) == invalid )
{
qWarning ( "converting characters failed" );
iconv_close ( cd );
delete[] outbuf;
break;
}
}
iconv_close ( cd );

// Debuggen und das ganze wieder zurück
std::cout << "Größe des Ausgabe Puffers:" << strlen ( outbuf ) << std::endl;
qDebug() << Q_FUNC_INFO << QTextCodec::codecForName ( "UTF-16LE" )->toUnicode ( outbuf );

return realm;

locus vivendi
09-01-2011, 11:46
Mit strlen kannst du nicht die Länge von Strings mit eingebetteten Null-Bytes herausfinden. Die Funktion wcslen müsste zu UTF-16 kompatibel sein, ganz sicher bin ich mir nicht.

Außerdem: Bist du dir sicher, dass die toAscii-Aufrufe richtig sind? Müssten die nicht eher toUtf8 lauten?

undefined
09-01-2011, 13:18
Ja - das mit dem *.toUtf8() ist mir Zwischenzeitlich auch aufgefallen.
Das eigentliche Problem war meine Größenangabe.
Was mich zusätzlich Irritiert hat war die Darstellung beim Debuggen ;)

Hier die entgültige Lösung - Der Code wird benötigt um sich bei AVM DSL Modems ab Firmware-Version xx.04.74 an zumelden.


const QByteArray PasswordDialog::createMd5Hash ()
{
QByteArray realm;
realm.append ( challenge.toUtf8() );
realm.append ( '-' );
realm.append ( textValue().toUtf8() );

size_t invalid = -1;
iconv_t cd = iconv_open ( "UTF-16LE", "UTF-8" );
char* inbuf = realm.data();
size_t inbytesleft = ( strlen ( inbuf ) * sizeof ( char ) );
size_t outbytesleft = ( inbytesleft * 2 );
QByteArray utf16str ( outbytesleft, Qt::Uninitialized );
char *outbuf = utf16str.data();
do
{
if ( iconv ( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ) == invalid )
{
qWarning ( "converting characters failed" );
iconv_close ( cd );
delete[] outbuf;
break;
}
}
while ( inbytesleft != 0 );
utf16str.resize ( utf16str.size() - outbytesleft );
iconv_close ( cd );

// qDebug() << QTextCodec::codecForMib ( 1015 )->toUnicode ( utf16str.constData(), utf16str.size() );

QCryptographicHash qcrHash ( QCryptographicHash::Md5 );
qcrHash.addData ( utf16str.constData(), utf16str.size() );
return qcrHash.result().toHex();
}