1338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
2338b8dc3SIngo Weinhold//	Copyright (c) 2001-2002, OpenBeOS
3338b8dc3SIngo Weinhold//
4338b8dc3SIngo Weinhold//	Permission is hereby granted, free of charge, to any person obtaining a
5338b8dc3SIngo Weinhold//	copy of this software and associated documentation files (the "Software"),
6338b8dc3SIngo Weinhold//	to deal in the Software without restriction, including without limitation
7338b8dc3SIngo Weinhold//	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8338b8dc3SIngo Weinhold//	and/or sell copies of the Software, and to permit persons to whom the
9338b8dc3SIngo Weinhold//	Software is furnished to do so, subject to the following conditions:
10338b8dc3SIngo Weinhold//
11338b8dc3SIngo Weinhold//	The above copyright notice and this permission notice shall be included in
12338b8dc3SIngo Weinhold//	all copies or substantial portions of the Software.
13338b8dc3SIngo Weinhold//
14338b8dc3SIngo Weinhold//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15338b8dc3SIngo Weinhold//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16338b8dc3SIngo Weinhold//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17338b8dc3SIngo Weinhold//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18338b8dc3SIngo Weinhold//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19338b8dc3SIngo Weinhold//	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20338b8dc3SIngo Weinhold//	DEALINGS IN THE SOFTWARE.
21338b8dc3SIngo Weinhold//
22338b8dc3SIngo Weinhold//	File Name:		Archivable.cpp
23338b8dc3SIngo Weinhold//	Author:			Erik Jaesler (erik@cgsoftware.com)
24338b8dc3SIngo Weinhold//	Description:	BArchivable mix-in class defines the archiving
25338b8dc3SIngo Weinhold//					protocol.  Also some global archiving functions.
26338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
27338b8dc3SIngo Weinhold
28338b8dc3SIngo Weinhold// Standard Includes -----------------------------------------------------------
29338b8dc3SIngo Weinhold#include <ctype.h>
30338b8dc3SIngo Weinhold#include <errno.h>
31338b8dc3SIngo Weinhold#include <stdlib.h>
32338b8dc3SIngo Weinhold#include <stdio.h>
33338b8dc3SIngo Weinhold#include <string>
34338b8dc3SIngo Weinhold#include <typeinfo>
35338b8dc3SIngo Weinhold#include <vector>
36338b8dc3SIngo Weinhold
37338b8dc3SIngo Weinhold// System Includes -------------------------------------------------------------
38338b8dc3SIngo Weinhold#include <AppFileInfo.h>
39338b8dc3SIngo Weinhold#include <Archivable.h>
40338b8dc3SIngo Weinhold#include <Entry.h>
41338b8dc3SIngo Weinhold#include <List.h>
42338b8dc3SIngo Weinhold#include <OS.h>
43338b8dc3SIngo Weinhold#include <Path.h>
44338b8dc3SIngo Weinhold//#include <Roster.h>
45338b8dc3SIngo Weinhold#include <String.h>
46338b8dc3SIngo Weinhold#include <SupportDefs.h>
47338b8dc3SIngo Weinhold#include <syslog.h>
48338b8dc3SIngo Weinhold
49338b8dc3SIngo Weinhold// Project Includes ------------------------------------------------------------
50338b8dc3SIngo Weinhold
51338b8dc3SIngo Weinhold// Local Includes --------------------------------------------------------------
52338b8dc3SIngo Weinhold
53338b8dc3SIngo Weinhold// Local Defines ---------------------------------------------------------------
54338b8dc3SIngo Weinhold
55338b8dc3SIngo Weinhold// Globals ---------------------------------------------------------------------
56338b8dc3SIngo Weinhold
57338b8dc3SIngo Weinhold
58338b8dc3SIngo Weinholdusing std::string;
59338b8dc3SIngo Weinholdusing std::vector;
60338b8dc3SIngo Weinhold
61338b8dc3SIngo Weinholdconst char* B_CLASS_FIELD = "class";
62338b8dc3SIngo Weinholdconst char* B_ADD_ON_FIELD = "add_on";
63338b8dc3SIngo Weinholdconst int32 FUNC_NAME_LEN = 1024;
64338b8dc3SIngo Weinhold
65338b8dc3SIngo Weinhold// TODO: consider moving these
66338b8dc3SIngo Weinhold//		 to a separate module, and making them more full-featured (e.g., taking
67338b8dc3SIngo Weinhold//		 NS::ClassName::Function(Param p) instead of just NS::ClassName)
68338b8dc3SIngo Weinholdstatic void Demangle(const char *name, BString &out);
69338b8dc3SIngo Weinholdstatic void Mangle(const char *name, BString &out);
70338b8dc3SIngo Weinhold// static instantiation_func FindFuncInImage(BString& funcName, image_id id,
71338b8dc3SIngo Weinhold// 										  status_t& err);
72338b8dc3SIngo Weinhold// static bool CheckSig(const char* sig, image_info& info);
73338b8dc3SIngo Weinhold
74338b8dc3SIngo Weinhold/*
75338b8dc3SIngo Weinhold// TODO: Where do these get triggered from?
76338b8dc3SIngo WeinholdLog entries graciously coughed up by the Be implementation:
77338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: NULL BMessage argument
78338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Failed to find an entrydefining the class name (Name not found).
79338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: No signature specified in archive, looking for class "TInvalidClassName".
80338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
81338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
82338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Failed to find exported Instantiate static function for class TInvalidClassName.
83338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Invalid argument (80000005)
84338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: No signature specified in archive, looking for class "TRemoteTestObject".
85338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object - couldn't get mime sig for /boot/home/src/projects/OpenBeOS/app_kit/test/lib/support/BArchivable/./BArchivableSystemTester
86338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
87338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
88338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
89338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
90338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Error finding app with signature "application/x-vnd.InvalidSignature" (Application could not be found)
91338b8dc3SIngo Weinhold	Nov 28 01:40:45 instantiate_object failed: Application could not be found (8000200b)
92338b8dc3SIngo Weinhold*/
93338b8dc3SIngo Weinhold
94338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
95338b8dc3SIngo WeinholdBArchivable::BArchivable()
96338b8dc3SIngo Weinhold{
97338b8dc3SIngo Weinhold	;
98338b8dc3SIngo Weinhold}
99338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
100338b8dc3SIngo WeinholdBArchivable::BArchivable(BMessage* from)
101338b8dc3SIngo Weinhold{
102338b8dc3SIngo Weinhold	;
103338b8dc3SIngo Weinhold}
104338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
105338b8dc3SIngo WeinholdBArchivable::~BArchivable()
106338b8dc3SIngo Weinhold{
107338b8dc3SIngo Weinhold	;
108338b8dc3SIngo Weinhold}
109338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
110338b8dc3SIngo Weinholdstatus_t BArchivable::Archive(BMessage* into, bool deep) const
111338b8dc3SIngo Weinhold{
112338b8dc3SIngo Weinhold	if (!into)
113338b8dc3SIngo Weinhold	{
114338b8dc3SIngo Weinhold		// TODO: logging/other error reporting?
115338b8dc3SIngo Weinhold		return B_BAD_VALUE;
116338b8dc3SIngo Weinhold	}
117338b8dc3SIngo Weinhold
118338b8dc3SIngo Weinhold	BString name;
119338b8dc3SIngo Weinhold	Demangle(typeid(*this).name(), name);
120338b8dc3SIngo Weinhold
121338b8dc3SIngo Weinhold	return into->AddString(B_CLASS_FIELD, name);
122338b8dc3SIngo Weinhold}
123338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
124338b8dc3SIngo WeinholdBArchivable* BArchivable::Instantiate(BMessage* from)
125338b8dc3SIngo Weinhold{
126338b8dc3SIngo Weinhold	debugger("Can't create a plain BArchivable object");
127338b8dc3SIngo Weinhold	return NULL;
128338b8dc3SIngo Weinhold}
129338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
130338b8dc3SIngo Weinholdstatus_t BArchivable::Perform(perform_code d, void* arg)
131338b8dc3SIngo Weinhold{
132338b8dc3SIngo Weinhold	// TODO: Check against original
133338b8dc3SIngo Weinhold	return B_ERROR;
134338b8dc3SIngo Weinhold}
135338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
136338b8dc3SIngo Weinholdvoid BArchivable::_ReservedArchivable1()
137338b8dc3SIngo Weinhold{
138338b8dc3SIngo Weinhold	;
139338b8dc3SIngo Weinhold}
140338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
141338b8dc3SIngo Weinholdvoid BArchivable::_ReservedArchivable2()
142338b8dc3SIngo Weinhold{
143338b8dc3SIngo Weinhold	;
144338b8dc3SIngo Weinhold}
145338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
146338b8dc3SIngo Weinholdvoid BArchivable::_ReservedArchivable3()
147338b8dc3SIngo Weinhold{
148338b8dc3SIngo Weinhold	;
149338b8dc3SIngo Weinhold}
150338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
151338b8dc3SIngo Weinholdvoid BuildFuncName(const char* className, BString& funcName)
152338b8dc3SIngo Weinhold{
153338b8dc3SIngo Weinhold	funcName = "";
154338b8dc3SIngo Weinhold
155338b8dc3SIngo Weinhold	//	This is what we're after:
156338b8dc3SIngo Weinhold	//		Instantiate__Q28OpenBeOS11BArchivableP8BMessage
157338b8dc3SIngo Weinhold	Mangle(className, funcName);
158338b8dc3SIngo Weinhold	funcName.Prepend("Instantiate__");
159338b8dc3SIngo Weinhold	funcName.Append("P8BMessage");
160338b8dc3SIngo Weinhold}
161338b8dc3SIngo Weinhold
162338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
163338b8dc3SIngo Weinholdbool validate_instantiation(BMessage* from, const char* class_name)
164338b8dc3SIngo Weinhold{
165338b8dc3SIngo Weinhold	errno = B_OK;
166338b8dc3SIngo Weinhold
167338b8dc3SIngo Weinhold	// Make sure our params are kosher -- original skimped here =P
168338b8dc3SIngo Weinhold	if (!from)
169338b8dc3SIngo Weinhold	{
170338b8dc3SIngo Weinhold		// Not standard; Be implementation has a segment
171338b8dc3SIngo Weinhold		// violation on this error mode
172338b8dc3SIngo Weinhold		errno = B_BAD_VALUE;
173338b8dc3SIngo Weinhold
174338b8dc3SIngo Weinhold		return false;
175338b8dc3SIngo Weinhold	}
176338b8dc3SIngo Weinhold
177338b8dc3SIngo Weinhold	status_t err = B_OK;
178338b8dc3SIngo Weinhold	const char* data;
179338b8dc3SIngo Weinhold	for (int32 index = 0; err == B_OK; ++index)
180338b8dc3SIngo Weinhold	{
181338b8dc3SIngo Weinhold		err = from->FindString(B_CLASS_FIELD, index, &data);
182338b8dc3SIngo Weinhold		if (!err && strcmp(data, class_name) == 0)
183338b8dc3SIngo Weinhold		{
184338b8dc3SIngo Weinhold			return true;
185338b8dc3SIngo Weinhold		}
186338b8dc3SIngo Weinhold	}
187338b8dc3SIngo Weinhold
188338b8dc3SIngo Weinhold	errno = B_MISMATCHED_VALUES;
189338b8dc3SIngo Weinhold	syslog(LOG_ERR, "validate_instantiation failed on class %s.", class_name);
190338b8dc3SIngo Weinhold
191338b8dc3SIngo Weinhold	return false;
192338b8dc3SIngo Weinhold}
193338b8dc3SIngo Weinhold
194338b8dc3SIngo Weinhold
195338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
196338b8dc3SIngo Weinholdint GetNumber(const char*& name)
197338b8dc3SIngo Weinhold{
198338b8dc3SIngo Weinhold	int val = atoi(name);
199338b8dc3SIngo Weinhold	while (isdigit(*name))
200338b8dc3SIngo Weinhold	{
201338b8dc3SIngo Weinhold		++name;
202338b8dc3SIngo Weinhold	}
203338b8dc3SIngo Weinhold
204338b8dc3SIngo Weinhold	return val;
205338b8dc3SIngo Weinhold}
206338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
207338b8dc3SIngo Weinholdvoid Demangle(const char* name, BString& out)
208338b8dc3SIngo Weinhold{
209338b8dc3SIngo Weinhold// TODO: add support for template classes
210338b8dc3SIngo Weinhold//	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
211338b8dc3SIngo Weinhold
212338b8dc3SIngo Weinhold	out = "";
213338b8dc3SIngo Weinhold
214338b8dc3SIngo Weinhold	// Are we in a namespace?
215338b8dc3SIngo Weinhold	if (*name == 'Q')
216338b8dc3SIngo Weinhold	{
217338b8dc3SIngo Weinhold		// Yessir, we are; how many deep are we?
218338b8dc3SIngo Weinhold		int nsCount = 0;
219338b8dc3SIngo Weinhold		++name;
220338b8dc3SIngo Weinhold		if (*name == '_')	// more than 10 deep
221338b8dc3SIngo Weinhold		{
222338b8dc3SIngo Weinhold			++name;
223338b8dc3SIngo Weinhold			if (!isdigit(*name))
224338b8dc3SIngo Weinhold				;	// TODO: error handling
225338b8dc3SIngo Weinhold
226338b8dc3SIngo Weinhold			nsCount = GetNumber(name);
227338b8dc3SIngo Weinhold			if (*name == '_')	// more than 10 deep
228338b8dc3SIngo Weinhold				++name;
229338b8dc3SIngo Weinhold			else
230338b8dc3SIngo Weinhold				;	// this should be an error condition
231338b8dc3SIngo Weinhold		}
232338b8dc3SIngo Weinhold		else
233338b8dc3SIngo Weinhold		{
234338b8dc3SIngo Weinhold			nsCount = *name - '0';
235338b8dc3SIngo Weinhold			++name;
236338b8dc3SIngo Weinhold		}
237338b8dc3SIngo Weinhold
238338b8dc3SIngo Weinhold		int nameLen = 0;
239338b8dc3SIngo Weinhold		for (int i = 0; i < nsCount - 1; ++i)
240338b8dc3SIngo Weinhold		{
241338b8dc3SIngo Weinhold			if (!isdigit(*name))
242338b8dc3SIngo Weinhold				;	// TODO: error handling
243338b8dc3SIngo Weinhold
244338b8dc3SIngo Weinhold			nameLen = GetNumber(name);
245338b8dc3SIngo Weinhold			out.Append(name, nameLen);
246338b8dc3SIngo Weinhold			out += "::";
247338b8dc3SIngo Weinhold			name += nameLen;
248338b8dc3SIngo Weinhold		}
249338b8dc3SIngo Weinhold	}
250338b8dc3SIngo Weinhold
251338b8dc3SIngo Weinhold	out.Append(name, GetNumber(name));
252338b8dc3SIngo Weinhold}
253338b8dc3SIngo Weinhold//------------------------------------------------------------------------------
254338b8dc3SIngo Weinholdvoid Mangle(const char* name, BString& out)
255338b8dc3SIngo Weinhold{
256338b8dc3SIngo Weinhold// TODO: add support for template classes
257338b8dc3SIngo Weinhold//	_find__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCccUlUl
258338b8dc3SIngo Weinhold
259338b8dc3SIngo Weinhold	//	Chop this:
260338b8dc3SIngo Weinhold	//		testthree::testfour::Testthree::Testfour
261338b8dc3SIngo Weinhold	//	up into little bite-sized pieces
262338b8dc3SIngo Weinhold	int count = 0;
263338b8dc3SIngo Weinhold	string origName(name);
264338b8dc3SIngo Weinhold	vector<string> spacenames;
265338b8dc3SIngo Weinhold
266338b8dc3SIngo Weinhold	string::size_type pos = 0;
267338b8dc3SIngo Weinhold	string::size_type oldpos = 0;
268338b8dc3SIngo Weinhold	while (pos != string::npos)
269338b8dc3SIngo Weinhold	{
270338b8dc3SIngo Weinhold		pos = origName.find_first_of("::", oldpos);
271338b8dc3SIngo Weinhold		spacenames.push_back(string(origName, oldpos, pos - oldpos));
272338b8dc3SIngo Weinhold		pos = origName.find_first_not_of("::", pos);
273338b8dc3SIngo Weinhold		oldpos = pos;
274338b8dc3SIngo Weinhold		++count;
275338b8dc3SIngo Weinhold	}
276338b8dc3SIngo Weinhold
277338b8dc3SIngo Weinhold	//	Now mangle it into this:
278338b8dc3SIngo Weinhold	//		Q49testthree8testfour9Testthree8Testfour
279338b8dc3SIngo Weinhold	out = "";
280338b8dc3SIngo Weinhold	if (count > 1)
281338b8dc3SIngo Weinhold	{
282338b8dc3SIngo Weinhold		out += 'Q';
283338b8dc3SIngo Weinhold		if (count > 10)
284338b8dc3SIngo Weinhold			out += '_';
285338b8dc3SIngo Weinhold		out << count;
286338b8dc3SIngo Weinhold		if (count > 10)
287338b8dc3SIngo Weinhold			out += '_';
288338b8dc3SIngo Weinhold	}
289338b8dc3SIngo Weinhold
290338b8dc3SIngo Weinhold	for (unsigned int i = 0; i < spacenames.size(); ++i)
291338b8dc3SIngo Weinhold	{
292338b8dc3SIngo Weinhold		out << (int)spacenames[i].length();
293338b8dc3SIngo Weinhold		out += spacenames[i].c_str();
294338b8dc3SIngo Weinhold	}
295338b8dc3SIngo Weinhold}
296338b8dc3SIngo Weinhold
297338b8dc3SIngo Weinhold
298338b8dc3SIngo Weinhold/*
299338b8dc3SIngo Weinhold * $Log $
300338b8dc3SIngo Weinhold *
301338b8dc3SIngo Weinhold * $Id  $
302338b8dc3SIngo Weinhold *
303338b8dc3SIngo Weinhold */
304338b8dc3SIngo Weinhold
305