new version "(16) Kreuz Köln Ost": #close JSON-12. remove dependency to awkward boost.archive for base64.
parent
12793cf92c
commit
3a138e06d6
|
@ -28,7 +28,7 @@ mt-server: main.o libjson-adapter.a
|
|||
libjson-adapter.a: json-adapter.o registry.o nfc.o json_rpc.o \
|
||||
function_map.o pep-types.o \
|
||||
security-token.o \
|
||||
nfc_sets.o \
|
||||
nfc_sets.o base64.o \
|
||||
json_spirit/json_spirit_reader.o json_spirit/json_spirit_value.o json_spirit/json_spirit_writer.o
|
||||
ar rcs $@ $^
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
#include "base64.hh"
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
#define __ (-1) // invalid char -> exception!
|
||||
#define SP (-2) // space char -> ignore
|
||||
#define EQ (-3) // '=' char -> special handling of EOF
|
||||
|
||||
const char* const b64c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
const int8_t values[256] = {
|
||||
// 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
__, __, __, __, __, __, __, __, __, SP, SP, __, SP, SP, __, __, // 0x00 .. 0x0F
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0x10 .. 0x1F
|
||||
SP, __, __, __, __, __, __, __, __, __, __, 62, __, __, __, 63, // 0x20 .. 0x2F
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, __, __, __, EQ, __, __, // 0x30 .. 0x3F 0x3D = '='
|
||||
__, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 0x40 .. 0x4F
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, __, __, __, __, __, // 0x50 .. 0x5F
|
||||
__, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 0x60 .. 0x6F
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, __, __, __, __, __, // 0x70 .. 0x7F
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0x80 .. 0x8F
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0x90 .. 0x9F
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0xA0 .. 0xAF
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0xB0 .. 0xBF
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0xC0 .. 0xCF
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0xD0 .. 0xDF
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0xE0 .. 0xEF
|
||||
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0xF0 .. 0xFF
|
||||
};
|
||||
|
||||
struct IllegalCharacter
|
||||
{
|
||||
char c;
|
||||
};
|
||||
|
||||
unsigned fetch(const char*& s, const char* end)
|
||||
{
|
||||
while( s < end)
|
||||
{
|
||||
const int8_t sc = values[ uint8_t(*s) ];
|
||||
if(sc==-1) throw IllegalCharacter{*s};
|
||||
++s;
|
||||
if(sc>=0)
|
||||
{
|
||||
return uint8_t(sc);
|
||||
}else{
|
||||
if(sc==EQ) { return 255; }
|
||||
}
|
||||
}
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
||||
// decodes base64-encoded 'input', skip whitespaces, throw if illegal character found in string
|
||||
std::string base64_decode(const std::string& input)
|
||||
try{
|
||||
std::string ret;
|
||||
ret.reserve( (input.size()+3)/4 * 3 );
|
||||
|
||||
const char* c = input.data();
|
||||
const char* const end = c + input.size();
|
||||
|
||||
uint8_t u0, u1, u2, u3=0;
|
||||
|
||||
while(c < end)
|
||||
{
|
||||
u0 = fetch(c,end);
|
||||
u1 = fetch(c,end);
|
||||
u2 = fetch(c,end);
|
||||
u3 = fetch(c,end);
|
||||
|
||||
if(u1!=255) { ret += char( (u0 << 2) | (u1 >> 4) ); }
|
||||
if(u2!=255) { ret += char( (u1 << 4) | (u2 >> 2) ); }
|
||||
if(u3!=255) { ret += char( (u2 << 6) | (u3 ) ); }
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
catch(const IllegalCharacter& ic)
|
||||
{
|
||||
throw std::runtime_error("Illegal character (" + std::to_string( int(ic.c) ) + ") in base64-encoded string \"" + input + "\"" );
|
||||
}
|
||||
|
||||
|
||||
std::string base64_encode(const std::string& input)
|
||||
{
|
||||
typedef uint8_t U8;
|
||||
|
||||
std::string ret;
|
||||
ret.reserve( (input.size()+2)/3 * 4 );
|
||||
|
||||
const unsigned triples = input.size()/3;
|
||||
const char* s = input.data();
|
||||
for(unsigned q=0; q<triples; ++q, s+=3)
|
||||
{
|
||||
const uint32_t u = U8(s[0])*65536 + U8(s[1])*256 + U8(s[2]);
|
||||
ret += b64c[ (u>>18) & 63 ];
|
||||
ret += b64c[ (u>>12) & 63 ];
|
||||
ret += b64c[ (u>> 6) & 63 ];
|
||||
ret += b64c[ (u ) & 63 ];
|
||||
}
|
||||
|
||||
switch(input.size() - triples*3)
|
||||
{
|
||||
case 2 :
|
||||
{
|
||||
const uint32_t u = U8(s[0])*65536 + U8(s[1])*256;
|
||||
ret += b64c[ (u>>18) & 63 ];
|
||||
ret += b64c[ (u>>12) & 63 ];
|
||||
ret += b64c[ (u>> 6) & 63 ];
|
||||
ret += '=';
|
||||
return ret;
|
||||
}
|
||||
|
||||
case 1 :
|
||||
{
|
||||
const uint32_t u = U8(s[0])*65536;
|
||||
ret += b64c[ (u>>18) & 63 ];
|
||||
ret += b64c[ (u>>12) & 63 ];
|
||||
ret += '=';
|
||||
ret += '=';
|
||||
return ret;
|
||||
}
|
||||
case 0: return ret;
|
||||
default : throw std::logic_error("Internal error in base64_encode()!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef JSON_ADAPTER_BASE64_HH
|
||||
#define JSON_ADAPTER_BASE64_HH
|
||||
|
||||
#include <string>
|
||||
|
||||
// decodes base64-encoded 'input', skip whitespaces, throw std::runtime_error if an illegal character found in string
|
||||
std::string base64_decode(const std::string& input);
|
||||
|
||||
// encodes base64-encoded 'input', without any whitespaces nor linebreaks
|
||||
std::string base64_encode(const std::string& input);
|
||||
|
||||
#endif // JSON_ADAPTER_BASE64_HH
|
|
@ -76,7 +76,8 @@ const std::string server_version =
|
|||
// "(12) Kreuz Köln Süd"; // support for attachments, so encrypt_message() works now! :-) but we have memory corruption, hence the FIXME in pep-types.cc :-(
|
||||
// "(13) Köln-Poll"; // refactoring to avoid copying of parameters. Fixes the memory corruption. Some other clean-ups
|
||||
// "(!4) Köln-Gremberg"; // refactoring to use JSON-Adapter as a library
|
||||
"(15) Dreieck Heumar"; // PEP_SESSIONs are now handled internally, so the adapter's users don't have to care about anymore. :-)
|
||||
// "(15) Dreieck Heumar"; // PEP_SESSIONs are now handled internally, so the adapter's users don't have to care about anymore. :-)
|
||||
"(16) Kreuz Köln Ost"; // mime_encode_message(), mime_decode_message(), blob_t are base64-encoded.
|
||||
|
||||
|
||||
typedef std::map<std::thread::id, PEP_SESSION> SessionRegistry;
|
||||
|
@ -127,8 +128,9 @@ PEP_STATUS unregisterEventListener(Context* ctx, std::string address, unsigned p
|
|||
// these are the pEp functions that are callable by the client
|
||||
const FunctionMap functions = {
|
||||
// from mime.h
|
||||
FP("mime_encode_message", new Func<PEP_STATUS, In<message*>, In<int>, Out<char *>>(&mime_encode_message)),
|
||||
FP("mime_decode_message", new Func<PEP_STATUS, In<const char*>, In<std::size_t>, Out<message*>>(&mime_decode_message)),
|
||||
FP("mime_encode_message", new Func<PEP_STATUS, In<message*>, In<int>, Out<char *>>(&mime_encode_message)),
|
||||
FP("mime_decode_message", new Func<PEP_STATUS, In<const char*>, In<std::size_t>, Out<message*>>(&mime_decode_message)),
|
||||
|
||||
// from message_api.h
|
||||
FP( "—— Message API ——", new Separator ),
|
||||
FP( "encrypt_message", new Func<PEP_STATUS, In<PEP_SESSION, false>, In<message*>, In<stringlist_t*>, Out<message*>, In<PEP_enc_format>, In<PEP_encrypt_flags_t>>( &encrypt_message ) ),
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
#include "json_spirit/json_spirit_utils.h"
|
||||
|
||||
#include <iostream> // Just to print debug stuff to std::cerr
|
||||
|
||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||
#include <boost/archive/iterators/insert_linebreaks.hpp>
|
||||
#include <boost/archive/iterators/transform_width.hpp>
|
||||
#include "base64.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -24,20 +20,11 @@ namespace
|
|||
);
|
||||
}
|
||||
|
||||
std::string base64_from_json_object(const js::Object& obj, const std::string& key){
|
||||
typedef boost::archive::iterators::transform_width<
|
||||
boost::archive::iterators::binary_from_base64<
|
||||
const char *>, 8, 6> from_base64;
|
||||
|
||||
std::string b64String = from_json_object<std::string, js::str_type> (obj, key);
|
||||
|
||||
if(b64String.length() % 4 != 0)
|
||||
throw std::runtime_error("JSON object has a member for key \"" + key + "\""
|
||||
" with incompatible size for base64 decoding. Base64 strings must be padded.");
|
||||
|
||||
std::string res(from_base64(b64String.data()), from_base64(b64String.data() + b64String.length()));
|
||||
return res;
|
||||
}
|
||||
std::string base64_from_json_object(const js::Object& obj, const std::string& key)
|
||||
{
|
||||
const std::string b64String = from_json_object<std::string, js::str_type> (obj, key);
|
||||
return base64_decode(b64String);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void to_json_object(js::Object& obj, const std::string& key, const T& value)
|
||||
|
@ -49,27 +36,13 @@ namespace
|
|||
}
|
||||
|
||||
void to_base64_json_object(js::Object& obj, const std::string& key, char *value, size_t size)
|
||||
{
|
||||
unsigned int overflow = size % 3;
|
||||
unsigned int padding = overflow ? 3 - overflow : 0;
|
||||
|
||||
typedef boost::archive::iterators::base64_from_binary<
|
||||
boost::archive::iterators::transform_width<
|
||||
const unsigned char *,6 ,8>> to_base64;
|
||||
|
||||
#ifdef BOOST_NEEDS_PADDED_INPUT
|
||||
std::vector<unsigned char> padded(size + padding, 0)
|
||||
std::copy(value, value + size, padded.begin());
|
||||
std::string b64String(to_base64(padded.begin()), to_base64(padded.begin() + size));
|
||||
#else
|
||||
std::string b64String(to_base64(value), to_base64(value + size));
|
||||
#endif
|
||||
|
||||
for(unsigned int i = 0; i < padding; i++)
|
||||
b64String.push_back('=');
|
||||
|
||||
obj.emplace_back(key, b64String);
|
||||
}
|
||||
{
|
||||
if(value != nullptr && size>0)
|
||||
{
|
||||
const std::string raw_string(value, value+size);
|
||||
obj.emplace_back( key, js::Value( base64_encode( raw_string ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue