1
/***************************************************************************
2
begin : Sun Apr 16 14:23:12 EST 2012
3
copyright : (C) 2012 by Michael Pyne
5
***************************************************************************/
7
/***************************************************************************
9
* This program is free software; you can redistribute it and/or modify *
10
* it under the terms of the GNU General Public License as published by *
11
* the Free Software Foundation; either version 2 of the License, or *
12
* (at your option) any later version. *
14
***************************************************************************/
18
#include <QtCore/QLatin1String>
19
#include <QtCore/QString>
20
#include <QtCore/QByteArray>
21
#include <QtCore/QFile>
23
#include <kdemacros.h>
25
// The 0-based position of an entry in this table indicates its value.
26
static const char zBase32EncodingTable [] = "ybndrfg8ejkmcpqxot1uwisza345h769";
28
// 8 5-bit entries for 40-bits total
29
static const int ZBASE32_PARTIAL_BUFFER_SIZE = 8;
31
static int locateCharacterInTable(const QChar ch)
33
for (int i = 0; i < 32; ++i) {
34
if (zBase32EncodingTable[i] == ch) {
42
// @p len is the number of **destination** items to utilize!
43
static void zBase32DecodeBufferIntoBuffer(
44
unsigned char *destination,
45
const unsigned char *source,
46
int destinationLength)
48
// Each item in source buffer is already masked to only take 5 bits.
49
// We need to pick the appropriate bits of each item and place in
52
// 00000000-11111111-22222222-33333333-44444444 destination
53
// 01234567-01234567-01234567-01234567-01234567
54
// 00000111-11222223-33334444-45555566-66677777 source
56
switch (destinationLength) {
57
case 5: destination[4] = ((source[6] & 0x07) << 5) | source[7];
59
case 4: destination[3] = ((source[4] & 0x01) << 7) | (source[5] << 2) | ((source[6]) >> 3);
61
case 3: destination[2] = ((source[3] & 0x0F) << 4) | (source[4] >> 1);
63
case 2: destination[1] = ((source[1] & 0x03) << 6) | (source[2] << 1) | (source[3] >> 4);
65
case 1: destination[0] = (source[0] << 3) | (source[1] >> 2);
72
// Returns number of decoded bytes that are left from the given remainder
73
// length of source characters. This means the remainder length should be
74
// between 1 and 7 inclusive.
75
static int zBase32BytesAffectedFromSource(int sourceRemainderLength)
77
switch (sourceRemainderLength) {
90
QByteArray zBase32DecodeData(const QByteArray &str)
93
unsigned char buffer[ZBASE32_PARTIAL_BUFFER_SIZE] = { 0 };
94
int strSize = str.size();
95
int runLength = (strSize / ZBASE32_PARTIAL_BUFFER_SIZE) * ZBASE32_PARTIAL_BUFFER_SIZE;
96
int remainder = strSize - runLength;
98
result.resize(strSize / ZBASE32_PARTIAL_BUFFER_SIZE * 5 + zBase32BytesAffectedFromSource(remainder));
99
int destinationPointer = 0;
101
for (int i = 0; i < runLength; ++i) {
102
int pos = locateCharacterInTable(str[i]);
103
if (KDE_ISUNLIKELY(pos < 0)) {
107
if (zBase32EncodingTable[pos] != str[i]) {
111
buffer[i % ZBASE32_PARTIAL_BUFFER_SIZE] = pos;
113
if (((i + 1) % ZBASE32_PARTIAL_BUFFER_SIZE) == 0) {
114
// End of row, compress
115
unsigned char *encodedData = reinterpret_cast<unsigned char *>(result.data()) + destinationPointer;
117
zBase32DecodeBufferIntoBuffer(encodedData, buffer, 5);
118
destinationPointer += 5;
120
for (int j = 0; j < ZBASE32_PARTIAL_BUFFER_SIZE; j++) {
126
// Complete weird remainder. buffer should have already been cleared
128
for (int i = 0; i < remainder; ++i) {
129
int pos = locateCharacterInTable(str[i + runLength]);
130
if (KDE_ISUNLIKELY(pos < 0)) {
137
zBase32DecodeBufferIntoBuffer(
138
reinterpret_cast<unsigned char *>(result.data()) + destinationPointer,
140
zBase32BytesAffectedFromSource(remainder));
145
// Returns the number of destination entries used to encode the given bytes
147
static int zBase32EncodeBufferIntoBuffer(
148
unsigned char *destination,
149
const unsigned char *source,
152
// Each item in destination buffer must be masked to only take 5 bits.
153
// We need to pick the appropriate bits of each item and place in
156
// 00000000-11111111-22222222-33333333-44444444 source
157
// 01234567-01234567-01234567-01234567-01234567
158
// 00000111-11222223-33334444-45555566-66677777 destination
160
for (int i = 0; i < ZBASE32_PARTIAL_BUFFER_SIZE; ++i) {
166
switch (sourceLength) {
169
destination[7] = source[4] & 0x1f;
172
entriesUsed = entriesUsed ? entriesUsed : 7;
173
destination[6] = ((source[4] & 0xe0) >> 5) | ((source[3] & 0x03) << 3);
174
destination[5] = ((source[3] & 0x7c) >> 2);
177
entriesUsed = entriesUsed ? entriesUsed : 5;
178
destination[4] = ((source[2] & 0x0f) << 1) | ((source[3] & 0x80) >> 7);
181
entriesUsed = entriesUsed ? entriesUsed : 4;
182
destination[3] = ((source[1] & 0x01) << 4) | ((source[2] & 0xf0) >> 4);
183
destination[2] = ((source[1] & 0x3e) >> 1);
186
entriesUsed = entriesUsed ? entriesUsed : 2;
187
destination[1] = ((source[0] & 0x07) << 2) | ((source[1] & 0xc0) >> 6);
188
destination[0] = ((source[0] & 0xf8) >> 3);
194
// We still have binary values, encode them to legible items from the table
195
for (int i = 0; i < entriesUsed; ++i) {
196
destination[i] = zBase32EncodingTable[destination[i]];
202
QByteArray zBase32EncodeData(const QByteArray &data)
205
result.reserve((data.size() * 8 / 5) + 1);
207
int runLength = data.size() / 5 * 5;
208
int remainder = data.size() - runLength;
210
unsigned char buffer[ZBASE32_PARTIAL_BUFFER_SIZE] = { 0 };
212
for (int i = 0; i < runLength; i += 5) {
213
zBase32EncodeBufferIntoBuffer(buffer, reinterpret_cast<unsigned const char *>(data.constData()) + i, 5);
214
result.append(reinterpret_cast<const char *>(buffer), 8);
217
int entriesUsed = zBase32EncodeBufferIntoBuffer(
219
reinterpret_cast<const unsigned char *>(data.constData()) + runLength,
222
result.append(reinterpret_cast<const char *>(buffer), entriesUsed);
223
result.resize((runLength / 5 * 8) + entriesUsed);