headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / storage / mime / Database.cpp
blob1717565ce628fafe9a53f9c1014f29c3106b6394
1 /*
2 * Copyright 2002-2014, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Tyler Dauwalder
7 * Axel Dörfler, axeld@pinc-software.de
8 * Rene Gollent, rene@gollent.com.
9 */
12 #include <mime/Database.h>
14 #include <stdio.h>
15 #include <string>
17 #include <iostream>
18 #include <new>
20 #include <Application.h>
21 #include <Bitmap.h>
22 #include <DataIO.h>
23 #include <Directory.h>
24 #include <Entry.h>
25 #include <fs_attr.h>
26 #include <Message.h>
27 #include <MimeType.h>
28 #include <Node.h>
29 #include <Path.h>
30 #include <String.h>
31 #include <TypeConstants.h>
33 #include <AutoLocker.h>
34 #include <mime/database_support.h>
35 #include <mime/DatabaseLocation.h>
36 #include <storage_support.h>
39 //#define DBG(x) x
40 #define DBG(x)
41 #define OUT printf
44 namespace BPrivate {
45 namespace Storage {
46 namespace Mime {
49 Database::NotificationListener::~NotificationListener()
54 /*!
55 \class Database
56 \brief Mime::Database is the master of the MIME data base.
58 All write and non-atomic read accesses are carried out by this class.
60 \note No error checking (other than checks for NULL pointers) is performed
61 by this class on the mime type strings passed to it. It's assumed
62 that this sort of checking has been done beforehand.
65 // constructor
66 /*! \brief Creates and initializes a Mime::Database object.
68 Database::Database(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer,
69 NotificationListener* notificationListener)
71 fStatus(B_NO_INIT),
72 fLocation(databaseLocation),
73 fNotificationListener(notificationListener),
74 fAssociatedTypes(databaseLocation, mimeSniffer),
75 fInstalledTypes(databaseLocation),
76 fSnifferRules(databaseLocation, mimeSniffer),
77 fSupportingApps(databaseLocation),
78 fDeferredInstallNotificationsLocker("deferred install notifications"),
79 fDeferredInstallNotifications()
81 // make sure the user's MIME DB directory exists
82 fStatus = create_directory(fLocation->WritableDirectory(),
83 S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
86 // destructor
87 /*! \brief Frees all resources associated with this object.
89 Database::~Database()
93 // InitCheck
94 /*! \brief Returns the initialization status of the object.
95 \return
96 - B_OK: success
97 - "error code": failure
99 status_t
100 Database::InitCheck() const
102 return fStatus;
105 // Install
106 /*! \brief Installs the given type in the database
107 \note The R5 version of this call returned an unreliable result if the
108 MIME type was already installed. Ours simply returns B_OK.
109 \param type Pointer to a NULL-terminated string containing the MIME type of interest
110 \param decsription Pointer to a NULL-terminated string containing the new long description
111 \return
112 - B_OK: success
113 - B_FILE_EXISTS: the type is already installed
114 - "error code": failure
116 status_t
117 Database::Install(const char *type)
119 if (type == NULL)
120 return B_BAD_VALUE;
122 BEntry entry;
123 status_t err = entry.SetTo(fLocation->WritablePathForType(type));
124 if (err == B_OK || err == B_ENTRY_NOT_FOUND) {
125 if (entry.Exists())
126 err = B_FILE_EXISTS;
127 else {
128 bool didCreate = false;
129 BNode node;
130 err = fLocation->OpenWritableType(type, node, true, &didCreate);
131 if (!err && didCreate) {
132 fInstalledTypes.AddType(type);
133 _SendInstallNotification(type);
137 return err;
140 // Delete
141 /*! \brief Removes the given type from the database
142 \param type Pointer to a NULL-terminated string containing the MIME type of interest
143 \return
144 - B_OK: success
145 - "error code": failure
147 status_t
148 Database::Delete(const char *type)
150 if (type == NULL)
151 return B_BAD_VALUE;
153 // Open the type
154 BEntry entry;
155 status_t status = entry.SetTo(fLocation->WritablePathForType(type));
156 if (status != B_OK)
157 return status;
159 // Remove it
160 if (entry.IsDirectory()) {
161 // We need to remove all files in this directory
162 BDirectory directory(&entry);
163 if (directory.InitCheck() == B_OK) {
164 size_t length = strlen(type);
165 char subType[B_PATH_NAME_LENGTH];
166 memcpy(subType, type, length);
167 subType[length++] = '/';
169 BEntry subEntry;
170 while (directory.GetNextEntry(&subEntry) == B_OK) {
171 // Construct MIME type and remove it
172 if (subEntry.GetName(subType + length) == B_OK) {
173 status = Delete(subType);
174 if (status != B_OK)
175 return status;
181 status = entry.Remove();
183 if (status == B_OK) {
184 // Notify the installed types database
185 fInstalledTypes.RemoveType(type);
186 // Notify the supporting apps database
187 fSupportingApps.DeleteSupportedTypes(type, true);
188 // Notify the monitor service
189 _SendDeleteNotification(type);
192 return status;
196 status_t
197 Database::_SetStringValue(const char *type, int32 what, const char* attribute,
198 type_code attributeType, size_t maxLength, const char *value)
200 size_t length = value != NULL ? strlen(value) : 0;
201 if (type == NULL || value == NULL || length >= maxLength)
202 return B_BAD_VALUE;
204 char oldValue[maxLength];
205 status_t status = fLocation->ReadAttribute(type, attribute, oldValue,
206 maxLength, attributeType);
207 if (status >= B_OK && !strcmp(value, oldValue)) {
208 // nothing has changed, no need to write back the data
209 return B_OK;
212 bool didCreate = false;
213 status = fLocation->WriteAttribute(type, attribute, value, length + 1,
214 attributeType, &didCreate);
216 if (status == B_OK) {
217 if (didCreate)
218 _SendInstallNotification(type);
219 else
220 _SendMonitorUpdate(what, type, B_META_MIME_MODIFIED);
223 return status;
227 // SetAppHint
228 /*! \brief Sets the application hint for the given MIME type
229 \param type Pointer to a NULL-terminated string containing the MIME type of interest
230 \param decsription Pointer to an entry_ref containing the location of an application
231 that should be used when launching an application with this signature.
233 status_t
234 Database::SetAppHint(const char *type, const entry_ref *ref)
236 DBG(OUT("Database::SetAppHint()\n"));
238 if (type == NULL || ref == NULL)
239 return B_BAD_VALUE;
241 BPath path;
242 status_t status = path.SetTo(ref);
243 if (status < B_OK)
244 return status;
246 return _SetStringValue(type, B_APP_HINT_CHANGED, kAppHintAttr,
247 kAppHintType, B_PATH_NAME_LENGTH, path.Path());
250 // SetAttrInfo
251 /*! \brief Stores a BMessage describing the format of attributes typically associated with
252 files of the given MIME type
254 See BMimeType::SetAttrInfo() for description of the expected message format.
256 The \c BMessage::what value is ignored.
258 \param info Pointer to a pre-allocated and properly formatted BMessage containing
259 information about the file attributes typically associated with the
260 MIME type.
261 \return
262 - \c B_OK: Success
263 - "error code": Failure
265 status_t
266 Database::SetAttrInfo(const char *type, const BMessage *info)
268 DBG(OUT("Database::SetAttrInfo()\n"));
270 if (type == NULL || info == NULL)
271 return B_BAD_VALUE;
273 bool didCreate = false;
274 status_t status = fLocation->WriteMessageAttribute(type, kAttrInfoAttr,
275 *info, &didCreate);
276 if (status == B_OK) {
277 if (didCreate)
278 _SendInstallNotification(type);
279 else
280 _SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_MODIFIED);
283 return status;
287 // SetShortDescription
288 /*! \brief Sets the short description for the given MIME type
289 \param type Pointer to a NULL-terminated string containing the MIME type of interest
290 \param decsription Pointer to a NULL-terminated string containing the new short description
292 status_t
293 Database::SetShortDescription(const char *type, const char *description)
295 DBG(OUT("Database::SetShortDescription()\n"));
297 return _SetStringValue(type, B_SHORT_DESCRIPTION_CHANGED, kShortDescriptionAttr,
298 kShortDescriptionType, B_MIME_TYPE_LENGTH, description);
301 // SetLongDescription
302 /*! \brief Sets the long description for the given MIME type
303 \param type Pointer to a NULL-terminated string containing the MIME type of interest
304 \param decsription Pointer to a NULL-terminated string containing the new long description
306 status_t
307 Database::SetLongDescription(const char *type, const char *description)
309 DBG(OUT("Database::SetLongDescription()\n"));
311 size_t length = description != NULL ? strlen(description) : 0;
312 if (type == NULL || description == NULL || length >= B_MIME_TYPE_LENGTH)
313 return B_BAD_VALUE;
315 return _SetStringValue(type, B_LONG_DESCRIPTION_CHANGED, kLongDescriptionAttr,
316 kLongDescriptionType, B_MIME_TYPE_LENGTH, description);
321 \brief Sets the list of filename extensions associated with the MIME type
323 The list of extensions is given in a pre-allocated BMessage pointed to by
324 the \c extensions parameter. Please see BMimeType::SetFileExtensions()
325 for a description of the expected message format.
327 \param extensions Pointer to a pre-allocated, properly formatted BMessage containing
328 the new list of file extensions to associate with this MIME type.
329 \return
330 - \c B_OK: Success
331 - "error code": Failure
333 status_t
334 Database::SetFileExtensions(const char *type, const BMessage *extensions)
336 DBG(OUT("Database::SetFileExtensions()\n"));
338 if (type == NULL || extensions == NULL)
339 return B_BAD_VALUE;
341 bool didCreate = false;
342 status_t status = fLocation->WriteMessageAttribute(type,
343 kFileExtensionsAttr, *extensions, &didCreate);
345 if (status == B_OK) {
346 if (didCreate) {
347 _SendInstallNotification(type);
348 } else {
349 _SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type,
350 B_META_MIME_MODIFIED);
354 return status;
359 \brief Sets a bitmap icon for the given mime type
361 status_t
362 Database::SetIcon(const char* type, const BBitmap* icon, icon_size which)
364 if (icon != NULL)
365 return SetIcon(type, icon->Bits(), icon->BitsLength(), which);
366 return SetIcon(type, NULL, 0, which);
371 \brief Sets a bitmap icon for the given mime type
373 status_t
374 Database::SetIcon(const char *type, const void *data, size_t dataSize,
375 icon_size which)
377 return SetIconForType(type, NULL, data, dataSize, which);
382 \brief Sets the vector icon for the given mime type
384 status_t
385 Database::SetIcon(const char *type, const void *data, size_t dataSize)
387 return SetIconForType(type, NULL, data, dataSize);
391 status_t
392 Database::SetIconForType(const char* type, const char* fileType,
393 const BBitmap* icon, icon_size which)
395 if (icon != NULL) {
396 return SetIconForType(type, fileType, icon->Bits(),
397 (size_t)icon->BitsLength(), which);
399 return SetIconForType(type, fileType, NULL, 0, which);
403 // SetIconForType
404 /*! \brief Sets the large or mini icon used by an application of this type for
405 files of the given type.
407 The type of the \c BMimeType object is not required to actually be a subtype of
408 \c "application/"; that is the intended use however, and application-specific
409 icons are not expected to be present for non-application types.
411 The bitmap data pointed to by \c data must be of the proper size (\c 32x32
412 for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and the proper color
413 space (B_CMAP8).
415 \param type The MIME type
416 \param fileType The MIME type whose custom icon you wish to set.
417 \param data Pointer to an array of bitmap data of proper dimensions and color depth
418 \param dataSize The length of the array pointed to by \c data
419 \param size The size icon you're expecting (\c B_LARGE_ICON or \c B_MINI_ICON)
420 \return
421 - \c B_OK: Success
422 - "error code": Failure
425 status_t
426 Database::SetIconForType(const char *type, const char *fileType,
427 const void *data, size_t dataSize, icon_size which)
429 DBG(OUT("Database::SetIconForType()\n"));
431 if (type == NULL || data == NULL)
432 return B_BAD_VALUE;
434 int32 attrType = 0;
436 // Figure out what kind of data we *should* have
437 switch (which) {
438 case B_MINI_ICON:
439 attrType = kMiniIconType;
440 break;
441 case B_LARGE_ICON:
442 attrType = kLargeIconType;
443 break;
445 default:
446 return B_BAD_VALUE;
449 size_t attrSize = (size_t)which * (size_t)which;
450 // Double check the data we've been given
451 if (dataSize != attrSize)
452 return B_BAD_VALUE;
454 // Construct our attribute name
455 std::string attr;
456 if (fileType) {
457 attr = (which == B_MINI_ICON
458 ? kMiniIconAttrPrefix : kLargeIconAttrPrefix)
459 + BPrivate::Storage::to_lower(fileType);
460 } else
461 attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr;
463 // Write the icon data
464 BNode node;
465 bool didCreate = false;
467 status_t err = fLocation->OpenWritableType(type, node, true, &didCreate);
468 if (err != B_OK)
469 return err;
471 if (!err)
472 err = node.WriteAttr(attr.c_str(), attrType, 0, data, attrSize);
473 if (err >= 0)
474 err = err == (ssize_t)attrSize ? (status_t)B_OK : (status_t)B_FILE_ERROR;
475 if (didCreate) {
476 _SendInstallNotification(type);
477 } else if (!err) {
478 if (fileType) {
479 _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
480 which == B_LARGE_ICON, B_META_MIME_MODIFIED);
481 } else {
482 _SendMonitorUpdate(B_ICON_CHANGED, type,
483 which == B_LARGE_ICON, B_META_MIME_MODIFIED);
486 return err;
489 // SetIconForType
490 /*! \brief Sets the vector icon used by an application of this type for
491 files of the given type.
493 The type of the \c BMimeType object is not required to actually be a subtype of
494 \c "application/"; that is the intended use however, and application-specific
495 icons are not expected to be present for non-application types.
497 \param type The MIME type
498 \param fileType The MIME type whose custom icon you wish to set.
499 \param data Pointer to an array of vector data
500 \param dataSize The length of the array pointed to by \c data
501 \return
502 - \c B_OK: Success
503 - "error code": Failure
506 status_t
507 Database::SetIconForType(const char *type, const char *fileType,
508 const void *data, size_t dataSize)
510 DBG(OUT("Database::SetIconForType()\n"));
512 if (type == NULL || data == NULL)
513 return B_BAD_VALUE;
515 int32 attrType = B_VECTOR_ICON_TYPE;
517 // Construct our attribute name
518 std::string attr;
519 if (fileType) {
520 attr = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType);
521 } else
522 attr = kIconAttr;
524 // Write the icon data
525 BNode node;
526 bool didCreate = false;
528 status_t err = fLocation->OpenWritableType(type, node, true, &didCreate);
529 if (err != B_OK)
530 return err;
532 if (!err)
533 err = node.WriteAttr(attr.c_str(), attrType, 0, data, dataSize);
534 if (err >= 0)
535 err = err == (ssize_t)dataSize ? (status_t)B_OK : (status_t)B_FILE_ERROR;
536 if (didCreate) {
537 _SendInstallNotification(type);
538 } else if (!err) {
539 // TODO: extra notification for vector icons (currently
540 // passing "true" for B_LARGE_ICON)?
541 if (fileType) {
542 _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
543 true, B_META_MIME_MODIFIED);
544 } else {
545 _SendMonitorUpdate(B_ICON_CHANGED, type, true,
546 B_META_MIME_MODIFIED);
549 return err;
552 // SetPreferredApp
553 /*! \brief Sets the signature of the preferred application for the given app verb
555 Currently, the only supported app verb is \c B_OPEN
556 \param type Pointer to a NULL-terminated string containing the MIME type of interest
557 \param signature Pointer to a NULL-terminated string containing the MIME signature
558 of the new preferred application
559 \param verb \c app_verb action for which the new preferred application is applicable
561 status_t
562 Database::SetPreferredApp(const char *type, const char *signature, app_verb verb)
564 DBG(OUT("Database::SetPreferredApp()\n"));
566 // TODO: use "verb" some day!
568 return _SetStringValue(type, B_PREFERRED_APP_CHANGED, kPreferredAppAttr,
569 kPreferredAppType, B_MIME_TYPE_LENGTH, signature);
572 // SetSnifferRule
573 /*! \brief Sets the mime sniffer rule for the given mime type
575 status_t
576 Database::SetSnifferRule(const char *type, const char *rule)
578 DBG(OUT("Database::SetSnifferRule()\n"));
580 if (type == NULL || rule == NULL)
581 return B_BAD_VALUE;
583 bool didCreate = false;
584 status_t status = fLocation->WriteAttribute(type, kSnifferRuleAttr, rule,
585 strlen(rule) + 1, kSnifferRuleType, &didCreate);
587 if (status == B_OK)
588 status = fSnifferRules.SetSnifferRule(type, rule);
590 if (didCreate) {
591 _SendInstallNotification(type);
592 } else if (status == B_OK) {
593 _SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type,
594 B_META_MIME_MODIFIED);
597 return status;
600 // SetSupportedTypes
601 /*! \brief Sets the list of MIME types supported by the MIME type and
602 syncs the internal supporting apps database either partially or
603 completely.
605 Please see BMimeType::SetSupportedTypes() for details.
606 \param type The mime type of interest
607 \param types The supported types to be assigned to the file.
608 \param syncAll \c true to also synchronize the previously supported
609 types, \c false otherwise.
610 \return
611 - \c B_OK: success
612 - other error codes: failure
614 status_t
615 Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSync)
617 DBG(OUT("Database::SetSupportedTypes()\n"));
619 if (type == NULL || types == NULL)
620 return B_BAD_VALUE;
622 // Install the types
623 const char *supportedType;
624 for (int32 i = 0; types->FindString("types", i, &supportedType) == B_OK; i++) {
625 if (!fLocation->IsInstalled(supportedType)) {
626 if (Install(supportedType) != B_OK)
627 break;
629 // Since the type has been introduced by this application
630 // we take the liberty and make it the preferred handler
631 // for them, too.
632 SetPreferredApp(supportedType, type, B_OPEN);
636 // Write the attr
637 bool didCreate = false;
638 status_t status = fLocation->WriteMessageAttribute(type,
639 kSupportedTypesAttr, *types, &didCreate);
641 // Notify the monitor if we created the type when we opened it
642 if (status != B_OK)
643 return status;
645 // Update the supporting apps map
646 if (status == B_OK)
647 status = fSupportingApps.SetSupportedTypes(type, types, fullSync);
649 // Notify the monitor
650 if (didCreate) {
651 _SendInstallNotification(type);
652 } else if (status == B_OK) {
653 _SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type,
654 B_META_MIME_MODIFIED);
657 return status;
661 // GetInstalledSupertypes
662 /*! \brief Fetches a BMessage listing all the MIME supertypes currently
663 installed in the MIME database.
665 The types are copied into the \c "super_types" field of the passed-in \c BMessage.
666 The \c BMessage must be pre-allocated.
668 \param super_types Pointer to a pre-allocated \c BMessage into which the
669 MIME supertypes will be copied.
670 \return
671 - \c B_OK: Success
672 - "error code": Failure
674 status_t
675 Database::GetInstalledSupertypes(BMessage *supertypes)
677 return fInstalledTypes.GetInstalledSupertypes(supertypes);
680 // GetInstalledTypes
681 /*! \brief Fetches a BMessage listing all the MIME types currently installed
682 in the MIME database.
684 The types are copied into the \c "types" field of the passed-in \c BMessage.
685 The \c BMessage must be pre-allocated.
687 \param types Pointer to a pre-allocated \c BMessage into which the
688 MIME types will be copied.
689 \return
690 - \c B_OK: Success
691 - "error code": Failure
693 status_t
694 Database::GetInstalledTypes(BMessage *types)
696 return fInstalledTypes.GetInstalledTypes(types);
699 // GetInstalledTypes
700 /*! \brief Fetches a BMessage listing all the MIME subtypes of the given
701 supertype currently installed in the MIME database.
703 The types are copied into the \c "types" field of the passed-in \c BMessage.
704 The \c BMessage must be pre-allocated.
706 \param super_type Pointer to a string containing the MIME supertype whose
707 subtypes you wish to retrieve.
708 \param subtypes Pointer to a pre-allocated \c BMessage into which the appropriate
709 MIME subtypes will be copied.
710 \return
711 - \c B_OK: Success
712 - "error code": Failure
714 status_t
715 Database::GetInstalledTypes(const char *supertype, BMessage *subtypes)
717 return fInstalledTypes.GetInstalledTypes(supertype, subtypes);
720 // GetSupportingApps
721 /*! \brief Fetches a \c BMessage containing a list of MIME signatures of
722 applications that are able to handle files of this MIME type.
724 Please see BMimeType::GetSupportingApps() for more details.
726 status_t
727 Database::GetSupportingApps(const char *type, BMessage *signatures)
729 return fSupportingApps.GetSupportingApps(type, signatures);
732 // GetAssociatedTypes
733 /*! \brief Returns a list of mime types associated with the given file extension
735 Please see BMimeType::GetAssociatedTypes() for more details.
737 status_t
738 Database::GetAssociatedTypes(const char *extension, BMessage *types)
740 return B_ERROR;
743 // GuessMimeType
744 /*! \brief Guesses a MIME type for the entry referred to by the given
745 \c entry_ref.
747 This version of GuessMimeType() combines the features of the other
748 versions, plus adds a few tricks of its own:
749 - If the entry is a meta mime entry (i.e. has a \c "META:TYPE" attribute),
750 the type returned is \c "application/x-vnd.be-meta-mime".
751 - If the entry is a directory, the type returned is
752 \c "application/x-vnd.be-directory".
753 - If the entry is a symlink, the type returned is
754 \c "application/x-vnd.be-symlink".
755 - If the entry is a regular file, the file data is sniffed and, the
756 type returned is the mime type with the matching rule of highest
757 priority.
758 - If sniffing fails, the filename is checked for known extensions.
759 - If the extension check fails, the type returned is
760 \c "application/octet-stream".
762 \param ref Pointer to the entry_ref referring to the entry.
763 \param type Pointer to a pre-allocated BString which is set to the
764 resulting MIME type.
765 \return
766 - \c B_OK: success (even if the guess returned is "application/octet-stream")
767 - other error code: failure
769 status_t
770 Database::GuessMimeType(const entry_ref *ref, BString *result)
772 if (ref == NULL || result == NULL)
773 return B_BAD_VALUE;
775 BNode node;
776 struct stat statData;
777 status_t status = node.SetTo(ref);
778 if (status < B_OK)
779 return status;
781 attr_info info;
782 if (node.GetAttrInfo(kTypeAttr, &info) == B_OK) {
783 // Check for a META:TYPE attribute
784 result->SetTo(kMetaMimeType);
785 return B_OK;
788 // See if we have a directory, a symlink, or a vanilla file
789 status = node.GetStat(&statData);
790 if (status < B_OK)
791 return status;
793 if (S_ISDIR(statData.st_mode)) {
794 // Directory
795 result->SetTo(kDirectoryType);
796 } else if (S_ISLNK(statData.st_mode)) {
797 // Symlink
798 result->SetTo(kSymlinkType);
799 } else if (S_ISREG(statData.st_mode)) {
800 // Vanilla file: sniff first
801 status = fSnifferRules.GuessMimeType(ref, result);
803 // If that fails, check extensions
804 if (status == kMimeGuessFailureError)
805 status = fAssociatedTypes.GuessMimeType(ref, result);
807 // If that fails, return the generic file type
808 if (status == kMimeGuessFailureError) {
809 result->SetTo(kGenericFileType);
810 status = B_OK;
812 } else {
813 // TODO: we could filter out devices, ...
814 return B_BAD_TYPE;
817 return status;
820 // GuessMimeType
821 /*! \brief Guesses a MIME type for the supplied chunk of data.
823 See \c SnifferRules::GuessMimeType(BPositionIO*, BString*)
824 for more details.
826 \param buffer Pointer to the data buffer.
827 \param length Size of the buffer in bytes.
828 \param type Pointer to a pre-allocated BString which is set to the
829 resulting MIME type.
830 \return
831 - \c B_OK: success
832 - error code: failure
834 status_t
835 Database::GuessMimeType(const void *buffer, int32 length, BString *result)
837 if (buffer == NULL || result == NULL)
838 return B_BAD_VALUE;
840 status_t status = fSnifferRules.GuessMimeType(buffer, length, result);
841 if (status == kMimeGuessFailureError) {
842 result->SetTo(kGenericFileType);
843 return B_OK;
846 return status;
849 // GuessMimeType
850 /*! \brief Guesses a MIME type for the given filename.
852 Only the filename itself is taken into consideration (in particular its
853 name extension), not the entry or corresponding data it refers to (in fact,
854 an entry with that name need not exist at all.
856 \param filename The filename.
857 \param type Pointer to a pre-allocated BString which is set to the
858 resulting MIME type.
859 \return
860 - \c B_OK: success
861 - error code: failure
863 status_t
864 Database::GuessMimeType(const char *filename, BString *result)
866 if (filename == NULL || result == NULL)
867 return B_BAD_VALUE;
869 status_t status = fAssociatedTypes.GuessMimeType(filename, result);
870 if (status == kMimeGuessFailureError) {
871 result->SetTo(kGenericFileType);
872 return B_OK;
875 return status;
879 /*! \brief Subscribes the given BMessenger to the MIME monitor service
881 Notification messages will be sent with a \c BMessage::what value
882 of \c B_META_MIME_CHANGED. Notification messages have the following
883 fields:
885 <table>
886 <tr>
887 <td> Name </td>
888 <td> Type </td>
889 <td> Description </td>
890 </tr>
891 <tr>
892 <td> \c be:type </td>
893 <td> \c B_STRING_TYPE </td>
894 <td> The MIME type that was changed </td>
895 </tr>
896 <tr>
897 <td> \c be:which </td>
898 <td> \c B_INT32_TYPE </td>
899 <td> Bitmask describing which attributes were changed (see below) </td>
900 </tr>
901 <tr>
902 <td> \c be:extra_type </td>
903 <td> \c B_STRING_TYPE </td>
904 <td> Additional MIME type string (applicable to B_ICON_FOR_TYPE_CHANGED notifications only)</td>
905 </tr>
906 <tr>
907 <td> \c be:large_icon </td>
908 <td> \c B_BOOL_TYPE </td>
909 <td> \c true if the large icon was changed, \c false if the small icon
910 was changed (applicable to B_ICON_[FOR_TYPE_]CHANGED updates only) </td>
911 </tr>
912 </table>
914 The \c be:which field of the message describes which attributes were updated, and
915 may be the bitwise \c OR of any of the following values:
917 <table>
918 <tr>
919 <td> Value </td>
920 <td> Triggered By </td>
921 </tr>
922 <tr>
923 <td> \c B_ICON_CHANGED </td>
924 <td> \c BMimeType::SetIcon() </td>
925 </tr>
926 <tr>
927 <td> \c B_PREFERRED_APP_CHANGED </td>
928 <td> \c BMimeType::SetPreferredApp() </td>
929 </tr>
930 <tr>
931 <td> \c B_ATTR_INFO_CHANGED </td>
932 <td> \c BMimeType::SetAttrInfo() </td>
933 </tr>
934 <tr>
935 <td> \c B_FILE_EXTENSIONS_CHANGED </td>
936 <td> \c BMimeType::SetFileExtensions() </td>
937 </tr>
938 <tr>
939 <td> \c B_SHORT_DESCRIPTION_CHANGED </td>
940 <td> \c BMimeType::SetShortDescription() </td>
941 </tr>
942 <tr>
943 <td> \c B_LONG_DESCRIPTION_CHANGED </td>
944 <td> \c BMimeType::SetLongDescription() </td>
945 </tr>
946 <tr>
947 <td> \c B_ICON_FOR_TYPE_CHANGED </td>
948 <td> \c BMimeType::SetIconForType() </td>
949 </tr>
950 <tr>
951 <td> \c B_APP_HINT_CHANGED </td>
952 <td> \c BMimeType::SetAppHint() </td>
953 </tr>
954 </table>
956 \param target The \c BMessenger to subscribe to the MIME monitor service
958 status_t
959 Database::StartWatching(BMessenger target)
961 DBG(OUT("Database::StartWatching()\n"));
963 if (!target.IsValid())
964 return B_BAD_VALUE;
966 fMonitorMessengers.insert(target);
967 return B_OK;
972 Unsubscribes the given BMessenger from the MIME monitor service
973 \param target The \c BMessenger to unsubscribe
975 status_t
976 Database::StopWatching(BMessenger target)
978 DBG(OUT("Database::StopWatching()\n"));
980 if (!target.IsValid())
981 return B_BAD_VALUE;
983 status_t status = fMonitorMessengers.find(target) != fMonitorMessengers.end()
984 ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND;
985 if (status == B_OK)
986 fMonitorMessengers.erase(target);
988 return status;
992 /*! \brief Deletes the app hint attribute for the given type
994 A \c B_APP_HINT_CHANGED notification is sent to the mime monitor service.
995 \param type The mime type of interest
996 \return
997 - B_OK: success
998 - B_ENTRY_NOT_FOUND: no such attribute existed
999 - "error code": failure
1001 status_t
1002 Database::DeleteAppHint(const char *type)
1004 status_t status = fLocation->DeleteAttribute(type, kAppHintAttr);
1005 if (status == B_OK)
1006 _SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_DELETED);
1007 else if (status == B_ENTRY_NOT_FOUND)
1008 status = B_OK;
1010 return status;
1014 /*! \brief Deletes the attribute info attribute for the given type
1016 A \c B_ATTR_INFO_CHANGED notification is sent to the mime monitor service.
1017 \param type The mime type of interest
1018 \return
1019 - B_OK: success
1020 - B_ENTRY_NOT_FOUND: no such attribute existed
1021 - "error code": failure
1023 status_t
1024 Database::DeleteAttrInfo(const char *type)
1026 status_t status = fLocation->DeleteAttribute(type, kAttrInfoAttr);
1027 if (status == B_OK)
1028 _SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_DELETED);
1029 else if (status == B_ENTRY_NOT_FOUND)
1030 status = B_OK;
1032 return status;
1036 /*! \brief Deletes the short description attribute for the given type
1038 A \c B_SHORT_DESCRIPTION_CHANGED notification is sent to the mime monitor service.
1039 \param type The mime type of interest
1040 \return
1041 - B_OK: success
1042 - B_ENTRY_NOT_FOUND: no such attribute existed
1043 - "error code": failure
1045 status_t
1046 Database::DeleteShortDescription(const char *type)
1048 status_t status = fLocation->DeleteAttribute(type, kShortDescriptionAttr);
1049 if (status == B_OK)
1050 _SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
1051 else if (status == B_ENTRY_NOT_FOUND)
1052 status = B_OK;
1054 return status;
1058 /*! \brief Deletes the long description attribute for the given type
1060 A \c B_LONG_DESCRIPTION_CHANGED notification is sent to the mime monitor service.
1061 \param type The mime type of interest
1062 \return
1063 - B_OK: success
1064 - B_ENTRY_NOT_FOUND: no such attribute existed
1065 - "error code": failure
1067 status_t
1068 Database::DeleteLongDescription(const char *type)
1070 status_t status = fLocation->DeleteAttribute(type, kLongDescriptionAttr);
1071 if (status == B_OK)
1072 _SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
1073 else if (status == B_ENTRY_NOT_FOUND)
1074 status = B_OK;
1076 return status;
1080 /*! \brief Deletes the associated file extensions attribute for the given type
1082 A \c B_FILE_EXTENSIONS_CHANGED notification is sent to the mime monitor service.
1083 \param type The mime type of interest
1084 \return
1085 - B_OK: success
1086 - B_ENTRY_NOT_FOUND: no such attribute existed
1087 - "error code": failure
1089 status_t
1090 Database::DeleteFileExtensions(const char *type)
1092 status_t status = fLocation->DeleteAttribute(type, kFileExtensionsAttr);
1093 if (status == B_OK)
1094 _SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_DELETED);
1095 else if (status == B_ENTRY_NOT_FOUND)
1096 status = B_OK;
1098 return status;
1102 /*! \brief Deletes the icon of the given size for the given type
1104 A \c B_ICON_CHANGED notification is sent to the mime monitor service.
1105 \param type The mime type of interest
1106 \param which The icon size of interest
1107 \return
1108 - B_OK: success
1109 - B_ENTRY_NOT_FOUND: no such attribute existed
1110 - "error code": failure
1112 status_t
1113 Database::DeleteIcon(const char *type, icon_size which)
1115 const char *attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr;
1116 status_t status = fLocation->DeleteAttribute(type, attr);
1117 if (status == B_OK) {
1118 _SendMonitorUpdate(B_ICON_CHANGED, type, which == B_LARGE_ICON,
1119 B_META_MIME_DELETED);
1120 } else if (status == B_ENTRY_NOT_FOUND)
1121 status = B_OK;
1123 return status;
1127 /*! \brief Deletes the vector icon for the given type
1129 A \c B_ICON_CHANGED notification is sent to the mime monitor service.
1130 \param type The mime type of interest
1131 \return
1132 - B_OK: success
1133 - B_ENTRY_NOT_FOUND: no such attribute existed
1134 - "error code": failure
1136 status_t
1137 Database::DeleteIcon(const char *type)
1139 // TODO: extra notification for vector icon (for now we notify a "large"
1140 // icon)
1141 status_t status = fLocation->DeleteAttribute(type, kIconAttr);
1142 if (status == B_OK) {
1143 _SendMonitorUpdate(B_ICON_CHANGED, type, true,
1144 B_META_MIME_DELETED);
1145 } else if (status == B_ENTRY_NOT_FOUND)
1146 status = B_OK;
1148 return status;
1152 /*! \brief Deletes the icon of the given size associated with the given file
1153 type for the given application signature.
1155 (If this function seems confusing, please see BMimeType::GetIconForType() for a
1156 better description of what the *IconForType() functions are used for.)
1158 A \c B_ICON_FOR_TYPE_CHANGED notification is sent to the mime monitor service.
1159 \param type The mime type of the application whose custom icon you are deleting.
1160 \param fileType The mime type for which you no longer wish \c type to have a custom icon.
1161 \param which The icon size of interest
1162 \return
1163 - B_OK: success
1164 - B_ENTRY_NOT_FOUND: no such attribute existed
1165 - "error code": failure
1167 status_t
1168 Database::DeleteIconForType(const char *type, const char *fileType, icon_size which)
1170 if (fileType == NULL)
1171 return B_BAD_VALUE;
1173 std::string attr = (which == B_MINI_ICON
1174 ? kMiniIconAttrPrefix : kLargeIconAttrPrefix) + BPrivate::Storage::to_lower(fileType);
1176 status_t status = fLocation->DeleteAttribute(type, attr.c_str());
1177 if (status == B_OK) {
1178 _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
1179 which == B_LARGE_ICON, B_META_MIME_DELETED);
1180 } else if (status == B_ENTRY_NOT_FOUND)
1181 status = B_OK;
1183 return status;
1187 /*! \brief Deletes the vector icon associated with the given file
1188 type for the given application signature.
1190 (If this function seems confusing, please see BMimeType::GetIconForType() for a
1191 better description of what the *IconForType() functions are used for.)
1193 A \c B_ICON_FOR_TYPE_CHANGED notification is sent to the mime monitor service.
1194 \param type The mime type of the application whose custom icon you are deleting.
1195 \param fileType The mime type for which you no longer wish \c type to have a custom icon.
1196 \return
1197 - B_OK: success
1198 - B_ENTRY_NOT_FOUND: no such attribute existed
1199 - "error code": failure
1201 status_t
1202 Database::DeleteIconForType(const char *type, const char *fileType)
1204 if (fileType == NULL)
1205 return B_BAD_VALUE;
1207 std::string attr = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType);
1209 // TODO: introduce extra notification for vector icons?
1210 // (uses B_LARGE_ICON now)
1211 status_t status = fLocation->DeleteAttribute(type, attr.c_str());
1212 if (status == B_OK) {
1213 _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
1214 true, B_META_MIME_DELETED);
1215 } else if (status == B_ENTRY_NOT_FOUND)
1216 status = B_OK;
1218 return status;
1222 // DeletePreferredApp
1223 //! Deletes the preferred app for the given app verb for the given type
1224 /*! A \c B_PREFERRED_APP_CHANGED notification is sent to the mime monitor service.
1225 \param type The mime type of interest
1226 \param which The app verb of interest
1227 \return
1228 - B_OK: success
1229 - B_ENTRY_NOT_FOUND: no such attribute existed
1230 - "error code": failure
1232 status_t
1233 Database::DeletePreferredApp(const char *type, app_verb verb)
1235 status_t status;
1237 switch (verb) {
1238 case B_OPEN:
1239 status = fLocation->DeleteAttribute(type, kPreferredAppAttr);
1240 break;
1242 default:
1243 return B_BAD_VALUE;
1246 /*! \todo The R5 monitor makes no note of which app_verb value was updated. If
1247 additional app_verb values besides \c B_OPEN are someday added, the format
1248 of the MIME monitor messages will need to be augmented.
1250 if (status == B_OK)
1251 _SendMonitorUpdate(B_PREFERRED_APP_CHANGED, type, B_META_MIME_DELETED);
1252 else if (status == B_ENTRY_NOT_FOUND)
1253 status = B_OK;
1255 return status;
1258 // DeleteSnifferRule
1259 //! Deletes the sniffer rule for the given type
1260 /*! A \c B_SNIFFER_RULE_CHANGED notification is sent to the mime monitor service,
1261 and the corresponding rule is removed from the internal database of sniffer
1262 rules.
1263 \param type The mime type of interest
1264 \return
1265 - B_OK: success
1266 - B_ENTRY_NOT_FOUND: no such attribute existed
1267 - "error code": failure
1269 status_t
1270 Database::DeleteSnifferRule(const char *type)
1272 status_t status = fLocation->DeleteAttribute(type, kSnifferRuleAttr);
1273 if (status == B_OK) {
1274 status = fSnifferRules.DeleteSnifferRule(type);
1275 if (status == B_OK) {
1276 _SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type,
1277 B_META_MIME_DELETED);
1279 } else if (status == B_ENTRY_NOT_FOUND)
1280 status = B_OK;
1282 return status;
1285 // DeleteSupportedTypes
1286 //! Deletes the supported types list for the given type
1287 /*! A \c B_SUPPORTED_TYPES_CHANGED notification is sent to the mime monitor service.
1288 If \c fullSync is \c true, the given type is removed from the internal list
1289 of supporting applictions for each previously supported type. If \c fullSync
1290 is \c false, the said removal will occur the next time SetSupportedTypes() or
1291 DeleteSupportedTypes() is called with a \c true \c fullSync paramter, or
1292 \c Delete() is called for the given type.
1293 \param type The mime type of interest
1294 \param fullSync Whether or not to remove the type as a supporting app for
1295 all previously supported types
1296 \return
1297 - B_OK: success
1298 - B_ENTRY_NOT_FOUND: no such attribute existed
1299 - "error code": failure
1301 status_t
1302 Database::DeleteSupportedTypes(const char *type, bool fullSync)
1304 status_t status = fLocation->DeleteAttribute(type, kSupportedTypesAttr);
1306 // Update the supporting apps database. If fullSync is specified,
1307 // do so even if the supported types attribute didn't exist, as
1308 // stranded types *may* exist in the database due to previous
1309 // calls to {Set,Delete}SupportedTypes() with fullSync == false.
1310 bool sendUpdate = true;
1311 if (status == B_OK)
1312 status = fSupportingApps.DeleteSupportedTypes(type, fullSync);
1313 else if (status == B_ENTRY_NOT_FOUND) {
1314 status = B_OK;
1315 if (fullSync)
1316 fSupportingApps.DeleteSupportedTypes(type, fullSync);
1317 else
1318 sendUpdate = false;
1321 // Send a monitor notification
1322 if (status == B_OK && sendUpdate)
1323 _SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type, B_META_MIME_DELETED);
1325 return status;
1329 void
1330 Database::DeferInstallNotification(const char* type)
1332 AutoLocker<BLocker> _(fDeferredInstallNotificationsLocker);
1334 // check, if already deferred
1335 if (_FindDeferredInstallNotification(type))
1336 return;
1338 // add new
1339 DeferredInstallNotification* notification
1340 = new(std::nothrow) DeferredInstallNotification;
1341 if (notification == NULL)
1342 return;
1344 strlcpy(notification->type, type, sizeof(notification->type));
1345 notification->notify = false;
1347 if (!fDeferredInstallNotifications.AddItem(notification))
1348 delete notification;
1352 void
1353 Database::UndeferInstallNotification(const char* type)
1355 AutoLocker<BLocker> locker(fDeferredInstallNotificationsLocker);
1357 // check, if deferred at all
1358 DeferredInstallNotification* notification
1359 = _FindDeferredInstallNotification(type, true);
1361 locker.Unlock();
1363 if (notification == NULL)
1364 return;
1366 // notify, if requested
1367 if (notification->notify)
1368 _SendInstallNotification(notification->type);
1370 delete notification;
1374 //! \brief Sends a \c B_MIME_TYPE_CREATED notification to the mime monitor service
1375 status_t
1376 Database::_SendInstallNotification(const char *type)
1378 return _SendMonitorUpdate(B_MIME_TYPE_CREATED, type, B_META_MIME_MODIFIED);
1382 //! \brief Sends a \c B_MIME_TYPE_DELETED notification to the mime monitor service
1383 status_t
1384 Database::_SendDeleteNotification(const char *type)
1386 // Tell the backend first
1387 return _SendMonitorUpdate(B_MIME_TYPE_DELETED, type, B_META_MIME_MODIFIED);
1390 // _SendMonitorUpdate
1391 /*! \brief Sends an update notification to all BMessengers that have
1392 subscribed to the MIME Monitor service
1393 \param type The MIME type that was updated
1394 \param which Bitmask describing which attribute was updated
1395 \param extraType The MIME type to which the change is applies
1396 \param largeIcon \true if the the large icon was updated, \false if the
1397 small icon was updated
1399 status_t
1400 Database::_SendMonitorUpdate(int32 which, const char *type, const char *extraType,
1401 bool largeIcon, int32 action)
1403 BMessage msg(B_META_MIME_CHANGED);
1404 status_t err;
1406 if (_CheckDeferredInstallNotification(which, type))
1407 return B_OK;
1409 err = msg.AddInt32("be:which", which);
1410 if (!err)
1411 err = msg.AddString("be:type", type);
1412 if (!err)
1413 err = msg.AddString("be:extra_type", extraType);
1414 if (!err)
1415 err = msg.AddBool("be:large_icon", largeIcon);
1416 if (!err)
1417 err = msg.AddInt32("be:action", action);
1418 if (!err)
1419 err = _SendMonitorUpdate(msg);
1420 return err;
1423 // _SendMonitorUpdate
1424 /*! \brief Sends an update notification to all BMessengers that have
1425 subscribed to the MIME Monitor service
1426 \param type The MIME type that was updated
1427 \param which Bitmask describing which attribute was updated
1428 \param extraType The MIME type to which the change is applies
1430 status_t
1431 Database::_SendMonitorUpdate(int32 which, const char *type, const char *extraType,
1432 int32 action)
1434 if (_CheckDeferredInstallNotification(which, type))
1435 return B_OK;
1437 BMessage msg(B_META_MIME_CHANGED);
1439 status_t err = msg.AddInt32("be:which", which);
1440 if (!err)
1441 err = msg.AddString("be:type", type);
1442 if (!err)
1443 err = msg.AddString("be:extra_type", extraType);
1444 if (!err)
1445 err = msg.AddInt32("be:action", action);
1446 if (!err)
1447 err = _SendMonitorUpdate(msg);
1448 return err;
1451 // _SendMonitorUpdate
1452 /*! \brief Sends an update notification to all BMessengers that have
1453 subscribed to the MIME Monitor service
1454 \param type The MIME type that was updated
1455 \param which Bitmask describing which attribute was updated
1456 \param largeIcon \true if the the large icon was updated, \false if the
1457 small icon was updated
1459 status_t
1460 Database::_SendMonitorUpdate(int32 which, const char *type, bool largeIcon, int32 action)
1462 if (_CheckDeferredInstallNotification(which, type))
1463 return B_OK;
1465 BMessage msg(B_META_MIME_CHANGED);
1467 status_t err = msg.AddInt32("be:which", which);
1468 if (!err)
1469 err = msg.AddString("be:type", type);
1470 if (!err)
1471 err = msg.AddBool("be:large_icon", largeIcon);
1472 if (!err)
1473 err = msg.AddInt32("be:action", action);
1474 if (!err)
1475 err = _SendMonitorUpdate(msg);
1476 return err;
1479 // _SendMonitorUpdate
1480 /*! \brief Sends an update notification to all BMessengers that have
1481 subscribed to the MIME Monitor service
1482 \param type The MIME type that was updated
1483 \param which Bitmask describing which attribute was updated
1485 status_t
1486 Database::_SendMonitorUpdate(int32 which, const char *type, int32 action)
1488 if (_CheckDeferredInstallNotification(which, type))
1489 return B_OK;
1491 BMessage msg(B_META_MIME_CHANGED);
1493 status_t err = msg.AddInt32("be:which", which);
1494 if (!err)
1495 err = msg.AddString("be:type", type);
1496 if (!err)
1497 err = msg.AddInt32("be:action", action);
1498 if (!err)
1499 err = _SendMonitorUpdate(msg);
1500 return err;
1503 // _SendMonitorUpdate
1504 /*! \brief Sends an update notification to all BMessengers that have subscribed to
1505 the MIME Monitor service
1506 \param BMessage A preformatted MIME monitor message to be sent to all subscribers
1508 status_t
1509 Database::_SendMonitorUpdate(BMessage &msg)
1511 if (fNotificationListener == NULL)
1512 return B_OK;
1514 status_t err;
1515 std::set<BMessenger>::const_iterator i;
1516 for (i = fMonitorMessengers.begin(); i != fMonitorMessengers.end(); i++) {
1517 status_t err = fNotificationListener->Notify(&msg, *i);
1518 if (err) {
1519 DBG(OUT("Database::_SendMonitorUpdate(BMessage&): DeliverMessage failed, 0x%lx\n", err));
1522 err = B_OK;
1523 return err;
1527 Database::DeferredInstallNotification*
1528 Database::_FindDeferredInstallNotification(const char* type, bool remove)
1530 for (int32 i = 0;
1531 DeferredInstallNotification* notification
1532 = (DeferredInstallNotification*)fDeferredInstallNotifications
1533 .ItemAt(i); i++) {
1534 if (strcmp(type, notification->type) == 0) {
1535 if (remove)
1536 fDeferredInstallNotifications.RemoveItem(i);
1537 return notification;
1541 return NULL;
1545 bool
1546 Database::_CheckDeferredInstallNotification(int32 which, const char* type)
1548 AutoLocker<BLocker> locker(fDeferredInstallNotificationsLocker);
1550 // check, if deferred at all
1551 DeferredInstallNotification* notification
1552 = _FindDeferredInstallNotification(type);
1553 if (notification == NULL)
1554 return false;
1556 if (which == B_MIME_TYPE_DELETED) {
1557 // MIME type deleted -- if the install notification had been
1558 // deferred, we don't send anything
1559 if (notification->notify) {
1560 fDeferredInstallNotifications.RemoveItem(notification);
1561 delete notification;
1562 return true;
1564 } else if (which == B_MIME_TYPE_CREATED) {
1565 // MIME type created -- defer notification
1566 notification->notify = true;
1567 return true;
1568 } else {
1569 // MIME type update -- don't send update, if deferred
1570 if (notification->notify)
1571 return true;
1574 return false;
1578 } // namespace Mime
1579 } // namespace Storage
1580 } // namespace BPrivate