pEpJSONServerAdapter/server/pep-types.cc

467 lines
10 KiB
C++

#include "pep-types.hh"
#include "json_spirit/json_spirit_utils.h"
namespace
{
// fetch a member from the given object, if set. (return a sensible NULL/default value if not)
template<class T, js::Value_type VALUE_TYPE>
T from_json_object(const js::Object& obj, const std::string& key)
{
const auto v = find_value(obj, key);
if(v.type() == js::null_type) return T{};
if(v.type() == VALUE_TYPE) return from_json<T>(v);
throw std::runtime_error("JSON object has a member for key \"" + key + "\""
" with incompatible type " + js::value_type_to_string( v.type())
+ " instead of expected type " + js::value_type_to_string(VALUE_TYPE)
);
}
template<class T>
void to_json_object(js::Object& obj, const std::string& key, const T& value)
{
if(value!=T{})
{
obj.emplace_back( key, js::Value( to_json<T>(value) ));
}
}
}
template<>
In<message*>::~In()
{
free_message(value);
}
template<>
In<stringlist_t*>::~In()
{
free_stringlist(value);
}
template<>
In<pEp_identity*>::~In()
{
free_identity(value);
}
template<>
Out<pEp_identity*>::~Out()
{
free_identity(*value);
delete value;
}
template<>
Out<pEp_identity*>::Out(const Out<pEp_identity*>& other)
: value( new pEp_identity* )
{
*value = identity_dup(*other.value);
}
template<>
In<PEP_enc_format>::~In()
{
// nothing to do here. :-)
}
template<>
Out<stringlist_t*>::Out(const Out<stringlist_t*>& other)
: value( new stringlist_t* )
{
*value = *other.value ? stringlist_dup(*other.value) : nullptr;
}
template<>
Out<stringlist_t*>::~Out()
{
if(value) free_stringlist(*value);
delete value;
}
template<>
Out<_message*>::Out(const Out<_message*>& other)
: value( new _message* )
{
*value = *other.value ? message_dup(*other.value) : nullptr;
}
template<>
Out<_message*>::~Out()
{
if(value) free_message(*value);
delete value;
}
template<>
Out<PEP_color>::Out(const Out<PEP_color>& other)
: value( new PEP_color(*other.value) )
{
}
template<>
Out<PEP_color>::~Out()
{
delete value;
}
template<>
message* from_json<message*>(const js::Value& v)
{
const js::Object& o = v.get_obj();
_message* msg = new_message(PEP_dir_incoming);
// fetch values from v and put them into msg
msg->dir = from_json_object<PEP_msg_direction, js::int_type>(o, "dir");
msg->id = from_json_object<char*, js::str_type>(o, "id");
msg->shortmsg = from_json_object<char*, js::str_type>(o, "short");
msg->longmsg = from_json_object<char*, js::str_type>(o, "long");
msg->longmsg_formatted = from_json_object<char*, js::str_type>(o, "fmt");
msg->attachments = from_json_object<bloblist_t*, js::array_type>(o, "attachments");
msg->sent = from_json_object<timestamp*, js::int_type>(o, "sent");
msg->recv = from_json_object<timestamp*, js::int_type>(o, "recv");
msg->from = from_json_object<pEp_identity*, js::obj_type>(o, "from");
msg->to = from_json_object<identity_list*, js::array_type>(o, "to");
msg->recv_by = from_json_object<pEp_identity*, js::obj_type>(o, "recv_by");
msg->cc = from_json_object<identity_list*, js::array_type>(o, "cc");
msg->bcc = from_json_object<identity_list*, js::array_type>(o, "bcc");
msg->reply_to = from_json_object<identity_list*, js::array_type>(o, "reply_to");
msg->in_reply_to = from_json_object<stringlist_t*, js::array_type>(o, "in_reply_to");
// TODO: refering_msg_ref
msg->references = from_json_object<stringlist_t*, js::array_type>(o, "references");
// TODO: refered_by
msg->keywords = from_json_object<stringlist_t*, js::int_type>(o, "keywords");
msg->comments = from_json_object<char*, js::str_type>(o, "comments");
msg->opt_fields = from_json_object<stringpair_list_t*, js::array_type>(o, "opt_fields");
msg->enc_format = from_json_object<PEP_enc_format, js::int_type>(o, "enc_format");
return msg;
}
template<>
pEp_identity* from_json<pEp_identity*>(const js::Value& v)
{
const js::Object& o = v.get_obj();
char* address = from_json_object<char*, js::str_type>(o, "address");
char* fingerprint = from_json_object<char*, js::str_type>(o, "fpr");
char* user_id = from_json_object<char*, js::str_type>(o, "user_id");
char* username = from_json_object<char*, js::str_type>(o, "username");
pEp_identity* ident = new_identity
(
address,
fingerprint,
user_id,
username
);
free(username);
free(user_id);
free(fingerprint);
free(address);
return ident;
}
template<>
js::Value to_json<message*>(message* const& msg)
{
if(msg == nullptr)
{
return js::Value("NULL-MESSAGE");
}
js::Object o;
to_json_object(o, "dir" , msg->dir);
to_json_object(o, "id" , msg->id);
to_json_object(o, "shortmsg", msg->shortmsg);
to_json_object(o, "longmsg" , msg->longmsg);
to_json_object(o, "longmsg_formatted" , msg->longmsg_formatted);
to_json_object(o, "from" , msg->from);
to_json_object(o, "recv_by" , msg->recv_by);
to_json_object(o, "to" , msg->to);
to_json_object(o, "cc" , msg->cc);
to_json_object(o, "bcc" , msg->bcc);
to_json_object(o, "reply_to", msg->reply_to);
to_json_object(o, "in_reply_to" , msg->in_reply_to);
// TODO: refering_msg_ref
to_json_object(o, "references", msg->references);
// TODO: refered_by
to_json_object(o, "keywords", msg->keywords);
to_json_object(o, "comments", msg->comments);
to_json_object(o, "opt_fields", msg->opt_fields);
to_json_object(o, "enc_format", msg->enc_format);
return js::Value( std::move(o) );
}
template<>
stringlist_t* from_json<stringlist_t*>(const js::Value& v)
{
const js::Array& a = v.get_array();
stringlist_t* sl = new_stringlist( nullptr );
for(const js::Value& v : a )
{
const std::string s = v.get_str();
stringlist_add(sl, s.c_str() );
}
return sl;
}
template<>
identity_list* from_json<identity_list*>(const js::Value& v)
{
const js::Array& a = v.get_array();
identity_list* il = new_identity_list( nullptr );
for(const js::Value& v : a )
{
pEp_identity* id = from_json<pEp_identity*>(v);
identity_list_add(il, id );
}
return il;
}
template<>
_bloblist_t* from_json<_bloblist_t*>(const js::Value& v)
{
const js::Array& a = v.get_array();
if(a.empty())
return nullptr;
auto element = a.begin();
const auto oelem = element->get_obj();
_bloblist_t* bl = new_bloblist
(
from_json_object<char*, js::str_type> (oelem, "data"),
from_json_object<size_t, js::int_type> (oelem, "size"),
from_json_object<const char*, js::str_type>(oelem, "mime_type"),
from_json_object<const char*, js::str_type>(oelem, "filename")
);
for(; element!=a.end(); ++element)
{
const auto oelem = element->get_obj();
bl = bloblist_add(bl,
from_json_object<char*, js::str_type> (oelem, "data"),
from_json_object<size_t, js::int_type> (oelem, "size"),
from_json_object<const char*, js::str_type>(oelem, "mime_type"),
from_json_object<const char*, js::str_type>(oelem, "filename")
);
}
return bl;
}
template<>
stringpair_t* from_json<stringpair_t*>(const js::Value& v)
{
const js::Object& o = v.get_obj();
char* key = from_json_object<char*, js::str_type>(o, "key");
char* val = from_json_object<char*, js::str_type>(o, "value");
stringpair_t* sp = new_stringpair( key, val );
free(val);
free(key);
return sp;
}
template<>
stringpair_list_t* from_json<stringpair_list_t*>(const js::Value& v)
{
const js::Array& a = v.get_array();
if(a.empty())
return nullptr;
auto element = a.begin();
stringpair_list_t* spl = new_stringpair_list( from_json<stringpair_t*>(*element) );
for(; element!=a.end(); ++element)
{
spl = stringpair_list_add(spl, from_json<stringpair_t*>(*element) );
}
return spl;
}
template<>
js::Value to_json<stringpair_list_t*>(stringpair_list_t* const& osl)
{
stringpair_list_t* spl = osl;
js::Array a;
while(spl)
{
js::Object o;
o.emplace_back( "key", spl->value->key );
o.emplace_back( "value", spl->value->value );
a.push_back( std::move(o) );
spl = spl->next;
}
return js::Value( std::move(a) );
}
template<>
tm* from_json<tm*>(const js::Value& v)
{
return new_timestamp( v.get_int64() );
}
template<>
js::Value to_json<stringlist_t*>(stringlist_t* const& osl)
{
stringlist_t* sl = osl;
js::Array a;
while(sl)
{
std::string value = sl->value;
a.push_back( std::move(value) );
sl = sl->next;
}
return js::Value( std::move(a) );
}
template<>
js::Value to_json<pEp_identity*>(pEp_identity* const& id)
{
if(id == nullptr)
{
return js::Value("NULL-IDENTITY");
}
js::Object o;
o.emplace_back( "struct_size", js::Value( uint64_t( id->struct_size) ));
to_json_object(o, "address", id->address);
to_json_object(o, "fpr", id->fpr);
to_json_object(o, "user_id", id->user_id);
to_json_object(o, "username", id->username);
o.emplace_back( "comm_type", js::Value( int( id->comm_type) ));
o.emplace_back( "lang", js::Value( std::string( id->lang, id->lang+2) ));
o.emplace_back( "me", js::Value( id->me ));
return js::Value( std::move(o) );
}
template<>
js::Value to_json<identity_list*>(identity_list* const& idl)
{
identity_list* il = idl;
js::Array a;
while(il)
{
const js::Value value = to_json<pEp_identity*>(il->ident);
a.push_back(value);
il = il->next;
}
return js::Value( std::move(a) );
}
template<>
js::Value to_json<PEP_color>(const PEP_color& color)
{
js::Object o;
o.emplace_back( "color", int(color) );
return o;
}
template<>
js::Value to_json<PEP_STATUS>(const PEP_STATUS& status)
{
js::Object o;
o.emplace_back( "status", int(status) );
return o;
}
template<>
PEP_enc_format from_json<PEP_enc_format>(const js::Value& v)
{
return PEP_enc_format(v.get_int());
}
template<>
js::Value to_json<PEP_enc_format>(const PEP_enc_format& v)
{
return js::Value( int(v) );
}
template<>
PEP_msg_direction from_json<PEP_msg_direction>(const js::Value& v)
{
return PEP_msg_direction(v.get_int());
}
template<>
js::Value to_json<PEP_msg_direction>(const PEP_msg_direction& v)
{
return js::Value( int(v) );
}
template<>
js::Value Type2String<PEP_SESSION>::get() { return "Session"; }
template<>
js::Value Type2String<_message*>::get() { return "Message"; }
template<>
js::Value Type2String<pEp_identity*>::get() { return "Identity"; }
template<>
js::Value Type2String<_stringlist_t*>::get() { return "StringList"; }
template<>
js::Value Type2String<_PEP_color>::get() { return "PEP_color"; }
template<>
js::Value Type2String<_PEP_enc_format>::get() { return "PEP_enc_format"; }
template<>
js::Value Type2String<PEP_STATUS>::get() { return "PEP_STATUS"; }