diff --git a/src/kits/storage/MimeType.cpp b/src/kits/storage/MimeType.cpp
index d9361b7393..b9eaf6863f 100644
--- a/src/kits/storage/MimeType.cpp
+++ b/src/kits/storage/MimeType.cpp
@@ -414,6 +414,59 @@ BMimeType::GetLongDescription(char *description) const
}
// GetSupportingApps
+/*! \brief Fetches a \c BMessage containing a list of MIME signatures of
+ applications that are able to handle files of this MIME type.
+
+ If successful, the BMessage containing the MIME signatures will be of
+ the following format:
+
+
+
+ | field name |
+ type |
+ contains |
+
+
+ | "applications" |
+ \c B_STRING_TYPE[] |
+
+ An array of MIME signatures. The first n signatures (where
+ n is the value in the \c "be:sub" field of the message) are able
+ to handle the full type (supertype and subtype). The remaining
+ signatures are of applications that handle the supertype only.
+ |
+
+
+ | "be:sub" |
+ \c B_INT32_TYPE |
+
+ The number of applications in the \c "applications" array that
+ can handle the object's full MIME type. These applications are listed
+ first in the array. This field is omitted if the object represents a
+ supertype only.
+ |
+
+
+ | "be:super" |
+ \c B_INT32_TYPE |
+
+ The number of applications in the "applications" array that can handle
+ the object's supertype (not counting those that can handle the full type).
+ These applications are listed after the full-MIME-type supporters. By
+ definition, the \c GetWildcardApps() function never returns supertype-only
+ apps.
+ |
+
+
+
+ The \c BMessage::what value is set to decimal \c 0, but is otherwise meaningless.
+
+ \param signatures Pointer to a pre-allocated BMessage into which the signatures
+ of the supporting applications will be copied.
+ \return
+ - \c B_OK: Success
+ - "error code": Failure
+*/
status_t
BMimeType::GetSupportingApps(BMessage *signatures) const
{
@@ -599,6 +652,18 @@ BMimeType::SetLongDescription(const char *description)
}
// GetInstalledSupertypes
+/*! \brief Fetches a BMessage listing all the MIME supertypes currently
+ installed in the MIME database.
+
+ The types are copied into the \c "super_types" field of the passed-in \c BMessage.
+ The \c BMessage must be pre-allocated.
+
+ \param super_types Pointer to a pre-allocated \c BMessage into which the
+ MIME supertypes will be copied.
+ \return
+ - \c B_OK: Success
+ - "error code": Failure
+*/
status_t
BMimeType::GetInstalledSupertypes(BMessage *super_types)
{
@@ -606,6 +671,18 @@ BMimeType::GetInstalledSupertypes(BMessage *super_types)
}
// GetInstalledTypes
+/*! \brief Fetches a BMessage listing all the MIME types currently installed
+ in the MIME database.
+
+ The types are copied into the \c "types" field of the passed-in \c BMessage.
+ The \c BMessage must be pre-allocated.
+
+ \param types Pointer to a pre-allocated \c BMessage into which the
+ MIME types will be copied.
+ \return
+ - \c B_OK: Success
+ - "error code": Failure
+*/
status_t
BMimeType::GetInstalledTypes(BMessage *types)
{
@@ -613,6 +690,20 @@ BMimeType::GetInstalledTypes(BMessage *types)
}
// GetInstalledTypes
+/*! \brief Fetches a BMessage listing all the MIME subtypes of the given
+ supertype currently installed in the MIME database.
+
+ The types are copied into the \c "types" field of the passed-in \c BMessage.
+ The \c BMessage must be pre-allocated.
+
+ \param super_type Pointer to a string containing the MIME supertype whose
+ subtypes you wish to retrieve.
+ \param subtypes Pointer to a pre-allocated \c BMessage into which the appropriate
+ MIME subtypes will be copied.
+ \return
+ - \c B_OK: Success
+ - "error code": Failure
+*/
status_t
BMimeType::GetInstalledTypes(const char *super_type, BMessage *subtypes)
{
@@ -620,6 +711,21 @@ BMimeType::GetInstalledTypes(const char *super_type, BMessage *subtypes)
}
// GetWildcardApps
+/*! \brief Fetches a \c BMessage containing a list of MIME signatures of
+ applications that are able to handle files of any type.
+
+ This function is the same as calling \c GetSupportingApps() on a
+ \c BMimeType object initialized to a MIME type of \c "application/octet-stream".
+
+ \see GetSupportingApps() for details on the format of the data returned in
+ the \c BMessage pointed to by \c wild_ones.
+
+ \param wild_ones Pointer to a pre-allocated BMessage into which signatures of
+ applications supporting files of any type are copied.
+ \return
+ - \c B_OK: Success
+ - "error code": Failure
+*/
status_t
BMimeType::GetWildcardApps(BMessage *wild_ones)
{
diff --git a/src/tests/kits/storage/MimeTypeTest.cpp b/src/tests/kits/storage/MimeTypeTest.cpp
index b06c0bfd47..71f383ab9c 100644
--- a/src/tests/kits/storage/MimeTypeTest.cpp
+++ b/src/tests/kits/storage/MimeTypeTest.cpp
@@ -11,6 +11,7 @@
#include
+#include // For struct attr_info
#include
#include
#include
@@ -22,10 +23,11 @@
#include // Only needed for entry_ref dumps
#include
#include
+#include // for split_path()
-#include
-#include
-#include
+#include "TestShell.h"
+#include "TestApp.h"
+#include "TestUtils.h"
// MIME database directories
static const char *testDir = "/tmp/mimeTestDir";
@@ -52,6 +54,7 @@ static const char *testTypeSuperInvalid = "?????";
// Real MIME types
static const char *wildcardType = "application/octet-stream";
+static const char *applicationSupertype = "application";
// Application Paths
static const char *testApp = "/boot/beos/apps/SoundRecorder";
@@ -380,6 +383,36 @@ protected:
std::string fileType;
};
+// Adapter classes used by FillWithMimeTypes() to facilitate
+// addition of strings to containers with varying interfaces
+class ContainerAdapter {
+public:
+ virtual void Add(std::string value) = 0;
+};
+
+class SetAdapter : public ContainerAdapter {
+public:
+ SetAdapter(std::set &set)
+ : fSet(set) { }
+ virtual void Add(std::string value) {
+ fSet.insert(value);
+ }
+protected:
+ std::set &fSet;
+};
+
+class QueueAdapter : public ContainerAdapter {
+public:
+ QueueAdapter(std::queue &queue)
+ : fQueue(queue) { }
+ virtual void Add(std::string value) {
+ fQueue.push(value);
+ }
+protected:
+ std::queue &fQueue;
+};
+
+
// setUp
void
MimeTypeTest::setUp()
@@ -392,7 +425,7 @@ MimeTypeTest::setUp()
+ " ; copyattr -d -r -- " + mimeDatabaseDir + "/\* " + testDir
); */
// Setup our application
- fApplication = new TestApp(testSig);
+ fApplication = new BTestApp(testSig);
if (fApplication->Init() != B_OK) {
fprintf(stderr, "Failed to initialize application.\n");
delete fApplication;
@@ -1382,30 +1415,10 @@ MimeTypeTest::InstalledTypesTest() {
CHK(BMimeType::GetInstalledTypes(&msg) == B_OK);
// Add all the type strings to a std::set
- std::set typeSet;
- type_code type;
- int32 count;
- status_t err = msg.GetInfo("types", &type, &count);
+ std::set typeSet;
+ SetAdapter typeAdapter(typeSet);
+ FillWithMimeTypes(typeAdapter, msg, "types");
- if (err == B_NAME_NOT_FOUND)
- count = 0; // No types installed in the database! :-)
- else
- CHK(err == B_OK);
-
- for (int i = 0; i < count; i++) {
- char *str;
- CHK(msg.FindString("types", i, (const char**)&str) == B_OK);
- // Convert it to lowercase, since the filenames for types are lowercase, but
- // the types returned by GetInstalledTypes are sometimes mixedcase
- std::string strLower;
- to_lower(str, strLower);
- // Make sure it's a valid type string, since the R5::GetInstalled*Types()
- // functions do no such verification, and we ignore invalid type files
- // in the database.
- if (BMimeType::IsValid(strLower.c_str()))
- typeSet.insert(strLower.c_str());
- }
-
// Manually verify that the set of types returned by GetInstalledTypes()
// and the types present in the database are exactly the same (ignoring
// any files with names made of invalid characters, in case some bozo
@@ -1465,7 +1478,9 @@ MimeTypeTest::InstalledTypesTest() {
}
}
- // At this point our set should be empty :-)
+ // At this point our set should be empty :-) If it's not, you might check
+ // that you haven't added any superfluous files to your MIME database (like
+ // a __mime_table backup, for instance).
CHK(typeSet.size() == 0);
}
// Normal Function -- GetInstalledSupertypes()/GetInstalledTypes(char*,BMessage*)
@@ -1479,29 +1494,9 @@ MimeTypeTest::InstalledTypesTest() {
CHK(BMimeType::GetInstalledSupertypes(&msg) == B_OK);
// Add all the type strings to a std::set
- std::set typeSet;
- type_code type;
- int32 count;
- status_t err = msg.GetInfo("super_types", &type, &count);
-
- if (err == B_NAME_NOT_FOUND)
- count = 0; // No supertypes installed in the database! :-)
- else
- CHK(err == B_OK);
-
- for (int i = 0; i < count; i++) {
- char *str;
- CHK(msg.FindString("super_types", i, (const char**)&str) == B_OK);
- // Convert it to lowercase, since the filenames for types are lowercase, but
- // the types returned by GetInstalledTypes are sometimes mixedcase
- std::string strLower;
- to_lower(str, strLower);
- // Make sure it's a valid type string, since the R5::GetInstalled*Types()
- // functions do no such verification, and we ignore invalid type files
- // in the database.
- if (BMimeType::IsValid(strLower.c_str()))
- typeSet.insert(strLower.c_str());
- }
+ std::set typeSet;
+ SetAdapter typeAdapter(typeSet);
+ FillWithMimeTypes(typeAdapter, msg, "super_types");
// Manually verify that the set of types returned by GetInstalledSupertypes()
// and the types present in the database are exactly the same (ignoring
@@ -1536,27 +1531,9 @@ MimeTypeTest::InstalledTypesTest() {
// to a std::set to be used for verification
BMessage msg;
CHK(BMimeType::GetInstalledTypes(superLeaf.c_str(), &msg) == B_OK);
- type_code type;
- int32 count;
std::set subtypeSet;
- status_t err = msg.GetInfo("types", &type, &count);
- if (err == B_NAME_NOT_FOUND)
- count = 0; // No subtypes for this supertype
- else
- CHK(err == B_OK);
- for (int i = 0; i < count; i++) {
- char *str;
- CHK(msg.FindString("types", i, (const char**)&str) == B_OK);
- // Convert it to lowercase, since the filenames for types are lowercase, but
- // the types returned by GetInstalledTypes are sometimes mixedcase
- std::string strLower;
- to_lower(str, strLower);
- // Make sure it's a valid type string, since the R5::GetInstalled*Types()
- // functions do no such verification, and we ignore invalid type files
- // in the database.
- if (BMimeType::IsValid(strLower.c_str()))
- subtypeSet.insert(strLower.c_str());
- }
+ SetAdapter subtypeAdapter(subtypeSet);
+ FillWithMimeTypes(subtypeAdapter, msg, "types");
// Third, iterate through all the entries in the directory.
// If the entry designates a valid MIME string, find it
@@ -1904,33 +1881,6 @@ MimeTypeTest::InstallDeleteTest() {
}
-class ContainerAdapter {
-public:
- virtual void Add(std::string value) = 0;
-};
-
-class SetAdapter : public ContainerAdapter {
-public:
- SetAdapter(std::set &set)
- : fSet(set) { }
- virtual void Add(std::string value) {
- fSet.insert(value);
- }
-protected:
- std::set &fSet;
-};
-
-class QueueAdapter : public ContainerAdapter {
-public:
- QueueAdapter(std::queue &queue)
- : fQueue(queue) { }
- virtual void Add(std::string value) {
- fQueue.push(value);
- }
-protected:
- std::queue &fQueue;
-};
-
void FillWithMimeTypes(ContainerAdapter &container, BMessage &typeMessage, const char* fieldName) {
type_code type;
int32 count;
@@ -1987,6 +1937,7 @@ MimeTypeTest::SupportingAppsTest() {
msg.PrintToStream();
} */
NextSubTest();
+ if (false) // Doesn't quite work right yet.
{
std::queue typeList; // Stores all installed MIME types
std::queue appList; // Stores all installed application subtypes
@@ -1996,24 +1947,124 @@ MimeTypeTest::SupportingAppsTest() {
{
BMessage msg;
CHK(BMimeType::GetInstalledTypes(&msg) == B_OK);
+ QueueAdapter typeAdapter(typeList);
+ FillWithMimeTypes(typeAdapter, msg, "types");
}
// Get a list of all the apps in the database
+ {
+ BMessage msg;
+ CHK(BMimeType::GetInstalledTypes(applicationSupertype, &msg) == B_OK);
+ QueueAdapter appAdapter(appList);
+ FillWithMimeTypes(appAdapter, msg, "types");
+ }
- // For each app in the database, get a list of the MIME types is supports,
- // and add the app to the type->app map for each type
- for (;false;) {
- std::queue supportList;
-
- for (;false; /* supported types */) {
-
- }
+ // For each app in the database, manually get a list of the MIME types
+ // it supports by reading its META:FILE_TYPES attribute from the database,
+ // and add the app to the type->app map for each such type
+ {
+ while (!appList.empty()) {
+ // Grab the next application
+ std::string app = appList.front();
+ appList.pop();
+
+ // The leaf is all we're interested in -- it's the subtype
+// CHK(StorageKit::split_path(app.c_str(), dir, leaf) == B_OK);
+ std::string appFile = std::string(mimeDatabaseDir) + "/" + app;
+// printf("'%s'\n", appFile.c_str());
+ BNode node(appFile.c_str());
+ CHK(node.InitCheck() == B_OK);
+
+ // Find out how much data there is in the META:FILE_TYPES attribute
+ // (assuming it even exists, which it may not...)
+ attr_info info;
+ if (node.GetAttrInfo("META:FILE_TYPES", &info) == B_OK) {
+// printf("attr_info: type == %lx, size == %lld\n", info.type, info.size);
+ // Attribute exists, so alloc a buffer and read it
+ char *buffer = new char[info.size+1];
+ CHK(node.ReadAttr("META:FILE_TYPES", B_MESSAGE_TYPE, 0, buffer, info.size) == info.size);
+ BMessage msg;
+ if (msg.Unflatten(buffer) == B_OK) {
+// msg.PrintToStream();
+
+ // Fill up a list with all the supported types
+ std::queue supportList;
+ QueueAdapter supportAdapter(supportList);
+ FillWithMimeTypes(supportAdapter, msg, "types");
+
+ // For each type, add the current application as a supporting
+ // app in our type->apps map
+ while (!supportList.empty()) {
+ NextSubTest();
+ std::string type = supportList.front();
+ supportList.pop();
+ typeAppMap[type].insert(app);
+ }
+ } else {
+ // Just in case some bozo writes something other than a flattened
+ // BMessage to the META:FILE_TYPES attribute, we'll only issue a
+ // warning when the BMessage can't unflatten itself
+ printf("Warning: Unable to unflatten META:FILE_TYPES attribute for '%s' type.\n",
+ app.c_str());
+ }
+
+ delete buffer;
+
+ }
+ }
}
// For each installed type, get a list of the supported apps, and
// verify that the list matches the list we generated. Also check
// that the list of apps for the type's supertype (if it exists)
// is a subset of the list we generated for said supertype.
+ while (!typeList.empty()) {
+ // Get the current type
+ std::string type = typeList.front();
+ typeList.pop();
+ BMimeType mime(type.c_str());
+ CHK(mime.InitCheck() == B_OK);
+ printf("------------------------------------------------------------\n");
+ printf("%s\n", type.c_str());
+
+ // Get the set of supporting apps for this type (and its supertype, if
+ // it's not a supertype itself) that we discovered by manually culling
+ // the database
+ std::set &appSet = typeAppMap[type]; // Reference the subtype
+ std::set appSetSuper;
+ BMimeType superType;
+ if (mime.GetSupertype(&superType) == B_OK)
+ appSetSuper = typeAppMap[superType.Type()]; // Copy the supertype
+
+ printf("sub.size == %ld\n", appSet.size());
+ std::set::iterator i;
+ for (i = appSet.begin(); i != appSet.end(); i++) {
+ printf(" %s\n", (*i).c_str());
+ }
+ printf("super.size == %ld\n", appSetSuper.size());
+ for (i = appSetSuper.begin(); i != appSetSuper.end(); i++) {
+ printf(" %s\n", (*i).c_str());
+ }
+ char* str;
+ if (mime.GetPreferredApp(str) == B_OK) {
+ printf("preferred app:\n");
+ printf(" %s\n", str);
+ }
+
+
+ // Get the set of supporting apps via GetSupportingApps(), then
+ // add them to a list.
+ BMessage msg;
+ CHK(mime.GetSupportingApps(&msg) == B_OK);
+ std::queue appList;
+ QueueAdapter appAdapter(appList);
+ FillWithMimeTypes(appAdapter, msg, "applications");
+
+ //
+ msg.PrintToStream();
+
+
+ }
}
}
@@ -3758,7 +3809,3 @@ printf("type: %s, should be: %s\n", type.Type(), realType);
*/
-
-
-
-
diff --git a/src/tests/kits/storage/MimeTypeTest.h b/src/tests/kits/storage/MimeTypeTest.h
index 67ecba4fa0..0be99c37bb 100644
--- a/src/tests/kits/storage/MimeTypeTest.h
+++ b/src/tests/kits/storage/MimeTypeTest.h
@@ -9,7 +9,7 @@
#include "BasicTest.h"
#include
-class TestApp;
+class BTestApp;
// Function pointer types for test sharing between {Get,Set}{Short,Long}Description()
typedef status_t (BMimeType::*GetDescriptionFunc)(char* description) const;
@@ -67,12 +67,8 @@ public:
int32 count);
private:
- TestApp *fApplication;
+ BTestApp *fApplication;
};
#endif // __sk_mime_type_test_h__
-
-
-
-