xref: /haiku/src/kits/storage/NodeInfo.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //---------------------------------------------------------------------
5 /*!
6 	\file NodeInfo.cpp
7 	BNodeInfo implementation.
8 */
9 
10 #include <NodeInfo.h>
11 
12 #include <new>
13 #include <string.h>
14 
15 #include <Bitmap.h>
16 #include <Entry.h>
17 #include <Node.h>
18 #include <Path.h>
19 #include <Rect.h>
20 
21 #include <fs_attr.h>
22 
23 using namespace std;
24 
25 // attribute names
26 #define NI_BEOS "BEOS"
27 static const char *kNITypeAttribute			= NI_BEOS ":TYPE";
28 static const char *kNIPreferredAppAttribute	= NI_BEOS ":PREF_APP";
29 static const char *kNIAppHintAttribute		= NI_BEOS ":PPATH";
30 static const char *kNIMiniIconAttribute		= NI_BEOS ":M:STD_ICON";
31 static const char *kNILargeIconAttribute	= NI_BEOS ":L:STD_ICON";
32 
33 // icon types
34 enum {
35 	B_MINI_ICON_TYPE	= 'MICN',
36 	B_LARGE_ICON_TYPE	= 'ICON',
37 };
38 
39 // constructor
40 /*!	\brief Creates an uninitialized BNodeInfo object.
41 
42 	After created a BNodeInfo with this, you should call SetTo().
43 
44 	\see SetTo(BNode *node)
45 */
46 BNodeInfo::BNodeInfo()
47 		 : fNode(NULL),
48 		   fCStatus(B_NO_INIT)
49 {
50 }
51 
52 // constructor
53 /*!	\brief Creates a BNodeInfo object and initializes it to the supplied node.
54 
55 	\param node The node to gather information on. Can be any flavor.
56 
57 	\see SetTo(BNode *node)
58 */
59 BNodeInfo::BNodeInfo(BNode *node)
60 		 : fNode(NULL),
61 		   fCStatus(B_NO_INIT)
62 {
63 	fCStatus = SetTo(node);
64 }
65 
66 // destructor
67 /*!	\brief Frees all resources associated with this object.
68 
69 	The BNode object passed to the constructor or to SetTo() is not deleted.
70 */
71 BNodeInfo::~BNodeInfo()
72 {
73 }
74 
75 // SetTo
76 /*!	\brief Initializes the BNodeInfo to the supplied node.
77 
78 	The BNodeInfo object does not copy the supplied object, but uses it
79 	directly. You must not delete the object you supply while the BNodeInfo
80 	does exist. The BNodeInfo does not take over ownership of the BNode and
81 	it doesn't delete it on destruction.
82 
83 	\param node The node to play with
84 
85 	\return
86 	- \c B_OK: Everything went fine.
87 	- \c B_BAD_VALUE: The node was bad.
88 */
89 status_t
90 BNodeInfo::SetTo(BNode *node)
91 {
92 	fNode = NULL;
93 	// check parameter
94 	fCStatus = (node && node->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
95 	if (fCStatus == B_OK)
96 		fNode = node;
97 	return fCStatus;
98 }
99 
100 // InitCheck
101 /*!	\brief returns whether the object has been properly initialized.
102 
103 	\return
104 	- \c B_OK: Everything went fine.
105 	- \c B_NO_INIT: The node is not properly initialized.
106 */
107 status_t
108 BNodeInfo::InitCheck() const
109 {
110 	return fCStatus;
111 }
112 
113 // GetType
114 /*!	\brief Gets the node's MIME type.
115 
116 	Writes the contents of the "BEOS:TYPE" attribute into the supplied buffer
117 	\a type.
118 
119 	\param type A pointer to a pre-allocated character buffer of size
120 		   \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the
121 		   node shall be written.
122 	\return
123 	- \c B_OK: Everything went fine.
124 	- \c B_NO_INIT: The object is not properly initialized.
125 	- \c B_BAD_VALUE: \c NULL \a type or the type string stored in the
126 	  attribute is longer than \c B_MIME_TYPE_LENGTH.
127 	- \c B_BAD_TYPE: The attribute the type string is stored in has the wrong
128 	   type.
129 	- \c B_ENTRY_NOT_FOUND: No type is set on the node.
130 	- other error codes
131 */
132 status_t
133 BNodeInfo::GetType(char *type) const
134 {
135 	// check parameter and initialization
136 	status_t error = (type ? B_OK : B_BAD_VALUE);
137 	if (error == B_OK && InitCheck() != B_OK)
138 		error = B_NO_INIT;
139 	// get the attribute info and check type and length of the attr contents
140 	attr_info attrInfo;
141 	if (error == B_OK)
142 		error = fNode->GetAttrInfo(kNITypeAttribute, &attrInfo);
143 	if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
144 		error = B_BAD_TYPE;
145 	if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH)
146 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
147 	// read the data
148 	if (error == B_OK) {
149 		ssize_t read = fNode->ReadAttr(kNITypeAttribute, attrInfo.type, 0,
150 									   type, attrInfo.size);
151 		if (read < 0)
152 			error = read;
153 		else if (read != attrInfo.size)
154 			error = B_ERROR;
155 		// to be save, null terminate the string at the very end
156 		if (error == B_OK)
157 			type[B_MIME_TYPE_LENGTH - 1] = '\0';
158 	}
159 	return error;
160 }
161 
162 // SetType
163 /*!	\brief Sets the node's MIME type.
164 
165 	The supplied string is written into the node's "BEOS:TYPE" attribute.
166 
167 	If \a type is \c NULL, the respective attribute is removed.
168 
169 	\param type The MIME type to be assigned to the node. Must not be longer
170 		   than \c B_MIME_TYPE_LENGTH (including the terminating null).
171 		   May be \c NULL.
172 	\return
173 	- \c B_OK: Everything went fine.
174 	- \c B_NO_INIT: The object is not properly initialized.
175 	- \c B_BAD_VALUE: \a type is longer than \c B_MIME_TYPE_LENGTH.
176 	- other error codes
177 */
178 status_t
179 BNodeInfo::SetType(const char *type)
180 {
181 	// check parameter and initialization
182 	status_t error = B_OK;
183 	if (error == B_OK && type && strlen(type) >= B_MIME_TYPE_LENGTH)
184 		error = B_BAD_VALUE;
185 	if (error == B_OK && InitCheck() != B_OK)
186 		error = B_NO_INIT;
187 	// write/remove the attribute
188 	if (error == B_OK) {
189 		if (type) {
190 			size_t toWrite = strlen(type) + 1;
191 			ssize_t written = fNode->WriteAttr(kNITypeAttribute,
192 											   B_MIME_STRING_TYPE, 0, type,
193 											   toWrite);
194 			if (written < 0)
195 				error = written;
196 			else if (written != (ssize_t)toWrite)
197 				error = B_ERROR;
198 		} else
199 			error = fNode->RemoveAttr(kNITypeAttribute);
200 	}
201 	return error;
202 }
203 
204 // GetIcon
205 /*!	\brief Gets the node's icon.
206 
207 	The icon stored in the node's "BEOS:L:STD_ICON" (large) or
208 	"BEOS:M:STD_ICON" (mini) attribute is retrieved.
209 
210 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
211 		   to store the requested icon (16x16 for the mini and 32x32 for the
212 		   large icon).
213 	\param k Specifies the size of the icon to be retrieved: \c B_MINI_ICON
214 		   for the mini and \c B_LARGE_ICON for the large icon.
215 	\return
216 	- \c B_OK: Everything went fine.
217 	- \c B_NO_INIT: The object is not properly initialized.
218 	- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a k or bitmap
219 		 dimensions (\a icon) and icon size (\a k) do not match.
220 	- other error codes
221 */
222 status_t
223 BNodeInfo::GetIcon(BBitmap *icon, icon_size k) const
224 {
225 	status_t error = B_OK;
226 	// set some icon size related variables
227 	const char *attribute = NULL;
228 	BRect bounds;
229 	uint32 attrType = 0;
230 	size_t attrSize = 0;
231 	switch (k) {
232 		case B_MINI_ICON:
233 			attribute = kNIMiniIconAttribute;
234 			bounds.Set(0, 0, 15, 15);
235 			attrType = B_MINI_ICON_TYPE;
236 			attrSize = 16 * 16;
237 			break;
238 		case B_LARGE_ICON:
239 			attribute = kNILargeIconAttribute;
240 			bounds.Set(0, 0, 31, 31);
241 			attrType = B_LARGE_ICON_TYPE;
242 			attrSize = 32 * 32;
243 			break;
244 		default:
245 			error = B_BAD_VALUE;
246 			break;
247 	}
248 	// check parameter and initialization
249 	if (error == B_OK
250 		&& (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
251 		error = B_BAD_VALUE;
252 	}
253 	if (error == B_OK && InitCheck() != B_OK)
254 		error = B_NO_INIT;
255 	// get the attribute info and check type and size of the attr contents
256 	attr_info attrInfo;
257 	if (error == B_OK)
258 		error = fNode->GetAttrInfo(attribute, &attrInfo);
259 	if (error == B_OK && attrInfo.type != attrType)
260 		error = B_BAD_TYPE;
261 	if (error == B_OK && attrInfo.size != attrSize)
262 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
263 	// read the attribute
264 	if (error == B_OK) {
265 		bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
266 		char *buffer = NULL;
267 		ssize_t read;
268 		if (otherColorSpace) {
269 			// other color space than stored in attribute
270 			buffer = new(nothrow) char[attrSize];
271 			if (!buffer)
272 				error = B_NO_MEMORY;
273 			if (error == B_OK) {
274 				read = fNode->ReadAttr(attribute, attrType, 0, buffer,
275 									   attrSize);
276 			}
277 		} else {
278 			read = fNode->ReadAttr(attribute, attrType, 0, icon->Bits(),
279 								   attrSize);
280 		}
281 		if (error == B_OK) {
282 			if (read < 0)
283 				error = read;
284 			else if (read != attrInfo.size)
285 				error = B_ERROR;
286 		}
287 		if (otherColorSpace) {
288 			// other color space than stored in attribute
289 			if (error == B_OK) {
290 				error = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
291 										 0, B_CMAP8);
292 			}
293 			delete[] buffer;
294 		}
295 	}
296 	return error;
297 }
298 
299 // SetIcon
300 /*!	\brief Sets the node's icon.
301 
302 	The icon is stored in the node's "BEOS:L:STD_ICON" (large) or
303 	"BEOS:M:STD_ICON" (mini) attribute.
304 
305 	If \a icon is \c NULL, the respective attribute is removed.
306 
307 	\param icon A pointer to the BBitmap containing the icon to be set.
308 		   May be \c NULL.
309 	\param k Specifies the size of the icon to be set: \c B_MINI_ICON
310 		   for the mini and \c B_LARGE_ICON for the large icon.
311 	\return
312 	- \c B_OK: Everything went fine.
313 	- \c B_NO_INIT: The object is not properly initialized.
314 	- \c B_BAD_VALUE: Unknown icon size \a k or bitmap dimensions (\a icon)
315 		 and icon size (\a k) do not match.
316 	- other error codes
317 */
318 status_t
319 BNodeInfo::SetIcon(const BBitmap *icon, icon_size k)
320 {
321 	status_t error = B_OK;
322 	// set some icon size related variables
323 	const char *attribute = NULL;
324 	BRect bounds;
325 	uint32 attrType = 0;
326 	size_t attrSize = 0;
327 	switch (k) {
328 		case B_MINI_ICON:
329 			attribute = kNIMiniIconAttribute;
330 			bounds.Set(0, 0, 15, 15);
331 			attrType = B_MINI_ICON_TYPE;
332 			attrSize = 16 * 16;
333 			break;
334 		case B_LARGE_ICON:
335 			attribute = kNILargeIconAttribute;
336 			bounds.Set(0, 0, 31, 31);
337 			attrType = B_LARGE_ICON_TYPE;
338 			attrSize = 32 * 32;
339 			break;
340 		default:
341 			error = B_BAD_VALUE;
342 			break;
343 	}
344 	// check parameter and initialization
345 	if (error == B_OK && icon
346 		&& (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
347 		error = B_BAD_VALUE;
348 	}
349 	if (error == B_OK && InitCheck() != B_OK)
350 		error = B_NO_INIT;
351 	// write/remove the attribute
352 	if (error == B_OK) {
353 		if (icon) {
354 			bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
355 			ssize_t written = 0;
356 			if (otherColorSpace) {
357 				BBitmap bitmap(bounds, B_CMAP8);
358 				error = bitmap.InitCheck();
359 				if (error == B_OK)
360 					error = bitmap.ImportBits(icon);
361 				if (error == B_OK) {
362 					written = fNode->WriteAttr(attribute, attrType, 0,
363 											   bitmap.Bits(), attrSize);
364 				}
365 			} else {
366 				written = fNode->WriteAttr(attribute, attrType, 0,
367 										   icon->Bits(), attrSize);
368 			}
369 			if (error == B_OK) {
370 				if (written < 0)
371 					error = written;
372 				else if (written != (ssize_t)attrSize)
373 					error = B_ERROR;
374 			}
375 		} else	// no icon given => remove
376 			error = fNode->RemoveAttr(attribute);
377 	}
378 	return error;
379 }
380 
381 // GetPreferredApp
382 /*!	\brief Gets the node's preferred application.
383 
384 	Writes the contents of the "BEOS:PREF_APP" attribute into the supplied
385 	buffer \a signature. The preferred application is identifief by its
386 	signature.
387 
388 	\param signature A pointer to a pre-allocated character buffer of size
389 		   \c B_MIME_TYPE_LENGTH or larger into which the MIME type of the
390 		   preferred application shall be written.
391 	\param verb Specifies the type of access the preferred application is
392 		   requested for. Currently only \c B_OPEN is meaningful.
393 	\return
394 	- \c B_OK: Everything went fine.
395 	- \c B_NO_INIT: The object is not properly initialized.
396 	- \c B_BAD_VALUE: \c NULL \a signature or bad app_verb \a verb.
397 	- other error codes
398 */
399 status_t
400 BNodeInfo::GetPreferredApp(char *signature, app_verb verb) const
401 {
402 	// check parameter and initialization
403 	status_t error = (signature && verb == B_OPEN ? B_OK : B_BAD_VALUE);
404 	if (error == B_OK && InitCheck() != B_OK)
405 		error = B_NO_INIT;
406 	// get the attribute info and check type and length of the attr contents
407 	attr_info attrInfo;
408 	if (error == B_OK)
409 		error = fNode->GetAttrInfo(kNIPreferredAppAttribute, &attrInfo);
410 	if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
411 		error = B_BAD_TYPE;
412 	if (error == B_OK && attrInfo.size > B_MIME_TYPE_LENGTH)
413 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
414 	// read the data
415 	if (error == B_OK) {
416 		ssize_t read = fNode->ReadAttr(kNIPreferredAppAttribute, attrInfo.type,
417 									   0, signature, attrInfo.size);
418 		if (read < 0)
419 			error = read;
420 		else if (read != attrInfo.size)
421 			error = B_ERROR;
422 		// to be save, null terminate the string at the very end
423 		if (error == B_OK)
424 			signature[B_MIME_TYPE_LENGTH - 1] = '\0';
425 	}
426 	return error;
427 }
428 
429 // SetPreferredApp
430 /*!	\brief Sets the node's preferred application.
431 
432 	The supplied string is written into the node's "BEOS:PREF_APP" attribute.
433 
434 	If \a signature is \c NULL, the respective attribute is removed.
435 
436 	\param signature The signature of the preferred application to be set.
437 		   Must not be longer than \c B_MIME_TYPE_LENGTH (including the
438 		   terminating null). May be \c NULL.
439 	\param verb Specifies the type of access the preferred application shall
440 		   be set for. Currently only \c B_OPEN is meaningful.
441 	\return
442 	- \c B_OK: Everything went fine.
443 	- \c B_NO_INIT: The object is not properly initialized.
444 	- \c B_BAD_VALUE: \c NULL \a signature, \a signature is longer than
445 	  \c B_MIME_TYPE_LENGTH or bad app_verb \a verb.
446 	- other error codes
447 */
448 status_t
449 BNodeInfo::SetPreferredApp(const char *signature, app_verb verb)
450 {
451 	// check parameters and initialization
452 	status_t error = (verb == B_OPEN ? B_OK : B_BAD_VALUE);
453 	if (error == B_OK && signature && strlen(signature) >= B_MIME_TYPE_LENGTH)
454 		error = B_BAD_VALUE;
455 	if (error == B_OK && InitCheck() != B_OK)
456 		error = B_NO_INIT;
457 	// write/remove the attribute
458 	if (error == B_OK) {
459 		if (signature) {
460 			size_t toWrite = strlen(signature) + 1;
461 			ssize_t written = fNode->WriteAttr(kNIPreferredAppAttribute,
462 											   B_MIME_STRING_TYPE, 0,
463 											   signature, toWrite);
464 			if (written < 0)
465 				error = written;
466 			else if (written != (ssize_t)toWrite)
467 				error = B_ERROR;
468 		} else
469 			error = fNode->RemoveAttr(kNIPreferredAppAttribute);
470 	}
471 	return error;
472 }
473 
474 // GetAppHint
475 /*!	\brief Returns a hint in form of and entry_ref to the application that
476 		   shall be used to open this node.
477 
478 	The path contained in the node's "BEOS:PPATH" attribute is converted into
479 	an entry_ref and returned in \a ref.
480 
481 	\param ref A pointer to a pre-allocated entry_ref into which the requested
482 		   app hint shall be written.
483 	\return
484 	- \c B_OK: Everything went fine.
485 	- \c B_NO_INIT: The object is not properly initialized.
486 	- \c B_BAD_VALUE: \c NULL \a ref.
487 	- other error codes
488 */
489 status_t
490 BNodeInfo::GetAppHint(entry_ref *ref) const
491 {
492 	// check parameter and initialization
493 	status_t error = (ref ? B_OK : B_BAD_VALUE);
494 	if (error == B_OK && InitCheck() != B_OK)
495 		error = B_NO_INIT;
496 	// get the attribute info and check type and length of the attr contents
497 	attr_info attrInfo;
498 	if (error == B_OK)
499 		error = fNode->GetAttrInfo(kNIAppHintAttribute, &attrInfo);
500 	// NOTE: The attribute type should be B_STRING_TYPE, but R5 uses
501 	// B_MIME_STRING_TYPE.
502 	if (error == B_OK && attrInfo.type != B_MIME_STRING_TYPE)
503 		error = B_BAD_TYPE;
504 	if (error == B_OK && attrInfo.size > B_PATH_NAME_LENGTH)
505 		error = B_BAD_VALUE;	// TODO: B_BAD_DATA?
506 	// read the data
507 	if (error == B_OK) {
508 		char path[B_PATH_NAME_LENGTH];
509 		ssize_t read = fNode->ReadAttr(kNIAppHintAttribute, attrInfo.type, 0,
510 									   path, attrInfo.size);
511 		if (read < 0)
512 			error = read;
513 		else if (read != attrInfo.size)
514 			error = B_ERROR;
515 		// get the entry_ref for the path
516 		if (error == B_OK) {
517 			// to be save, null terminate the path at the very end
518 			path[B_PATH_NAME_LENGTH - 1] = '\0';
519 			error = get_ref_for_path(path, ref);
520 		}
521 	}
522 	return error;
523 }
524 
525 // SetAppHint
526 /*!	\brief Sets the node's app hint.
527 
528 	The supplied entry_ref is converted into a path and stored in the node's
529 	"BEOS:PPATH" attribute.
530 
531 	If \a ref is \c NULL, the respective attribute is removed.
532 
533 	\param ref A pointer to an entry_ref referring to the application.
534 		   May be \c NULL.
535 	\return
536 	- \c B_OK: Everything went fine.
537 	- \c B_NO_INIT: The object is not properly initialized.
538 	- \c B_BAD_VALUE: \c NULL \a ref.
539 	- other error codes
540 */
541 status_t
542 BNodeInfo::SetAppHint(const entry_ref *ref)
543 {
544 	// check parameter and initialization
545 	status_t error = B_OK;
546 	if (error == B_OK && InitCheck() != B_OK)
547 		error = B_NO_INIT;
548 	// write/remove the attribute
549 	if (error == B_OK) {
550 		if (ref) {
551 			BPath path;
552 			error = path.SetTo(ref);
553 			if (error == B_OK) {
554 				size_t toWrite = strlen(path.Path()) + 1;
555 				ssize_t written = fNode->WriteAttr(kNIAppHintAttribute,
556 												   B_MIME_STRING_TYPE, 0,
557 												   path.Path(), toWrite);
558 				if (written < 0)
559 					error = written;
560 				else if (written != (ssize_t)toWrite)
561 					error = B_ERROR;
562 			}
563 		} else
564 			error = fNode->RemoveAttr(kNIAppHintAttribute);
565 	}
566 	return error;
567 }
568 
569 // GetTrackerIcon
570 /*!	\brief Gets the icon which tracker displays.
571 
572 	This method tries real hard to find an icon for the node:
573 	- If the node has no type, return the icon for "application/octet-stream"
574 	  from the MIME database. Even, if the node has an own icon!
575 	- Ask GetIcon().
576 	- Get the preferred application and ask the MIME database, if that
577 	  application has a special icon for the node's file type.
578 	- Ask the MIME database whether there is an icon for the node's file type.
579 	- Ask the MIME database for the preferred application for the node's
580 	  file type and whether this application has a special icon for the type.
581 	- Return the icon for "application/octet-stream" from the MIME database.
582 	This list is processed in the given order and the icon the first
583 	successful attempt provides is returned. In case none of them yields an
584 	icon, this method fails. This is very unlikely though.
585 
586 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
587 		   to store the requested icon (16x16 for the mini and 32x32 for the
588 		   large icon).
589 	\param k Specifies the size of the icon to be retrieved: \c B_MINI_ICON
590 		   for the mini and \c B_LARGE_ICON for the large icon.
591 	\return
592 	- \c B_OK: Everything went fine.
593 	- \c B_NO_INIT: The object is not properly initialized.
594 	- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size \a k or bitmap
595 		 dimensions (\a icon) and icon size (\a k) do not match.
596 	- other error codes
597 */
598 status_t
599 BNodeInfo::GetTrackerIcon(BBitmap *icon, icon_size k) const
600 {
601 	// set some icon size related variables
602 	status_t error = B_OK;
603 	BRect bounds;
604 	switch (k) {
605 		case B_MINI_ICON:
606 			bounds.Set(0, 0, 15, 15);
607 			break;
608 		case B_LARGE_ICON:
609 			bounds.Set(0, 0, 31, 31);
610 			break;
611 		default:
612 			error = B_BAD_VALUE;
613 			break;
614 	}
615 	// check parameters and initialization
616 	if (error == B_OK
617 		&& (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
618 		error = B_BAD_VALUE;
619 	}
620 	if (error == B_OK && InitCheck() != B_OK)
621 		error = B_NO_INIT;
622 	bool success = false;
623 	// get node MIME type, and, if that fails, the generic icon
624 	char mimeString[B_MIME_TYPE_LENGTH];
625 	if (error == B_OK) {
626 		if (GetType(mimeString) != B_OK) {
627 			// no type available -- get the "application/octet-stream" icon
628 			BMimeType type("application/octet-stream");
629 			error = type.GetIcon(icon, k);
630 			success = (error == B_OK);
631 		}
632 	}
633 	// Ask GetIcon().
634 	if (error == B_OK && !success)
635 		success = (GetIcon(icon, k) == B_OK);
636 	// Get the preferred application and ask the MIME database, if that
637 	// application has a special icon for the node's file type.
638 	if (error == B_OK && !success) {
639 		char signature[B_MIME_TYPE_LENGTH];
640 		if (GetPreferredApp(signature) == B_OK) {
641 			BMimeType type(signature);
642 			success = (type.GetIconForType(mimeString, icon, k) == B_OK);
643 		}
644 	}
645 	// Ask the MIME database whether there is an icon for the node's file type.
646 	BMimeType nodeType;
647 	if (error == B_OK && !success) {
648 		nodeType.SetTo(mimeString);
649 		success = (nodeType.GetIcon(icon, k) == B_OK);
650 	}
651 	// Ask the MIME database for the preferred application for the node's
652 	// file type and whether this application has a special icon for the type.
653 	if (error == B_OK && !success) {
654 		char signature[B_MIME_TYPE_LENGTH];
655 		if (nodeType.GetPreferredApp(signature) == B_OK) {
656 			BMimeType type(signature);
657 			success = (type.GetIconForType(mimeString, icon, k) == B_OK);
658 		}
659 	}
660 	// Return the icon for "application/octet-stream" from the MIME database.
661 	if (error == B_OK && !success) {
662 		// get the "application/octet-stream" icon
663 		BMimeType type("application/octet-stream");
664 		error = type.GetIcon(icon, k);
665 		success = (error == B_OK);
666 	}
667 	return error;
668 }
669 
670 // GetTrackerIcon
671 /*!	\brief Gets the icon which tracker displays for the node referred to by
672 		   the supplied entry_ref.
673 
674 	This methods works similar to the non-static version. The first argument
675 	\a ref identifies the node in question.
676 
677 	\param ref An entry_ref referring to the node for which the icon shall be
678 		   retrieved.
679 	\param icon A pointer to a pre-allocated BBitmap of the correct dimension
680 		   to store the requested icon (16x16 for the mini and 32x32 for the
681 		   large icon).
682 	\param k Specifies the size of the icon to be retrieved: \c B_MINI_ICON
683 		   for the mini and \c B_LARGE_ICON for the large icon.
684 	\return
685 	- \c B_OK: Everything went fine.
686 	- \c B_NO_INIT: The object is not properly initialized.
687 	- \c B_BAD_VALUE: \c NULL ref or \a icon, unsupported icon size \a k or
688 		 bitmap dimensions (\a icon) and icon size (\a k) do not match.
689 	- other error codes
690 */
691 status_t
692 BNodeInfo::GetTrackerIcon(const entry_ref *ref, BBitmap *icon, icon_size k)
693 {
694 	// check ref param
695 	status_t error = (ref ? B_OK : B_BAD_VALUE);
696 	// init a BNode
697 	BNode node;
698 	if (error == B_OK)
699 		error = node.SetTo(ref);
700 	// init a BNodeInfo
701 	BNodeInfo nodeInfo;
702 	if (error == B_OK)
703 		error = nodeInfo.SetTo(&node);
704 	// let the non-static GetTrackerIcon() do the dirty work
705 	if (error == B_OK)
706 		error = nodeInfo.GetTrackerIcon(icon, k);
707 	return error;
708 }
709 
710 void
711 BNodeInfo::_ReservedNodeInfo1()
712 {
713 }
714 
715 void
716 BNodeInfo::_ReservedNodeInfo2()
717 {
718 }
719 
720 void
721 BNodeInfo::_ReservedNodeInfo3()
722 {
723 }
724 
725 // =
726 /*!	\brief Privatized assignment operator to prevent usage.
727 */
728 BNodeInfo &
729 BNodeInfo::operator=(const BNodeInfo &nodeInfo)
730 {
731 	return *this;
732 }
733 
734 // copy constructor
735 /*!	\brief Privatized copy constructor to prevent usage.
736 */
737 BNodeInfo::BNodeInfo(const BNodeInfo &)
738 {
739 }
740 
741