Suche schöne C++ Base64 Klasse
-
Hey!
Natürlich habe ich google schon bemüht, aber ich finde einfach keine schöne, sauber programmierte C++ Lösung einer Base64 Klasse.
Ich finde nur Codeschnipsel die nicht funktioneren oder welche die die MFC verwenden.
Da ich selbst keine Zeit und auch keine Lust habe (Programmierer sind faul ;)) mich in die Theorie einzuarbeiten und das selber zu machen wollte ich einfach mal nachfragen.Die Klasse bräuchte nur die üblichen Decode / Encode Methoden. Es muss ja nichtmal eine Klasse sein, Hauptsache die Lösung ist brauchbar und standard C++ konform
Danke!
-
Hallo,
im Doom 3 SDK findest du solch eine Klasse basierend auf dem Code von Lars Wirzenius. Damit du dir das nicht alles runterladen musst, kopier ich einfach den Code
Du musst den Code leicht modifizieren, damit du nicht von idStr, idFile, byte und ID_INLINE abhaengig bist, was aber kein Problem sein sollte.#ifndef __BASE64_H__ #define __BASE64_H__ /* =============================================================================== base64 =============================================================================== */ class idBase64 { public: idBase64( void ); idBase64( const idStr &s ); ~idBase64( void ); void Encode( const byte *from, int size ); void Encode( const idStr &src ); int DecodeLength( void ) const; // minimum size in bytes of destination buffer for decoding int Decode( byte *to ) const; // does not append a \0 - needs a DecodeLength() bytes buffer void Decode( idStr &dest ) const; // decodes the binary content to an idStr (a bit dodgy, \0 and other non-ascii are possible in the decoded content) void Decode( idFile *dest ) const; const char *c_str() const; void operator=( const idStr &s ); private: byte * data; int len; int alloced; void Init( void ); void Release( void ); void EnsureAlloced( int size ); }; ID_INLINE idBase64::idBase64( void ) { Init(); } ID_INLINE idBase64::idBase64( const idStr &s ) { Init(); *this = s; } ID_INLINE idBase64::~idBase64( void ) { Release(); } ID_INLINE const char *idBase64::c_str( void ) const { return (const char *)data; } ID_INLINE void idBase64::Init( void ) { len = 0; alloced = 0; data = NULL; } ID_INLINE void idBase64::Release( void ) { if ( data ) { delete[] data; } Init(); } ID_INLINE void idBase64::EnsureAlloced( int size ) { if ( size > alloced ) { Release(); } data = new byte[size]; alloced = size; } ID_INLINE void idBase64::operator=( const idStr &s ) { EnsureAlloced( s.Length()+1 ); // trailing \0 - beware, this does a Release strcpy( (char *)data, s.c_str() ); len = s.Length(); } #endif /* !__BASE64_H__ */
/* Copyright (c) 1996 Lars Wirzenius. All rights reserved. June 14 2003: TTimo <ttimo@idsoftware.com> modified + endian bug fixes http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=197039 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* ============ idBase64::Encode ============ */ static const char sixtet_to_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; void idBase64::Encode( const byte *from, int size ) { int i, j; unsigned long w; byte *to; EnsureAlloced( 4*(size+3)/3 + 2 ); // ratio and padding + trailing \0 to = data; w = 0; i = 0; while (size > 0) { w |= *from << i*8; ++from; --size; ++i; if (size == 0 || i == 3) { byte out[4]; SixtetsForInt( out, w ); for (j = 0; j*6 < i*8; ++j) { *to++ = sixtet_to_base64[ out[j] ]; } if (size == 0) { for (j = i; j < 3; ++j) { *to++ = '='; } } w = 0; i = 0; } } *to++ = '\0'; len = to - data; } /* ============ idBase64::DecodeLength returns the minimum size in bytes of the target buffer for decoding 4 base64 digits <-> 3 bytes ============ */ int idBase64::DecodeLength( void ) const { return 3*len/4; } /* ============ idBase64::Decode ============ */ int idBase64::Decode( byte *to ) const { unsigned long w; int i, j; size_t n; static char base64_to_sixtet[256]; static int tab_init = 0; byte *from = data; if (!tab_init) { memset( base64_to_sixtet, 0, 256 ); for (i = 0; (j = sixtet_to_base64[i]) != '\0'; ++i) { base64_to_sixtet[j] = i; } tab_init = 1; } w = 0; i = 0; n = 0; byte in[4] = {0,0,0,0}; while (*from != '\0' && *from != '=' ) { if (*from == ' ' || *from == '\n') { ++from; continue; } in[i] = base64_to_sixtet[* (unsigned char *) from]; ++i; ++from; if (*from == '\0' || *from == '=' || i == 4) { w = IntForSixtets( in ); for (j = 0; j*8 < i*6; ++j) { *to++ = w & 0xff; ++n; w >>= 8; } i = 0; w = 0; } } return n; } /* ============ idBase64::Encode ============ */ void idBase64::Encode( const idStr &src ) { Encode( (const byte *)src.c_str(), src.Length() ); } /* ============ idBase64::Decode ============ */ void idBase64::Decode( idStr &dest ) const { byte *buf = new byte[ DecodeLength()+1 ]; // +1 for trailing \0 int out = Decode( buf ); buf[out] = '\0'; dest = (const char *)buf; delete[] buf; } /* ============ idBase64::Decode ============ */ void idBase64::Decode( idFile *dest ) const { byte *buf = new byte[ DecodeLength()+1 ]; // +1 for trailing \0 int out = Decode( buf ); dest->Write( buf, out ); delete[] buf; }
-
Schonmal danke dafür !
Leider hat ID sehr viel selbstgemacht (strings, eigenes inline, eigenes filehandle), aber wenn niemand eine schönere Lösung hat werde ich mich wohl ransetzen und die ganzen Datentypen durch standard C++ Datentypen ersetzen
-
Ist keine Arbeit, nur ein wenig find&replace. Die meisten Sachen sind nur typedefs auf Standardkram und ID_INLINE wird wohl ein #define auf inline oder __forceinline sein.
-
na ja wenn man sich
idFile *dest
[...]
dest->Write( buf, out);anschaut muss man da doch ein wenig mehr umbiegen als einfach die Datentypen zu ersetzen, aber scheinbar werde ich da nicht herumkommen.
Eigentlich unverständlich das es keine standard C++ Lösung gibt
-
base schrieb:
Eigentlich unverständlich das es keine standard C++ Lösung gibt
Dann mach doch eine. Warum muss immer alles vorgekaut sein?
-
Die Crypto++ Bibliothek besitzt Base64-Konverter: http://www.cryptopp.com
Ist aufgrund mangelnder Dokumentation allerdings schwierig, den Einstieg zu finden. Für Base64 allein lohnt es sich vielleicht auch nicht. Zumindest aber ist das eine solide C++-Lösung
-
Walli schrieb:
base schrieb:
Eigentlich unverständlich das es keine standard C++ Lösung gibt
Dann mach doch eine. Warum muss immer alles vorgekaut sein?
Weil ich, wie bereits geschrieben, keine Lust (ja ich habe keine Lust! Ich will wie bei der STL auf etwas vorgefertigtes zugreifen) und keine Zeit habe.
Es gibt so viel zu tun, da verwende ich so viel wie möglich aus bereits vorhanden Bibliotheken, nicht jeder der hier Code haben will versucht sich darum zu drücken seine Hausaufgaben machen zu müssen
-
base schrieb:
Es gibt so viel zu tun, da verwende ich so viel wie möglich aus bereits vorhanden Bibliotheken, nicht jeder der hier Code haben will versucht sich darum zu drücken seine Hausaufgaben machen zu müssen
Ja, habe ich auch nicht behauptet. Aber wenn keine Standard-Lösung da ist, dann muss man sich eben schnell eine bestehende an die eigenen Bedürfnisse anpassen oder eben was eigenes machen. Den ID-Code hätte man zumindest in ner Viertelstunde umschreiben können.
-
Hmm. Ich hab da vor ner Weile mal was in C gecodet. Sollte sich ziemlich einfach nach C++ ummodeln lassen; ich poste es einfach mal, für den Fall, dass es jemand brauchen kann:
#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> char *base64_encode(char *dest, size_t n, char const *src) { static char const b64_tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; size_t i, j; for(i = j = 0; ; i += 4, j += 3) { if(src[j]) { dest[i ] = b64_tbl[src[j] >> 2 & 0x3f]; dest[i + 1] = b64_tbl[((src[j ] << 4 & 0x30) | (src[j + 1] >> 4 & 0x0f)) & 0x3f]; } else { dest[i] = '\0'; break; } if(i >= n - 5) return NULL; if(src[j + 1]) { dest[i + 2] = b64_tbl[((src[j + 1] & 0x0f) << 2 | (src[j + 2] & 0xc0) >> 6) & 0x3f]; } else { dest[i + 2] = dest[i + 3] = '='; dest[i + 4] = '\0'; break; } if(src[j + 2]) { dest[i + 3] = b64_tbl[src[j + 2] & 0x3f]; } else { dest[i + 3] = '='; dest[i + 4] = '\0'; break; } }; return dest; } static char base64_char_decode(char c) { if(islower(c)) return c - 'a' + 26; if(isupper(c)) return c - 'A'; if(isdigit(c)) return c - '0' + 52; if(c == '+') return 62; if(c == '/') return 63; /* Das ist zwar das selbe wie bei 'A', und von daher als Fehlermeldung * ungeeignet, aber diese Funktion ist eh nur intern gedacht, und das * hier _sollte_ nur auftreten, wenn c == '='. In dem Fall füllt * base64_decode halt einfach mit '\0' auf, was den String terminiert * und uns alle glücklich macht. */ return 0; } char *base64_decode(char *dest, size_t n, char const *src) { size_t i, j; char c, d, e, f; i = strlen(src); if(i % 4 != 0 || i / 4 * 3 > n - 1) return NULL; for(i = j = 0; src[j]; i += 3, j += 4) { c = base64_char_decode(src[j ]); d = base64_char_decode(src[j + 1]); e = base64_char_decode(src[j + 2]); f = base64_char_decode(src[j + 3]); dest[i ] = (c << 2) | (d >> 4 & 0x03); dest[i + 1] = (d << 4) | (e >> 2 & 0x0f); dest[i + 2] = (e << 6) | f; } dest[i] = '\0'; return dest; }
Ist im Grunde immer drei byte von Hand gemangelt. Ich hab mich dabei im Wesentlichen nach der ERklärung auf http://de.wikipedia.org/wiki/Base64 gerichtet. Gut, es ließe sich bestimmt noch an der einen oder anderen Ecke was optimieren, aber es funktioniert, und ich finds eigentlich ziemlich übersichtlich.
-
Frage am rande und sorry das ich den Thread wieder rausgeholt habe, aber wofür benötigt man sowas?
-
CDU Wähler brauchen sowas nicht.
-
Damit kannst du einen String verschlüsselt... mehr muss man nicht sagen, oder?
Und wofür? Naja, wenn du halt mal Daten hast, die ein anderer nicht lesen können soll (zumindest nicht auf Anhieb, für wirklich vertrauliche Sachen ist Base64 dann längst zu unsicher)...
-
Reyx schrieb:
Damit kannst du einen String verschlüsselt...
Nein, als Verschlüsselung ist es nicht zu gebrauchen. Mit Base64 kann man Binärdaten auf den ASCII Zeichensatz abbilden u.a. zur Übertragung mit Protokollen, die nur Textinhalte zulassen.