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