xref: /haiku/src/kits/storage/AppFileInfo.cpp (revision b289aaf66bbf6e173aa90fa194fc256965f1b34d)
1 /*
2  * Copyright 2002-2007, Haiku Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ingo Weinhold, bonefish@users.sf.net
7  */
8 
9 
10 #include <new>
11 #include <set>
12 #include <stdlib.h>
13 #include <string>
14 
15 #include <AppFileInfo.h>
16 #include <Bitmap.h>
17 #include <File.h>
18 #include <fs_attr.h>
19 #include <IconUtils.h>
20 #include <MimeType.h>
21 #include <RegistrarDefs.h>
22 #include <Resources.h>
23 #include <Roster.h>
24 #include <String.h>
25 
26 using namespace std;
27 
28 // attributes
29 static const char *kTypeAttribute				= "BEOS:TYPE";
30 static const char *kSignatureAttribute			= "BEOS:APP_SIG";
31 static const char *kAppFlagsAttribute			= "BEOS:APP_FLAGS";
32 static const char *kSupportedTypesAttribute		= "BEOS:FILE_TYPES";
33 static const char *kVersionInfoAttribute		= "BEOS:APP_VERSION";
34 static const char *kMiniIconAttribute			= "BEOS:M:";
35 static const char *kLargeIconAttribute			= "BEOS:L:";
36 static const char *kIconAttribute				= "BEOS:";
37 static const char *kStandardIconType			= "STD_ICON";
38 static const char *kIconType					= "ICON";
39 
40 // resource IDs
41 static const int32 kTypeResourceID				= 2;
42 static const int32 kSignatureResourceID			= 1;
43 static const int32 kAppFlagsResourceID			= 1;
44 static const int32 kSupportedTypesResourceID	= 1;
45 static const int32 kMiniIconResourceID			= 101;
46 static const int32 kLargeIconResourceID			= 101;
47 static const int32 kIconResourceID				= 101;
48 static const int32 kVersionInfoResourceID		= 1;
49 static const int32 kMiniIconForTypeResourceID	= 0;
50 static const int32 kLargeIconForTypeResourceID	= 0;
51 static const int32 kIconForTypeResourceID		= 0;
52 
53 // type codes
54 enum {
55 	B_APP_FLAGS_TYPE	= 'APPF',
56 	B_VERSION_INFO_TYPE	= 'APPV',
57 };
58 
59 // R5 also exports these (Tracker is using them):
60 // (maybe we better want to drop them silently and declare
61 // the above in a public Haiku header - and use that one in
62 // Tracker when compiled for Haiku)
63 extern const uint32 MINI_ICON_TYPE, LARGE_ICON_TYPE;
64 const uint32 MINI_ICON_TYPE = 'MICN';
65 const uint32 LARGE_ICON_TYPE = 'ICON';
66 
67 // debugging
68 //#define DBG(x) x
69 #define DBG(x)
70 #define OUT	printf
71 
72 // constructor
73 /*!	\brief Creates an uninitialized BAppFileInfo object.
74 */
75 BAppFileInfo::BAppFileInfo()
76 	: fResources(NULL),
77 	fWhere(B_USE_BOTH_LOCATIONS)
78 {
79 }
80 
81 // constructor
82 /*!	\brief Creates an BAppFileInfo object and initializes it to the supplied
83 		   file.
84 
85 	The caller retains ownership of the supplied BFile object. It must not
86 	be deleted during the life time of the BAppFileInfo. It is not deleted
87 	when the BAppFileInfo is destroyed.
88 
89 	\param file The file the object shall be initialized to.
90 */
91 BAppFileInfo::BAppFileInfo(BFile *file)
92 	: fResources(NULL),
93 	fWhere(B_USE_BOTH_LOCATIONS)
94 {
95 	SetTo(file);
96 }
97 
98 // destructor
99 /*!	\brief Frees all resources associated with this object.
100 
101 	The BFile the object is set to is not deleted.
102 */
103 BAppFileInfo::~BAppFileInfo()
104 {
105 	delete fResources;
106 }
107 
108 // SetTo
109 /*!	\brief Initializes the BAppFileInfo to the supplied file.
110 
111 	The caller retains ownership of the supplied BFile object. It must not
112 	be deleted during the life time of the BAppFileInfo. It is not deleted
113 	when the BAppFileInfo is destroyed.
114 
115 	\param file The file the object shall be initialized to.
116 
117 	\return
118 	- \c B_OK: Everything went fine.
119 	- \c B_BAD_VALUE: \c NULL \a file or \a file is not properly initialized.
120 */
121 status_t
122 BAppFileInfo::SetTo(BFile *file)
123 {
124 	// unset the old file
125 	BNodeInfo::SetTo(NULL);
126 	if (fResources) {
127 		delete fResources;
128 		fResources = NULL;
129 	}
130 
131 	// check param
132 	status_t error = (file && file->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
133 
134 	info_location where = B_USE_BOTH_LOCATIONS;
135 
136 	// create resources
137 	if (error == B_OK) {
138 		fResources = new(nothrow) BResources();
139 		if (fResources) {
140 			error = fResources->SetTo(file);
141 			if (error != B_OK) {
142 				// no resources - this is no critical error, we'll just use
143 				// attributes only, then
144 				where = B_USE_ATTRIBUTES;
145 				error = B_OK;
146 			}
147 		} else
148 			error = B_NO_MEMORY;
149 	}
150 
151 	// set node info
152 	if (error == B_OK)
153 		error = BNodeInfo::SetTo(file);
154 
155 	if (error != B_OK || (where & B_USE_RESOURCES) == 0) {
156 		delete fResources;
157 		fResources = NULL;
158 	}
159 
160 	// clean up on error
161 	if (error != B_OK) {
162 		if (InitCheck() == B_OK)
163 			BNodeInfo::SetTo(NULL);
164 	}
165 
166 	// set data location
167 	if (error == B_OK)
168 		SetInfoLocation(where);
169 
170 	// set error
171 	fCStatus = error;
172 	return error;
173 }
174 
175 // GetType
176 /*!	\brief Gets the file's MIME type.
177 
178 	\param type A pointer to a pre-allocated character buffer of size
179 		   \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the
180 		   file shall be written.
181 	\return
182 	- \c B_OK: Everything went fine.
183 	- \c B_NO_INIT: The object is not properly initialized.
184 	- \c B_BAD_VALUE: \c NULL \a type or the type string stored in the
185 	  attribute/resources is longer than \c B_MIME_TYPE_LENGTH.
186 	- \c B_BAD_TYPE: The attribute/resources the type string is stored in have
187 	  the wrong type.
188 	- \c B_ENTRY_NOT_FOUND: No type is set on the file.
189 	- other error codes
190 */
191 status_t
192 BAppFileInfo::GetType(char *type) const
193 {
194 	// check param and initialization
195 	status_t error = (type ? B_OK : B_BAD_VALUE);
196 	if (error == B_OK && InitCheck() != B_OK)
197 		error = B_NO_INIT;
198 	// read the data
199 	size_t read = 0;
200 	if (error == B_OK) {
201 		error = _ReadData(kTypeAttribute, kTypeResourceID, B_MIME_STRING_TYPE,
202 						  type, B_MIME_TYPE_LENGTH, read);
203 	}
204 	// check the read data -- null terminate the string
205 	if (error == B_OK && type[read - 1] != '\0') {
206 		if (read == B_MIME_TYPE_LENGTH)
207 			error = B_ERROR;
208 		else
209 			type[read] = '\0';
210 	}
211 	return error;
212 }
213 
214 // SetType
215 /*!	\brief Sets the file's MIME type.
216 
217 	If \a type is \c NULL the file's MIME type is unset.
218 
219 	\param type The MIME type to be assigned to the file. Must not be longer
220 		   than \c B_MIME_TYPE_LENGTH (including the terminating null).
221 		   May be \c NULL.
222 	\return
223 	- \c B_OK: Everything went fine.
224 	- \c B_NO_INIT: The object is not properly initialized.
225 	- \c B_BAD_VALUE: \a type is longer than \c B_MIME_TYPE_LENGTH.
226 	- other error codes
227 */
228 status_t
229 BAppFileInfo::SetType(const char *type)
230 {
231 	// check initialization
232 	status_t error = B_OK;
233 	if (error == B_OK && InitCheck() != B_OK)
234 		error = B_NO_INIT;
235 	if (error == B_OK) {
236 		if (type) {
237 			// check param
238 			size_t typeLen = strlen(type);
239 			if (error == B_OK && typeLen >= B_MIME_TYPE_LENGTH)
240 				error = B_BAD_VALUE;
241 			// write the data
242 			if (error == B_OK) {
243 				error = _WriteData(kTypeAttribute, kTypeResourceID,
244 								   B_MIME_STRING_TYPE, type, typeLen + 1);
245 			}
246 		} else
247 			error = _RemoveData(kTypeAttribute, B_MIME_STRING_TYPE);
248 	}
249 	return error;
250 }
251 
252 // GetSignature
253 /*!	\brief Gets the file's application signature.
254 
255 	\param signature A pointer to a pre-allocated character buffer of size
256 		   \c B_MIME_TYPE_LENGTH or larger into which the application
257 		   signature of the file shall be written.
258 	\return
259 	- \c B_OK: Everything went fine.
260 	- \c B_NO_INIT: The object is not properly initialized.
261 	- \c B_BAD_VALUE: \c NULL \a signature or the signature stored in the
262 	  attribute/resources is longer than \c B_MIME_TYPE_LENGTH.
263 	- \c B_BAD_TYPE: The attribute/resources the signature is stored in have
264 	  the wrong type.
265 	- \c B_ENTRY_NOT_FOUND: No signature is set on the file.
266 	- other error codes
267 */
268 status_t
269 BAppFileInfo::GetSignature(char *signature) const
270 {
271 	// check param and initialization
272 	status_t error = (signature ? B_OK : B_BAD_VALUE);
273 	if (error == B_OK && InitCheck() != B_OK)
274 		error = B_NO_INIT;
275 	// read the data
276 	size_t read = 0;
277 	if (error == B_OK) {
278 		error = _ReadData(kSignatureAttribute, kSignatureResourceID,
279 						  B_MIME_STRING_TYPE, signature, B_MIME_TYPE_LENGTH,
280 						  read);
281 	}
282 	// check the read data -- null terminate the string
283 	if (error == B_OK && signature[read - 1] != '\0') {
284 		if (read == B_MIME_TYPE_LENGTH)
285 			error = B_ERROR;
286 		else
287 			signature[read] = '\0';
288 	}
289 	return error;
290 }
291 
292 // SetSignature
293 /*!	\brief Sets the file's application signature.
294 
295 	If \a signature is \c NULL the file's application signature is unset.
296 
297 	\param signature The application signature to be assigned to the file.
298 		   Must not be longer than \c B_MIME_TYPE_LENGTH (including the
299 		   terminating null). May be \c NULL.
300 	\return
301 	- \c B_OK: Everything went fine.
302 	- \c B_NO_INIT: The object is not properly initialized.
303 	- \c B_BAD_VALUE: \a signature is longer than \c B_MIME_TYPE_LENGTH.
304 	- other error codes
305 */
306 status_t
307 BAppFileInfo::SetSignature(const char *signature)
308 {
309 	// check initialization
310 	status_t error = B_OK;
311 	if (error == B_OK && InitCheck() != B_OK)
312 		error = B_NO_INIT;
313 	if (error == B_OK) {
314 		if (signature) {
315 			// check param
316 			size_t signatureLen = strlen(signature);
317 			if (error == B_OK && signatureLen >= B_MIME_TYPE_LENGTH)
318 				error = B_BAD_VALUE;
319 			// write the data
320 			if (error == B_OK) {
321 				error = _WriteData(kSignatureAttribute, kSignatureResourceID,
322 								   B_MIME_STRING_TYPE, signature,
323 								   signatureLen + 1);
324 			}
325 		} else
326 			error = _RemoveData(kSignatureAttribute, B_MIME_STRING_TYPE);
327 	}
328 	return error;
329 }
330 
331 // GetAppFlags
332 /*!	\brief Gets the file's application flags.
333 
334 	\param flags A pointer to a pre-allocated uint32 into which the application
335 		   flags of the file shall be written.
336 	\return
337 	- \c B_OK: Everything went fine.
338 	- \c B_NO_INIT: The object is not properly initialized.
339 	- \c B_BAD_VALUE: \c NULL \a flags.
340 	- \c B_BAD_TYPE: The attribute/resources the flags are stored in have
341 	  the wrong type.
342 	- \c B_ENTRY_NOT_FOUND: No application flags are set on the file.
343 	- other error codes
344 */
345 status_t
346 BAppFileInfo::GetAppFlags(uint32 *flags) const
347 {
348 	// check param and initialization
349 	status_t error = (flags ? B_OK : B_BAD_VALUE);
350 	if (error == B_OK && InitCheck() != B_OK)
351 		error = B_NO_INIT;
352 	// read the data
353 	size_t read = 0;
354 	if (error == B_OK) {
355 		error = _ReadData(kAppFlagsAttribute, kAppFlagsResourceID,
356 						  B_APP_FLAGS_TYPE, flags, sizeof(uint32),
357 						  read);
358 	}
359 	// check the read data
360 	if (error == B_OK && read != sizeof(uint32))
361 		error = B_ERROR;
362 	return error;
363 }
364 
365 // SetAppFlags
366 /*!	\brief Sets the file's application flags.
367 	\param flags The application flags to be assigned to the file.
368 	\return
369 	- \c B_OK: Everything went fine.
370 	- \c B_NO_INIT: The object is not properly initialized.
371 	- other error codes
372 */
373 status_t
374 BAppFileInfo::SetAppFlags(uint32 flags)
375 {
376 	// check initialization
377 	status_t error = B_OK;
378 	if (error == B_OK && InitCheck() != B_OK)
379 		error = B_NO_INIT;
380 	if (error == B_OK) {
381 		// write the data
382 		error = _WriteData(kAppFlagsAttribute, kAppFlagsResourceID,
383 						   B_APP_FLAGS_TYPE, &flags, sizeof(uint32));
384 	}
385 	return error;
386 }
387 
388 // RemoveAppFlags
389 /*!	\brief Removes the file's application flags.
390 	\return
391 	- \c B_OK: Everything went fine.
392 	- \c B_NO_INIT: The object is not properly initialized.
393 	- other error codes
394 */
395 status_t
396 BAppFileInfo::RemoveAppFlags()
397 {
398 	// check initialization
399 	status_t error = B_OK;
400 	if (error == B_OK && InitCheck() != B_OK)
401 		error = B_NO_INIT;
402 	if (error == B_OK) {
403 		// remove the data
404 		error = _RemoveData(kAppFlagsAttribute, B_APP_FLAGS_TYPE);
405 	}
406 	return error;
407 }
408 
409 // GetSupportedTypes
410 /*!	\brief Gets the MIME types supported by the application.
411 
412 	The supported MIME types are added to a field "types" of type
413 	\c B_STRING_TYPE in \a types.
414 
415 	\param types A pointer to a pre-allocated BMessage into which the
416 		   MIME types supported by the appplication shall be written.
417 	\return
418 	- \c B_OK: Everything went fine.
419 	- \c B_NO_INIT: The object is not properly initialized.
420 	- \c B_BAD_VALUE: \c NULL \a types.
421 	- \c B_BAD_TYPE: The attribute/resources the supported types are stored in
422 	  have the wrong type.
423 	- \c B_ENTRY_NOT_FOUND: No supported types are set on the file.
424 	- other error codes
425 */
426 status_t
427 BAppFileInfo::GetSupportedTypes(BMessage *types) const
428 {
429 	// check param and initialization
430 	status_t error = (types ? B_OK : B_BAD_VALUE);
431 	if (error == B_OK && InitCheck() != B_OK)
432 		error = B_NO_INIT;
433 	// read the data
434 	size_t read = 0;
435 	void *buffer = NULL;
436 	if (error == B_OK) {
437 		error = _ReadData(kSupportedTypesAttribute, kSupportedTypesResourceID,
438 						  B_MESSAGE_TYPE, NULL, 0, read, &buffer);
439 	}
440 	// unflatten the buffer
441 	if (error == B_OK)
442 		error = types->Unflatten((const char*)buffer);
443 	// clean up
444 	free(buffer);
445 	return error;
446 }
447 
448 // SetSupportedTypes
449 /*!	\brief Sets the MIME types supported by the application.
450 
451 	If \a types is \c NULL the application's supported types are unset.
452 
453 	The supported MIME types must be stored in a field "types" of type
454 	\c B_STRING_TYPE in \a types.
455 
456 	The method informs the registrar about this news.
457 	For each supported type the result of BMimeType::GetSupportingApps() will
458 	afterwards include the signature of this application. That is, the
459 	application file needs to have a signature set.
460 
461 	\a syncAll specifies whether the not longer supported types shall be
462 	updated as well, i.e. whether this application shall be remove from the
463 	lists of supporting applications.
464 
465 	\param types The supported types to be assigned to the file.
466 		   May be \c NULL.
467 	\param syncAll \c true to also synchronize the not longer supported
468 		   types, \c false otherwise.
469 	\return
470 	- \c B_OK: Everything went fine.
471 	- \c B_NO_INIT: The object is not properly initialized.
472 	- other error codes
473 */
474 status_t
475 BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
476 {
477 	// check initialization
478 	status_t error = B_OK;
479 	if (error == B_OK && InitCheck() != B_OK)
480 		error = B_NO_INIT;
481 	BMimeType mimeType;
482 	if (error == B_OK)
483 		error = GetMetaMime(&mimeType);
484 	if (error == B_OK || error == B_ENTRY_NOT_FOUND) {
485 		error = B_OK;
486 		if (types) {
487 			// check param -- supported types must be valid
488 			const char *type;
489 			for (int32 i = 0;
490 				 error == B_OK && types->FindString("types", i, &type) == B_OK;
491 				 i++) {
492 				if (!BMimeType::IsValid(type))
493 					error = B_BAD_VALUE;
494 			}
495 			// get flattened size
496 			ssize_t size = 0;
497 			if (error == B_OK) {
498 				size = types->FlattenedSize();
499 				if (size < 0)
500 					error = size;
501 			}
502 			// allocate a buffer for the flattened data
503 			char *buffer = NULL;
504 			if (error == B_OK) {
505 				buffer = new(nothrow) char[size];
506 				if (!buffer)
507 					error = B_NO_MEMORY;
508 			}
509 			// flatten the message
510 			if (error == B_OK)
511 				error = types->Flatten(buffer, size);
512 			// write the data
513 			if (error == B_OK) {
514 				error = _WriteData(kSupportedTypesAttribute,
515 								   kSupportedTypesResourceID, B_MESSAGE_TYPE,
516 								   buffer, size);
517 			}
518 			// clean up
519 			delete[] buffer;
520 		} else
521 			error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE);
522 		// update the MIME database, if the app signature is installed
523 		if (error == B_OK && mimeType.IsInstalled())
524 			error = mimeType.SetSupportedTypes(types, syncAll);
525 	}
526 	return error;
527 }
528 
529 // SetSupportedTypes
530 /*!	\brief Sets the MIME types supported by the application.
531 
532 	This method is a short-hand for SetSupportedTypes(types, false).
533 	\see SetSupportedType(const BMessage*, bool) for detailed information.
534 
535 	\param types The supported types to be assigned to the file.
536 		   May be \c NULL.
537 	\return
538 	- \c B_OK: Everything went fine.
539 	- \c B_NO_INIT: The object is not properly initialized.
540 	- other error codes
541 */
542 status_t
543 BAppFileInfo::SetSupportedTypes(const BMessage *types)
544 {
545 	return SetSupportedTypes(types, false);
546 }
547 
548 // IsSupportedType
549 /*!	\brief Returns whether the application supports the supplied MIME type.
550 
551 	If the application supports the wildcard type "application/octet-stream"
552 	any this method returns \c true for any MIME type.
553 
554 	\param type The MIME type in question.
555 	\return \c true, if \a type is a valid MIME type and it is supported by
556 			the application, \c false otherwise.
557 */
558 bool
559 BAppFileInfo::IsSupportedType(const char *type) const
560 {
561 	status_t error = (type ? B_OK : B_BAD_VALUE);
562 	// get the supported types
563 	BMessage types;
564 	if (error == B_OK)
565 		error = GetSupportedTypes(&types);
566 	// turn type into a BMimeType
567 	BMimeType mimeType;
568 	if (error == B_OK)
569 		error = mimeType.SetTo(type);
570 	// iterate through the supported types
571 	bool found = false;
572 	if (error == B_OK) {
573 		const char *supportedType;
574 		for (int32 i = 0;
575 			 !found && types.FindString("types", i, &supportedType) == B_OK;
576 			 i++) {
577 			found = !strcmp(supportedType, "application/octet-stream")
578 					|| BMimeType(supportedType).Contains(&mimeType);
579 		}
580 	}
581 	return found;
582 }
583 
584 // Supports
585 /*!	\brief Returns whether the application supports the supplied MIME type
586 		   explicitly.
587 
588 	Unlike IsSupportedType(), this method returns \c true, only if the type
589 	is explicitly supported, regardless of whether it supports
590 	"application/octet-stream".
591 
592 	\param type The MIME type in question.
593 	\return \c true, if \a type is a valid MIME type and it is explicitly
594 			supported by the application, \c false otherwise.
595 */
596 bool
597 BAppFileInfo::Supports(BMimeType *type) const
598 {
599 	status_t error = (type && type->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
600 	// get the supported types
601 	BMessage types;
602 	if (error == B_OK)
603 		error = GetSupportedTypes(&types);
604 	// iterate through the supported types
605 	bool found = false;
606 	if (error == B_OK) {
607 		const char *supportedType;
608 		for (int32 i = 0;
609 			 !found && types.FindString("types", i, &supportedType) == B_OK;
610 			 i++) {
611 			found = BMimeType(supportedType).Contains(type);
612 		}
613 	}
614 	return found;
615 }
616 
617 // GetIcon
618 /*!	\brief Gets the file's icon.
619 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
620 		   to store the requested icon (16x16 for the mini and 32x32 for the
621 		   large icon).
622 	\param which Specifies the size of the icon to be retrieved:
623 		   \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon.
624 	\return
625 	- \c B_OK: Everything went fine.
626 	- \c B_NO_INIT: The object is not properly initialized.
627 	- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a which or bitmap
628 		 dimensions (\a icon) and icon size (\a which) do not match.
629 	- other error codes
630 */
631 status_t
632 BAppFileInfo::GetIcon(BBitmap *icon, icon_size which) const
633 {
634 	return GetIconForType(NULL, icon, which);
635 }
636 
637 // GetIcon
638 /*!	\brief Gets the file's icon.
639 	\param data The pointer in which the flat icon data will be returned.
640 	\param size The pointer in which the size of the data found will be returned.
641 	\return
642 	- \c B_OK: Everything went fine.
643 	- \c B_NO_INIT: The object is not properly initialized.
644 	- \c B_BAD_VALUE: \c NULL \a data or \c NULL size.
645 	- other error codes
646 */
647 status_t
648 BAppFileInfo::GetIcon(uint8** data, size_t* size) const
649 {
650 	return GetIconForType(NULL, data, size);
651 }
652 
653 // SetIcon
654 /*!	\brief Sets the file's icon.
655 
656 	If \a icon is \c NULL the file's icon is unset.
657 
658 	\param icon A pointer to the BBitmap containing the icon to be set.
659 		   May be \c NULL.
660 	\param which Specifies the size of the icon to be set: \c B_MINI_ICON
661 		   for the mini and \c B_LARGE_ICON for the large icon.
662 	\return
663 	- \c B_OK: Everything went fine.
664 	- \c B_NO_INIT: The object is not properly initialized.
665 	- \c B_BAD_VALUE: Unknown icon size \a which or bitmap dimensions (\a icon)
666 		 and icon size (\a which) do not match.
667 	- other error codes
668 */
669 status_t
670 BAppFileInfo::SetIcon(const BBitmap *icon, icon_size which)
671 {
672 	return SetIconForType(NULL, icon, which);
673 }
674 
675 // SetIcon
676 /*!	\brief Sets the file's icon.
677 
678 	If \a icon is \c NULL the file's icon is unset.
679 
680 	\param data A pointer to the data buffer containing the vector icon
681 		   to be set. May be \c NULL.
682 	\param size Specifies the size of buffer pointed to by \a data.
683 	\return
684 	- \c B_OK: Everything went fine.
685 	- \c B_NO_INIT: The object is not properly initialized.
686 	- \c B_BAD_VALUE: \c NULL data.
687 	- other error codes
688 */
689 status_t
690 BAppFileInfo::SetIcon(const uint8* data, size_t size)
691 {
692 	return SetIconForType(NULL, data, size);
693 }
694 
695 // GetVersionInfo
696 /*!	\brief Gets the file's version info.
697 	\param info A pointer to a pre-allocated version_info structure into which
698 		   the version info should be written.
699 	\param kind Specifies the kind of the version info to be retrieved:
700 		   \c B_APP_VERSION_KIND for the application's version info and
701 		   \c B_SYSTEM_VERSION_KIND for the suite's info the application
702 		   belongs to.
703 	\return
704 	- \c B_OK: Everything went fine.
705 	- \c B_NO_INIT: The object is not properly initialized.
706 	- \c B_BAD_VALUE: \c NULL \a info.
707 	- other error codes
708 */
709 status_t
710 BAppFileInfo::GetVersionInfo(version_info *info, version_kind kind) const
711 {
712 	// check params and initialization
713 	if (!info)
714 		return B_BAD_VALUE;
715 
716 	int32 index = 0;
717 	switch (kind) {
718 		case B_APP_VERSION_KIND:
719 			index = 0;
720 			break;
721 		case B_SYSTEM_VERSION_KIND:
722 			index = 1;
723 			break;
724 		default:
725 			return B_BAD_VALUE;
726 	}
727 
728 	if (InitCheck() != B_OK)
729 		return B_NO_INIT;
730 
731 	// read the data
732 	size_t read = 0;
733 	version_info infos[2];
734 	status_t error = _ReadData(kVersionInfoAttribute, kVersionInfoResourceID,
735 		B_VERSION_INFO_TYPE, infos, 2 * sizeof(version_info), read);
736 	if (error != B_OK)
737 		return error;
738 
739 	// check the read data
740 	if (read == sizeof(version_info)) {
741 		// only the app version info is there -- return a cleared system info
742 		if (index == 0)
743 			*info = infos[index];
744 		else if (index == 1)
745 			memset(info, 0, sizeof(version_info));
746 	} else if (read == 2 * sizeof(version_info)) {
747 		*info = infos[index];
748 	} else
749 		return B_ERROR;
750 
751 	// return result
752 	return B_OK;
753 }
754 
755 // SetVersionInfo
756 /*!	\brief Sets the file's version info.
757 
758 	If \a info is \c NULL the file's version info is unset.
759 
760 	\param info The version info to be set. May be \c NULL.
761 	\param kind Specifies kind of version info to be set:
762 		   \c B_APP_VERSION_KIND for the application's version info and
763 		   \c B_SYSTEM_VERSION_KIND for the suite's info the application
764 		   belongs to.
765 	\return
766 	- \c B_OK: Everything went fine.
767 	- \c B_NO_INIT: The object is not properly initialized.
768 	- other error codes
769 */
770 status_t
771 BAppFileInfo::SetVersionInfo(const version_info *info, version_kind kind)
772 {
773 	// check initialization
774 	status_t error = B_OK;
775 	if (error == B_OK && InitCheck() != B_OK)
776 		error = B_NO_INIT;
777 	if (error == B_OK) {
778 		if (info) {
779 			// check param
780 			int32 index = 0;
781 			if (error == B_OK) {
782 				switch (kind) {
783 					case B_APP_VERSION_KIND:
784 						index = 0;
785 						break;
786 					case B_SYSTEM_VERSION_KIND:
787 						index = 1;
788 						break;
789 					default:
790 						error = B_BAD_VALUE;
791 						break;
792 				}
793 			}
794 			// read both infos
795 			version_info infos[2];
796 			if (error == B_OK) {
797 				size_t read;
798 				if (_ReadData(kVersionInfoAttribute, kVersionInfoResourceID,
799 						B_VERSION_INFO_TYPE, infos, 2 * sizeof(version_info),
800 						read) == B_OK) {
801 					// clear the part that hasn't been read
802 					if (read < sizeof(infos))
803 						memset((char*)infos + read, 0, sizeof(infos) - read);
804 				} else {
805 					// failed to read -- clear
806 					memset(infos, 0, sizeof(infos));
807 				}
808 			}
809 			infos[index] = *info;
810 			// write the data
811 			if (error == B_OK) {
812 				error = _WriteData(kVersionInfoAttribute,
813 								   kVersionInfoResourceID,
814 								   B_VERSION_INFO_TYPE, infos,
815 								   2 * sizeof(version_info));
816 			}
817 		} else
818 			error = _RemoveData(kVersionInfoAttribute, B_VERSION_INFO_TYPE);
819 	}
820 	return error;
821 }
822 
823 // GetIconForType
824 /*!	\brief Gets the icon the application provides for a given MIME type.
825 
826 	If \a type is \c NULL, the application's icon is retrieved.
827 
828 	\param type The MIME type in question. May be \c NULL.
829 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
830 		   to store the requested icon (16x16 for the mini and 32x32 for the
831 		   large icon).
832 	\param which Specifies the size of the icon to be retrieved:
833 		   \c B_MINI_ICON for the mini and \c B_LARGE_ICON for the large icon.
834 	\return
835 	- \c B_OK: Everything went fine.
836 	- \c B_NO_INIT: The object is not properly initialized.
837 	- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size
838 		 \a which or bitmap dimensions (\a icon) and icon size (\a which) do
839 		 not match.
840 	- other error codes
841 */
842 status_t
843 BAppFileInfo::GetIconForType(const char* type, BBitmap* icon,
844 							 icon_size size) const
845 {
846 	if (InitCheck() != B_OK)
847 		return B_NO_INIT;
848 
849 	if (!icon || icon->InitCheck() != B_OK)
850 		return B_BAD_VALUE;
851 
852 	// TODO: for consistency with attribute based icon reading, we
853 	// could also prefer B_CMAP8 icons here if the provided bitmap
854 	// is in that format. Right now, an existing B_CMAP8 icon resource
855 	// would be ignored as soon as a vector icon is present. On the other
856 	// hand, maybe this still results in a more consistent user interface,
857 	// since Tracker/Deskbar would surely show the vector icon.
858 
859 	// try vector icon first
860 	BString vectorAttributeName(kIconAttribute);
861 
862 	// check type param
863 	if (type) {
864 		if (BMimeType::IsValid(type))
865 			vectorAttributeName += type;
866 		else
867 			return B_BAD_VALUE;
868 	} else {
869 		vectorAttributeName += kIconType;
870 	}
871 	const char* attribute = vectorAttributeName.String();
872 
873 	size_t bytesRead;
874 	void* allocatedBuffer;
875 	status_t error = _ReadData(attribute, -1, B_VECTOR_ICON_TYPE, NULL, 0,
876 							   bytesRead, &allocatedBuffer);
877 	if (error == B_OK) {
878 		error = BIconUtils::GetVectorIcon((uint8*)allocatedBuffer,
879 										  bytesRead, icon);
880 		free(allocatedBuffer);
881 		return error;
882 	}
883 
884 	// no vector icon if we got this far,
885 	// align size argument just in case
886 	if (size < B_LARGE_ICON)
887 		size = B_MINI_ICON;
888 	else
889 		size = B_LARGE_ICON;
890 
891 	error = B_OK;
892 	// set some icon size related variables
893 	BString attributeString;
894 	BRect bounds;
895 	uint32 attrType = 0;
896 	size_t attrSize = 0;
897 	switch (size) {
898 		case B_MINI_ICON:
899 			attributeString = kMiniIconAttribute;
900 			bounds.Set(0, 0, 15, 15);
901 			attrType = B_MINI_ICON_TYPE;
902 			attrSize = 16 * 16;
903 			break;
904 		case B_LARGE_ICON:
905 			attributeString = kLargeIconAttribute;
906 			bounds.Set(0, 0, 31, 31);
907 			attrType = B_LARGE_ICON_TYPE;
908 			attrSize = 32 * 32;
909 			break;
910 		default:
911 			return B_BAD_VALUE;
912 	}
913 	// check type param
914 	if (type) {
915 		if (BMimeType::IsValid(type))
916 			attributeString += type;
917 		else
918 			return B_BAD_VALUE;
919 	} else
920 		attributeString += kStandardIconType;
921 
922 	attribute = attributeString.String();
923 
924 	// check parameters
925 	// currently, scaling B_CMAP8 icons is not supported
926 	if (icon->ColorSpace() == B_CMAP8 && icon->Bounds() != bounds)
927 		return B_BAD_VALUE;
928 
929 	// read the data
930 	if (error == B_OK) {
931 		bool tempBuffer = (icon->ColorSpace() != B_CMAP8
932 						   || icon->Bounds() != bounds);
933 		uint8* buffer = NULL;
934 		size_t read;
935 		if (tempBuffer) {
936 			// other color space or bitmap size than stored in attribute
937 			buffer = new(nothrow) uint8[attrSize];
938 			if (!buffer) {
939 				error = B_NO_MEMORY;
940 			} else {
941 				error = _ReadData(attribute, -1, attrType, buffer, attrSize,
942 								  read);
943 			}
944 		} else {
945 			error = _ReadData(attribute, -1, attrType, icon->Bits(), attrSize,
946 							  read);
947 		}
948 		if (error == B_OK && read != attrSize)
949 			error = B_ERROR;
950 		if (tempBuffer) {
951 			// other color space than stored in attribute
952 			if (error == B_OK) {
953 				error = BIconUtils::ConvertFromCMAP8(buffer,
954 													 (uint32)size,
955 													 (uint32)size,
956 													 (uint32)size,
957 													 icon);
958 			}
959 			delete[] buffer;
960 		}
961 	}
962 	return error;
963 }
964 
965 // GetIconForType
966 /*!	\brief Gets the icon the application provides for a given MIME type.
967 
968 	If \a type is \c NULL, the application's icon is retrieved.
969 
970 	\param type The MIME type in question. May be \c NULL.
971 	\param data A pointer in which the icon data will be returned. When you
972 	are done with the data, you should use free() to deallocate it.
973 	\param size A pointer in which the size of the retrieved data is returned.
974 	\return
975 	- \c B_OK: Everything went fine.
976 	- \c B_NO_INIT: The object is not properly initialized.
977 	- \c B_BAD_VALUE: \c NULL \a data and/or \a size. Or the supplied
978 	\a type is not a valid MIME type.
979 	- other error codes
980 */
981 status_t
982 BAppFileInfo::GetIconForType(const char *type, uint8** data,
983 							 size_t* size) const
984 {
985 	if (InitCheck() != B_OK)
986 		return B_NO_INIT;
987 
988 	if (!data || !size)
989 		return B_BAD_VALUE;
990 
991 	// get vector icon
992 	BString attributeName(kIconAttribute);
993 
994 	// check type param
995 	if (type) {
996 		if (BMimeType::IsValid(type))
997 			attributeName += type;
998 		else
999 			return B_BAD_VALUE;
1000 	} else {
1001 		attributeName += kIconType;
1002 	}
1003 
1004 	void* allocatedBuffer = NULL;
1005 	status_t ret = _ReadData(attributeName.String(), -1,
1006 							 B_VECTOR_ICON_TYPE, NULL, 0, *size, &allocatedBuffer);
1007 
1008 	if (ret < B_OK)
1009 		return ret;
1010 
1011 	*data = (uint8*)allocatedBuffer;
1012 	return B_OK;
1013 }
1014 
1015 // SetIconForType
1016 /*!	\brief Sets the icon the application provides for a given MIME type.
1017 
1018 	If \a type is \c NULL, the application's icon is set.
1019 	If \a icon is \c NULL the icon is unset.
1020 
1021 	If the file has a signature, then the icon is also set on the MIME type.
1022 	If the type for the signature has not been installed yet, it is installed
1023 	before.
1024 
1025 	\param type The MIME type in question. May be \c NULL.
1026 	\param icon A pointer to the BBitmap containing the icon to be set.
1027 		   May be \c NULL.
1028 	\param which Specifies the size of the icon to be set: \c B_MINI_ICON
1029 		   for the mini and \c B_LARGE_ICON for the large icon.
1030 	\return
1031 	- \c B_OK: Everything went fine.
1032 	- \c B_NO_INIT: The object is not properly initialized.
1033 	- \c B_BAD_VALUE: Either the icon size \a which is unkown, bitmap dimensions (\a icon)
1034 		 and icon size (\a which) do not match, or the provided \a type is
1035 		 not a valid MIME type.
1036 	- other error codes
1037 */
1038 status_t
1039 BAppFileInfo::SetIconForType(const char *type, const BBitmap *icon,
1040 							 icon_size which)
1041 {
1042 	status_t error = B_OK;
1043 	// set some icon size related variables
1044 	BString attributeString;
1045 	BRect bounds;
1046 	uint32 attrType = 0;
1047 	size_t attrSize = 0;
1048 	int32 resourceID = 0;
1049 	switch (which) {
1050 		case B_MINI_ICON:
1051 			attributeString = kMiniIconAttribute;
1052 			bounds.Set(0, 0, 15, 15);
1053 			attrType = B_MINI_ICON_TYPE;
1054 			attrSize = 16 * 16;
1055 			resourceID = (type ? kMiniIconForTypeResourceID
1056 							   : kMiniIconResourceID);
1057 			break;
1058 		case B_LARGE_ICON:
1059 			attributeString = kLargeIconAttribute;
1060 			bounds.Set(0, 0, 31, 31);
1061 			attrType = B_LARGE_ICON_TYPE;
1062 			attrSize = 32 * 32;
1063 			resourceID = (type ? kLargeIconForTypeResourceID
1064 							   : kLargeIconResourceID);
1065 			break;
1066 		default:
1067 			error = B_BAD_VALUE;
1068 			break;
1069 	}
1070 	// check type param
1071 	if (error == B_OK) {
1072 		if (type) {
1073 			if (BMimeType::IsValid(type))
1074 				attributeString += type;
1075 			else
1076 				error = B_BAD_VALUE;
1077 		} else
1078 			attributeString += kStandardIconType;
1079 	}
1080 	const char *attribute = attributeString.String();
1081 	// check parameter and initialization
1082 	if (error == B_OK && icon
1083 		&& (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
1084 		error = B_BAD_VALUE;
1085 	}
1086 	if (error == B_OK && InitCheck() != B_OK)
1087 		error = B_NO_INIT;
1088 	// write/remove the attribute
1089 	if (error == B_OK) {
1090 		if (icon) {
1091 			bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
1092 			if (otherColorSpace) {
1093 				BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8);
1094 				error = bitmap.InitCheck();
1095 				if (error == B_OK)
1096 					error = bitmap.ImportBits(icon);
1097 				if (error == B_OK) {
1098 					error = _WriteData(attribute, resourceID, attrType,
1099 									   bitmap.Bits(), attrSize, true);
1100 				}
1101 			} else {
1102 				error = _WriteData(attribute, resourceID, attrType,
1103 								   icon->Bits(), attrSize, true);
1104 			}
1105 		} else	// no icon given => remove
1106 			error = _RemoveData(attribute, attrType);
1107 	}
1108 	// set the attribute on the MIME type, if the file has a signature
1109 	BMimeType mimeType;
1110 	if (error == B_OK && GetMetaMime(&mimeType) == B_OK) {
1111 		if (!mimeType.IsInstalled())
1112 			error = mimeType.Install();
1113 		if (error == B_OK)
1114 			error = mimeType.SetIconForType(type, icon, which);
1115 	}
1116 	return error;
1117 }
1118 
1119 // SetIconForType
1120 /*!	\brief Sets the icon the application provides for a given MIME type.
1121 
1122 	If \a type is \c NULL, the application's icon is set.
1123 	If \a data is \c NULL the icon is unset.
1124 
1125 	If the file has a signature, then the icon is also set on the MIME type.
1126 	If the type for the signature has not been installed yet, it is installed
1127 	before.
1128 
1129 	\param type The MIME type in question. May be \c NULL.
1130 	\param data A pointer to the data containing the icon to be set.
1131 		   May be \c NULL.
1132 	\param size Specifies the size of buffer provided in \a data.
1133 	\return
1134 	- \c B_OK: Everything went fine.
1135 	- \c B_NO_INIT: The object is not properly initialized.
1136 	- \c B_BAD_VALUE: The provided \a type is not a valid MIME type.
1137 	- other error codes
1138 */
1139 status_t
1140 BAppFileInfo::SetIconForType(const char* type, const uint8* data,
1141 							 size_t size)
1142 {
1143 	if (InitCheck() != B_OK)
1144 		return B_NO_INIT;
1145 
1146 	// set some icon related variables
1147 	BString attributeString = kIconAttribute;
1148 	int32 resourceID = type ? kIconForTypeResourceID : kIconResourceID;
1149 	uint32 attrType = B_VECTOR_ICON_TYPE;
1150 
1151 	// check type param
1152 	if (type) {
1153 		if (BMimeType::IsValid(type))
1154 			attributeString += type;
1155 		else
1156 			return B_BAD_VALUE;
1157 	} else
1158 		attributeString += kIconType;
1159 
1160 	const char *attribute = attributeString.String();
1161 
1162 	status_t error;
1163 	// write/remove the attribute
1164 	if (data)
1165 		error = _WriteData(attribute, resourceID, attrType, data, size, true);
1166 	else	// no icon given => remove
1167 		error = _RemoveData(attribute, attrType);
1168 
1169 	// set the attribute on the MIME type, if the file has a signature
1170 	BMimeType mimeType;
1171 	if (error == B_OK && GetMetaMime(&mimeType) == B_OK) {
1172 		if (!mimeType.IsInstalled())
1173 			error = mimeType.Install();
1174 		if (error == B_OK)
1175 			error = mimeType.SetIconForType(type, data, size);
1176 	}
1177 	return error;
1178 }
1179 
1180 // SetInfoLocation
1181 /*!	\brief Specifies the location where the meta data shall be stored.
1182 
1183 	The options for \a location are:
1184 	- \c B_USE_ATTRIBUTES: Store the data in the attributes.
1185 	- \c B_USE_RESOURCES: Store the data in the resources.
1186 	- \c B_USE_BOTH_LOCATIONS: Store the data in attributes and resources.
1187 
1188 	\param location The location where the meta data shall be stored.
1189 */
1190 void
1191 BAppFileInfo::SetInfoLocation(info_location location)
1192 {
1193 	// if the resources failed to initialize, we must not use them
1194 	if (fResources == NULL)
1195 		location = info_location(location & ~B_USE_RESOURCES);
1196 
1197 	fWhere = location;
1198 }
1199 
1200 // IsUsingAttributes
1201 /*!	\brief Returns whether the object stores the meta data (also) in the
1202 		   file's attributes.
1203 	\return \c true, if the meta data are (also) stored in the file's
1204 			attributes, \c false otherwise.
1205 */
1206 bool
1207 BAppFileInfo::IsUsingAttributes() const
1208 {
1209 	return (fWhere & B_USE_ATTRIBUTES) != 0;
1210 }
1211 
1212 // IsUsingResources
1213 /*!	\brief Returns whether the object stores the meta data (also) in the
1214 		   file's resources.
1215 	\return \c true, if the meta data are (also) stored in the file's
1216 			resources, \c false otherwise.
1217 */
1218 bool
1219 BAppFileInfo::IsUsingResources() const
1220 {
1221 	return (fWhere & B_USE_RESOURCES) != 0;
1222 }
1223 
1224 // FBC
1225 void BAppFileInfo::_ReservedAppFileInfo1() {}
1226 void BAppFileInfo::_ReservedAppFileInfo2() {}
1227 void BAppFileInfo::_ReservedAppFileInfo3() {}
1228 
1229 // =
1230 /*!	\brief Privatized assignment operator to prevent usage.
1231 */
1232 BAppFileInfo &
1233 BAppFileInfo::operator=(const BAppFileInfo &)
1234 {
1235 	return *this;
1236 }
1237 
1238 // copy constructor
1239 /*!	\brief Privatized copy constructor to prevent usage.
1240 */
1241 BAppFileInfo::BAppFileInfo(const BAppFileInfo &)
1242 {
1243 }
1244 
1245 // GetMetaMime
1246 /*!	\brief Initializes a BMimeType to the file's signature.
1247 
1248 	The parameter \a meta is not checked.
1249 
1250 	\param meta A pointer to a pre-allocated BMimeType that shall be
1251 		   initialized to the file's signature.
1252 	\return
1253 	- \c B_OK: Everything went fine.
1254 	- \c B_BAD_VALUE: \c NULL \a meta
1255 	- \c B_ENTRY_NOT_FOUND: The file has not signature or the signature is
1256 (	  not installed in the MIME database.)
1257 	  no valid MIME string.
1258 	- other error codes
1259 */
1260 status_t
1261 BAppFileInfo::GetMetaMime(BMimeType *meta) const
1262 {
1263 	char signature[B_MIME_TYPE_LENGTH];
1264 	status_t error = GetSignature(signature);
1265 	if (error == B_OK)
1266 		error = meta->SetTo(signature);
1267 	else if (error == B_BAD_VALUE)
1268 		error = B_ENTRY_NOT_FOUND;
1269 	if (error == B_OK && !meta->IsValid())
1270 		error = B_BAD_VALUE;
1271 	return error;
1272 }
1273 
1274 // _ReadData
1275 /*!	\brief Reads data from an attribute or resource.
1276 
1277 	The data are read from the location specified by \a fWhere.
1278 
1279 	The object must be properly initialized. The parameters are NOT checked.
1280 
1281 	\param name The name of the attribute/resource to be read.
1282 	\param id The resource ID of the resource to be read. Is ignored, when
1283 		   < 0.
1284 	\param type The type of the attribute/resource to be read.
1285 	\param buffer A pre-allocated buffer for the data to be read.
1286 	\param bufferSize The size of the supplied buffer.
1287 	\param bytesRead A reference parameter, set to the number of bytes
1288 		   actually read.
1289 	\param allocatedBuffer If not \c NULL, the method allocates a buffer
1290 		   large enough too store the whole data and writes a pointer to it
1291 		   into this variable. If \c NULL, the supplied buffer is used.
1292 	\return
1293 	- \c B_OK: Everything went fine.
1294 	- error code
1295 */
1296 status_t
1297 BAppFileInfo::_ReadData(const char *name, int32 id, type_code type,
1298 						void *buffer, size_t bufferSize,
1299 						size_t &bytesRead, void **allocatedBuffer) const
1300 {
1301 	status_t error = B_OK;
1302 
1303 	if (allocatedBuffer)
1304 		buffer = NULL;
1305 
1306 	bool foundData = false;
1307 
1308 	if (IsUsingAttributes()) {
1309 		// get an attribute info
1310 		attr_info info;
1311 		if (error == B_OK)
1312 			error = fNode->GetAttrInfo(name, &info);
1313 
1314 		// check type and size, allocate a buffer, if required
1315 		if (error == B_OK && info.type != type)
1316 			error = B_BAD_VALUE;
1317 		if (error == B_OK && allocatedBuffer) {
1318 			buffer = malloc(info.size);
1319 			if (!buffer)
1320 				error = B_NO_MEMORY;
1321 			bufferSize = info.size;
1322 		}
1323 		if (error == B_OK && bufferSize < info.size)
1324 			error = B_BAD_VALUE;
1325 
1326 		// read the data
1327 		if (error == B_OK) {
1328 			ssize_t read = fNode->ReadAttr(name, type, 0, buffer, info.size);
1329 			if (read < 0)
1330 				error = read;
1331 			else if (read != info.size)
1332 				error = B_ERROR;
1333 			else
1334 				bytesRead = read;
1335 		}
1336 
1337 		foundData = (error == B_OK);
1338 
1339 		// free the allocated buffer on error
1340 		if (!foundData && allocatedBuffer && buffer) {
1341 			free(buffer);
1342 			buffer = NULL;
1343 		}
1344 	}
1345 
1346 	if (!foundData && IsUsingResources()) {
1347 		// get a resource info
1348 		error = B_OK;
1349 		int32 idFound;
1350 		size_t sizeFound;
1351 		if (error == B_OK) {
1352 			if (!fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
1353 				error = B_ENTRY_NOT_FOUND;
1354 		}
1355 
1356 		// check id and size, allocate a buffer, if required
1357 		if (error == B_OK && id >= 0 && idFound != id)
1358 			error = B_ENTRY_NOT_FOUND;
1359 		if (error == B_OK && allocatedBuffer) {
1360 			buffer = malloc(sizeFound);
1361 			if (!buffer)
1362 				error = B_NO_MEMORY;
1363 			bufferSize = sizeFound;
1364 		}
1365 		if (error == B_OK && bufferSize < sizeFound)
1366 			error = B_BAD_VALUE;
1367 
1368 		// load resource
1369 		const void *resourceData = NULL;
1370 		if (error == B_OK) {
1371 			resourceData = fResources->LoadResource(type, name, &bytesRead);
1372 			if (resourceData && sizeFound == bytesRead)
1373 				memcpy(buffer, resourceData, bytesRead);
1374 			else
1375 				error = B_ERROR;
1376 		}
1377 	} else if (!foundData)
1378 		error = B_BAD_VALUE;
1379 
1380 	// return the allocated buffer, or free it on error
1381 	if (allocatedBuffer) {
1382 		if (error == B_OK)
1383 			*allocatedBuffer = buffer;
1384 		else
1385 			free(buffer);
1386 	}
1387 
1388 	return error;
1389 }
1390 
1391 // _WriteData
1392 /*!	\brief Writes data to an attribute or resource.
1393 
1394 	The data are written to the location(s) specified by \a fWhere.
1395 
1396 	The object must be properly initialized. The parameters are NOT checked.
1397 
1398 	\param name The name of the attribute/resource to be written.
1399 	\param id The resource ID of the resource to be written.
1400 	\param type The type of the attribute/resource to be written.
1401 	\param buffer A buffer containing the data to be written.
1402 	\param bufferSize The size of the supplied buffer.
1403 	\param findID If set to \c true use the ID that is already assigned to the
1404 		   \a name / \a type pair or take the first unused ID >= \a id.
1405 		   If \c false, \a id is used.
1406 	If \a id is already in use and .
1407 	\return
1408 	- \c B_OK: Everything went fine.
1409 	- error code
1410 */
1411 status_t
1412 BAppFileInfo::_WriteData(const char *name, int32 id, type_code type,
1413 						 const void *buffer, size_t bufferSize, bool findID)
1414 {
1415 	if (!IsUsingAttributes() && !IsUsingResources())
1416 		return B_NO_INIT;
1417 
1418 	status_t error = B_OK;
1419 
1420 	// write to attribute
1421 	if (IsUsingAttributes()) {
1422 		ssize_t written = fNode->WriteAttr(name, type, 0, buffer, bufferSize);
1423 		if (written < 0)
1424 			error = written;
1425 		else if (written != (ssize_t)bufferSize)
1426 			error = B_ERROR;
1427 	}
1428 	// write to resource
1429 	if (IsUsingResources() && error == B_OK) {
1430 		if (findID) {
1431 			// get the resource info
1432 			int32 idFound;
1433 			size_t sizeFound;
1434 			if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
1435 				id = idFound;
1436 			else {
1437 				// type-name pair doesn't exist yet -- find unused ID
1438 				while (fResources->HasResource(type, id))
1439 					id++;
1440 			}
1441 		}
1442 		error = fResources->AddResource(type, id, buffer, bufferSize, name);
1443 	}
1444 	return error;
1445 }
1446 
1447 // _RemoveData
1448 /*!	\brief Removes an attribute or resource.
1449 
1450 	The removal location is specified by \a fWhere.
1451 
1452 	The object must be properly initialized. The parameters are NOT checked.
1453 
1454 	\param name The name of the attribute/resource to be remove.
1455 	\param type The type of the attribute/resource to be removed.
1456 	\return
1457 	- \c B_OK: Everything went fine.
1458 	- error code
1459 */
1460 status_t
1461 BAppFileInfo::_RemoveData(const char *name, type_code type)
1462 {
1463 	if (!IsUsingAttributes() && !IsUsingResources())
1464 		return B_NO_INIT;
1465 
1466 	status_t error = B_OK;
1467 
1468 	// remove the attribute
1469 	if (IsUsingAttributes()) {
1470 		error = fNode->RemoveAttr(name);
1471 		// It's no error, if there has been no attribute.
1472 		if (error == B_ENTRY_NOT_FOUND)
1473 			error = B_OK;
1474 	}
1475 	// remove the resource
1476 	if (IsUsingResources() && error == B_OK) {
1477 		// get a resource info
1478 		int32 idFound;
1479 		size_t sizeFound;
1480 		if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
1481 			error = fResources->RemoveResource(type, idFound);
1482 	}
1483 	return error;
1484 }
1485 
1486