From ee0cf101849bcb32068a5666a192b48735d98829 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Wed, 28 Aug 2002 23:52:52 +0000 Subject: [PATCH] Handles supporting application management. This is an initial, theoretically fully functional implementation. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@919 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/storage/mime/SupportingApps.h | 47 ++++ src/kits/storage/mime/SupportingApps.cpp | 264 ++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 headers/private/storage/mime/SupportingApps.h create mode 100644 src/kits/storage/mime/SupportingApps.cpp diff --git a/headers/private/storage/mime/SupportingApps.h b/headers/private/storage/mime/SupportingApps.h new file mode 100644 index 0000000000..e31caedaf3 --- /dev/null +++ b/headers/private/storage/mime/SupportingApps.h @@ -0,0 +1,47 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file SupportingApps.h + SupportingApps class declarations +*/ + +#ifndef _MIME_SUPPORTING_APPS_H +#define _MIME_SUPPORTING_APPS_H + +#include + +#include +#include +#include + +class BMessage; + +namespace BPrivate { +namespace Storage { +namespace Mime { + +class SupportingApps { +public: + SupportingApps(); + ~SupportingApps(); + + status_t GetSupportingApps(const char *type, BMessage *apps); + status_t SetSupportedTypes(const char *app, const BMessage *types, bool fullSync); +private: + status_t AddSupportingApp(const char *type, const char *app); + status_t RemoveSupportingApp(const char *type, const char *app); + + status_t BuildSupportingAppsTable(); + + std::map > fSupportedTypes; // app sig => set of supported types + std::map > fSupportingApps; // mime type => set of supporting apps + bool fHaveDoneFullBuild; +}; + +} // namespace Mime +} // namespace Storage +} // namespace BPrivate + +#endif // _MIME_SUPPORTING_APPS_H diff --git a/src/kits/storage/mime/SupportingApps.cpp b/src/kits/storage/mime/SupportingApps.cpp new file mode 100644 index 0000000000..193cf59afa --- /dev/null +++ b/src/kits/storage/mime/SupportingApps.cpp @@ -0,0 +1,264 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file SupportingApps.cpp + SupportingApps class implementation +*/ + +#include "mime/SupportingApps.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DBG(x) x +//#define DBG(x) +#define OUT printf + +namespace BPrivate { +namespace Storage { +namespace Mime { + +/*! + \class SupportingApps + \brief Supporting apps information for the entire database +*/ + +// Constructor +//! Constructs a new SupportingApps object +SupportingApps::SupportingApps() + : fHaveDoneFullBuild(false) +{ +} + +// Destructor +//! Destroys the SupportingApps object +SupportingApps::~SupportingApps() +{ +} + +// GetSupportingApps +/*! \brief Returns a list of signatures of supporting applications for the + given type in the pre-allocated \c BMessage pointed to by \c apps. + + See \c BMimeType::GetSupportingApps(BMessage*) for more information. +*/ +status_t +SupportingApps::GetSupportingApps(const char *type, BMessage *apps) +{ + status_t err = type && apps ? B_OK : B_BAD_VALUE; + // See if we need to do our initial build still + if (!err && !fHaveDoneFullBuild) { + err = BuildSupportingAppsTable(); + } + if (!err) { + // Clear the message, as we're just going to add to it + apps->MakeEmpty(); + + BMimeType mime(type); + err = mime.InitCheck(); + if (!err) { + if (mime.IsSupertypeOnly()) { + // Add the apps that support this supertype (plus their count) + std::set &superApps = fSupportingApps[type]; + int32 count = 0; + std::set::const_iterator i; + for (i = superApps.begin(); i != superApps.end() && !err; i++) { + err = apps->AddString(kApplicationsField, (*i).c_str()); + count++; + } + if (!err) + err = apps->AddInt32(kSupportingAppsSuperCountField, count); + } else { + // Add the apps that support this subtype (plus their count) + std::set &subApps = fSupportingApps[type]; + int32 count = 0; + std::set::const_iterator i; + for (i = subApps.begin(); i != subApps.end() && !err; i++) { + err = apps->AddString(kApplicationsField, (*i).c_str()); + count++; + } + if (!err) + err = apps->AddInt32(kSupportingAppsSubCountField, count); + + // Now add any apps that support the supertype, but not the + // subtype (plus their count). + BMimeType superMime; + err = mime.GetSupertype(&superMime); + if (!err) + err = superMime.InitCheck(); + if (!err) { + std::set &superApps = fSupportingApps[type]; + count = 0; + for (i = superApps.begin(); i != superApps.end() && !err; i++) { + if (subApps.find(*i) == subApps.end()) { + err = apps->AddString(kApplicationsField, (*i).c_str()); + count++; + } + } + if (!err) + err = apps->AddInt32(kSupportingAppsSuperCountField, count); + } + } + } + } + return err; +} + +// SetSupportedTypes +/*! \brief Sets the list of supported types for the given application. + \param app The application whose supported types you are setting + \param types Pointer to a \c BMessage containing an array of supported + mime types in its \c Mime::kTypesField field. + \param fullSync If \c true, \c app is removed as a supporting application + of any types for which it is no longer a supporting application + as of this call to SetSupportedTypes(). If \c false, said + mappings are not updated. +*/ +status_t +SupportingApps::SetSupportedTypes(const char *app, const BMessage *types, bool fullSync) +{ + status_t err = app && types ? B_OK : B_BAD_VALUE; + if (!fHaveDoneFullBuild) + return err; + + std::set oldTypes; + std::set &newTypes = fSupportedTypes[app]; + // Make a copy of the previous types if we're doing a full sync + if (!err && fullSync) + oldTypes = newTypes; + if (!err) { + // Read through the list of new supported types, creating the new + // supported types list and adding the app as a supporting app for + // each type. + newTypes.clear(); + const char *type; + for (int32 i = 0; types->FindString(kTypesField, &type) == B_OK; i++) { + newTypes.insert(type); + AddSupportingApp(type, app); + } + + // Now, if we're doing a full sync, remove the app as a supporting + // app for any types it no longer supports + if (fullSync) { + for (std::set::iterator i = oldTypes.begin(); + i != oldTypes.end(); + i++) + { + if (newTypes.find(*i) == newTypes.end()) + RemoveSupportingApp((*i).c_str(), app); + } + } + } + return err; +} + +// AddSupportingApp +/*! \brief Adds the given application signature to the set of supporting + apps for the given type. + + \param type The full mime type + \param app The full application signature (i.e. "application/app-subtype") + \return + - B_OK: success, even if the app was already in the supporting apps list + - "error code": failure +*/ +status_t +SupportingApps::AddSupportingApp(const char *type, const char *app) +{ + status_t err = type && app ? B_OK : B_BAD_VALUE; + if (!err) + fSupportingApps[type].insert(app); + return err; +} + +// RemoveSupportingApp +/*! \brief Removes the given application signature from the set of supporting + apps for the given type. + + \param type The full mime type + \param app The full application signature (i.e. "application/app-subtype") + \return + - B_OK: success, even if the app was not found in the supporting apps list + - "error code": failure +*/ +status_t +SupportingApps::RemoveSupportingApp(const char *type, const char *app) +{ + status_t err = app ? B_OK : B_BAD_VALUE; + if (!err) + fSupportingApps[type].erase(app); + return err; +} + +// BuildSupportingAppsTable +/*! \brief Crawls the mime database and builds a list of supporting application + signatures for every supported type. +*/ +status_t +SupportingApps::BuildSupportingAppsTable() +{ + fSupportedTypes.clear(); + fSupportingApps.clear(); + + BDirectory dir; + status_t err = dir.SetTo(kApplicationDatabaseDir.c_str()); + + // Build the supporting apps table based on the mime database + if (!err) { + dir.Rewind(); + + // Handle each application type + while (true) { + entry_ref ref; + err = dir.GetNextRef(&ref); + 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 { + BPath path; + BMessage msg; + char appSig[B_PATH_NAME_LENGTH+1]; + err = path.SetTo(&ref); + if (!err) { + // Construct a mime type string + const char *appName = path.Leaf(); + sprintf(appSig, "application/%s", appName); + + // Read in the list of supported types + if (read_mime_attr_message(appSig, kSupportedTypesAttr, &msg) == B_OK) { + // Iterate through the supported types, adding them to the list of + // supported types for the application and adding the application's + // signature to the list of supporting apps for each type + const char *type; + std::set &supportedTypes = fSupportedTypes[appName]; + for (int i = 0; msg.FindString(kTypesField, i, &type) == B_OK; i++) { + supportedTypes.insert(type); + AddSupportingApp(type, appSig); + } + } + } + } + } + } + if (err) + DBG(OUT("Mime::SupportingApps::BuildSupportingAppsTable() failed, error code == 0x%lx\n", err)); + else + fHaveDoneFullBuild = true; + return err; +} + +} // namespace Mime +} // namespace Storage +} // namespace BPrivate +