* Large cleanup. Removed inconsistent usage of errno in instantiate_object();
instead, it will now use the image_id parameter to store errors in. * find_instantiation_func() and validate_instantiation() will no longer overwrite errno with B_OK. * Made private functions static, and moved them to the top. * If the class name starts with '_', it will now try to add a BPrivate namespace in case it could not find the class. This should help with the compatibility issues Shinta reported (also part of ticket #2086). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25124 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+326
-346
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001-2007, Haiku, Inc.
|
* Copyright (c) 2001-2008, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -40,298 +40,9 @@ const int32 FUNC_NAME_LEN = 1024;
|
|||||||
// TODO: consider moving these to a separate module, and making them more
|
// TODO: consider moving these to a separate module, and making them more
|
||||||
// full-featured (e.g., taking NS::ClassName::Function(Param p) instead
|
// full-featured (e.g., taking NS::ClassName::Function(Param p) instead
|
||||||
// of just NS::ClassName)
|
// of just NS::ClassName)
|
||||||
static void Demangle(const char *name, BString &out);
|
|
||||||
static void Mangle(const char *name, BString &out);
|
|
||||||
static instantiation_func FindFuncInImage(BString& funcName, image_id id,
|
|
||||||
status_t& err);
|
|
||||||
static bool CheckSig(const char* sig, image_info& info);
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable::BArchivable()
|
static int
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable::BArchivable(BMessage* from)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable::~BArchivable()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BArchivable::Archive(BMessage* into, bool deep) const
|
|
||||||
{
|
|
||||||
if (!into) {
|
|
||||||
// TODO: logging/other error reporting?
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BString name;
|
|
||||||
Demangle(typeid(*this).name(), name);
|
|
||||||
|
|
||||||
return into->AddString(B_CLASS_FIELD, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable*
|
|
||||||
BArchivable::Instantiate(BMessage* from)
|
|
||||||
{
|
|
||||||
debugger("Can't create a plain BArchivable object");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BArchivable::Perform(perform_code d, void* arg)
|
|
||||||
{
|
|
||||||
// TODO: Check against original
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BArchivable::_ReservedArchivable1() {}
|
|
||||||
void BArchivable::_ReservedArchivable2() {}
|
|
||||||
void BArchivable::_ReservedArchivable3() {}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BuildFuncName(const char* className, BString& funcName)
|
|
||||||
{
|
|
||||||
funcName = "";
|
|
||||||
|
|
||||||
// This is what we're after:
|
|
||||||
// Instantiate__Q28OpenBeOS11BArchivableP8BMessage
|
|
||||||
Mangle(className, funcName);
|
|
||||||
#if __GNUC__ >= 4
|
|
||||||
funcName.Prepend("_ZN");
|
|
||||||
funcName.Append("11InstantiateE");
|
|
||||||
#else
|
|
||||||
funcName.Prepend("Instantiate__");
|
|
||||||
#endif
|
|
||||||
funcName.Append("P8BMessage");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable*
|
|
||||||
instantiate_object(BMessage* archive, image_id* id)
|
|
||||||
{
|
|
||||||
// Check our params
|
|
||||||
if (id)
|
|
||||||
*id = B_BAD_VALUE;
|
|
||||||
|
|
||||||
if (!archive) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
errno = B_BAD_VALUE;
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: NULL BMessage argument");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get class name from archive
|
|
||||||
const char* name = NULL;
|
|
||||||
status_t err = archive->FindString(B_CLASS_FIELD, &name);
|
|
||||||
if (err) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: Failed to find an entry "
|
|
||||||
"defining the class name (%s).", strerror(err));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get sig from archive
|
|
||||||
const char* sig = NULL;
|
|
||||||
bool hasSig = (archive->FindString(B_ADD_ON_FIELD, &sig) == B_OK);
|
|
||||||
|
|
||||||
instantiation_func iFunc = find_instantiation_func(name, sig);
|
|
||||||
|
|
||||||
// if find_instantiation_func() can't locate Class::Instantiate()
|
|
||||||
// and a signature was specified
|
|
||||||
if (!iFunc && hasSig) {
|
|
||||||
// use BRoster::FindApp() to locate an app or add-on with the symbol
|
|
||||||
BRoster Roster;
|
|
||||||
entry_ref ref;
|
|
||||||
err = Roster.FindApp(sig, &ref);
|
|
||||||
|
|
||||||
// if an entry_ref is obtained
|
|
||||||
BEntry entry;
|
|
||||||
if (!err)
|
|
||||||
err = entry.SetTo(&ref);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: Error finding app "
|
|
||||||
"with signature \"%s\" (%s)", sig, strerror(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!err) {
|
|
||||||
BPath path;
|
|
||||||
err = entry.GetPath(&path);
|
|
||||||
if (!err) {
|
|
||||||
// load the app/add-on
|
|
||||||
image_id addOn = load_add_on(path.Path());
|
|
||||||
if (addOn < 0) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: Could not load "
|
|
||||||
"add-on %s: %s.", path.Path(), strerror(addOn));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the image_id
|
|
||||||
if (id)
|
|
||||||
*id = addOn;
|
|
||||||
|
|
||||||
BString funcName;
|
|
||||||
BuildFuncName(name, funcName);
|
|
||||||
|
|
||||||
iFunc = FindFuncInImage(funcName, addOn, err);
|
|
||||||
if (!iFunc) {
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: Failed to find exported "
|
|
||||||
"Instantiate static function for class %s.", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!iFunc) {
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: No signature specified "
|
|
||||||
"in archive, looking for class \"%s\".", name);
|
|
||||||
errno = B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
syslog(LOG_ERR, "instantiate_object failed: %s (%x)",
|
|
||||||
strerror(err), err);
|
|
||||||
errno = err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if Class::Instantiate(BMessage*) was found
|
|
||||||
if (iFunc) {
|
|
||||||
// use to create and return an object instance
|
|
||||||
return iFunc(archive);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BArchivable*
|
|
||||||
instantiate_object(BMessage* from)
|
|
||||||
{
|
|
||||||
return instantiate_object(from, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
validate_instantiation(BMessage* from, const char* class_name)
|
|
||||||
{
|
|
||||||
errno = B_OK;
|
|
||||||
|
|
||||||
// Make sure our params are kosher -- original skimped here =P
|
|
||||||
if (!from) {
|
|
||||||
// Not standard; Be implementation has a segment
|
|
||||||
// violation on this error mode
|
|
||||||
errno = B_BAD_VALUE;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t err = B_OK;
|
|
||||||
const char* data;
|
|
||||||
for (int32 index = 0; err == B_OK; ++index) {
|
|
||||||
err = from->FindString(B_CLASS_FIELD, index, &data);
|
|
||||||
if (!err && strcmp(data, class_name) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = B_MISMATCHED_VALUES;
|
|
||||||
syslog(LOG_ERR, "validate_instantiation failed on class %s.", class_name);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
instantiation_func
|
|
||||||
find_instantiation_func(const char* class_name, const char* sig)
|
|
||||||
{
|
|
||||||
errno = B_OK;
|
|
||||||
if (!class_name) {
|
|
||||||
errno = B_BAD_VALUE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
instantiation_func theFunc = NULL;
|
|
||||||
BString funcName;
|
|
||||||
|
|
||||||
BuildFuncName(class_name, funcName);
|
|
||||||
|
|
||||||
//printf("find_instantiation_func() - looking for '%s'\n", funcName.String());
|
|
||||||
|
|
||||||
thread_id tid = find_thread(NULL);
|
|
||||||
thread_info ti;
|
|
||||||
status_t err = get_thread_info(tid, &ti);
|
|
||||||
if (!err) {
|
|
||||||
// for each image_id in team_id
|
|
||||||
image_info info;
|
|
||||||
int32 cookie = 0;
|
|
||||||
while (!theFunc && (get_next_image_info(ti.team, &cookie, &info) == B_OK)) {
|
|
||||||
theFunc = FindFuncInImage(funcName, info.id, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theFunc && !CheckSig(sig, info)) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
theFunc = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("find_instantiation_func(): %p\n", theFunc);
|
|
||||||
|
|
||||||
return theFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
instantiation_func
|
|
||||||
find_instantiation_func(const char* class_name)
|
|
||||||
{
|
|
||||||
return find_instantiation_func(class_name, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
instantiation_func
|
|
||||||
find_instantiation_func(BMessage* archive_data)
|
|
||||||
{
|
|
||||||
errno = B_OK;
|
|
||||||
|
|
||||||
if (!archive_data) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
errno = B_BAD_VALUE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* name = NULL;
|
|
||||||
const char* sig = NULL;
|
|
||||||
status_t err;
|
|
||||||
|
|
||||||
err = archive_data->FindString(B_CLASS_FIELD, &name);
|
|
||||||
if (err) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = archive_data->FindString(B_ADD_ON_FIELD, &sig);
|
|
||||||
|
|
||||||
return find_instantiation_func(name, sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
GetNumber(const char*& name)
|
GetNumber(const char*& name)
|
||||||
{
|
{
|
||||||
int val = atoi(name);
|
int val = atoi(name);
|
||||||
@@ -343,8 +54,8 @@ GetNumber(const char*& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
Demangle(const char* name, BString& out)
|
demangle_class_name(const char* name, BString& out)
|
||||||
{
|
{
|
||||||
// TODO: add support for template classes
|
// TODO: add support for template classes
|
||||||
// _find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
|
// _find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
|
||||||
@@ -388,8 +99,8 @@ Demangle(const char* name, BString& out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
Mangle(const char* name, BString& out)
|
mangle_class_name(const char* name, BString& out)
|
||||||
{
|
{
|
||||||
// TODO: add support for template classes
|
// TODO: add support for template classes
|
||||||
// _find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
|
// _find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
|
||||||
@@ -430,74 +141,343 @@ Mangle(const char* name, BString& out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
instantiation_func
|
static void
|
||||||
FindFuncInImage(BString& funcName, image_id id, status_t& err)
|
build_function_name(const BString& className, BString& funcName)
|
||||||
{
|
{
|
||||||
err = B_OK;
|
funcName = "";
|
||||||
instantiation_func theFunc = NULL;
|
|
||||||
|
|
||||||
// Don't need to do it this way ...
|
// This is what we're after:
|
||||||
#if 0
|
// Instantiate__Q28OpenBeOS11BArchivableP8BMessage
|
||||||
char foundFuncName[FUNC_NAME_LEN];
|
mangle_class_name(className.String(), funcName);
|
||||||
int32 symbolType;
|
#if __GNUC__ >= 4
|
||||||
int32 funcNameLen;
|
funcName.Prepend("_ZN");
|
||||||
|
funcName.Append("11InstantiateE");
|
||||||
// for each B_SYMBOL_TYPE_TEXT in image_id
|
#else
|
||||||
for (int32 i = 0; !err; ++i) {
|
funcName.Prepend("Instantiate__");
|
||||||
funcNameLen = FUNC_NAME_LEN;
|
|
||||||
err = get_nth_image_symbol(id, i, foundFuncName, &funcNameLen,
|
|
||||||
&symbolType, (void**)&theFunc);
|
|
||||||
|
|
||||||
if (!err && symbolType == B_SYMBOL_TYPE_TEXT) {
|
|
||||||
// try to match Class::Instantiate(BMessage*) signature
|
|
||||||
if (funcName.ICompare(foundFuncName, funcNameLen) == 0)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
theFunc = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
funcName.Append("P8BMessage");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
add_private_namespace(BString& name)
|
||||||
|
{
|
||||||
|
if (name.Compare("_", 1) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
name.Prepend("BPrivate::");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static instantiation_func
|
||||||
|
find_function_in_image(BString& funcName, image_id id, status_t& err)
|
||||||
|
{
|
||||||
|
instantiation_func instantiationFunc = NULL;
|
||||||
err = get_image_symbol(id, funcName.String(), B_SYMBOL_TYPE_TEXT,
|
err = get_image_symbol(id, funcName.String(), B_SYMBOL_TYPE_TEXT,
|
||||||
(void**)&theFunc);
|
(void**)&instantiationFunc);
|
||||||
|
if (err != B_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (err) {
|
return instantiationFunc;
|
||||||
// TODO: error handling
|
}
|
||||||
theFunc = NULL;
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
check_signature(const char* signature, image_info& info)
|
||||||
|
{
|
||||||
|
if (signature == NULL) {
|
||||||
|
// If it wasn't specified, anything "matches"
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return theFunc;
|
// Get image signature
|
||||||
|
BFile file(info.name, B_READ_ONLY);
|
||||||
|
status_t err = file.InitCheck();
|
||||||
|
if (err != B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
char imageSignature[B_MIME_TYPE_LENGTH];
|
||||||
|
BAppFileInfo appFileInfo(&file);
|
||||||
|
err = appFileInfo.GetSignature(imageSignature);
|
||||||
|
if (err != B_OK) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object - couldn't get mime sig for %s",
|
||||||
|
info.name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(signature, imageSignature))
|
||||||
|
return B_MISMATCHED_VALUES;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable::BArchivable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable::BArchivable(BMessage* from)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable::~BArchivable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BArchivable::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
if (!into) {
|
||||||
|
// TODO: logging/other error reporting?
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BString name;
|
||||||
|
demangle_class_name(typeid(*this).name(), name);
|
||||||
|
|
||||||
|
return into->AddString(B_CLASS_FIELD, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable*
|
||||||
|
BArchivable::Instantiate(BMessage* from)
|
||||||
|
{
|
||||||
|
debugger("Can't create a plain BArchivable object");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BArchivable::Perform(perform_code d, void* arg)
|
||||||
|
{
|
||||||
|
// TODO: Check against original
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BArchivable::_ReservedArchivable1() {}
|
||||||
|
void BArchivable::_ReservedArchivable2() {}
|
||||||
|
void BArchivable::_ReservedArchivable3() {}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable*
|
||||||
|
instantiate_object(BMessage* archive, image_id* _id)
|
||||||
|
{
|
||||||
|
status_t statusBuffer;
|
||||||
|
status_t* status = &statusBuffer;
|
||||||
|
if (_id != NULL)
|
||||||
|
status = _id;
|
||||||
|
|
||||||
|
// Check our params
|
||||||
|
if (archive == NULL) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object failed: NULL BMessage argument");
|
||||||
|
*status = B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get class name from archive
|
||||||
|
const char* className = NULL;
|
||||||
|
status_t err = archive->FindString(B_CLASS_FIELD, &className);
|
||||||
|
if (err) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object failed: Failed to find an entry "
|
||||||
|
"defining the class name (%s).", strerror(err));
|
||||||
|
*status = B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get sig from archive
|
||||||
|
const char* signature = NULL;
|
||||||
|
bool hasSignature = archive->FindString(B_ADD_ON_FIELD, &signature) == B_OK;
|
||||||
|
|
||||||
|
instantiation_func instantiationFunc = find_instantiation_func(className,
|
||||||
|
signature);
|
||||||
|
|
||||||
|
// if find_instantiation_func() can't locate Class::Instantiate()
|
||||||
|
// and a signature was specified
|
||||||
|
if (!instantiationFunc && hasSignature) {
|
||||||
|
// use BRoster::FindApp() to locate an app or add-on with the symbol
|
||||||
|
BRoster Roster;
|
||||||
|
entry_ref ref;
|
||||||
|
err = Roster.FindApp(signature, &ref);
|
||||||
|
|
||||||
|
// if an entry_ref is obtained
|
||||||
|
BEntry entry;
|
||||||
|
if (err == B_OK)
|
||||||
|
err = entry.SetTo(&ref);
|
||||||
|
|
||||||
|
BPath path;
|
||||||
|
if (err == B_OK)
|
||||||
|
err = entry.GetPath(&path);
|
||||||
|
|
||||||
|
if (err != B_OK) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object failed: Error finding app "
|
||||||
|
"with signature \"%s\" (%s)", signature, strerror(err));
|
||||||
|
*status = err;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the app/add-on
|
||||||
|
image_id addOn = load_add_on(path.Path());
|
||||||
|
if (addOn < B_OK) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object failed: Could not load "
|
||||||
|
"add-on %s: %s.", path.Path(), strerror(addOn));
|
||||||
|
*status = addOn;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the image_id
|
||||||
|
if (_id != NULL)
|
||||||
|
*_id = addOn;
|
||||||
|
|
||||||
|
BString name = className;
|
||||||
|
for (int32 pass = 0; pass < 2; pass++) {
|
||||||
|
BString funcName;
|
||||||
|
build_function_name(name, funcName);
|
||||||
|
|
||||||
|
instantiationFunc = find_function_in_image(funcName, addOn, err);
|
||||||
|
if (instantiationFunc != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Check if we have a private class, and add the BPrivate namespace
|
||||||
|
// (for backwards compatibility)
|
||||||
|
if (!add_private_namespace(name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instantiationFunc == NULL) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object failed: Failed to find exported "
|
||||||
|
"Instantiate static function for class %s.", className);
|
||||||
|
*status = B_NAME_NOT_FOUND;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else if (instantiationFunc == NULL) {
|
||||||
|
syslog(LOG_ERR, "instantiate_object failed: No signature specified "
|
||||||
|
"in archive, looking for class \"%s\".", className);
|
||||||
|
*status = B_NAME_NOT_FOUND;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Class::Instantiate(BMessage*) was found
|
||||||
|
if (instantiationFunc != NULL) {
|
||||||
|
// use to create and return an object instance
|
||||||
|
return instantiationFunc(archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BArchivable*
|
||||||
|
instantiate_object(BMessage* from)
|
||||||
|
{
|
||||||
|
return instantiate_object(from, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CheckSig(const char* sig, image_info& info)
|
validate_instantiation(BMessage* from, const char* className)
|
||||||
{
|
{
|
||||||
if (!sig) {
|
// Make sure our params are kosher -- original skimped here =P
|
||||||
// If it wasn't specified, anything "matches"
|
if (!from) {
|
||||||
return true;
|
errno = B_BAD_VALUE;
|
||||||
}
|
|
||||||
|
|
||||||
status_t err = B_OK;
|
|
||||||
|
|
||||||
// Get image signature
|
|
||||||
BFile ImageFile(info.name, B_READ_ONLY);
|
|
||||||
err = ImageFile.InitCheck();
|
|
||||||
if (err) {
|
|
||||||
// TODO: extended error handling
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char imageSig[B_MIME_TYPE_LENGTH];
|
const char* data;
|
||||||
BAppFileInfo AFI(&ImageFile);
|
for (int32 index = 0; from->FindString(B_CLASS_FIELD, index, &data) == B_OK;
|
||||||
err = AFI.GetSignature(imageSig);
|
++index) {
|
||||||
if (err) {
|
if (!strcmp(data, className))
|
||||||
// TODO: extended error handling
|
return true;
|
||||||
syslog(LOG_ERR, "instantiate_object - couldn't get mime sig for %s",
|
|
||||||
info.name);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return strcmp(sig, imageSig) == 0;
|
errno = B_MISMATCHED_VALUES;
|
||||||
|
syslog(LOG_ERR, "validate_instantiation failed on class %s.", className);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
instantiation_func
|
||||||
|
find_instantiation_func(const char* className, const char* signature)
|
||||||
|
{
|
||||||
|
if (className == NULL) {
|
||||||
|
errno = B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_info threadInfo;
|
||||||
|
status_t err = get_thread_info(find_thread(NULL), &threadInfo);
|
||||||
|
if (err != B_OK) {
|
||||||
|
errno = err;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
instantiation_func instantiationFunc = NULL;
|
||||||
|
image_info imageInfo;
|
||||||
|
|
||||||
|
BString name = className;
|
||||||
|
for (int32 pass = 0; pass < 2; pass++) {
|
||||||
|
BString funcName;
|
||||||
|
build_function_name(name, funcName);
|
||||||
|
|
||||||
|
// for each image_id in team_id
|
||||||
|
int32 cookie = 0;
|
||||||
|
while (instantiationFunc == NULL
|
||||||
|
&& get_next_image_info(threadInfo.team, &cookie, &imageInfo)
|
||||||
|
== B_OK) {
|
||||||
|
instantiationFunc = find_function_in_image(funcName, imageInfo.id,
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
if (instantiationFunc != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Check if we have a private class, and add the BPrivate namespace
|
||||||
|
// (for backwards compatibility)
|
||||||
|
if (!add_private_namespace(name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instantiationFunc != NULL
|
||||||
|
&& check_signature(signature, imageInfo) != B_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return instantiationFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
instantiation_func
|
||||||
|
find_instantiation_func(const char* className)
|
||||||
|
{
|
||||||
|
return find_instantiation_func(className, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
instantiation_func
|
||||||
|
find_instantiation_func(BMessage* archive)
|
||||||
|
{
|
||||||
|
if (archive == NULL) {
|
||||||
|
errno = B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* name = NULL;
|
||||||
|
const char* signature = NULL;
|
||||||
|
if (archive->FindString(B_CLASS_FIELD, &name) != B_OK
|
||||||
|
|| archive->FindString(B_ADD_ON_FIELD, &signature)) {
|
||||||
|
errno = B_BAD_VALUE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return find_instantiation_func(name, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user