2 * Copyright 2002-2014, Haiku.
3 * Distributed under the terms of the MIT License.
7 * Axel Dörfler, axeld@pinc-software.de
8 * Rene Gollent, rene@gollent.com.
12 #include <mime/Database.h>
20 #include <Application.h>
23 #include <Directory.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>
49 Database::NotificationListener::~NotificationListener()
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.
66 /*! \brief Creates and initializes a Mime::Database object.
68 Database::Database(DatabaseLocation
* databaseLocation
, MimeSniffer
* mimeSniffer
,
69 NotificationListener
* notificationListener
)
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
);
87 /*! \brief Frees all resources associated with this object.
94 /*! \brief Returns the initialization status of the object.
97 - "error code": failure
100 Database::InitCheck() const
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
113 - B_FILE_EXISTS: the type is already installed
114 - "error code": failure
117 Database::Install(const char *type
)
123 status_t err
= entry
.SetTo(fLocation
->WritablePathForType(type
));
124 if (err
== B_OK
|| err
== B_ENTRY_NOT_FOUND
) {
128 bool didCreate
= false;
130 err
= fLocation
->OpenWritableType(type
, node
, true, &didCreate
);
131 if (!err
&& didCreate
) {
132 fInstalledTypes
.AddType(type
);
133 _SendInstallNotification(type
);
141 /*! \brief Removes the given type from the database
142 \param type Pointer to a NULL-terminated string containing the MIME type of interest
145 - "error code": failure
148 Database::Delete(const char *type
)
155 status_t status
= entry
.SetTo(fLocation
->WritablePathForType(type
));
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
++] = '/';
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
);
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
);
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
)
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
212 bool didCreate
= false;
213 status
= fLocation
->WriteAttribute(type
, attribute
, value
, length
+ 1,
214 attributeType
, &didCreate
);
216 if (status
== B_OK
) {
218 _SendInstallNotification(type
);
220 _SendMonitorUpdate(what
, type
, B_META_MIME_MODIFIED
);
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.
234 Database::SetAppHint(const char *type
, const entry_ref
*ref
)
236 DBG(OUT("Database::SetAppHint()\n"));
238 if (type
== NULL
|| ref
== NULL
)
242 status_t status
= path
.SetTo(ref
);
246 return _SetStringValue(type
, B_APP_HINT_CHANGED
, kAppHintAttr
,
247 kAppHintType
, B_PATH_NAME_LENGTH
, path
.Path());
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
263 - "error code": Failure
266 Database::SetAttrInfo(const char *type
, const BMessage
*info
)
268 DBG(OUT("Database::SetAttrInfo()\n"));
270 if (type
== NULL
|| info
== NULL
)
273 bool didCreate
= false;
274 status_t status
= fLocation
->WriteMessageAttribute(type
, kAttrInfoAttr
,
276 if (status
== B_OK
) {
278 _SendInstallNotification(type
);
280 _SendMonitorUpdate(B_ATTR_INFO_CHANGED
, type
, B_META_MIME_MODIFIED
);
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
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
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
)
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.
331 - "error code": Failure
334 Database::SetFileExtensions(const char *type
, const BMessage
*extensions
)
336 DBG(OUT("Database::SetFileExtensions()\n"));
338 if (type
== NULL
|| extensions
== NULL
)
341 bool didCreate
= false;
342 status_t status
= fLocation
->WriteMessageAttribute(type
,
343 kFileExtensionsAttr
, *extensions
, &didCreate
);
345 if (status
== B_OK
) {
347 _SendInstallNotification(type
);
349 _SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED
, type
,
350 B_META_MIME_MODIFIED
);
359 \brief Sets a bitmap icon for the given mime type
362 Database::SetIcon(const char* type
, const BBitmap
* icon
, icon_size which
)
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
374 Database::SetIcon(const char *type
, const void *data
, size_t dataSize
,
377 return SetIconForType(type
, NULL
, data
, dataSize
, which
);
382 \brief Sets the vector icon for the given mime type
385 Database::SetIcon(const char *type
, const void *data
, size_t dataSize
)
387 return SetIconForType(type
, NULL
, data
, dataSize
);
392 Database::SetIconForType(const char* type
, const char* fileType
,
393 const BBitmap
* icon
, icon_size which
)
396 return SetIconForType(type
, fileType
, icon
->Bits(),
397 (size_t)icon
->BitsLength(), which
);
399 return SetIconForType(type
, fileType
, NULL
, 0, which
);
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
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)
422 - "error code": Failure
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
)
436 // Figure out what kind of data we *should* have
439 attrType
= kMiniIconType
;
442 attrType
= kLargeIconType
;
449 size_t attrSize
= (size_t)which
* (size_t)which
;
450 // Double check the data we've been given
451 if (dataSize
!= attrSize
)
454 // Construct our attribute name
457 attr
= (which
== B_MINI_ICON
458 ? kMiniIconAttrPrefix
: kLargeIconAttrPrefix
)
459 + BPrivate::Storage::to_lower(fileType
);
461 attr
= which
== B_MINI_ICON
? kMiniIconAttr
: kLargeIconAttr
;
463 // Write the icon data
465 bool didCreate
= false;
467 status_t err
= fLocation
->OpenWritableType(type
, node
, true, &didCreate
);
472 err
= node
.WriteAttr(attr
.c_str(), attrType
, 0, data
, attrSize
);
474 err
= err
== (ssize_t
)attrSize
? (status_t
)B_OK
: (status_t
)B_FILE_ERROR
;
476 _SendInstallNotification(type
);
479 _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED
, type
, fileType
,
480 which
== B_LARGE_ICON
, B_META_MIME_MODIFIED
);
482 _SendMonitorUpdate(B_ICON_CHANGED
, type
,
483 which
== B_LARGE_ICON
, B_META_MIME_MODIFIED
);
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
503 - "error code": Failure
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
)
515 int32 attrType
= B_VECTOR_ICON_TYPE
;
517 // Construct our attribute name
520 attr
= kIconAttrPrefix
+ BPrivate::Storage::to_lower(fileType
);
524 // Write the icon data
526 bool didCreate
= false;
528 status_t err
= fLocation
->OpenWritableType(type
, node
, true, &didCreate
);
533 err
= node
.WriteAttr(attr
.c_str(), attrType
, 0, data
, dataSize
);
535 err
= err
== (ssize_t
)dataSize
? (status_t
)B_OK
: (status_t
)B_FILE_ERROR
;
537 _SendInstallNotification(type
);
539 // TODO: extra notification for vector icons (currently
540 // passing "true" for B_LARGE_ICON)?
542 _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED
, type
, fileType
,
543 true, B_META_MIME_MODIFIED
);
545 _SendMonitorUpdate(B_ICON_CHANGED
, type
, true,
546 B_META_MIME_MODIFIED
);
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
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
);
573 /*! \brief Sets the mime sniffer rule for the given mime type
576 Database::SetSnifferRule(const char *type
, const char *rule
)
578 DBG(OUT("Database::SetSnifferRule()\n"));
580 if (type
== NULL
|| rule
== NULL
)
583 bool didCreate
= false;
584 status_t status
= fLocation
->WriteAttribute(type
, kSnifferRuleAttr
, rule
,
585 strlen(rule
) + 1, kSnifferRuleType
, &didCreate
);
588 status
= fSnifferRules
.SetSnifferRule(type
, rule
);
591 _SendInstallNotification(type
);
592 } else if (status
== B_OK
) {
593 _SendMonitorUpdate(B_SNIFFER_RULE_CHANGED
, type
,
594 B_META_MIME_MODIFIED
);
601 /*! \brief Sets the list of MIME types supported by the MIME type and
602 syncs the internal supporting apps database either partially or
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.
612 - other error codes: failure
615 Database::SetSupportedTypes(const char *type
, const BMessage
*types
, bool fullSync
)
617 DBG(OUT("Database::SetSupportedTypes()\n"));
619 if (type
== NULL
|| types
== NULL
)
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
)
629 // Since the type has been introduced by this application
630 // we take the liberty and make it the preferred handler
632 SetPreferredApp(supportedType
, type
, B_OPEN
);
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
645 // Update the supporting apps map
647 status
= fSupportingApps
.SetSupportedTypes(type
, types
, fullSync
);
649 // Notify the monitor
651 _SendInstallNotification(type
);
652 } else if (status
== B_OK
) {
653 _SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED
, type
,
654 B_META_MIME_MODIFIED
);
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.
672 - "error code": Failure
675 Database::GetInstalledSupertypes(BMessage
*supertypes
)
677 return fInstalledTypes
.GetInstalledSupertypes(supertypes
);
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.
691 - "error code": Failure
694 Database::GetInstalledTypes(BMessage
*types
)
696 return fInstalledTypes
.GetInstalledTypes(types
);
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.
712 - "error code": Failure
715 Database::GetInstalledTypes(const char *supertype
, BMessage
*subtypes
)
717 return fInstalledTypes
.GetInstalledTypes(supertype
, subtypes
);
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.
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.
738 Database::GetAssociatedTypes(const char *extension
, BMessage
*types
)
744 /*! \brief Guesses a MIME type for the entry referred to by the given
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
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
766 - \c B_OK: success (even if the guess returned is "application/octet-stream")
767 - other error code: failure
770 Database::GuessMimeType(const entry_ref
*ref
, BString
*result
)
772 if (ref
== NULL
|| result
== NULL
)
776 struct stat statData
;
777 status_t status
= node
.SetTo(ref
);
782 if (node
.GetAttrInfo(kTypeAttr
, &info
) == B_OK
) {
783 // Check for a META:TYPE attribute
784 result
->SetTo(kMetaMimeType
);
788 // See if we have a directory, a symlink, or a vanilla file
789 status
= node
.GetStat(&statData
);
793 if (S_ISDIR(statData
.st_mode
)) {
795 result
->SetTo(kDirectoryType
);
796 } else if (S_ISLNK(statData
.st_mode
)) {
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
);
813 // TODO: we could filter out devices, ...
821 /*! \brief Guesses a MIME type for the supplied chunk of data.
823 See \c SnifferRules::GuessMimeType(BPositionIO*, BString*)
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
832 - error code: failure
835 Database::GuessMimeType(const void *buffer
, int32 length
, BString
*result
)
837 if (buffer
== NULL
|| result
== NULL
)
840 status_t status
= fSnifferRules
.GuessMimeType(buffer
, length
, result
);
841 if (status
== kMimeGuessFailureError
) {
842 result
->SetTo(kGenericFileType
);
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
861 - error code: failure
864 Database::GuessMimeType(const char *filename
, BString
*result
)
866 if (filename
== NULL
|| result
== NULL
)
869 status_t status
= fAssociatedTypes
.GuessMimeType(filename
, result
);
870 if (status
== kMimeGuessFailureError
) {
871 result
->SetTo(kGenericFileType
);
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
889 <td> Description </td>
892 <td> \c be:type </td>
893 <td> \c B_STRING_TYPE </td>
894 <td> The MIME type that was changed </td>
897 <td> \c be:which </td>
898 <td> \c B_INT32_TYPE </td>
899 <td> Bitmask describing which attributes were changed (see below) </td>
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>
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>
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:
920 <td> Triggered By </td>
923 <td> \c B_ICON_CHANGED </td>
924 <td> \c BMimeType::SetIcon() </td>
927 <td> \c B_PREFERRED_APP_CHANGED </td>
928 <td> \c BMimeType::SetPreferredApp() </td>
931 <td> \c B_ATTR_INFO_CHANGED </td>
932 <td> \c BMimeType::SetAttrInfo() </td>
935 <td> \c B_FILE_EXTENSIONS_CHANGED </td>
936 <td> \c BMimeType::SetFileExtensions() </td>
939 <td> \c B_SHORT_DESCRIPTION_CHANGED </td>
940 <td> \c BMimeType::SetShortDescription() </td>
943 <td> \c B_LONG_DESCRIPTION_CHANGED </td>
944 <td> \c BMimeType::SetLongDescription() </td>
947 <td> \c B_ICON_FOR_TYPE_CHANGED </td>
948 <td> \c BMimeType::SetIconForType() </td>
951 <td> \c B_APP_HINT_CHANGED </td>
952 <td> \c BMimeType::SetAppHint() </td>
956 \param target The \c BMessenger to subscribe to the MIME monitor service
959 Database::StartWatching(BMessenger target
)
961 DBG(OUT("Database::StartWatching()\n"));
963 if (!target
.IsValid())
966 fMonitorMessengers
.insert(target
);
972 Unsubscribes the given BMessenger from the MIME monitor service
973 \param target The \c BMessenger to unsubscribe
976 Database::StopWatching(BMessenger target
)
978 DBG(OUT("Database::StopWatching()\n"));
980 if (!target
.IsValid())
983 status_t status
= fMonitorMessengers
.find(target
) != fMonitorMessengers
.end()
984 ? (status_t
)B_OK
: (status_t
)B_ENTRY_NOT_FOUND
;
986 fMonitorMessengers
.erase(target
);
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
998 - B_ENTRY_NOT_FOUND: no such attribute existed
999 - "error code": failure
1002 Database::DeleteAppHint(const char *type
)
1004 status_t status
= fLocation
->DeleteAttribute(type
, kAppHintAttr
);
1006 _SendMonitorUpdate(B_APP_HINT_CHANGED
, type
, B_META_MIME_DELETED
);
1007 else if (status
== B_ENTRY_NOT_FOUND
)
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
1020 - B_ENTRY_NOT_FOUND: no such attribute existed
1021 - "error code": failure
1024 Database::DeleteAttrInfo(const char *type
)
1026 status_t status
= fLocation
->DeleteAttribute(type
, kAttrInfoAttr
);
1028 _SendMonitorUpdate(B_ATTR_INFO_CHANGED
, type
, B_META_MIME_DELETED
);
1029 else if (status
== B_ENTRY_NOT_FOUND
)
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
1042 - B_ENTRY_NOT_FOUND: no such attribute existed
1043 - "error code": failure
1046 Database::DeleteShortDescription(const char *type
)
1048 status_t status
= fLocation
->DeleteAttribute(type
, kShortDescriptionAttr
);
1050 _SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED
, type
, B_META_MIME_DELETED
);
1051 else if (status
== B_ENTRY_NOT_FOUND
)
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
1064 - B_ENTRY_NOT_FOUND: no such attribute existed
1065 - "error code": failure
1068 Database::DeleteLongDescription(const char *type
)
1070 status_t status
= fLocation
->DeleteAttribute(type
, kLongDescriptionAttr
);
1072 _SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED
, type
, B_META_MIME_DELETED
);
1073 else if (status
== B_ENTRY_NOT_FOUND
)
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
1086 - B_ENTRY_NOT_FOUND: no such attribute existed
1087 - "error code": failure
1090 Database::DeleteFileExtensions(const char *type
)
1092 status_t status
= fLocation
->DeleteAttribute(type
, kFileExtensionsAttr
);
1094 _SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED
, type
, B_META_MIME_DELETED
);
1095 else if (status
== B_ENTRY_NOT_FOUND
)
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
1109 - B_ENTRY_NOT_FOUND: no such attribute existed
1110 - "error code": failure
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
)
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
1133 - B_ENTRY_NOT_FOUND: no such attribute existed
1134 - "error code": failure
1137 Database::DeleteIcon(const char *type
)
1139 // TODO: extra notification for vector icon (for now we notify a "large"
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
)
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
1164 - B_ENTRY_NOT_FOUND: no such attribute existed
1165 - "error code": failure
1168 Database::DeleteIconForType(const char *type
, const char *fileType
, icon_size which
)
1170 if (fileType
== NULL
)
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
)
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.
1198 - B_ENTRY_NOT_FOUND: no such attribute existed
1199 - "error code": failure
1202 Database::DeleteIconForType(const char *type
, const char *fileType
)
1204 if (fileType
== NULL
)
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
)
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
1229 - B_ENTRY_NOT_FOUND: no such attribute existed
1230 - "error code": failure
1233 Database::DeletePreferredApp(const char *type
, app_verb verb
)
1239 status
= fLocation
->DeleteAttribute(type
, kPreferredAppAttr
);
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.
1251 _SendMonitorUpdate(B_PREFERRED_APP_CHANGED
, type
, B_META_MIME_DELETED
);
1252 else if (status
== B_ENTRY_NOT_FOUND
)
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
1263 \param type The mime type of interest
1266 - B_ENTRY_NOT_FOUND: no such attribute existed
1267 - "error code": failure
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
)
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
1298 - B_ENTRY_NOT_FOUND: no such attribute existed
1299 - "error code": failure
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;
1312 status
= fSupportingApps
.DeleteSupportedTypes(type
, fullSync
);
1313 else if (status
== B_ENTRY_NOT_FOUND
) {
1316 fSupportingApps
.DeleteSupportedTypes(type
, fullSync
);
1321 // Send a monitor notification
1322 if (status
== B_OK
&& sendUpdate
)
1323 _SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED
, type
, B_META_MIME_DELETED
);
1330 Database::DeferInstallNotification(const char* type
)
1332 AutoLocker
<BLocker
> _(fDeferredInstallNotificationsLocker
);
1334 // check, if already deferred
1335 if (_FindDeferredInstallNotification(type
))
1339 DeferredInstallNotification
* notification
1340 = new(std::nothrow
) DeferredInstallNotification
;
1341 if (notification
== NULL
)
1344 strlcpy(notification
->type
, type
, sizeof(notification
->type
));
1345 notification
->notify
= false;
1347 if (!fDeferredInstallNotifications
.AddItem(notification
))
1348 delete notification
;
1353 Database::UndeferInstallNotification(const char* type
)
1355 AutoLocker
<BLocker
> locker(fDeferredInstallNotificationsLocker
);
1357 // check, if deferred at all
1358 DeferredInstallNotification
* notification
1359 = _FindDeferredInstallNotification(type
, true);
1363 if (notification
== NULL
)
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
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
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
1400 Database::_SendMonitorUpdate(int32 which
, const char *type
, const char *extraType
,
1401 bool largeIcon
, int32 action
)
1403 BMessage
msg(B_META_MIME_CHANGED
);
1406 if (_CheckDeferredInstallNotification(which
, type
))
1409 err
= msg
.AddInt32("be:which", which
);
1411 err
= msg
.AddString("be:type", type
);
1413 err
= msg
.AddString("be:extra_type", extraType
);
1415 err
= msg
.AddBool("be:large_icon", largeIcon
);
1417 err
= msg
.AddInt32("be:action", action
);
1419 err
= _SendMonitorUpdate(msg
);
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
1431 Database::_SendMonitorUpdate(int32 which
, const char *type
, const char *extraType
,
1434 if (_CheckDeferredInstallNotification(which
, type
))
1437 BMessage
msg(B_META_MIME_CHANGED
);
1439 status_t err
= msg
.AddInt32("be:which", which
);
1441 err
= msg
.AddString("be:type", type
);
1443 err
= msg
.AddString("be:extra_type", extraType
);
1445 err
= msg
.AddInt32("be:action", action
);
1447 err
= _SendMonitorUpdate(msg
);
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
1460 Database::_SendMonitorUpdate(int32 which
, const char *type
, bool largeIcon
, int32 action
)
1462 if (_CheckDeferredInstallNotification(which
, type
))
1465 BMessage
msg(B_META_MIME_CHANGED
);
1467 status_t err
= msg
.AddInt32("be:which", which
);
1469 err
= msg
.AddString("be:type", type
);
1471 err
= msg
.AddBool("be:large_icon", largeIcon
);
1473 err
= msg
.AddInt32("be:action", action
);
1475 err
= _SendMonitorUpdate(msg
);
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
1486 Database::_SendMonitorUpdate(int32 which
, const char *type
, int32 action
)
1488 if (_CheckDeferredInstallNotification(which
, type
))
1491 BMessage
msg(B_META_MIME_CHANGED
);
1493 status_t err
= msg
.AddInt32("be:which", which
);
1495 err
= msg
.AddString("be:type", type
);
1497 err
= msg
.AddInt32("be:action", action
);
1499 err
= _SendMonitorUpdate(msg
);
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
1509 Database::_SendMonitorUpdate(BMessage
&msg
)
1511 if (fNotificationListener
== NULL
)
1515 std::set
<BMessenger
>::const_iterator i
;
1516 for (i
= fMonitorMessengers
.begin(); i
!= fMonitorMessengers
.end(); i
++) {
1517 status_t err
= fNotificationListener
->Notify(&msg
, *i
);
1519 DBG(OUT("Database::_SendMonitorUpdate(BMessage&): DeliverMessage failed, 0x%lx\n", err
));
1527 Database::DeferredInstallNotification
*
1528 Database::_FindDeferredInstallNotification(const char* type
, bool remove
)
1531 DeferredInstallNotification
* notification
1532 = (DeferredInstallNotification
*)fDeferredInstallNotifications
1534 if (strcmp(type
, notification
->type
) == 0) {
1536 fDeferredInstallNotifications
.RemoveItem(i
);
1537 return notification
;
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
)
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
;
1564 } else if (which
== B_MIME_TYPE_CREATED
) {
1565 // MIME type created -- defer notification
1566 notification
->notify
= true;
1569 // MIME type update -- don't send update, if deferred
1570 if (notification
->notify
)
1579 } // namespace Storage
1580 } // namespace BPrivate