/*! \brief Reads through the database and builds a complete set of installed types lists. An initial set of cached messages are also created. */ status_t InstalledTypes::_BuildInstalledTypesList() { status_t err = B_OK; _Unset(); // Create empty "cached messages" so proper messages // will be built up as we add new types try { fCachedMessage = new BMessage(); fCachedSupertypesMessage = new BMessage(); } catch (std::bad_alloc) { err = B_NO_MEMORY; } BDirectory root; if (!err) err = root.SetTo(get_database_directory().c_str()); if (!err) { root.Rewind(); while (true) { BEntry entry; err = root.GetNextEntry(&entry); if (err) { // If we've come to the end of list, it's not an error if (err == B_ENTRY_NOT_FOUND) err = B_OK; break; } else { // Check that this entry is both a directory and a valid MIME string char supertype[B_PATH_NAME_LENGTH]; if (entry.IsDirectory() && entry.GetName(supertype) == B_OK && BMimeType::IsValid(supertype)) { // Make sure our string is all lowercase BPrivate::Storage::to_lower(supertype); // Add this supertype std::map<std::string, Supertype>::iterator i; if (_AddSupertype(supertype, i) != B_OK) DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList() -- Error adding supertype '%s': 0x%lx\n", supertype, err)); Supertype &supertypeRef = fSupertypes[supertype]; // Now iterate through this supertype directory and add // all of its subtypes BDirectory dir; if (dir.SetTo(&entry) == B_OK) { dir.Rewind(); while (true) { BEntry subEntry; err = dir.GetNextEntry(&subEntry); if (err) { // If we've come to the end of list, it's not an error if (err == B_ENTRY_NOT_FOUND) err = B_OK; break; } else { // We need to preserve the case of the type name for // queries, so we can't use the file name directly BString type; int32 subStart; BNode node(&subEntry); if (node.InitCheck() == B_OK && node.ReadAttrString(kTypeAttr, &type) >= B_OK && (subStart = type.FindFirst('/')) > 0) { // Add the subtype if (_AddSubtype(supertypeRef, type.String() + subStart + 1) != B_OK) { DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList() -- Error adding subtype '%s/%s': 0x%lx\n", supertype, type.String() + subStart + 1, err)); } } } } } else { DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList(): " "Failed opening supertype directory '%s'\n", supertype)); } } } } } else { DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList(): " "Failed opening mime database directory '%s'\n", get_database_directory().c_str())); } fHaveDoneFullBuild = true; return err; }
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; }