You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pEpJSONServerAdapter/server/server_version.cc

211 lines
11 KiB
C++

#include "server_version.hh"
#include "inout.hh"
#include <fstream>
#include <sstream>
#include "logger.hh"
#include "pEp-utils-json.hh"
#include <pEp/pEpEngine.h> // for PEP_VERSION and get_engine_version()
#include <boost/algorithm/string/trim.hpp>
#include "json_spirit/json_spirit_reader.h"
#include <pEp/slurp.hh>
namespace js = json_spirit;
namespace {
#ifdef PACKAGE_VERSION
const char* PackageVersion = PACKAGE_VERSION;
#else
const char* PackageVersion = nullptr;
#endif
// version names comes from here:
// https://de.wikipedia.org/wiki/Bundesautobahn_4
static const std::string VersionName =
// "(4) Kreuz Aachen"; // first version with this version scheme :-)
// "(5a) Eschweiler-West"; // add support for log_event() and trustwords()
// "(5b) Eschweiler-Ost"; // add support for get_identity() and get_languagelist()
// "(5c) Weisweiler"; // add missing members of struct message
// "(5d) Langerwehe"; // add the remaining functions from pEpEngine.h
// "(6) Düren"; // some bug fixes for missing data types, UTF-8 output etc., status in hex etc.
// "(7a) Merzenich"; // InOut parameters added. Untested, yet.
// "(7b) Elsdorf"; // add own_key functions, which are new in the pEp Engine
// "(8) Kerpen"; // pEp_identity fixes due to changes in the pEp Engine
// "(8a) Kreuz Kerpen"; // remove own_key_add() because pEpEngine doesn't have it anymore.
// "(9a) Frechen-Königsdorf"; // add security-token
// "(10) Kreuz Köln-West"; // More fields in JavaScript for "message", 1-element identity list to support message->to attribute
// "(11) Köln-Klettenberg"; // support for identity_list as output parameter, as needed by import_key() now. Fix some issue with identity.lang
// "(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. :-)
// "(16) Kreuz Köln Ost"; // mime_encode_message(), mime_decode_message(), blob_t are base64-encoded.
// "(17) Köln Mehrheim"; // MIME_encrypt_message() and MIME_decrypt_message() instead, because the other two were internal functions
// "(18) Refrath"; // add trust_personal_key(), key_mistrusted(), key_reset_trust()
// "(19) Bensberg"; // command-line parameters, daemonize(), silent all output in daemon mode
// "(20) Moitzfeld"; // showHandshake() -> notifyHandshake() and other Engine's API changes
// "(21) Untereschbach"; // JSON-11: replace trustwords() by get_trustwords()
// "(22) Overath"; // add blacklist_retrieve(), rename identity_color() and outgoing_message_color() into ..._rating().
// "(23) Engelskirchen"; // fix JSON-19. Support "Bool" and "Language" as separate data types in JavaScript.
// "(24) Bielstein"; // add MIME_encrypt_message_ex() and MIME_decrypt_message_ex() as a HACK.
// "(25) Gummersbach"; // JSON-22: add MIME_encrypt_message_for_self() and change API for encrypt_message_for_self().
// "(26) Reichshof"; // change return type from JSON array into JSON object {"output":[...], "return":..., "errorstack":[...]}
// "(27) Eckenhagen"; // add command line switch "--sync false" to disable automatic start of keysync at startup
// "(28) Olpe-Süd"; // add re_evaluate_message_rating(). Jira: JSON-29
// "(29) Wenden"; // {start|stop}{KeySync|KeyserverLookup} JSON-28
// "(30) Krombach"; // JSON-49, add call_with_lock() around init() and release().
// "(31) Altenkleusheim"; // JSON-57: change location of server token file. breaking API change, so API_VERSION=0x0003.
// "(32) Littfeld"; // JSON-72: add is_pep_user() to the API
// "(33) Hilchenbach"; // JSON-71: Setup C++11 Multi-threading in libevent properly to avoid deadlocks in MT server code"
// "(34) Erndtebrück"; // remove apiVersion(), change version() to return a semver-compatible version number in a JSON object.
// "(35) Bad Berleburg"; // fix the fork() problem on MacOS. daemonize() now got a function parameter. \o/
// "(36) Hatzfeld"; // JSON-81: add package_version, rename "version" into "api_version" in ServerVersion, add versions from the Engine, too
// "(37) Battenberg"; // JSON-75: change debonize() behavior, especially on MS Windows
// "(38) Frankenberg"; // JSON-92: API CHANGE: decrypt_message() has InOut src message, MIME_decrypt_message() returns changed src msg, too.
// "(39) Gemünden"; // JSON-93: support for InLengt<> to calculate string lengths automatically.
// Renumbering due to political decisions - the planned exits 31..39 through the Sauerland will never be build. :-(
// So we got a new exit with the same number:
// "(39) Eisenach"; // JSON-118: fix to_json() for KeySync callbacks to avoid crashes. Add attachment support in interactive.js \o/
// "(40) Eisenach-Ost"; // remove all Enigmail leftovers. Bump API version to 0.17.0
// "(40b) Sättelstädt"; // JSON-139: support for NULL pointers in "const char*" parameters: In<c_string, NullOkay>
// 41a,b were skipped, intentionally
// "(42) Gotha"; // JSON-152: 2-parameter version of pollForEvents().
// "(43) Wandersleben"; // JSON-153 passphrase support. *sigh*
// "(44) Neudietendorf"; // replace my own sync thread code by libpEpAdapter's implementation.
// "(45) Kreuz Erfurt"; // fix of context-saved function parameters that would cause trouble when >1 request is processed in parallel.
"(46) Erfurt-West"; // JSON-156: delete client cached values after timeout.
} // end of anonymous namespace
////////////////////////////////////////////////////////////////////////////
const ServerVersion& server_version()
{
//const ServerVersion sv{0, 10, 0, version_name}; // first version defined.
//const ServerVersion sv{0, 11, 0, version_name}; // add set_own_key()
//const ServerVersion sv{0, 12, 0, version_name}; // rename mis-spelled undo_last_mitrust() into undo_last_mistrust()
//const ServerVersion sv{0, 12, 1, version_name}; // add assert_utf8() for every string to/from the Engine (except blobdata)
//const ServerVersion sv{0, 12, 2, version_name}; // fix the fork() problem on MacOS. daemonize() now got a function parameter.
//const ServerVersion sv(0,13,0); // add package_version, rename "version" into "api_version" in ServerVersion, add versions from the Engine, too
//const ServerVersion sv(0,13,1); // JSON-91: add MIME_encrypt_message_for_self() and encrypt_message_for_self()
//const ServerVersion sv(0,14,0); // JSON-75: incompatible behavior of daemonize() especially in MS Windows
//const ServerVersion sv(0,15,0); // JSON-92: API CHANGE.
//const ServerVersion sv(0,15,1); // JSON-92 again: Change "keylist" in (MIME_)decrypt_message() from Out to InOutP. Is a compatible API change for JSON/JavaScript due to the handling of output parameters. :-)
//const ServerVersion sv(0,15,2); // JSON-93 InLength<> is a compatible API change, because length parameter is still there but ignored. :-)
//static const ServerVersion sv(0,15,3); // JSON-110: add encrypt_message_and_add_priv_key()
//static const ServerVersion sv(0,15,4); // JSON-117: add trust_own_key()
//static const ServerVersion sv(0,15,5); // JSON-119: add get_key_rating_for_user()
//static const ServerVersion sv(0,16,0); // Kick-out Enigmail 2.0 compat, remove MIME_*() methods, deliverHandshakeResult() changes parameter types
//static const ServerVersion sv(0,16,1); // JSON-120: add support for key_reset_identity(), key_reset_user(), and key_reset_all_own_keys()
//static const ServerVersion sv(0,17,0); // kick out getGpgEnvironment(). It was Enigmail-only (JSON-18) and breaks architecture. Kick-out hotfixer un-feature.
//static const ServerVersion sv(0,18,0); // JSON-127: 'src' in encrypt_message() is InOut.
//static const ServerVersion sv(0,18,1); // JSON-130: some data members in pEp_identity added
//static const ServerVersion sv(0,18,2); // JSON-135: Add mime_encode_message() and mime_decode_message() to the JSON API
//static const ServerVersion sv(0,18,3); // JSON-137: Add outgoing_message_rating_preview() to the JSON API
//static const ServerVersion sv(0,18,4); // JSON-141: fix handling of parameters of type PEP_rating
// 0.19 was skipped intentionally.
//static const ServerVersion sv(0,20,0); // JSON-152: 2-parameter version of pollForEvents().
//static const ServerVersion sv(0,20,1); // JSON-153: passphrase support
//static const ServerVersion sv(0,21,0); // import_key() expects binary data, so they are always base64-encoded!
//static const ServerVersion sv(0,21,1); // wrap _all_ Engine functions with passphrase_cache.api(), except config_*() functions.
static const ServerVersion sv(0,21,2); // JSON-165 the msg param of re_evaluate_message_rating() is now "inout" and not "in" any more
return sv;
}
ServerVersion::ServerVersion(unsigned maj, unsigned min, unsigned p)
: major{maj}
, minor{min}
, patch{p}
, name {VersionName}
, package_version{PackageVersion}
{
Logger L("ServerVersion");
if (!PackageVersion)
{
try{
PackageVersion = "0.0.0"; /* break the loop */
const std::string file_content =
boost::algorithm::trim_copy(
pEp::slurp("PackageVersion")
);
try{
js::Value v;
js::read_or_throw(file_content, v);
const js::Object obj = v.get_obj();
PackageVersion = pEp::utility::from_json_object<char*, js::str_type>(obj, "package_version");
}
catch(std::runtime_error& e)
{
L.warning(std::string("Cannot parse file \"PackageVersion\" as JSON object: ") + e.what() );
PackageVersion = strdup(file_content.c_str());
}
this->package_version = PackageVersion;
}
catch(std::runtime_error& e)
{
// slurp() throws when it cannot read the file.
L.info(std::string("Cannot read file \"PackageVersion\": ") + e.what() );
}
}
L.debug("ServerVersion set as %u.%u.%u name=\"%s\" package_version=\"%s\".",
major, minor, patch, name.c_str(), package_version
);
}
std::string ServerVersion::major_minor_patch() const
{
return std::to_string(major) + "."
+ std::to_string(minor) + "."
+ std::to_string(patch);
}
std::ostream& operator<<(std::ostream& o, const ServerVersion& sv)
{
o << sv.major_minor_patch() << " \"" << sv.name << '\"';
if(sv.package_version)
{
o << ". package_version=\"" << sv.package_version << "\" ";
}
return o;
}
template<>
js::Value to_json<ServerVersion>(const ServerVersion& sv)
{
js::Object o;
o.emplace_back("major", uint64_t(sv.major));
o.emplace_back("minor", uint64_t(sv.minor));
o.emplace_back("patch", uint64_t(sv.patch));
o.emplace_back("api_version", sv.major_minor_patch());
o.emplace_back("name", sv.name);
o.emplace_back("package_version",
(sv.package_version ? std::string(sv.package_version) : js::Value() )
);
o.emplace_back("engine_version", std::string(get_engine_version()));
o.emplace_back("pep_protocol_version", std::string(PEP_VERSION));
return o;
}
template<>
Out<ServerVersion>::~Out()
{
}
template<>
js::Value Type2String<ServerVersion>::get() { return "ServerVersion"; }