//============================================================================= // // File : UglyBase64.cpp // Creation date : Sun Feb 6 2011 22:25:10 CEST by Fabio Bas // // This file is part of the KVIrc IRC client distribution // Copyright (C) 2011 Fabio Bas (ctrlaltca at gmail dot com) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #include "UglyBase64.h" #include "KviCString.h" #include "KviMemory.h" namespace UglyBase64 { static unsigned char fake_base64[] = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; void byteswap_buffer(unsigned char * p, int len) { while(len > 0) { unsigned char aux = p[0]; p[0] = p[3]; p[3] = aux; aux = p[1]; p[1] = p[2]; p[2] = aux; p += 4; len -= 4; } } unsigned int fake_base64dec(unsigned char c) { static char base64unmap[255]; static bool didinit = false; if(!didinit) { // initialize base64unmap for(char & i : base64unmap) i = 0; for(int i = 0; i < 64; ++i) base64unmap[fake_base64[i]] = i; didinit = true; } return base64unmap[c]; } void encode(const unsigned char * out, const int len, KviCString & szText) { // FIXME: this is probably needed only on LittleEndian machines! byteswap_buffer((unsigned char *)out, len); // da uglybase64 encoding const unsigned char * outb = out; const unsigned char * oute = out + len; int ll = (len * 3) / 2; szText.setLen(ll); unsigned char * p = (unsigned char *)szText.ptr(); while(outb < oute) { quint32 * dd1 = (quint32 *)outb; outb += 4; quint32 * dd2 = (quint32 *)outb; outb += 4; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; } } void decode(KviCString & szText, unsigned char ** buf, int * len) { // make sure its length is multiple of 12 (eventually pad with zeroes) if(szText.len() % 12) { int oldL = szText.len(); szText.setLen(szText.len() + (12 - (szText.len() % 12))); char * padB = szText.ptr() + oldL; char * padE = szText.ptr() + szText.len(); while(padB < padE) *padB++ = 0; } *len = (int)(szText.len() * 2) / 3; *buf = (unsigned char *)KviMemory::allocate(*len); unsigned char * p = (unsigned char *)szText.ptr(); unsigned char * e = p + szText.len(); int i; unsigned char * bufp = *buf; while(p < e) { quint32 * dw1 = (quint32 *)bufp; bufp += 4; quint32 * dw2 = (quint32 *)bufp; bufp += 4; *dw2 = 0; for(i = 0; i < 6; i++) *dw2 |= (fake_base64dec(*p++)) << (i * 6); *dw1 = 0; for(i = 0; i < 6; i++) *dw1 |= (fake_base64dec(*p++)) << (i * 6); } // FIXME: this is probably needed only on LittleEndian machines! byteswap_buffer(*buf, *len); } };