You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
394 lines
11 KiB
394 lines
11 KiB
#include <iostream>
|
|
#include <cctype>
|
|
#include <pEp/pEpEngine.h>
|
|
#include <pEp/message_api.h>
|
|
#include <pEp/keymanagement.h>
|
|
#include <pEp/identity_list.h>
|
|
#include <pEp/utils.hh>
|
|
#include <pEp/pEpLog.hh>
|
|
#include <sstream>
|
|
#include <type_traits>
|
|
//using namespace pEp;
|
|
|
|
|
|
namespace pEp {
|
|
|
|
template<class T>
|
|
std::string type_add_val(const T c, size_t val_len = 30)
|
|
{
|
|
static_assert(std::is_pointer<T>::value, "only pointer types are valid");
|
|
std::stringstream ss_type;
|
|
//type
|
|
ss_type << typeid(T).name();
|
|
|
|
//addr
|
|
std::stringstream ss_addr{};
|
|
ss_addr << static_cast<const void*>(c);
|
|
|
|
//value
|
|
std::stringstream ss_val{};
|
|
if (c != nullptr) {
|
|
ss_val << "\"" << c << "\"";
|
|
} else {
|
|
ss_val << "<NULL>";
|
|
}
|
|
|
|
std::stringstream ret{};
|
|
ret << "{ " << ss_type.str() << " | " + ss_addr.str() << " | "
|
|
<< pEp::Utils::clip(ss_val.str(), val_len) << " }";
|
|
return ret.str();
|
|
}
|
|
|
|
char* alloc(const std::string& str)
|
|
{
|
|
char* ret = strdup(str.c_str());
|
|
pEpLog(type_add_val(ret));
|
|
return ret;
|
|
}
|
|
|
|
template<class T>
|
|
void free(T ptr_type)
|
|
{
|
|
pEpLog(type_add_val(ptr_type));
|
|
::pEp_free(ptr_type);
|
|
}
|
|
|
|
template<>
|
|
void free(char* ptr_type)
|
|
{
|
|
pEpLog(type_add_val(ptr_type));
|
|
::pEp_free(ptr_type);
|
|
}
|
|
|
|
template<>
|
|
void free(::pEp_identity* ptr_type)
|
|
{
|
|
pEpLog(type_add_val(ptr_type));
|
|
::pEp_free(ptr_type);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------
|
|
#define EXSTR(msg) std::string(__FUNCTION__) + " - " + msg
|
|
|
|
|
|
// Manages a char* to appear like a std::string
|
|
// char* c_str
|
|
// c_str MUST point to either:
|
|
// * NULL - means there is no value/mem alloc yet
|
|
// * dyn allocated memory
|
|
// in case the mem is already allocated, there must be 2 modes
|
|
// * take ownership (and free it)
|
|
// * dont take ownership, only provide a C++ interface
|
|
// There must be the option to construct the object before the wrapped c_str (char*)
|
|
// is known. This leads to a pEp::String object in invalid state, and it must be initialized using
|
|
// set(). Otherwise all(most) functions will throw.
|
|
// set() can only be called once, will throw otherwise.
|
|
class String {
|
|
public:
|
|
// Usually you _have_ to use this ctor, because its impossible to create a static
|
|
// object if you have to know the address of a dynamically created one.
|
|
String() = default;
|
|
|
|
// Best to use this constructor, as the object is in a valid state when the wrapped
|
|
// c_str (char*) is known
|
|
explicit String(char** c_str_pp)
|
|
{
|
|
initialize(c_str_pp);
|
|
}
|
|
|
|
~String()
|
|
{
|
|
_free();
|
|
}
|
|
|
|
void initialize(char** c_str_pp)
|
|
{
|
|
if (c_str_pp == nullptr) {
|
|
throw Exception{ EXSTR("cant initialize on a nullptr") };
|
|
}
|
|
|
|
if (_is_initialized) {
|
|
throw Exception{ EXSTR("double initialization") };
|
|
}
|
|
|
|
// init
|
|
_c_str_pp = c_str_pp;
|
|
_c_str_p = *_c_str_pp;
|
|
_is_initialized = true;
|
|
pEpLogClass(to_string() + " - taking ownership");
|
|
}
|
|
|
|
// make a copy
|
|
String& operator=(const std::string& str)
|
|
{
|
|
pEpLogClass("Before: " + to_string() + " - new val: '" + pEp::Utils::clip(str, 30) + "'");
|
|
if (_c_str_pp == nullptr) {
|
|
throw Exception{ EXSTR("invalid state") };
|
|
}
|
|
|
|
// DEALLOCATION
|
|
_free();
|
|
|
|
// ALLOCATION
|
|
if (str.empty()) {
|
|
// if the new value is empty str, lets point to nothing
|
|
*_c_str_pp = nullptr;
|
|
_c_str_p = *_c_str_pp;
|
|
} else {
|
|
*_c_str_pp = pEp::alloc(str);
|
|
_c_str_p = *_c_str_pp;
|
|
}
|
|
pEpLogClass("After: " + to_string());
|
|
return *this;
|
|
}
|
|
|
|
// return a copy of whatever c_str currently is (maybe created by us, maybe changed meanwhile)
|
|
operator std::string() const
|
|
{
|
|
if (_c_str_pp == nullptr) {
|
|
throw Exception{ EXSTR("invalid state") };
|
|
}
|
|
|
|
if (*_c_str_pp != nullptr) {
|
|
return { *_c_str_pp };
|
|
}
|
|
return {};
|
|
}
|
|
|
|
char** data()
|
|
{
|
|
return _c_str_pp;
|
|
}
|
|
|
|
const char* c_data() const
|
|
{
|
|
if (_c_str_pp == nullptr) {
|
|
throw Exception{ EXSTR("invalid state") };
|
|
}
|
|
return *_c_str_pp;
|
|
}
|
|
|
|
std::string to_string() const
|
|
{
|
|
if (_c_str_pp == nullptr) {
|
|
throw Exception{ EXSTR("invalid state") };
|
|
}
|
|
|
|
std::string ret{ "[" + type_add_val(_c_str_pp) + " / " + type_add_val(*_c_str_pp) + "]" };
|
|
return ret;
|
|
}
|
|
|
|
static bool log_enabled;
|
|
|
|
private:
|
|
void _free()
|
|
{
|
|
// if the c_str points to a different address now, than the one we created
|
|
if (*_c_str_pp != _c_str_p) {
|
|
// a new string has been created, and we need to free it as well
|
|
pEpLog("raw access string change detected");
|
|
pEp::free(*_c_str_pp);
|
|
} else {
|
|
// we anyways need to free the one we created
|
|
// NO: WE ASSUME THAT:
|
|
// if the char* has been replaced, it has been freed, as well
|
|
if (_c_str_p != nullptr) {
|
|
pEp::free(_c_str_p);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool _is_initialized{ false };
|
|
char** _c_str_pp{ nullptr };
|
|
char* _c_str_p{ nullptr };
|
|
|
|
Adapter::pEpLog::pEpLogger logger{ "pEp::String", log_enabled };
|
|
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;
|
|
|
|
class Exception : public std::runtime_error {
|
|
public:
|
|
explicit Exception(const std::string& msg) : std::runtime_error(msg) {}
|
|
};
|
|
};
|
|
|
|
bool pEp::String::log_enabled{ true };
|
|
|
|
std::ostream& operator<<(std::ostream& o, const pEp::String& pEpStr)
|
|
{
|
|
return o << std::string(pEpStr);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------
|
|
|
|
// TOOD:
|
|
// ctor not exception safe
|
|
class Identity {
|
|
public:
|
|
Identity(
|
|
const std::string& address = "",
|
|
const std::string& username = "",
|
|
const std::string& user_id = "",
|
|
const std::string& fpr = "")
|
|
{
|
|
pEpLogClass("called");
|
|
_wrappee = ::new_identity(nullptr, nullptr, nullptr, nullptr);
|
|
|
|
// set the pEp::String wrapper underlying c_str
|
|
this->address.initialize(&_wrappee->address);
|
|
this->username.initialize(&_wrappee->username);
|
|
this->user_id.initialize(&_wrappee->user_id);
|
|
this->fpr.initialize(&_wrappee->fpr);
|
|
|
|
// set the values
|
|
this->address = address;
|
|
this->username = username;
|
|
this->user_id = user_id;
|
|
this->fpr = fpr;
|
|
}
|
|
|
|
~Identity()
|
|
{
|
|
_free();
|
|
}
|
|
|
|
|
|
pEp::String address{};
|
|
pEp::String username{};
|
|
pEp::String user_id{};
|
|
pEp::String fpr{};
|
|
|
|
operator ::pEp_identity*()
|
|
{
|
|
return _wrappee;
|
|
}
|
|
|
|
static bool log_enabled;
|
|
|
|
private:
|
|
void _free()
|
|
{
|
|
// pEp::free(_wrappee);
|
|
}
|
|
|
|
::pEp_identity* _wrappee{ nullptr };
|
|
Adapter::pEpLog::pEpLogger logger{ "IdentWrappySP", log_enabled };
|
|
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;
|
|
};
|
|
|
|
bool Identity::log_enabled{ true };
|
|
|
|
} // namespace pEp
|
|
|
|
|
|
::PEP_SESSION session;
|
|
|
|
void test_getters(char const* const* const c_str_p, pEp::String& pstr)
|
|
{
|
|
pEpLog("to_string(): " + pstr.to_string());
|
|
assert(pstr.c_data() == *c_str_p);
|
|
assert(pstr.data() == c_str_p);
|
|
|
|
if (*c_str_p != nullptr) {
|
|
std::string tmp{ pstr };
|
|
pEpLog("operator std::string(): " + tmp);
|
|
assert(tmp == std::string(*c_str_p));
|
|
|
|
// will segfault with nullptr, and this is correct
|
|
std::string tmp2{ *pstr.data() };
|
|
pEpLog("data(): " + tmp2);
|
|
assert(tmp2 == std::string(*c_str_p));
|
|
|
|
std::string tmp3{ pstr.c_data() };
|
|
pEpLog("c_data(): " + tmp2);
|
|
assert(tmp3 == std::string(*c_str_p));
|
|
} else {
|
|
std::string tmp{ pstr };
|
|
pEpLog("operator std::string(): " + tmp);
|
|
assert(tmp.empty());
|
|
}
|
|
}
|
|
|
|
void test_assign_and_getters(char** c_str_p, pEp::String& pstr)
|
|
{
|
|
test_getters(c_str_p, pstr);
|
|
pEpLogH2("assign operator");
|
|
pstr = "assign operator";
|
|
test_getters(c_str_p, pstr);
|
|
|
|
pEpLogH2("raw c_str assign");
|
|
*c_str_p = strdup("raw c_str assign");
|
|
test_getters(c_str_p, pstr);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
// pEp::Utils::readKey();
|
|
pEp::Adapter::pEpLog::set_enabled(true);
|
|
|
|
// pEp::String::log_enabled = false;
|
|
if (1) {
|
|
// INVALID USAGE
|
|
// char* c_str_u; // uninitialized == INVALID
|
|
// undefined behaviour, most likely "pointer being freed was not allocated"
|
|
// {
|
|
// char* c_str;
|
|
// pEp::String pstr(c_str);
|
|
// }
|
|
// char* c_str_s = "fdsfs"; // statically initialized == INVALID
|
|
// {
|
|
// char ca[4] = { 'p', 'E', 'p'};
|
|
// char* c_str = ca;
|
|
// pEp::String pstr(c_str);
|
|
// }
|
|
|
|
// VALID USAGE
|
|
// new pEp::String on char* pointing to NULL
|
|
{
|
|
pEpLogH1("new pEp::String on char* pointing to NULL");
|
|
char* c_str = NULL; // nullptr
|
|
|
|
pEp::String pstr(&c_str);
|
|
test_assign_and_getters(&c_str, pstr);
|
|
}
|
|
|
|
// new pEp::String on already initalized char*
|
|
{
|
|
pEpLogH1("new pEp::String on already initalized char*");
|
|
char* c_str = strdup("initialized c string");
|
|
|
|
pEp::String pstr(&c_str);
|
|
test_assign_and_getters(&c_str, pstr);
|
|
}
|
|
|
|
// initialize()
|
|
{
|
|
pEpLogH1("initialize()");
|
|
pEp::String pstr{};
|
|
|
|
char* c_str = strdup("initialized c string");
|
|
//TODO: PITYASSERT_THROWS
|
|
pstr.initialize(&c_str);
|
|
|
|
test_assign_and_getters(&c_str, pstr);
|
|
}
|
|
}
|
|
|
|
setenv("HOME", ".", 1);
|
|
::init(&session, nullptr, nullptr, nullptr);
|
|
|
|
// create identity
|
|
pEp::Identity id1{ "wrong@entry.lol", "wrong", "23", "INVA_FPR" };
|
|
|
|
pEpLog(*id1);
|
|
id1.username = "alice";
|
|
id1.address = "alice@peptest.org";
|
|
pEpLog(id1.address);
|
|
pEpLog(id1.username);
|
|
::myself(session, id1);
|
|
pEpLog(*id1);
|
|
|
|
pEp::Identity id2{ "bob" };
|
|
::update_identity(session, id2);
|
|
pEpLog(*id2);
|
|
}
|
|
|