/*! \brief Sets the MIME types supported by the application. If \a types is \c NULL the application's supported types are unset. The supported MIME types must be stored in a field "types" of type \c B_STRING_TYPE in \a types. The method informs the registrar about this news. For each supported type the result of BMimeType::GetSupportingApps() will afterwards include the signature of this application. That is, the application file needs to have a signature set. \a syncAll specifies whether the not longer supported types shall be updated as well, i.e. whether this application shall be remove from the lists of supporting applications. \param types The supported types to be assigned to the file. May be \c NULL. \param syncAll \c true to also synchronize the not longer supported types, \c false otherwise. \return - \c B_OK: Everything went fine. - \c B_NO_INIT: The object is not properly initialized. - other error codes */ status_t BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll) { // check initialization status_t error = B_OK; if (error == B_OK && InitCheck() != B_OK) error = B_NO_INIT; BMimeType mimeType; if (error == B_OK) error = GetMetaMime(&mimeType); if (error == B_OK || error == B_ENTRY_NOT_FOUND) { error = B_OK; if (types) { // check param -- supported types must be valid const char *type; for (int32 i = 0; error == B_OK && types->FindString("types", i, &type) == B_OK; i++) { if (!BMimeType::IsValid(type)) error = B_BAD_VALUE; } // get flattened size ssize_t size = 0; if (error == B_OK) { size = types->FlattenedSize(); if (size < 0) error = size; } // allocate a buffer for the flattened data char *buffer = NULL; if (error == B_OK) { buffer = new(nothrow) char[size]; if (!buffer) error = B_NO_MEMORY; } // flatten the message if (error == B_OK) error = types->Flatten(buffer, size); // write the data if (error == B_OK) { error = _WriteData(kSupportedTypesAttribute, kSupportedTypesResourceID, B_MESSAGE_TYPE, buffer, size); } // clean up delete[] buffer; } else error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE); // update the MIME database, if the app signature is installed if (error == B_OK && mimeType.IsInstalled()) error = mimeType.SetSupportedTypes(types, syncAll); } return error; }
status_t CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir) { if (ref == NULL) return B_BAD_VALUE; BNode typeNode; BFile file; status_t status = file.SetTo(ref, B_READ_ONLY); if (status < B_OK) return status; bool isDir = file.IsDirectory(); if (_entryIsDir != NULL) *_entryIsDir = isDir; if (isDir) return B_OK; BAppFileInfo appInfo(&file); status = appInfo.InitCheck(); if (status < B_OK) return status; // Read the app sig (which consequently keeps us from updating // non-applications, since we get an error if the file has no // app sig) BString signature; status = file.ReadAttrString("BEOS:APP_SIG", &signature); if (status < B_OK) return B_BAD_TYPE; // Init our various objects BMimeType mime; status = mime.SetTo(signature.String()); if (status < B_OK) return status; InstallNotificationDeferrer _(fDatabase, signature.String()); if (!mime.IsInstalled()) mime.Install(); BString path = "/"; path.Append(signature); path.ToLower(); // Signatures and MIME types are case insensitive, but we want to // preserve the case wherever possible path.Prepend(get_database_directory().c_str()); status = typeNode.SetTo(path.String()); if (status < B_OK) return status; // Preferred App attr_info info; if (status == B_OK && (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) status = mime.SetPreferredApp(signature.String()); // Short Description (name of the application) if (status == B_OK && (fForce || typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) status = mime.SetShortDescription(ref->name); // App Hint if (status == B_OK && (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) status = mime.SetAppHint(ref); // Vector Icon if (status == B_OK && (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) { uint8* data = NULL; size_t size = 0; if (appInfo.GetIcon(&data, &size) == B_OK) { status = mime.SetIcon(data, size); free(data); } } // Mini Icon BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8); if (status == B_OK && (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) { if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) status = mime.SetIcon(&miniIcon, B_MINI_ICON); } // Large Icon BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8); if (status == B_OK && (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) { if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) status = mime.SetIcon(&largeIcon, B_LARGE_ICON); } // Supported Types bool setSupportedTypes = false; BMessage supportedTypes; if (status == B_OK && (fForce || typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) { if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK) setSupportedTypes = true; } // defer notifications for supported types const char* type; for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) fDatabase->DeferInstallNotification(type); // set supported types if (setSupportedTypes) status = mime.SetSupportedTypes(&supportedTypes); // Icons for supported types for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) { // vector icon uint8* data = NULL; size_t size = 0; if (status == B_OK && appInfo.GetIconForType(type, &data, &size) == B_OK) { status = mime.SetIconForType(type, data, size); free(data); } // mini icon if (status == B_OK && appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) status = mime.SetIconForType(type, &miniIcon, B_MINI_ICON); // large icon if (status == B_OK && appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) status = mime.SetIconForType(type, &largeIcon, B_LARGE_ICON); } // undefer notifications for supported types for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) fDatabase->UndeferInstallNotification(type); return status; }