xref: /haiku/src/kits/storage/AppFileInfo.cpp (revision f23596149e0d173463f70629581aa10cc305d32e)
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 which) 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_RAW_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 
862 	error = B_OK;
863 	// set some icon size related variables
864 	BString attributeString;
865 	BRect bounds;
866 	uint32 attrType = 0;
867 	size_t attrSize = 0;
868 	switch (which) {
869 		case B_MINI_ICON:
870 			attributeString = kMiniIconAttribute;
871 			bounds.Set(0, 0, 15, 15);
872 			attrType = B_MINI_ICON_TYPE;
873 			attrSize = 16 * 16;
874 			break;
875 		case B_LARGE_ICON:
876 			attributeString = kLargeIconAttribute;
877 			bounds.Set(0, 0, 31, 31);
878 			attrType = B_LARGE_ICON_TYPE;
879 			attrSize = 32 * 32;
880 			break;
881 		default:
882 			return B_BAD_VALUE;
883 	}
884 	// check type param
885 	if (type) {
886 		if (BMimeType::IsValid(type))
887 			attributeString += type;
888 		else
889 			return B_BAD_VALUE;
890 	} else
891 		attributeString += kStandardIconType;
892 
893 	attribute = attributeString.String();
894 
895 	// check parameter and initialization
896 	if (icon->Bounds() != bounds)
897 		return B_BAD_VALUE;
898 
899 	// read the data
900 	if (error == B_OK) {
901 		bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
902 		char *buffer = NULL;
903 		size_t read;
904 		if (otherColorSpace) {
905 			// other color space than stored in attribute
906 			buffer = new(nothrow) char[attrSize];
907 			if (!buffer)
908 				error = B_NO_MEMORY;
909 			if (error == B_OK) {
910 				error = _ReadData(attribute, -1, attrType, buffer, attrSize,
911 								  read);
912 			}
913 		} else {
914 			error = _ReadData(attribute, -1, attrType, icon->Bits(), attrSize,
915 							  read);
916 		}
917 		if (error == B_OK && read != attrSize)
918 			error = B_ERROR;
919 		if (otherColorSpace) {
920 			// other color space than stored in attribute
921 			if (error == B_OK) {
922 				error = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
923 										 0, B_CMAP8);
924 			}
925 			delete[] buffer;
926 		}
927 	}
928 	return error;
929 }
930 
931 // GetIconForType
932 /*!	\brief Gets the icon the application provides for a given MIME type.
933 
934 	If \a type is \c NULL, the application's icon is retrieved.
935 
936 	\param type The MIME type in question. May be \c NULL.
937 	\param data A pointer in which the icon data will be returned. When you
938 	are done with the data, you should use free() to deallocate it.
939 	\param size A pointer in which the size of the retrieved data is returned.
940 	\return
941 	- \c B_OK: Everything went fine.
942 	- \c B_NO_INIT: The object is not properly initialized.
943 	- \c B_BAD_VALUE: \c NULL \a data and/or \a size. Or the supplied
944 	\a type is not a valid MIME type.
945 	- other error codes
946 */
947 status_t
948 BAppFileInfo::GetIconForType(const char *type, uint8** data,
949 							 size_t* size) const
950 {
951 	if (InitCheck() != B_OK)
952 		return B_NO_INIT;
953 
954 	if (!data || !size)
955 		return B_BAD_VALUE;
956 
957 	// get vector icon
958 	BString attributeName(kIconAttribute);
959 
960 	// check type param
961 	if (type) {
962 		if (BMimeType::IsValid(type))
963 			attributeName += type;
964 		else
965 			return B_BAD_VALUE;
966 	} else {
967 		attributeName += kIconType;
968 	}
969 
970 	void* allocatedBuffer = NULL;
971 	status_t ret = _ReadData(attributeName.String(), -1,
972 							 B_RAW_TYPE, NULL, 0, *size, &allocatedBuffer);
973 
974 	if (ret < B_OK)
975 		return ret;
976 
977 	*data = (uint8*)allocatedBuffer;
978 	return B_OK;
979 }
980 
981 // SetIconForType
982 /*!	\brief Sets the icon the application provides for a given MIME type.
983 
984 	If \a type is \c NULL, the application's icon is set.
985 	If \a icon is \c NULL the icon is unset.
986 
987 	If the file has a signature, then the icon is also set on the MIME type.
988 	If the type for the signature has not been installed yet, it is installed
989 	before.
990 
991 	\param type The MIME type in question. May be \c NULL.
992 	\param icon A pointer to the BBitmap containing the icon to be set.
993 		   May be \c NULL.
994 	\param which Specifies the size of the icon to be set: \c B_MINI_ICON
995 		   for the mini and \c B_LARGE_ICON for the large icon.
996 	\return
997 	- \c B_OK: Everything went fine.
998 	- \c B_NO_INIT: The object is not properly initialized.
999 	- \c B_BAD_VALUE: Either the icon size \a which is unkown, bitmap dimensions (\a icon)
1000 		 and icon size (\a which) do not match, or the provided \a type is
1001 		 not a valid MIME type.
1002 	- other error codes
1003 */
1004 status_t
1005 BAppFileInfo::SetIconForType(const char *type, const BBitmap *icon,
1006 							 icon_size which)
1007 {
1008 	status_t error = B_OK;
1009 	// set some icon size related variables
1010 	BString attributeString;
1011 	BRect bounds;
1012 	uint32 attrType = 0;
1013 	size_t attrSize = 0;
1014 	int32 resourceID = 0;
1015 	switch (which) {
1016 		case B_MINI_ICON:
1017 			attributeString = kMiniIconAttribute;
1018 			bounds.Set(0, 0, 15, 15);
1019 			attrType = B_MINI_ICON_TYPE;
1020 			attrSize = 16 * 16;
1021 			resourceID = (type ? kMiniIconForTypeResourceID
1022 							   : kMiniIconResourceID);
1023 			break;
1024 		case B_LARGE_ICON:
1025 			attributeString = kLargeIconAttribute;
1026 			bounds.Set(0, 0, 31, 31);
1027 			attrType = B_LARGE_ICON_TYPE;
1028 			attrSize = 32 * 32;
1029 			resourceID = (type ? kLargeIconForTypeResourceID
1030 							   : kLargeIconResourceID);
1031 			break;
1032 		default:
1033 			error = B_BAD_VALUE;
1034 			break;
1035 	}
1036 	// check type param
1037 	if (error == B_OK) {
1038 		if (type) {
1039 			if (BMimeType::IsValid(type))
1040 				attributeString += type;
1041 			else
1042 				error = B_BAD_VALUE;
1043 		} else
1044 			attributeString += kStandardIconType;
1045 	}
1046 	const char *attribute = attributeString.String();
1047 	// check parameter and initialization
1048 	if (error == B_OK && icon
1049 		&& (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
1050 		error = B_BAD_VALUE;
1051 	}
1052 	if (error == B_OK && InitCheck() != B_OK)
1053 		error = B_NO_INIT;
1054 	// write/remove the attribute
1055 	if (error == B_OK) {
1056 		if (icon) {
1057 			bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
1058 			if (otherColorSpace) {
1059 				BBitmap bitmap(bounds, B_BITMAP_NO_SERVER_LINK, B_CMAP8);
1060 				error = bitmap.InitCheck();
1061 				if (error == B_OK)
1062 					error = bitmap.ImportBits(icon);
1063 				if (error == B_OK) {
1064 					error = _WriteData(attribute, resourceID, attrType,
1065 									   bitmap.Bits(), attrSize, true);
1066 				}
1067 			} else {
1068 				error = _WriteData(attribute, resourceID, attrType,
1069 								   icon->Bits(), attrSize, true);
1070 			}
1071 		} else	// no icon given => remove
1072 			error = _RemoveData(attribute, attrType);
1073 	}
1074 	// set the attribute on the MIME type, if the file has a signature
1075 	BMimeType mimeType;
1076 	if (error == B_OK && GetMetaMime(&mimeType) == B_OK) {
1077 		if (!mimeType.IsInstalled())
1078 			error = mimeType.Install();
1079 		if (error == B_OK)
1080 			error = mimeType.SetIconForType(type, icon, which);
1081 	}
1082 	return error;
1083 }
1084 
1085 // SetIconForType
1086 /*!	\brief Sets the icon the application provides for a given MIME type.
1087 
1088 	If \a type is \c NULL, the application's icon is set.
1089 	If \a data is \c NULL the icon is unset.
1090 
1091 	If the file has a signature, then the icon is also set on the MIME type.
1092 	If the type for the signature has not been installed yet, it is installed
1093 	before.
1094 
1095 	\param type The MIME type in question. May be \c NULL.
1096 	\param data A pointer to the data containing the icon to be set.
1097 		   May be \c NULL.
1098 	\param size Specifies the size of buffer provided in \a data.
1099 	\return
1100 	- \c B_OK: Everything went fine.
1101 	- \c B_NO_INIT: The object is not properly initialized.
1102 	- \c B_BAD_VALUE: The provided \a type is not a valid MIME type.
1103 	- other error codes
1104 */
1105 status_t
1106 BAppFileInfo::SetIconForType(const char* type, const uint8* data,
1107 							 size_t size)
1108 {
1109 	if (InitCheck() != B_OK)
1110 		return B_NO_INIT;
1111 
1112 	// set some icon related variables
1113 	BString attributeString = kIconAttribute;
1114 	int32 resourceID = type ? kIconForTypeResourceID : kIconResourceID;
1115 	uint32 attrType = B_RAW_TYPE;
1116 
1117 	// check type param
1118 	if (type) {
1119 		if (BMimeType::IsValid(type))
1120 			attributeString += type;
1121 		else
1122 			return B_BAD_VALUE;
1123 	} else
1124 		attributeString += kIconType;
1125 
1126 	const char *attribute = attributeString.String();
1127 
1128 	status_t error;
1129 	// write/remove the attribute
1130 	if (data)
1131 		error = _WriteData(attribute, resourceID, attrType, data, size, true);
1132 	else	// no icon given => remove
1133 		error = _RemoveData(attribute, attrType);
1134 
1135 	// set the attribute on the MIME type, if the file has a signature
1136 	BMimeType mimeType;
1137 	if (error == B_OK && GetMetaMime(&mimeType) == B_OK) {
1138 		if (!mimeType.IsInstalled())
1139 			error = mimeType.Install();
1140 		if (error == B_OK)
1141 			error = mimeType.SetIconForType(type, data, size);
1142 	}
1143 	return error;
1144 }
1145 
1146 // SetInfoLocation
1147 /*!	\brief Specifies the location where the meta data shall be stored.
1148 
1149 	The options for \a location are:
1150 	- \c B_USE_ATTRIBUTES: Store the data in the attributes.
1151 	- \c B_USE_RESOURCES: Store the data in the resources.
1152 	- \c B_USE_BOTH_LOCATIONS: Store the data in attributes and resources.
1153 
1154 	\param location The location where the meta data shall be stored.
1155 */
1156 void
1157 BAppFileInfo::SetInfoLocation(info_location location)
1158 {
1159 	fWhere = location;
1160 }
1161 
1162 // IsUsingAttributes
1163 /*!	\brief Returns whether the object stores the meta data (also) in the
1164 		   file's attributes.
1165 	\return \c true, if the meta data are (also) stored in the file's
1166 			attributes, \c false otherwise.
1167 */
1168 bool
1169 BAppFileInfo::IsUsingAttributes() const
1170 {
1171 	return (fWhere & B_USE_ATTRIBUTES);
1172 }
1173 
1174 // IsUsingResources
1175 /*!	\brief Returns whether the object stores the meta data (also) in the
1176 		   file's resources.
1177 	\return \c true, if the meta data are (also) stored in the file's
1178 			resources, \c false otherwise.
1179 */
1180 bool
1181 BAppFileInfo::IsUsingResources() const
1182 {
1183 	return (fWhere & B_USE_RESOURCES);
1184 }
1185 
1186 // FBC
1187 void BAppFileInfo::_ReservedAppFileInfo1() {}
1188 void BAppFileInfo::_ReservedAppFileInfo2() {}
1189 void BAppFileInfo::_ReservedAppFileInfo3() {}
1190 
1191 // =
1192 /*!	\brief Privatized assignment operator to prevent usage.
1193 */
1194 BAppFileInfo &
1195 BAppFileInfo::operator=(const BAppFileInfo &)
1196 {
1197 	return *this;
1198 }
1199 
1200 // copy constructor
1201 /*!	\brief Privatized copy constructor to prevent usage.
1202 */
1203 BAppFileInfo::BAppFileInfo(const BAppFileInfo &)
1204 {
1205 }
1206 
1207 // GetMetaMime
1208 /*!	\brief Initializes a BMimeType to the file's signature.
1209 
1210 	The parameter \a meta is not checked.
1211 
1212 	\param meta A pointer to a pre-allocated BMimeType that shall be
1213 		   initialized to the file's signature.
1214 	\return
1215 	- \c B_OK: Everything went fine.
1216 	- \c B_BAD_VALUE: \c NULL \a meta
1217 	- \c B_ENTRY_NOT_FOUND: The file has not signature or the signature is
1218 (	  not installed in the MIME database.)
1219 	  no valid MIME string.
1220 	- other error codes
1221 */
1222 status_t
1223 BAppFileInfo::GetMetaMime(BMimeType *meta) const
1224 {
1225 	char signature[B_MIME_TYPE_LENGTH];
1226 	status_t error = GetSignature(signature);
1227 	if (error == B_OK)
1228 		error = meta->SetTo(signature);
1229 	else if (error == B_BAD_VALUE)
1230 		error = B_ENTRY_NOT_FOUND;
1231 	if (error == B_OK && !meta->IsValid())
1232 		error = B_BAD_VALUE;
1233 	return error;
1234 }
1235 
1236 // _ReadData
1237 /*!	\brief Reads data from an attribute or resource.
1238 
1239 	The data are read from the location specified by \a fWhere.
1240 
1241 	The object must be properly initialized. The parameters are NOT checked.
1242 
1243 	\param name The name of the attribute/resource to be read.
1244 	\param id The resource ID of the resource to be read. Is ignored, when
1245 		   < 0.
1246 	\param type The type of the attribute/resource to be read.
1247 	\param buffer A pre-allocated buffer for the data to be read.
1248 	\param bufferSize The size of the supplied buffer.
1249 	\param bytesRead A reference parameter, set to the number of bytes
1250 		   actually read.
1251 	\param allocatedBuffer If not \c NULL, the method allocates a buffer
1252 		   large enough too store the whole data and writes a pointer to it
1253 		   into this variable. If \c NULL, the supplied buffer is used.
1254 	\return
1255 	- \c B_OK: Everything went fine.
1256 	- error code
1257 */
1258 status_t
1259 BAppFileInfo::_ReadData(const char *name, int32 id, type_code type,
1260 						void *buffer, size_t bufferSize,
1261 						size_t &bytesRead, void **allocatedBuffer) const
1262 {
1263 	status_t error = B_OK;
1264 
1265 	if (allocatedBuffer)
1266 		buffer = NULL;
1267 
1268 	bool foundData = false;
1269 
1270 	if (IsUsingAttributes()) {
1271 		// get an attribute info
1272 		attr_info info;
1273 		if (error == B_OK)
1274 			error = fNode->GetAttrInfo(name, &info);
1275 
1276 		// check type and size, allocate a buffer, if required
1277 		if (error == B_OK && info.type != type)
1278 			error = B_BAD_VALUE;
1279 		if (error == B_OK && allocatedBuffer) {
1280 			buffer = malloc(info.size);
1281 			if (!buffer)
1282 				error = B_NO_MEMORY;
1283 			bufferSize = info.size;
1284 		}
1285 		if (error == B_OK && bufferSize < info.size)
1286 			error = B_BAD_VALUE;
1287 
1288 		// read the data
1289 		if (error == B_OK) {
1290 			ssize_t read = fNode->ReadAttr(name, type, 0, buffer, info.size);
1291 			if (read < 0)
1292 				error = read;
1293 			else if (read != info.size)
1294 				error = B_ERROR;
1295 			else
1296 				bytesRead = read;
1297 		}
1298 
1299 		foundData = (error == B_OK);
1300 
1301 		// free the allocated buffer on error
1302 		if (!foundData && allocatedBuffer && buffer) {
1303 			free(buffer);
1304 			buffer = NULL;
1305 		}
1306 	}
1307 
1308 	if (!foundData && IsUsingResources()) {
1309 		// get a resource info
1310 		error = B_OK;
1311 		int32 idFound;
1312 		size_t sizeFound;
1313 		if (error == B_OK) {
1314 			if (!fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
1315 				error = B_ENTRY_NOT_FOUND;
1316 		}
1317 
1318 		// check id and size, allocate a buffer, if required
1319 		if (error == B_OK && id >= 0 && idFound != id)
1320 			error = B_ENTRY_NOT_FOUND;
1321 		if (error == B_OK && allocatedBuffer) {
1322 			buffer = malloc(sizeFound);
1323 			if (!buffer)
1324 				error = B_NO_MEMORY;
1325 			bufferSize = sizeFound;
1326 		}
1327 		if (error == B_OK && bufferSize < sizeFound)
1328 			error = B_BAD_VALUE;
1329 
1330 		// load resource
1331 		const void *resourceData = NULL;
1332 		if (error == B_OK) {
1333 			resourceData = fResources->LoadResource(type, name, &bytesRead);
1334 			if (resourceData && sizeFound == bytesRead)
1335 				memcpy(buffer, resourceData, bytesRead);
1336 			else
1337 				error = B_ERROR;
1338 		}
1339 	} else if (!foundData)
1340 		error = B_BAD_VALUE;
1341 
1342 	// return the allocated buffer, or free it on error
1343 	if (allocatedBuffer) {
1344 		if (error == B_OK)
1345 			*allocatedBuffer = buffer;
1346 		else
1347 			free(buffer);
1348 	}
1349 
1350 	return error;
1351 }
1352 
1353 // _WriteData
1354 /*!	\brief Writes data to an attribute or resource.
1355 
1356 	The data are written to the location(s) specified by \a fWhere.
1357 
1358 	The object must be properly initialized. The parameters are NOT checked.
1359 
1360 	\param name The name of the attribute/resource to be written.
1361 	\param id The resource ID of the resource to be written.
1362 	\param type The type of the attribute/resource to be written.
1363 	\param buffer A buffer containing the data to be written.
1364 	\param bufferSize The size of the supplied buffer.
1365 	\param findID If set to \c true use the ID that is already assigned to the
1366 		   \a name / \a type pair or take the first unused ID >= \a id.
1367 		   If \c false, \a id is used.
1368 	If \a id is already in use and .
1369 	\return
1370 	- \c B_OK: Everything went fine.
1371 	- error code
1372 */
1373 status_t
1374 BAppFileInfo::_WriteData(const char *name, int32 id, type_code type,
1375 						 const void *buffer, size_t bufferSize, bool findID)
1376 {
1377 	status_t error = B_OK;
1378 	// write to attribute
1379 	if (IsUsingAttributes() && error == B_OK) {
1380 		ssize_t written = fNode->WriteAttr(name, type, 0, buffer, bufferSize);
1381 		if (written < 0)
1382 			error = written;
1383 		else if (written != (ssize_t)bufferSize)
1384 			error = B_ERROR;
1385 	}
1386 	// write to resource
1387 	if (IsUsingResources() && error == B_OK) {
1388 		if (findID) {
1389 			// get the resource info
1390 			int32 idFound;
1391 			size_t sizeFound;
1392 			if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
1393 				id = idFound;
1394 			else {
1395 				// type-name pair doesn't exist yet -- find unused ID
1396 				while (fResources->HasResource(type, id))
1397 					id++;
1398 			}
1399 		}
1400 		error = fResources->AddResource(type, id, buffer, bufferSize, name);
1401 	}
1402 	return error;
1403 }
1404 
1405 // _RemoveData
1406 /*!	\brief Removes an attribute or resource.
1407 
1408 	The removal location is specified by \a fWhere.
1409 
1410 	The object must be properly initialized. The parameters are NOT checked.
1411 
1412 	\param name The name of the attribute/resource to be remove.
1413 	\param type The type of the attribute/resource to be removed.
1414 	\return
1415 	- \c B_OK: Everything went fine.
1416 	- error code
1417 */
1418 status_t
1419 BAppFileInfo::_RemoveData(const char *name, type_code type)
1420 {
1421 	status_t error = B_OK;
1422 	// remove the attribute
1423 	if (IsUsingAttributes() && error == B_OK) {
1424 		error = fNode->RemoveAttr(name);
1425 		// It's no error, if there has been no attribute.
1426 		if (error == B_ENTRY_NOT_FOUND)
1427 			error = B_OK;
1428 	}
1429 	// remove the resource
1430 	if (IsUsingResources() && error == B_OK) {
1431 		// get a resource info
1432 		int32 idFound;
1433 		size_t sizeFound;
1434 		if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
1435 			error = fResources->RemoveResource(type, idFound);
1436 	}
1437 	return error;
1438 }
1439 
1440