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