Refactor MIME DB access

* Add class DatabaseLocation. It contains a list of the MIME DB
  directory paths plus methods to access type files.
* Move all low-level MIME DB access functions from
  database_{support,access} to DatabaseLocation. All code that formerly
  used those now requires a DatabaseLocation object. In BMimeType and in
  the registrar the default object is used, but the low-level classes
  can now be reused with different locations.
* Move get_icon_data() from database_access to database_support and
  delete the former, which is now empty.
This commit is contained in:
Ingo Weinhold
2013-05-07 23:15:36 +02:00
parent 9cda9c9905
commit b94857b322
23 changed files with 1294 additions and 1155 deletions
@@ -21,12 +21,15 @@ namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
class DatabaseLocation;
class MimeSniffer; class MimeSniffer;
class AssociatedTypes { class AssociatedTypes {
public: public:
AssociatedTypes(MimeSniffer* mimeSniffer); AssociatedTypes(DatabaseLocation* databaseLocation,
MimeSniffer* mimeSniffer);
~AssociatedTypes(); ~AssociatedTypes();
status_t GetAssociatedTypes(const char *extension, BMessage *types); status_t GetAssociatedTypes(const char *extension, BMessage *types);
@@ -50,8 +53,9 @@ private:
std::map<std::string, std::set<std::string> > fAssociatedTypes; // file extension => set of associated mime types std::map<std::string, std::set<std::string> > fAssociatedTypes; // file extension => set of associated mime types
private: private:
MimeSniffer* fMimeSniffer; DatabaseLocation* fDatabaseLocation;
bool fHaveDoneFullBuild; MimeSniffer* fMimeSniffer;
bool fHaveDoneFullBuild;
}; };
} // namespace Mime } // namespace Mime
+9 -4
View File
@@ -19,7 +19,6 @@
#include <StorageDefs.h> #include <StorageDefs.h>
#include <mime/AssociatedTypes.h> #include <mime/AssociatedTypes.h>
#include <mime/database_access.h>
#include <mime/InstalledTypes.h> #include <mime/InstalledTypes.h>
#include <mime/SnifferRules.h> #include <mime/SnifferRules.h>
#include <mime/SupportingApps.h> #include <mime/SupportingApps.h>
@@ -36,8 +35,11 @@ namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
class DatabaseLocation;
class MimeSniffer; class MimeSniffer;
// types of mime update functions that may be run asynchronously // types of mime update functions that may be run asynchronously
typedef enum { typedef enum {
B_REG_UPDATE_MIME_INFO, B_REG_UPDATE_MIME_INFO,
@@ -49,16 +51,18 @@ class Database {
class NotificationListener; class NotificationListener;
public: public:
Database(MimeSniffer* mimeSniffer, Database(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer,
NotificationListener* notificationListener); NotificationListener* notificationListener);
~Database(); ~Database();
status_t InitCheck() const; status_t InitCheck() const;
DatabaseLocation* Location() const { return fLocation; }
// Type management // Type management
status_t Install(const char *type); status_t Install(const char *type);
status_t Delete(const char *type); status_t Delete(const char *type);
// Set() // Set()
status_t SetAppHint(const char *type, const entry_ref *ref); status_t SetAppHint(const char *type, const entry_ref *ref);
status_t SetAttrInfo(const char *type, const BMessage *info); status_t SetAttrInfo(const char *type, const BMessage *info);
@@ -142,6 +146,7 @@ class Database {
private: private:
status_t fStatus; status_t fStatus;
DatabaseLocation* fLocation;
NotificationListener* fNotificationListener; NotificationListener* fNotificationListener;
std::set<BMessenger> fMonitorMessengers; std::set<BMessenger> fMonitorMessengers;
AssociatedTypes fAssociatedTypes; AssociatedTypes fAssociatedTypes;
@@ -17,12 +17,16 @@ namespace Storage {
namespace Mime { namespace Mime {
class DatabaseLocation;
class DatabaseDirectory : public BMergedDirectory { class DatabaseDirectory : public BMergedDirectory {
public: public:
DatabaseDirectory(); DatabaseDirectory();
virtual ~DatabaseDirectory(); virtual ~DatabaseDirectory();
status_t Init(const char* superType = NULL); status_t Init(DatabaseLocation* databaseLocation,
const char* superType = NULL);
protected: protected:
virtual bool ShallPreferFirstEntry(const entry_ref& entry1, virtual bool ShallPreferFirstEntry(const entry_ref& entry1,
@@ -0,0 +1,119 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#ifndef _MIME_DATABASE_LOCATION_H
#define _MIME_DATABASE_LOCATION_H
#include <Mime.h>
#include <StringList.h>
namespace BPrivate {
namespace Storage {
namespace Mime {
class DatabaseLocation {
public:
DatabaseLocation();
~DatabaseLocation();
bool AddDirectory(const BString& directory);
// paths
const BStringList& Directories() const
{ return fDirectories; }
BString WritableDirectory() const
{ return fDirectories.StringAt(0); }
BString WritablePathForType(const char* type) const
{ return _TypeToFilename(type, 0); }
// opening type nodes
status_t OpenType(const char* type, BNode& _node) const;
status_t OpenOrCreateType(const char* type,
BNode& _node, bool* _didCreate = NULL)
const;
// generic type attributes access
ssize_t ReadAttribute(const char* type,
const char* attribute, void* data,
size_t length, type_code datatype) const;
status_t ReadMessageAttribute(const char* type,
const char* attribute, BMessage& _message)
const;
status_t ReadStringAttribute(const char* type,
const char* attribute, BString& _string)
const;
status_t WriteAttribute(const char* type,
const char* attribute, const void* data,
size_t length, type_code datatype,
bool* _didCreate) const;
status_t WriteMessageAttribute(const char* type,
const char* attribute,
const BMessage& message, bool* _didCreate)
const;
status_t DeleteAttribute(const char* type,
const char* attribute) const;
// type attribute convenience getters
status_t GetAppHint(const char* type, entry_ref& _ref);
status_t GetAttributesInfo(const char* type,
BMessage& _info);
status_t GetShortDescription(const char* type,
char* description);
status_t GetLongDescription(const char* type,
char* description);
status_t GetFileExtensions(const char* type,
BMessage& _extensions);
status_t GetIcon(const char* type, BBitmap& _icon,
icon_size size);
status_t GetIcon(const char* type, uint8*& _data,
size_t& _size);
status_t GetIconForType(const char* type,
const char* fileType, BBitmap& _icon,
icon_size which);
status_t GetIconForType(const char* type,
const char* fileType, uint8*& _data,
size_t& _size);
status_t GetPreferredApp(const char* type,
char* signature, app_verb verb);
status_t GetSnifferRule(const char* type,
BString& _result);
status_t GetSupportedTypes(const char* type,
BMessage& _types);
bool IsInstalled(const char* type);
private:
BString _TypeToFilename(const char* type, int32 index)
const;
status_t _OpenType(const char* type, BNode& _node,
int32& _index) const;
status_t _CreateTypeNode(const char* type, BNode& _node)
const;
status_t _CopyTypeNode(BNode& source, const char* type,
BNode& _target) const;
private:
BStringList fDirectories;
};
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
#endif // _MIME_DATABASE_LOCATION_H
@@ -25,9 +25,13 @@ namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
class DatabaseLocation;
class InstalledTypes { class InstalledTypes {
public: public:
InstalledTypes(); InstalledTypes(DatabaseLocation* databaseLocation);
~InstalledTypes(); ~InstalledTypes();
status_t GetInstalledTypes(BMessage *types); status_t GetInstalledTypes(BMessage *types);
@@ -55,6 +59,8 @@ class InstalledTypes {
status_t _BuildInstalledTypesList(); status_t _BuildInstalledTypesList();
private:
DatabaseLocation* fDatabaseLocation;
std::map<std::string, Supertype> fSupertypes; std::map<std::string, Supertype> fSupertypes;
BMessage *fCachedMessage; BMessage *fCachedMessage;
BMessage *fCachedSupertypesMessage; BMessage *fCachedSupertypesMessage;
+7 -4
View File
@@ -25,12 +25,14 @@ namespace Sniffer {
namespace Mime { namespace Mime {
class DatabaseLocation;
class MimeSniffer; class MimeSniffer;
class SnifferRules { class SnifferRules {
public: public:
SnifferRules(MimeSniffer* mimeSniffer); SnifferRules(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer);
~SnifferRules(); ~SnifferRules();
status_t GuessMimeType(const entry_ref *ref, BString *type); status_t GuessMimeType(const entry_ref *ref, BString *type);
@@ -59,9 +61,10 @@ private:
std::list<sniffer_rule> fRuleList; std::list<sniffer_rule> fRuleList;
private: private:
MimeSniffer* fMimeSniffer; DatabaseLocation* fDatabaseLocation;
ssize_t fMaxBytesNeeded; MimeSniffer* fMimeSniffer;
bool fHaveDoneFullBuild; ssize_t fMaxBytesNeeded;
bool fHaveDoneFullBuild;
}; };
} // namespace Mime } // namespace Mime
@@ -22,11 +22,15 @@ namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
class DatabaseLocation;
class SupportingApps { class SupportingApps {
public: public:
SupportingApps(); SupportingApps(DatabaseLocation* databaseLocation);
~SupportingApps(); ~SupportingApps();
status_t GetSupportingApps(const char *type, BMessage *apps); status_t GetSupportingApps(const char *type, BMessage *apps);
status_t SetSupportedTypes(const char *app, const BMessage *types, bool fullSync); status_t SetSupportedTypes(const char *app, const BMessage *types, bool fullSync);
@@ -41,6 +45,9 @@ private:
std::map<std::string, std::set<std::string> > fSupportingApps; // mime type => set of supporting apps std::map<std::string, std::set<std::string> > fSupportingApps; // mime type => set of supporting apps
std::map<std::string, std::set<std::string> > fStrandedTypes; // app sig => set of no longer supported types for whom the std::map<std::string, std::set<std::string> > fStrandedTypes; // app sig => set of no longer supported types for whom the
// given app is still listed as a supporting app // given app is still listed as a supporting app
private:
DatabaseLocation* fDatabaseLocation;
bool fHaveDoneFullBuild; bool fHaveDoneFullBuild;
}; };
@@ -1,49 +0,0 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//---------------------------------------------------------------------
/*!
\file database_access.h
Mime database atomic read functions and miscellany declarations
*/
#ifndef _MIME_DATABASE_ACCESS_H
#define _MIME_DATABASE_ACCESS_H
#include <Mime.h>
class BNode;
class BBitmap;
class BMessage;
namespace BPrivate {
namespace Storage {
namespace Mime {
// Get() functions
status_t get_app_hint(const char *type, entry_ref *ref);
status_t get_attr_info(const char *type, BMessage *info);
status_t get_short_description(const char *type, char *description);
status_t get_long_description(const char *type, char *description);
status_t get_file_extensions(const char *type, BMessage *extensions);
status_t get_icon(const char *type, BBitmap *icon, icon_size size);
status_t get_icon(const char *type, uint8** data, size_t* size);
status_t get_icon_for_type(const char *type, const char *fileType,
BBitmap *icon, icon_size which);
status_t get_icon_for_type(const char *type, const char *fileType,
uint8** data, size_t* size);
status_t get_preferred_app(const char *type, char *signature, app_verb verb);
status_t get_sniffer_rule(const char *type, BString *result);
status_t get_supported_types(const char *type, BMessage *types);
bool is_installed(const char *type);
// Called by BMimeType to get properly formatted icon data ready
// to be shipped off to SetIcon*() and written to the database
status_t get_icon_data(const BBitmap *icon, icon_size size, void **data, int32 *dataSize);
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
#endif // _MIME_DATABASE_H
+13 -21
View File
@@ -1,27 +1,25 @@
/* /*
* Copyright 2002-2007, Haiku, Inc. All Rights Reserved. * Copyright 2002-2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _MIME_DATABASE_SUPPORT_H #ifndef _MIME_DATABASE_SUPPORT_H
#define _MIME_DATABASE_SUPPORT_H #define _MIME_DATABASE_SUPPORT_H
#include <StorageDefs.h> #include <Mime.h>
#include <String.h> #include <SupportDefs.h>
class BNode; class BBitmap;
class BMessage;
class BStringList;
namespace BPrivate { namespace BPrivate {
namespace Storage { namespace Storage {
namespace Mime { namespace Mime {
// Database directory
const BStringList& get_database_directories(); class DatabaseLocation;
BString get_writable_database_directory();
// Attribute Prefixes // Attribute Prefixes
extern const char *kMiniIconAttrPrefix; extern const char *kMiniIconAttrPrefix;
@@ -75,24 +73,18 @@ extern const char *kMetaMimeType;
// Error codes (to be used only by BPrivate::Storage::Mime members) // Error codes (to be used only by BPrivate::Storage::Mime members)
extern const status_t kMimeGuessFailureError; extern const status_t kMimeGuessFailureError;
BString type_to_writable_filename(const char *type);
status_t open_type(const char *type, BNode *result); DatabaseLocation* default_database_location();
status_t open_or_create_type(const char *type, BNode *result, bool *didCreate);
ssize_t read_mime_attr(const char *type, const char *attr, void *data, // Called by BMimeType to get properly formatted icon data ready
size_t len, type_code datatype); // to be shipped off to SetIcon*() and written to the database
status_t read_mime_attr_message(const char *type, const char *attr, BMessage *msg); status_t get_icon_data(const BBitmap *icon, icon_size size, void **data,
status_t read_mime_attr_string(const char *type, const char *attr, BString *str); int32 *dataSize);
status_t write_mime_attr(const char *type, const char *attr, const void *data,
size_t len, type_code datatype, bool *didCreate);
status_t write_mime_attr_message(const char *type, const char *attr,
const BMessage *msg, bool *didCreate);
status_t delete_attribute(const char *type, const char *attr);
} // namespace Mime } // namespace Mime
} // namespace Storage } // namespace Storage
} // namespace BPrivate } // namespace BPrivate
#endif // _MIME_DATABASE_SUPPORT_H #endif // _MIME_DATABASE_SUPPORT_H
-1
View File
@@ -31,7 +31,6 @@
#include <IconUtils.h> #include <IconUtils.h>
#include <Mime.h> #include <Mime.h>
#include <MimeType.h> #include <MimeType.h>
#include <mime/database_access.h>
#include <Node.h> #include <Node.h>
#include <Path.h> #include <Path.h>
#include <RegistrarDefs.h> #include <RegistrarDefs.h>
+59 -19
View File
@@ -12,7 +12,8 @@
#include "MimeType.h" #include "MimeType.h"
#include <Bitmap.h> #include <Bitmap.h>
#include <mime/database_access.h> #include <mime/database_support.h>
#include <mime/DatabaseLocation.h>
#include <sniffer/Rule.h> #include <sniffer/Rule.h>
#include <sniffer/Parser.h> #include <sniffer/Parser.h>
@@ -176,7 +177,8 @@ BMimeType::IsSupertypeOnly() const
bool bool
BMimeType::IsInstalled() const BMimeType::IsInstalled() const
{ {
return InitCheck() == B_OK && is_installed(Type()); return InitCheck() == B_OK
&& default_database_location()->IsInstalled(Type());
} }
@@ -307,9 +309,12 @@ BMimeType::Delete()
status_t status_t
BMimeType::GetIcon(BBitmap *icon, icon_size size) const BMimeType::GetIcon(BBitmap *icon, icon_size size) const
{ {
if (icon == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err)
err = get_icon(Type(), icon, size); err = default_database_location()->GetIcon(Type(), *icon, size);
return err; return err;
} }
@@ -319,9 +324,12 @@ BMimeType::GetIcon(BBitmap *icon, icon_size size) const
status_t status_t
BMimeType::GetIcon(uint8** data, size_t* size) const BMimeType::GetIcon(uint8** data, size_t* size) const
{ {
if (data == NULL || size == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err)
err = get_icon(Type(), data, size); err = default_database_location()->GetIcon(Type(), *data, *size);
return err; return err;
} }
@@ -333,8 +341,10 @@ status_t
BMimeType::GetPreferredApp(char *signature, app_verb verb) const BMimeType::GetPreferredApp(char *signature, app_verb verb) const
{ {
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err) {
err = get_preferred_app(Type(), signature, verb); err = default_database_location()->GetPreferredApp(Type(), signature,
verb);
}
return err; return err;
} }
@@ -345,9 +355,12 @@ BMimeType::GetPreferredApp(char *signature, app_verb verb) const
status_t status_t
BMimeType::GetAttrInfo(BMessage *info) const BMimeType::GetAttrInfo(BMessage *info) const
{ {
if (info == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err)
err = get_attr_info(Type(), info); err = default_database_location()->GetAttributesInfo(Type(), *info);
return err; return err;
} }
@@ -358,9 +371,14 @@ BMimeType::GetAttrInfo(BMessage *info) const
status_t status_t
BMimeType::GetFileExtensions(BMessage *extensions) const BMimeType::GetFileExtensions(BMessage *extensions) const
{ {
if (extensions == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err) {
err = get_file_extensions(Type(), extensions); err = default_database_location()->GetFileExtensions(Type(),
*extensions);
}
return err; return err;
} }
@@ -371,8 +389,10 @@ status_t
BMimeType::GetShortDescription(char *description) const BMimeType::GetShortDescription(char *description) const
{ {
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err) {
err = get_short_description(Type(), description); err = default_database_location()->GetShortDescription(Type(),
description);
}
return err; return err;
} }
@@ -383,8 +403,10 @@ status_t
BMimeType::GetLongDescription(char *description) const BMimeType::GetLongDescription(char *description) const
{ {
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err) {
err = get_long_description(Type(), description); err = default_database_location()->GetLongDescription(Type(),
description);
}
return err; return err;
} }
@@ -703,9 +725,12 @@ BMimeType::IsValid(const char *string)
status_t status_t
BMimeType::GetAppHint(entry_ref *ref) const BMimeType::GetAppHint(entry_ref *ref) const
{ {
if (ref == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err)
err = get_app_hint(Type(), ref); err = default_database_location()->GetAppHint(Type(), *ref);
return err; return err;
} }
@@ -745,13 +770,18 @@ BMimeType::SetAppHint(const entry_ref *ref)
status_t status_t
BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) const BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) const
{ {
if (icon == NULL)
return B_BAD_VALUE;
// If type is NULL, this function works just like GetIcon(), othewise, // If type is NULL, this function works just like GetIcon(), othewise,
// we need to make sure the give type is valid. // we need to make sure the give type is valid.
status_t err; status_t err;
if (type) { if (type) {
err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE;
if (!err) if (!err) {
err = get_icon_for_type(Type(), type, icon, which); err = default_database_location()->GetIconForType(Type(), type,
*icon, which);
}
} else } else
err = GetIcon(icon, which); err = GetIcon(icon, which);
@@ -764,6 +794,9 @@ BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) cons
status_t status_t
BMimeType::GetIconForType(const char *type, uint8** _data, size_t* _size) const BMimeType::GetIconForType(const char *type, uint8** _data, size_t* _size) const
{ {
if (_data == NULL || _size == NULL)
return B_BAD_VALUE;
// If type is NULL, this function works just like GetIcon(), otherwise, // If type is NULL, this function works just like GetIcon(), otherwise,
// we need to make sure the give type is valid. // we need to make sure the give type is valid.
if (type == NULL) if (type == NULL)
@@ -772,7 +805,8 @@ BMimeType::GetIconForType(const char *type, uint8** _data, size_t* _size) const
if (!BMimeType::IsValid(type)) if (!BMimeType::IsValid(type))
return B_BAD_VALUE; return B_BAD_VALUE;
return get_icon_for_type(Type(), type, _data, _size); return default_database_location()->GetIconForType(Type(), type, *_data,
*_size);
} }
@@ -871,9 +905,12 @@ BMimeType::SetIconForType(const char* type, const uint8* data, size_t dataSize)
status_t status_t
BMimeType::GetSnifferRule(BString *result) const BMimeType::GetSnifferRule(BString *result) const
{ {
if (result == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err)
err = get_sniffer_rule(Type(), result); err = default_database_location()->GetSnifferRule(Type(), *result);
return err; return err;
} }
@@ -1096,9 +1133,12 @@ BMimeType::BMimeType(const BMimeType &)
status_t status_t
BMimeType::GetSupportedTypes(BMessage *types) BMimeType::GetSupportedTypes(BMessage *types)
{ {
if (types == NULL)
return B_BAD_VALUE;
status_t err = InitCheck(); status_t err = InitCheck();
if (!err) if (!err)
err = get_supported_types(Type(), types); err = default_database_location()->GetSupportedTypes(Type(), *types);
return err; return err;
} }
+8 -4
View File
@@ -18,6 +18,7 @@
#include <Message.h> #include <Message.h>
#include <mime/database_support.h> #include <mime/database_support.h>
#include <mime/DatabaseDirectory.h> #include <mime/DatabaseDirectory.h>
#include <mime/DatabaseLocation.h>
#include <mime/MimeSniffer.h> #include <mime/MimeSniffer.h>
#include <MimeType.h> #include <MimeType.h>
#include <Path.h> #include <Path.h>
@@ -40,8 +41,10 @@ namespace Mime {
// Constructor // Constructor
//! Constructs a new AssociatedTypes object //! Constructs a new AssociatedTypes object
AssociatedTypes::AssociatedTypes(MimeSniffer* mimeSniffer) AssociatedTypes::AssociatedTypes(DatabaseLocation* databaseLocation,
MimeSniffer* mimeSniffer)
: :
fDatabaseLocation(databaseLocation),
fMimeSniffer(mimeSniffer), fMimeSniffer(mimeSniffer),
fHaveDoneFullBuild(false) fHaveDoneFullBuild(false)
{ {
@@ -333,7 +336,7 @@ AssociatedTypes::BuildAssociatedTypesTable()
fAssociatedTypes.clear(); fAssociatedTypes.clear();
DatabaseDirectory root; DatabaseDirectory root;
status_t err = root.Init(); status_t err = root.Init(fDatabaseLocation);
if (!err) { if (!err) {
root.Rewind(); root.Rewind();
while (true) { while (true) {
@@ -357,7 +360,7 @@ AssociatedTypes::BuildAssociatedTypesTable()
// First, iterate through this supertype directory and process // First, iterate through this supertype directory and process
// all of its subtypes // all of its subtypes
DatabaseDirectory dir; DatabaseDirectory dir;
if (dir.Init(supertype) == B_OK) { if (dir.Init(fDatabaseLocation, supertype) == B_OK) {
dir.Rewind(); dir.Rewind();
while (true) { while (true) {
BEntry subEntry; BEntry subEntry;
@@ -424,7 +427,8 @@ AssociatedTypes::ProcessType(const char *type)
if (!err) { if (!err) {
// Read in the list of file extension types // Read in the list of file extension types
BMessage msg; BMessage msg;
if (read_mime_attr_message(type, kFileExtensionsAttr, &msg) == B_OK) { if (fDatabaseLocation->ReadMessageAttribute(type, kFileExtensionsAttr,
msg) == B_OK) {
// Iterate through the file extesions, adding them to the list of // Iterate through the file extesions, adding them to the list of
// file extensions for the mime type and adding the mime type // file extensions for the mime type and adding the mime type
// to the list of associated types for each file extension // to the list of associated types for each file extension
+36 -32
View File
@@ -30,8 +30,8 @@
#include <TypeConstants.h> #include <TypeConstants.h>
#include <AutoLocker.h> #include <AutoLocker.h>
#include <mime/database_access.h>
#include <mime/database_support.h> #include <mime/database_support.h>
#include <mime/DatabaseLocation.h>
#include <storage_support.h> #include <storage_support.h>
@@ -64,18 +64,21 @@ Database::NotificationListener::~NotificationListener()
// constructor // constructor
/*! \brief Creates and initializes a Mime::Database object. /*! \brief Creates and initializes a Mime::Database object.
*/ */
Database::Database(MimeSniffer* mimeSniffer, Database::Database(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer,
NotificationListener* notificationListener) NotificationListener* notificationListener)
: :
fStatus(B_NO_INIT), fStatus(B_NO_INIT),
fLocation(databaseLocation),
fNotificationListener(notificationListener), fNotificationListener(notificationListener),
fAssociatedTypes(mimeSniffer), fAssociatedTypes(databaseLocation, mimeSniffer),
fSnifferRules(mimeSniffer), fInstalledTypes(databaseLocation),
fSnifferRules(databaseLocation, mimeSniffer),
fSupportingApps(databaseLocation),
fDeferredInstallNotificationsLocker("deferred install notifications"), fDeferredInstallNotificationsLocker("deferred install notifications"),
fDeferredInstallNotifications() fDeferredInstallNotifications()
{ {
// make sure the user's MIME DB directory exists // make sure the user's MIME DB directory exists
fStatus = create_directory(get_writable_database_directory(), fStatus = create_directory(fLocation->WritableDirectory(),
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
} }
@@ -116,14 +119,14 @@ Database::Install(const char *type)
return B_BAD_VALUE; return B_BAD_VALUE;
BEntry entry; BEntry entry;
status_t err = entry.SetTo(type_to_writable_filename(type)); status_t err = entry.SetTo(fLocation->WritablePathForType(type));
if (!err) { if (!err) {
if (entry.Exists()) if (entry.Exists())
err = B_FILE_EXISTS; err = B_FILE_EXISTS;
else { else {
bool didCreate = false; bool didCreate = false;
BNode node; BNode node;
err = open_or_create_type(type, &node, &didCreate); err = fLocation->OpenOrCreateType(type, node, &didCreate);
if (!err && didCreate) { if (!err && didCreate) {
fInstalledTypes.AddType(type); fInstalledTypes.AddType(type);
_SendInstallNotification(type); _SendInstallNotification(type);
@@ -148,7 +151,7 @@ Database::Delete(const char *type)
// Open the type // Open the type
BEntry entry; BEntry entry;
status_t status = entry.SetTo(type_to_writable_filename(type)); status_t status = entry.SetTo(fLocation->WritablePathForType(type));
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -198,7 +201,7 @@ Database::_SetStringValue(const char *type, int32 what, const char* attribute,
return B_BAD_VALUE; return B_BAD_VALUE;
char oldValue[maxLength]; char oldValue[maxLength];
status_t status = read_mime_attr(type, attribute, oldValue, status_t status = fLocation->ReadAttribute(type, attribute, oldValue,
maxLength, attributeType); maxLength, attributeType);
if (status >= B_OK && !strcmp(value, oldValue)) { if (status >= B_OK && !strcmp(value, oldValue)) {
// nothing has changed, no need to write back the data // nothing has changed, no need to write back the data
@@ -206,7 +209,7 @@ Database::_SetStringValue(const char *type, int32 what, const char* attribute,
} }
bool didCreate = false; bool didCreate = false;
status = write_mime_attr(type, attribute, value, length + 1, status = fLocation->WriteAttribute(type, attribute, value, length + 1,
attributeType, &didCreate); attributeType, &didCreate);
if (status == B_OK) { if (status == B_OK) {
@@ -267,7 +270,8 @@ Database::SetAttrInfo(const char *type, const BMessage *info)
return B_BAD_VALUE; return B_BAD_VALUE;
bool didCreate = false; bool didCreate = false;
status_t status = write_mime_attr_message(type, kAttrInfoAttr, info, &didCreate); status_t status = fLocation->WriteMessageAttribute(type, kAttrInfoAttr,
*info, &didCreate);
if (status == B_OK) { if (status == B_OK) {
if (didCreate) if (didCreate)
_SendInstallNotification(type); _SendInstallNotification(type);
@@ -334,8 +338,8 @@ Database::SetFileExtensions(const char *type, const BMessage *extensions)
return B_BAD_VALUE; return B_BAD_VALUE;
bool didCreate = false; bool didCreate = false;
status_t status = write_mime_attr_message(type, kFileExtensionsAttr, status_t status = fLocation->WriteMessageAttribute(type,
extensions, &didCreate); kFileExtensionsAttr, *extensions, &didCreate);
if (status == B_OK) { if (status == B_OK) {
if (didCreate) { if (didCreate) {
@@ -439,7 +443,7 @@ Database::SetIconForType(const char *type, const char *fileType,
BNode node; BNode node;
bool didCreate = false; bool didCreate = false;
status_t err = open_or_create_type(type, &node, &didCreate); status_t err = fLocation->OpenOrCreateType(type, node, &didCreate);
if (err != B_OK) if (err != B_OK)
return err; return err;
@@ -500,7 +504,7 @@ Database::SetIconForType(const char *type, const char *fileType,
BNode node; BNode node;
bool didCreate = false; bool didCreate = false;
status_t err = open_or_create_type(type, &node, &didCreate); status_t err = fLocation->OpenOrCreateType(type, node, &didCreate);
if (err != B_OK) if (err != B_OK)
return err; return err;
@@ -556,8 +560,8 @@ Database::SetSnifferRule(const char *type, const char *rule)
return B_BAD_VALUE; return B_BAD_VALUE;
bool didCreate = false; bool didCreate = false;
status_t status = write_mime_attr(type, kSnifferRuleAttr, rule, strlen(rule) + 1, status_t status = fLocation->WriteAttribute(type, kSnifferRuleAttr, rule,
kSnifferRuleType, &didCreate); strlen(rule) + 1, kSnifferRuleType, &didCreate);
if (status == B_OK) if (status == B_OK)
status = fSnifferRules.SetSnifferRule(type, rule); status = fSnifferRules.SetSnifferRule(type, rule);
@@ -597,7 +601,7 @@ Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSy
// Install the types // Install the types
const char *supportedType; const char *supportedType;
for (int32 i = 0; types->FindString("types", i, &supportedType) == B_OK; i++) { for (int32 i = 0; types->FindString("types", i, &supportedType) == B_OK; i++) {
if (!is_installed(supportedType)) { if (!fLocation->IsInstalled(supportedType)) {
if (Install(supportedType) != B_OK) if (Install(supportedType) != B_OK)
break; break;
@@ -610,8 +614,8 @@ Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSy
// Write the attr // Write the attr
bool didCreate = false; bool didCreate = false;
status_t status = write_mime_attr_message(type, kSupportedTypesAttr, types, status_t status = fLocation->WriteMessageAttribute(type,
&didCreate); kSupportedTypesAttr, *types, &didCreate);
// Notify the monitor if we created the type when we opened it // Notify the monitor if we created the type when we opened it
if (status != B_OK) if (status != B_OK)
@@ -976,7 +980,7 @@ Database::StopWatching(BMessenger target)
status_t status_t
Database::DeleteAppHint(const char *type) Database::DeleteAppHint(const char *type)
{ {
status_t status = delete_attribute(type, kAppHintAttr); status_t status = fLocation->DeleteAttribute(type, kAppHintAttr);
if (status == B_OK) if (status == B_OK)
_SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_DELETED); _SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_DELETED);
else if (status == B_ENTRY_NOT_FOUND) else if (status == B_ENTRY_NOT_FOUND)
@@ -998,7 +1002,7 @@ Database::DeleteAppHint(const char *type)
status_t status_t
Database::DeleteAttrInfo(const char *type) Database::DeleteAttrInfo(const char *type)
{ {
status_t status = delete_attribute(type, kAttrInfoAttr); status_t status = fLocation->DeleteAttribute(type, kAttrInfoAttr);
if (status == B_OK) if (status == B_OK)
_SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_DELETED); _SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_DELETED);
else if (status == B_ENTRY_NOT_FOUND) else if (status == B_ENTRY_NOT_FOUND)
@@ -1020,7 +1024,7 @@ Database::DeleteAttrInfo(const char *type)
status_t status_t
Database::DeleteShortDescription(const char *type) Database::DeleteShortDescription(const char *type)
{ {
status_t status = delete_attribute(type, kShortDescriptionAttr); status_t status = fLocation->DeleteAttribute(type, kShortDescriptionAttr);
if (status == B_OK) if (status == B_OK)
_SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED); _SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
else if (status == B_ENTRY_NOT_FOUND) else if (status == B_ENTRY_NOT_FOUND)
@@ -1042,7 +1046,7 @@ Database::DeleteShortDescription(const char *type)
status_t status_t
Database::DeleteLongDescription(const char *type) Database::DeleteLongDescription(const char *type)
{ {
status_t status = delete_attribute(type, kLongDescriptionAttr); status_t status = fLocation->DeleteAttribute(type, kLongDescriptionAttr);
if (status == B_OK) if (status == B_OK)
_SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED); _SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
else if (status == B_ENTRY_NOT_FOUND) else if (status == B_ENTRY_NOT_FOUND)
@@ -1064,7 +1068,7 @@ Database::DeleteLongDescription(const char *type)
status_t status_t
Database::DeleteFileExtensions(const char *type) Database::DeleteFileExtensions(const char *type)
{ {
status_t status = delete_attribute(type, kFileExtensionsAttr); status_t status = fLocation->DeleteAttribute(type, kFileExtensionsAttr);
if (status == B_OK) if (status == B_OK)
_SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_DELETED); _SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_DELETED);
else if (status == B_ENTRY_NOT_FOUND) else if (status == B_ENTRY_NOT_FOUND)
@@ -1088,7 +1092,7 @@ status_t
Database::DeleteIcon(const char *type, icon_size which) Database::DeleteIcon(const char *type, icon_size which)
{ {
const char *attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr; const char *attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr;
status_t status = delete_attribute(type, attr); status_t status = fLocation->DeleteAttribute(type, attr);
if (status == B_OK) if (status == B_OK)
_SendMonitorUpdate(B_ICON_CHANGED, type, which, B_META_MIME_DELETED); _SendMonitorUpdate(B_ICON_CHANGED, type, which, B_META_MIME_DELETED);
else if (status == B_ENTRY_NOT_FOUND) else if (status == B_ENTRY_NOT_FOUND)
@@ -1111,7 +1115,7 @@ status_t
Database::DeleteIcon(const char *type) Database::DeleteIcon(const char *type)
{ {
// TODO: extra notification for vector icon (uses B_LARGE_ICON now) // TODO: extra notification for vector icon (uses B_LARGE_ICON now)
status_t status = delete_attribute(type, kIconAttr); status_t status = fLocation->DeleteAttribute(type, kIconAttr);
if (status == B_OK) { if (status == B_OK) {
_SendMonitorUpdate(B_ICON_CHANGED, type, B_LARGE_ICON, _SendMonitorUpdate(B_ICON_CHANGED, type, B_LARGE_ICON,
B_META_MIME_DELETED); B_META_MIME_DELETED);
@@ -1146,7 +1150,7 @@ Database::DeleteIconForType(const char *type, const char *fileType, icon_size wh
std::string attr = (which == B_MINI_ICON std::string attr = (which == B_MINI_ICON
? kMiniIconAttrPrefix : kLargeIconAttrPrefix) + BPrivate::Storage::to_lower(fileType); ? kMiniIconAttrPrefix : kLargeIconAttrPrefix) + BPrivate::Storage::to_lower(fileType);
status_t status = delete_attribute(type, attr.c_str()); status_t status = fLocation->DeleteAttribute(type, attr.c_str());
if (status == B_OK) { if (status == B_OK) {
_SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType, _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
which == B_LARGE_ICON, B_META_MIME_DELETED); which == B_LARGE_ICON, B_META_MIME_DELETED);
@@ -1181,7 +1185,7 @@ Database::DeleteIconForType(const char *type, const char *fileType)
// TODO: introduce extra notification for vector icons? // TODO: introduce extra notification for vector icons?
// (uses B_LARGE_ICON now) // (uses B_LARGE_ICON now)
status_t status = delete_attribute(type, attr.c_str()); status_t status = fLocation->DeleteAttribute(type, attr.c_str());
if (status == B_OK) { if (status == B_OK) {
_SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType, _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
true, B_META_MIME_DELETED); true, B_META_MIME_DELETED);
@@ -1209,7 +1213,7 @@ Database::DeletePreferredApp(const char *type, app_verb verb)
switch (verb) { switch (verb) {
case B_OPEN: case B_OPEN:
status = delete_attribute(type, kPreferredAppAttr); status = fLocation->DeleteAttribute(type, kPreferredAppAttr);
break; break;
default: default:
@@ -1242,7 +1246,7 @@ Database::DeletePreferredApp(const char *type, app_verb verb)
status_t status_t
Database::DeleteSnifferRule(const char *type) Database::DeleteSnifferRule(const char *type)
{ {
status_t status = delete_attribute(type, kSnifferRuleAttr); status_t status = fLocation->DeleteAttribute(type, kSnifferRuleAttr);
if (status == B_OK) { if (status == B_OK) {
status = fSnifferRules.DeleteSnifferRule(type); status = fSnifferRules.DeleteSnifferRule(type);
if (status == B_OK) { if (status == B_OK) {
@@ -1274,7 +1278,7 @@ Database::DeleteSnifferRule(const char *type)
status_t status_t
Database::DeleteSupportedTypes(const char *type, bool fullSync) Database::DeleteSupportedTypes(const char *type, bool fullSync)
{ {
status_t status = delete_attribute(type, kSupportedTypesAttr); status_t status = fLocation->DeleteAttribute(type, kSupportedTypesAttr);
// Update the supporting apps database. If fullSync is specified, // Update the supporting apps database. If fullSync is specified,
// do so even if the supported types attribute didn't exist, as // do so even if the supported types attribute didn't exist, as
+4 -3
View File
@@ -14,6 +14,7 @@
#include <StringList.h> #include <StringList.h>
#include <mime/database_support.h> #include <mime/database_support.h>
#include <mime/DatabaseLocation.h>
namespace BPrivate { namespace BPrivate {
@@ -34,14 +35,14 @@ DatabaseDirectory::~DatabaseDirectory()
status_t status_t
DatabaseDirectory::Init(const char* superType) DatabaseDirectory::Init(DatabaseLocation* databaseLocation,
const char* superType)
{ {
status_t error = BMergedDirectory::Init(); status_t error = BMergedDirectory::Init();
if (error != B_OK) if (error != B_OK)
return error; return error;
const BStringList& directories const BStringList& directories = databaseLocation->Directories();
= BPrivate::Storage::Mime::get_database_directories();
int32 count = directories.CountStrings(); int32 count = directories.CountStrings();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
BString directory = directories.StringAt(i); BString directory = directories.StringAt(i);
+909
View File
@@ -0,0 +1,909 @@
/*
* Copyright 2002-2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Tyler Dauwalder
* Ingo Weinhold <ingo_weinhold@gmx.de>
*/
#include <mime/DatabaseLocation.h>
#include <stdlib.h>
#include <syslog.h>
#include <Bitmap.h>
#include <DataIO.h>
#include <Directory.h>
#include <File.h>
#include <fs_attr.h>
#include <IconUtils.h>
#include <Message.h>
#include <Node.h>
#include <AutoDeleter.h>
#include <mime/database_support.h>
namespace BPrivate {
namespace Storage {
namespace Mime {
DatabaseLocation::DatabaseLocation()
:
fDirectories()
{
}
DatabaseLocation::~DatabaseLocation()
{
}
bool
DatabaseLocation::AddDirectory(const BString& directory)
{
return !directory.IsEmpty() && fDirectories.Add(directory);
}
/*! \brief Opens a BNode on the given type, failing if the type has no
corresponding file in the database.
\param type The MIME type to open.
\param _node Node opened on the given MIME type.
*/
status_t
DatabaseLocation::OpenType(const char* type, BNode& _node) const
{
if (type == NULL)
return B_BAD_VALUE;
int32 index;
return _OpenType(type, _node, index);
}
/*! \brief Opens a BNode on the given type, creating a node of the
appropriate flavor if necessary.
All MIME types are converted to lowercase for use in the filesystem.
\param type The MIME type to open.
\param _node Node opened on the given MIME type.
\param _didCreate If not \c NULL, the variable the pointer refers to is
set to \c true, if the node has been newly create, to \c false
otherwise.
*/
status_t
DatabaseLocation::OpenOrCreateType(const char* type, BNode& _node,
bool* _didCreate) const
{
if (_didCreate)
*_didCreate = false;
// See, if the type already exists.
int32 index;
status_t error = _OpenType(type, _node, index);
if (error == B_OK) {
if (index == 0)
return B_OK;
// The caller wants a editable node, but the node found is not in the
// user's settings directory. Copy the node.
BNode nodeToClone(_node);
if (nodeToClone.InitCheck() != B_OK)
return nodeToClone.InitCheck();
error = _CopyTypeNode(nodeToClone, type, _node);
if (error != B_OK) {
_node.Unset();
return error;
}
if (_didCreate != NULL)
*_didCreate = true;
return error;
}
// type doesn't exist yet -- create the respective node
error = _CreateTypeNode(type, _node);
if (error != B_OK)
return error;
// write the type attribute
error = _node.WriteAttr(kTypeAttr, B_STRING_TYPE, 0, type,
strlen(type) + 1);
if (error != B_OK) {
_node.Unset();
return error;
}
if (_didCreate != NULL)
*_didCreate = true;
return B_OK;
}
/*! \brief Reads up to \c len bytes of the given data from the given attribute
for the given MIME type.
If no entry for the given type exists in the database, the function fails,
and the contents of \c data are undefined.
\param type The MIME type
\param attribute The attribute name
\param data Pointer to a memory buffer into which the data should be copied
\param length The maximum number of bytes to read
\param datatype The expected data type
\return If successful, the number of bytes read is returned, otherwise, an
error code is returned.
*/
ssize_t
DatabaseLocation::ReadAttribute(const char* type, const char* attribute,
void* data, size_t length, type_code datatype) const
{
if (type == NULL || attribute == NULL || data == NULL)
return B_BAD_VALUE;
BNode node;
status_t error = OpenType(type, node);
if (error != B_OK)
return error;
return node.ReadAttr(attribute, datatype, 0, data, length);
}
/*! \brief Reads a flattened BMessage from the given attribute of the given
MIME type.
If no entry for the given type exists in the database, or if the data
stored in the attribute is not a flattened BMessage, the function fails
and the contents of \c msg are undefined.
\param type The MIME type
\param attribute The attribute name
\param data Reference to a pre-allocated BMessage into which the attribute
data is unflattened.
*/
status_t
DatabaseLocation::ReadMessageAttribute(const char* type, const char* attribute,
BMessage& _message) const
{
if (type == NULL || attribute == NULL)
return B_BAD_VALUE;
BNode node;
attr_info info;
status_t error = OpenType(type, node);
if (error != B_OK)
return error;
error = node.GetAttrInfo(attribute, &info);
if (error != B_OK)
return error;
if (info.type != B_MESSAGE_TYPE)
return B_BAD_VALUE;
void* buffer = malloc(info.size);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter bufferDeleter(buffer);
ssize_t bytesRead = node.ReadAttr(attribute, B_MESSAGE_TYPE, 0, buffer,
info.size);
if (bytesRead != info.size)
return bytesRead < 0 ? (status_t)bytesRead : (status_t)B_FILE_ERROR;
return _message.Unflatten((const char*)buffer);
}
/*! \brief Reads a BString from the given attribute of the given
MIME type.
If no entry for the given type exists in the database, the function fails
and the contents of \c str are undefined.
\param type The MIME type
\param attribute The attribute name
\param _string Reference to a pre-allocated BString into which the attribute
data stored.
*/
status_t
DatabaseLocation::ReadStringAttribute(const char* type, const char* attribute,
BString& _string) const
{
if (type == NULL || attribute == NULL)
return B_BAD_VALUE;
BNode node;
status_t error = OpenType(type, node);
if (error != B_OK)
return error;
return node.ReadAttrString(attribute, &_string);
}
/*! \brief Writes \c len bytes of the given data to the given attribute
for the given MIME type.
If no entry for the given type exists in the database, it is created.
\param type The MIME type
\param attribute The attribute name
\param data Pointer to the data to write
\param length The number of bytes to write
\param datatype The data type of the given data
*/
status_t
DatabaseLocation::WriteAttribute(const char* type, const char* attribute,
const void* data, size_t length, type_code datatype, bool* _didCreate) const
{
if (type == NULL || attribute == NULL || data == NULL)
return B_BAD_VALUE;
BNode node;
status_t error = OpenOrCreateType(type, node, _didCreate);
if (error != B_OK)
return error;
ssize_t bytesWritten = node.WriteAttr(attribute, datatype, 0, data, length);
if (bytesWritten < 0)
return bytesWritten;
return bytesWritten == (ssize_t)length ? B_OK : B_FILE_ERROR;
}
/*! \brief Flattens the given \c BMessage and writes it to the given attribute
of the given MIME type.
If no entry for the given type exists in the database, it is created.
\param type The MIME type
\param attribute The attribute name
\param message The BMessage to flatten and write
*/
status_t
DatabaseLocation::WriteMessageAttribute(const char* type, const char* attribute,
const BMessage& message, bool* _didCreate) const
{
BMallocIO data;
status_t error = data.SetSize(message.FlattenedSize());
if (error != B_OK)
return error;
ssize_t bytes;
error = message.Flatten(&data, &bytes);
if (error != B_OK)
return error;
return WriteAttribute(type, attribute, data.Buffer(), data.BufferLength(),
B_MESSAGE_TYPE, _didCreate);
}
//! Deletes the given attribute for the given type
/*!
\param type The mime type
\param attribute The attribute name
\return
- B_OK: success
- B_ENTRY_NOT_FOUND: no such type or attribute
- "error code": failure
*/
status_t
DatabaseLocation::DeleteAttribute(const char* type, const char* attribute) const
{
if (type == NULL || attribute == NULL)
return B_BAD_VALUE;
BNode node;
int32 index;
status_t error = _OpenType(type, node, index);
if (error != B_OK)
return error;
if (index != 0)
return B_NOT_ALLOWED;
return node.RemoveAttr(attribute);
}
/*! \brief Fetches the application hint for the given MIME type.
The entry_ref pointed to by \c ref must be pre-allocated.
\param type The MIME type of interest
\param _ref Reference to a pre-allocated \c entry_ref struct into
which the location of the hint application is copied.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No app hint exists for the given type
- "error code": Failure
*/
status_t
DatabaseLocation::GetAppHint(const char* type, entry_ref& _ref)
{
if (type == NULL)
return B_BAD_VALUE;
char path[B_PATH_NAME_LENGTH];
BEntry entry;
ssize_t status = ReadAttribute(type, kAppHintAttr, path, B_PATH_NAME_LENGTH,
kAppHintType);
if (status >= B_OK)
status = entry.SetTo(path);
if (status == B_OK)
status = entry.GetRef(&_ref);
return status;
}
/*! \brief Fetches from the MIME database a BMessage describing the attributes
typically associated with files of the given MIME type
The attribute information is returned in a pre-allocated BMessage pointed to
by the \c info parameter (note that the any prior contents of the message
will be destroyed). Please see BMimeType::SetAttrInfo() for a description
of the expected format of such a message.
\param _info Reference to a pre-allocated BMessage into which information
about the MIME type's associated file attributes is stored.
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
DatabaseLocation::GetAttributesInfo(const char* type, BMessage& _info)
{
status_t err = ReadMessageAttribute(type, kAttrInfoAttr, _info);
if (err == B_ENTRY_NOT_FOUND) {
// return an empty message
_info.MakeEmpty();
err = B_OK;
}
if (err == B_OK) {
_info.what = 233;
// Don't know why, but that's what R5 does.
err = _info.AddString("type", type);
}
return err;
}
/*! \brief Fetches the short description for the given MIME type.
The string pointed to by \c description must be long enough to
hold the short description; a length of \c B_MIME_TYPE_LENGTH is
recommended.
\param type The MIME type of interest
\param description Pointer to a pre-allocated string into which the short
description is copied. If the function fails, the contents of the string
are undefined.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No short description exists for the given type
- "error code": Failure
*/
status_t
DatabaseLocation::GetShortDescription(const char* type, char* description)
{
ssize_t err = ReadAttribute(type, kShortDescriptionAttr, description,
B_MIME_TYPE_LENGTH, kShortDescriptionType);
return err >= 0 ? B_OK : err ;
}
//! Fetches the long description for the given MIME type.
/*! The string pointed to by \c description must be long enough to
hold the long description; a length of \c B_MIME_TYPE_LENGTH is
recommended.
\param type The MIME type of interest
\param description Pointer to a pre-allocated string into which the long
description is copied. If the function fails, the contents of the string
are undefined.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No long description exists for the given type
- "error code": Failure
*/
status_t
DatabaseLocation::GetLongDescription(const char* type, char* description)
{
ssize_t err = ReadAttribute(type, kLongDescriptionAttr, description,
B_MIME_TYPE_LENGTH, kLongDescriptionType);
return err >= 0 ? B_OK : err ;
}
/*! \brief Fetches a BMessage describing the MIME type's associated filename
extensions
The list of extensions is returned in a pre-allocated BMessage pointed to
by the \c extensions parameter (note that the any prior contents of the
message will be destroyed). Please see BMimeType::GetFileExtensions() for
a description of the message format.
\param extensions Reference to a pre-allocated BMessage into which the MIME
type's associated file extensions will be stored.
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
DatabaseLocation::GetFileExtensions(const char* type, BMessage& _extensions)
{
status_t err = ReadMessageAttribute(type, kFileExtensionsAttr, _extensions);
if (err == B_ENTRY_NOT_FOUND) {
// return an empty message
_extensions.MakeEmpty();
err = B_OK;
}
if (err == B_OK) {
_extensions.what = 234; // Don't know why, but that's what R5 does.
err = _extensions.AddString("type", type);
}
return err;
}
/*! \brief Fetches the icon of given size associated with the given MIME type
The bitmap pointed to by \c icon must be of the proper size (\c 32x32
for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and color depth
(\c B_CMAP8).
\param type The mime type
\param icon Reference to a pre-allocated bitmap of proper dimensions and
color depth
\param size The size icon you're interested in (\c B_LARGE_ICON or
\c B_MINI_ICON)
*/
status_t
DatabaseLocation::GetIcon(const char* type, BBitmap& _icon, icon_size size)
{
return GetIconForType(type, NULL, _icon, size);
}
//! Fetches the vector icon associated with the given MIME type
/** \param type The mime type
\param _data Reference via which the allocated icon data is returned. You
need to free the buffer once you're done with it.
\param _size Reference via which the size of the icon data is returned.
*/
status_t
DatabaseLocation::GetIcon(const char* type, uint8*& _data, size_t& _size)
{
return GetIconForType(type, NULL, _data, _size);
}
/*! \brief Fetches the large or mini icon used by an application of this type
for files of the given type.
The type of the \c BMimeType object is not required to actually be a subtype
of \c "application/"; that is the intended use however, and calling
\c GetIconForType() on a non-application type will likely return
\c B_ENTRY_NOT_FOUND.
The icon is copied into the \c BBitmap pointed to by \c icon. The bitmap
must be the proper size: \c 32x32 for the large icon, \c 16x16 for the mini
icon.
\param type The MIME type
\param fileType Pointer to a pre-allocated string containing the MIME type
whose custom icon you wish to fetch. If NULL, works just like
GetIcon().
\param icon Reference to a pre-allocated \c BBitmap of proper size and
colorspace into which the icon is copied.
\param icon_size Value that specifies which icon to return. Currently
\c B_LARGE_ICON and \c B_MINI_ICON are supported.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type
- "error code": Failure
*/
status_t
DatabaseLocation::GetIconForType(const char* type, const char* fileType,
BBitmap& _icon, icon_size which)
{
if (type == NULL)
return B_BAD_VALUE;
// open the node for the given type
BNode node;
ssize_t err = OpenType(type, node);
if (err < B_OK)
return (status_t)err;
// construct our attribute name
BString vectorIconAttrName;
BString smallIconAttrName;
BString largeIconAttrName;
if (fileType) {
BString lowerCaseFileType(fileType);
lowerCaseFileType.ToLower();
vectorIconAttrName << kIconAttrPrefix << lowerCaseFileType;
smallIconAttrName << kMiniIconAttrPrefix << lowerCaseFileType;
largeIconAttrName << kLargeIconAttrPrefix << lowerCaseFileType;
} else {
vectorIconAttrName = kIconAttr;
smallIconAttrName = kMiniIconAttr;
largeIconAttrName = kLargeIconAttr;
}
return BIconUtils::GetIcon(&node, vectorIconAttrName, smallIconAttrName,
largeIconAttrName, which, &_icon);
// ssize_t err = type && icon ? B_OK : B_BAD_VALUE;
//
// // Figure out what kind of data we *should* find
// uint32 attrType = 0;
// ssize_t attrSize = 0;
// BRect bounds;
//
// if (!err) {
// switch (which) {
// case B_MINI_ICON:
// bounds.Set(0, 0, 15, 15);
// attrType = kMiniIconType;
// attrSize = 16 * 16;
// break;
// case B_LARGE_ICON:
// bounds.Set(0, 0, 31, 31);
// attrType = kLargeIconType;
// attrSize = 32 * 32;
// break;
// default:
// err = B_BAD_VALUE;
// break;
// }
// }
// // Construct our attribute name
// std::string attr;
// if (fileType) {
// attr = (which == B_MINI_ICON
// ? kMiniIconAttrPrefix
// : kLargeIconAttrPrefix)
// + BPrivate::Storage::to_lower(fileType);
// } else {
// attr = (which == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr;
// }
// // Check the icon and attribute to see if they match
// if (!err) {
// err = (icon->InitCheck() == B_OK
// && icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE;
// }
//
// BNode node;
// if (!err)
// err = open_type(type, &node);
//
// attr_info info;
// if (!err)
// err = node.GetAttrInfo(attr.c_str(), &info);
//
// if (!err)
// err = (attrType == info.type && attrSize == info.size) ? B_OK : B_BAD_VALUE;
// // read the attribute
// if (!err) {
// bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
// char *buffer = NULL;
// if (otherColorSpace) {
// // other color space than stored in attribute
// buffer = new(std::nothrow) char[attrSize];
// if (!buffer)
// err = B_NO_MEMORY;
// if (!err)
// err = node.ReadAttr(attr.c_str(), attrType, 0, buffer, attrSize);
// } else {
// // same color space, just read direct
// err = node.ReadAttr(attr.c_str(), attrType, 0, icon->Bits(), attrSize);
// }
// if (err >= 0)
// err = (err == attrSize) ? (status_t)B_OK : (status_t)B_FILE_ERROR;
// if (otherColorSpace) {
// if (!err) {
// err = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
// 0, B_CMAP8);
// }
// delete[] buffer;
// }
// }
//
// return err;
}
/*! \brief Fetches the vector icon used by an application of this type for files
of the given type.
The type of the \c BMimeType object is not required to actually be a subtype
of \c "application/"; that is the intended use however, and calling
\c GetIconForType() on a non-application type will likely return
\c B_ENTRY_NOT_FOUND.
The icon data is allocated and returned in \a _data.
\param type The MIME type
\param fileType Reference to a pre-allocated string containing the MIME type
whose custom icon you wish to fetch. If NULL, works just like GetIcon().
\param _data Reference via which the icon data is returned on success.
\param _size Reference via which the size of the icon data is returned.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No vector icon exists for the given type
- "error code": Failure
*/
status_t
DatabaseLocation::GetIconForType(const char* type, const char* fileType,
uint8*& _data, size_t& _size)
{
if (type == NULL)
return B_BAD_VALUE;
// open the node for the given type
BNode node;
ssize_t err = OpenType(type, node);
if (err < B_OK)
return (status_t)err;
// construct our attribute name
BString iconAttrName;
if (fileType)
iconAttrName << kIconAttrPrefix << BString(fileType).ToLower();
else
iconAttrName = kIconAttr;
// get info about attribute for that name
attr_info info;
if (!err)
err = node.GetAttrInfo(iconAttrName, &info);
// validate attribute type
if (!err)
err = (info.type == B_VECTOR_ICON_TYPE) ? B_OK : B_BAD_VALUE;
// allocate a buffer and read the attribute data into it
if (!err) {
uint8* buffer = new(std::nothrow) uint8[info.size];
if (!buffer)
err = B_NO_MEMORY;
if (!err) {
err = node.ReadAttr(iconAttrName, B_VECTOR_ICON_TYPE, 0, buffer,
info.size);
}
if (err >= 0)
err = (err == info.size) ? (ssize_t)B_OK : (ssize_t)B_FILE_ERROR;
if (!err) {
// success, set data pointer and size
_data = buffer;
_size = info.size;
} else {
delete[] buffer;
}
}
return err;
}
/*! \brief Fetches signature of the MIME type's preferred application for the
given action.
The string pointed to by \c signature must be long enough to
hold the short description; a length of \c B_MIME_TYPE_LENGTH is
recommended.
Currently, the only supported app verb is \c B_OPEN.
\param type The MIME type of interest
\param description Pointer to a pre-allocated string into which the
preferred application's signature is copied. If the function fails,
the contents of the string are undefined.
\param verb \c The action of interest
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No such preferred application exists
- "error code": Failure
*/
status_t
DatabaseLocation::GetPreferredApp(const char* type, char* signature,
app_verb verb)
{
// Since B_OPEN is the currently the only app_verb, it is essentially
// ignored
ssize_t err = ReadAttribute(type, kPreferredAppAttr, signature,
B_MIME_TYPE_LENGTH, kPreferredAppType);
return err >= 0 ? B_OK : err ;
}
/*! \brief Fetches the sniffer rule for the given MIME type.
\param type The MIME type of interest
\param _result Pointer to a pre-allocated BString into which the type's
sniffer rule is copied.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No such preferred application exists
- "error code": Failure
*/
status_t
DatabaseLocation::GetSnifferRule(const char* type, BString& _result)
{
return ReadStringAttribute(type, kSnifferRuleAttr, _result);
}
status_t
DatabaseLocation::GetSupportedTypes(const char* type, BMessage& _types)
{
status_t err = ReadMessageAttribute(type, kSupportedTypesAttr, _types);
if (err == B_ENTRY_NOT_FOUND) {
// return an empty message
_types.MakeEmpty();
err = B_OK;
}
if (err == B_OK) {
_types.what = 0;
err = _types.AddString("type", type);
}
return err;
}
//! Checks if the given MIME type is present in the database
bool
DatabaseLocation::IsInstalled(const char* type)
{
BNode node;
return OpenType(type, node) == B_OK;
}
BString
DatabaseLocation::_TypeToFilename(const char* type, int32 index) const
{
BString path = fDirectories.StringAt(index);
return path << '/' << BString(type).ToLower();
}
status_t
DatabaseLocation::_OpenType(const char* type, BNode& _node, int32& _index) const
{
int32 count = fDirectories.CountStrings();
for (int32 i = 0; i < count; i++) {
status_t error = _node.SetTo(_TypeToFilename(type, i));
attr_info attrInfo;
if (error == B_OK && _node.GetAttrInfo(kTypeAttr, &attrInfo) == B_OK) {
_index = i;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
DatabaseLocation::_CreateTypeNode(const char* type, BNode& _node) const
{
const char* slash = strchr(type, '/');
BString superTypeName;
if (slash != NULL)
superTypeName.SetTo(type, slash - type);
else
superTypeName = type;
superTypeName.ToLower();
// open/create the directory for the supertype
BDirectory parent(WritableDirectory());
status_t error = parent.InitCheck();
if (error != B_OK)
return error;
BDirectory superTypeDirectory;
if (BEntry(&parent, superTypeName).Exists())
error = superTypeDirectory.SetTo(&parent, superTypeName);
else
error = parent.CreateDirectory(superTypeName, &superTypeDirectory);
if (error != B_OK)
return error;
// create the subtype
BFile subTypeFile;
if (slash != NULL) {
error = superTypeDirectory.CreateFile(BString(slash + 1).ToLower(),
&subTypeFile);
if (error != B_OK)
return error;
}
// assign the result
if (slash != NULL)
_node = subTypeFile;
else
_node = superTypeDirectory;
return _node.InitCheck();
}
status_t
DatabaseLocation::_CopyTypeNode(BNode& source, const char* type, BNode& _target)
const
{
status_t error = _CreateTypeNode(type, _target);
if (error != B_OK)
return error;
// copy the attributes
MemoryDeleter bufferDeleter;
size_t bufferSize = 0;
source.RewindAttrs();
char attribute[B_ATTR_NAME_LENGTH];
while (source.GetNextAttrName(attribute) == B_OK) {
attr_info info;
error = source.GetAttrInfo(attribute, &info);
if (error != B_OK) {
syslog(LOG_ERR, "Failed to get info for attribute \"%s\" of MIME "
"type \"%s\": %s", attribute, type, strerror(error));
continue;
}
// resize our buffer, if necessary
if (info.size > bufferSize) {
bufferDeleter.SetTo(malloc(info.size));
if (bufferDeleter.Get() == NULL)
return B_NO_MEMORY;
bufferSize = info.size;
}
ssize_t bytesRead = source.ReadAttr(attribute, info.type, 0,
bufferDeleter.Get(), info.size);
if (bytesRead != info.size) {
syslog(LOG_ERR, "Failed to read attribute \"%s\" of MIME "
"type \"%s\": %s", attribute, type,
bytesRead < 0 ? strerror(bytesRead) : "short read");
continue;
}
ssize_t bytesWritten = _target.WriteAttr(attribute, info.type, 0,
bufferDeleter.Get(), info.size);
if (bytesWritten < 0) {
syslog(LOG_ERR, "Failed to write attribute \"%s\" of MIME "
"type \"%s\": %s", attribute, type,
bytesWritten < 0 ? strerror(bytesWritten) : "short write");
continue;
}
}
return B_OK;
}
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
+4 -3
View File
@@ -40,8 +40,9 @@ namespace Mime {
*/ */
//! Constructs a new InstalledTypes object //! Constructs a new InstalledTypes object
InstalledTypes::InstalledTypes() InstalledTypes::InstalledTypes(DatabaseLocation* databaseLocation)
: :
fDatabaseLocation(databaseLocation),
fCachedMessage(NULL), fCachedMessage(NULL),
fCachedSupertypesMessage(NULL), fCachedSupertypesMessage(NULL),
fHaveDoneFullBuild(false) fHaveDoneFullBuild(false)
@@ -385,7 +386,7 @@ InstalledTypes::_BuildInstalledTypesList()
DatabaseDirectory root; DatabaseDirectory root;
if (!err) if (!err)
err = root.Init(); err = root.Init(fDatabaseLocation);
if (!err) { if (!err) {
root.Rewind(); root.Rewind();
while (true) { while (true) {
@@ -417,7 +418,7 @@ InstalledTypes::_BuildInstalledTypesList()
// Now iterate through this supertype directory and add // Now iterate through this supertype directory and add
// all of its subtypes // all of its subtypes
DatabaseDirectory dir; DatabaseDirectory dir;
if (dir.Init(supertype) == B_OK) { if (dir.Init(fDatabaseLocation, supertype) == B_OK) {
dir.Rewind(); dir.Rewind();
while (true) { while (true) {
BEntry subEntry; BEntry subEntry;
+1 -1
View File
@@ -13,7 +13,7 @@ StaticLibrary libstorage_kit_mime.a :
AssociatedTypes.cpp AssociatedTypes.cpp
Database.cpp Database.cpp
DatabaseDirectory.cpp DatabaseDirectory.cpp
database_access.cpp DatabaseLocation.cpp
database_support.cpp database_support.cpp
InstalledTypes.cpp InstalledTypes.cpp
MimeSniffer.cpp MimeSniffer.cpp
+10 -5
View File
@@ -23,6 +23,7 @@
#include <MimeType.h> #include <MimeType.h>
#include <mime/database_support.h> #include <mime/database_support.h>
#include <mime/DatabaseDirectory.h> #include <mime/DatabaseDirectory.h>
#include <mime/DatabaseLocation.h>
#include <mime/MimeSniffer.h> #include <mime/MimeSniffer.h>
#include <sniffer/Parser.h> #include <sniffer/Parser.h>
#include <sniffer/Rule.h> #include <sniffer/Rule.h>
@@ -112,8 +113,10 @@ bool operator<(SnifferRules::sniffer_rule &left, SnifferRules::sniffer_rule &rig
// Constructor // Constructor
//! Constructs a new SnifferRules object //! Constructs a new SnifferRules object
SnifferRules::SnifferRules(MimeSniffer* mimeSniffer) SnifferRules::SnifferRules(DatabaseLocation* databaseLocation,
MimeSniffer* mimeSniffer)
: :
fDatabaseLocation(databaseLocation),
fMimeSniffer(mimeSniffer), fMimeSniffer(mimeSniffer),
fMaxBytesNeeded(0), fMaxBytesNeeded(0),
fHaveDoneFullBuild(false) fHaveDoneFullBuild(false)
@@ -338,7 +341,7 @@ SnifferRules::BuildRuleList()
ssize_t bytesNeeded = 0; ssize_t bytesNeeded = 0;
DatabaseDirectory root; DatabaseDirectory root;
status_t err = root.Init(); status_t err = root.Init(fDatabaseLocation);
if (!err) { if (!err) {
root.Rewind(); root.Rewind();
while (true) { while (true) {
@@ -362,7 +365,7 @@ SnifferRules::BuildRuleList()
// First, iterate through this supertype directory and process // First, iterate through this supertype directory and process
// all of its subtypes // all of its subtypes
DatabaseDirectory dir; DatabaseDirectory dir;
if (dir.Init(supertype) == B_OK) { if (dir.Init(fDatabaseLocation, supertype) == B_OK) {
dir.Rewind(); dir.Rewind();
while (true) { while (true) {
BEntry subEntry; BEntry subEntry;
@@ -562,8 +565,10 @@ SnifferRules::ProcessType(const char *type, ssize_t *bytesNeeded)
if (!err) if (!err)
err = rule.rule ? B_OK : B_NO_MEMORY; err = rule.rule ? B_OK : B_NO_MEMORY;
// Read the attr // Read the attr
if (!err) if (!err) {
err = read_mime_attr_string(type, kSnifferRuleAttr, &str); err = fDatabaseLocation->ReadStringAttribute(type, kSnifferRuleAttr,
str);
}
// Parse the rule // Parse the rule
if (!err) { if (!err) {
err = Sniffer::parse(str.String(), rule.rule, &errorMsg); err = Sniffer::parse(str.String(), rule.rule, &errorMsg);
+8 -5
View File
@@ -24,6 +24,7 @@
#include <mime/database_support.h> #include <mime/database_support.h>
#include <mime/DatabaseDirectory.h> #include <mime/DatabaseDirectory.h>
#include <mime/DatabaseLocation.h>
#include <storage_support.h> #include <storage_support.h>
@@ -42,8 +43,10 @@ namespace Mime {
// Constructor // Constructor
//! Constructs a new SupportingApps object //! Constructs a new SupportingApps object
SupportingApps::SupportingApps() SupportingApps::SupportingApps(DatabaseLocation* databaseLocation)
: fHaveDoneFullBuild(false) :
fDatabaseLocation(databaseLocation),
fHaveDoneFullBuild(false)
{ {
} }
@@ -266,7 +269,7 @@ SupportingApps::BuildSupportingAppsTable()
fStrandedTypes.clear(); fStrandedTypes.clear();
DatabaseDirectory dir; DatabaseDirectory dir;
status_t status = dir.Init("application"); status_t status = dir.Init(fDatabaseLocation, "application");
// Build the supporting apps table based on the mime database // Build the supporting apps table based on the mime database
if (status == B_OK) { if (status == B_OK) {
@@ -290,8 +293,8 @@ SupportingApps::BuildSupportingAppsTable()
&appSignature) >= B_OK) { &appSignature) >= B_OK) {
// Read in the list of supported types // Read in the list of supported types
BMessage msg; BMessage msg;
if (read_mime_attr_message(appSignature.String(), kSupportedTypesAttr, if (fDatabaseLocation->ReadMessageAttribute(appSignature,
&msg) == B_OK) { kSupportedTypesAttr, msg) == B_OK) {
// Iterate through the supported types, adding them to the list of // Iterate through the supported types, adding them to the list of
// supported types for the application and adding the application's // supported types for the application and adding the application's
// signature to the list of supporting apps for each type // signature to the list of supporting apps for each type
-585
View File
@@ -1,585 +0,0 @@
/*
* Copyright 2002-2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Tyler Dauwalder
*/
/*!
\file database_access.cpp
Mime database atomic read functions
*/
#include <mime/database_access.h>
#include <Bitmap.h>
#include <Entry.h>
#include <Directory.h>
#include <IconUtils.h>
#include <Message.h>
#include <mime/database_support.h>
#include <Node.h>
#include <Path.h>
#include <RegistrarDefs.h>
#include <String.h>
#include <storage_support.h>
#include <fs_attr.h> // For struct attr_info
#include <iostream>
#include <new> // For new(nothrow)
#include <stdio.h>
#include <string>
#define DBG(x) x
//#define DBG(x)
#define OUT printf
namespace BPrivate {
namespace Storage {
namespace Mime {
/*! \brief Fetches the application hint for the given MIME type.
The entry_ref pointed to by \c ref must be pre-allocated.
\param type The MIME type of interest
\param ref Pointer to a pre-allocated \c entry_ref struct into
which the location of the hint application is copied.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No app hint exists for the given type
- "error code": Failure
*/
status_t
get_app_hint(const char *type, entry_ref *ref)
{
if (type == NULL || ref == NULL)
return B_BAD_VALUE;
char path[B_PATH_NAME_LENGTH];
BEntry entry;
ssize_t status = read_mime_attr(type, kAppHintAttr, path,
B_PATH_NAME_LENGTH, kAppHintType);
if (status >= B_OK)
status = entry.SetTo(path);
if (status == B_OK)
status = entry.GetRef(ref);
return status;
}
/*! \brief Fetches from the MIME database a BMessage describing the attributes
typically associated with files of the given MIME type
The attribute information is returned in a pre-allocated BMessage pointed to by
the \c info parameter (note that the any prior contents of the message
will be destroyed). Please see BMimeType::SetAttrInfo() for a description
of the expected format of such a message.
\param info Pointer to a pre-allocated BMessage into which information about
the MIME type's associated file attributes is stored.
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
get_attr_info(const char *type, BMessage *info)
{
status_t err = read_mime_attr_message(type, kAttrInfoAttr, info);
if (err == B_ENTRY_NOT_FOUND) {
// return an empty message
info->MakeEmpty();
err = B_OK;
}
if (err == B_OK) {
info->what = 233;
// Don't know why, but that's what R5 does.
err = info->AddString("type", type);
}
return err;
}
/*! \brief Fetches the short description for the given MIME type.
The string pointed to by \c description must be long enough to
hold the short description; a length of \c B_MIME_TYPE_LENGTH is
recommended.
\param type The MIME type of interest
\param description Pointer to a pre-allocated string into which the short
description is copied. If the function fails, the contents
of the string are undefined.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No short description exists for the given type
- "error code": Failure
*/
status_t
get_short_description(const char *type, char *description)
{
/// DBG(OUT("Mime::Database::get_short_description()\n"));
ssize_t err = read_mime_attr(type, kShortDescriptionAttr, description,
B_MIME_TYPE_LENGTH, kShortDescriptionType);
return err >= 0 ? B_OK : err ;
}
// get_long_description
//! Fetches the long description for the given MIME type.
/*! The string pointed to by \c description must be long enough to
hold the long description; a length of \c B_MIME_TYPE_LENGTH is
recommended.
\param type The MIME type of interest
\param description Pointer to a pre-allocated string into which the long
description is copied. If the function fails, the contents
of the string are undefined.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No long description exists for the given type
- "error code": Failure
*/
status_t
get_long_description(const char *type, char *description)
{
// DBG(OUT("Mime::Database::get_long_description()\n"));
ssize_t err = read_mime_attr(type, kLongDescriptionAttr, description,
B_MIME_TYPE_LENGTH, kLongDescriptionType);
return err >= 0 ? B_OK : err ;
}
/*! \brief Fetches a BMessage describing the MIME type's associated filename
extensions
The list of extensions is returned in a pre-allocated BMessage pointed to
by the \c extensions parameter (note that the any prior contents of the
message will be destroyed). Please see BMimeType::GetFileExtensions() for
a description of the message format.
\param extensions Pointer to a pre-allocated BMessage into which the MIME
type's associated file extensions will be stored.
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
get_file_extensions(const char *type, BMessage *extensions)
{
status_t err = read_mime_attr_message(type, kFileExtensionsAttr, extensions);
if (err == B_ENTRY_NOT_FOUND) {
// return an empty message
extensions->MakeEmpty();
err = B_OK;
}
if (err == B_OK) {
extensions->what = 234; // Don't know why, but that's what R5 does.
err = extensions->AddString("type", type);
}
return err;
}
/*! \brief Fetches the icon of given size associated with the given MIME type
The bitmap pointed to by \c icon must be of the proper size (\c 32x32
for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and color depth
(\c B_CMAP8).
\param type The mime type
\param icon Pointer to a pre-allocated bitmap of proper dimensions and color depth
\param size The size icon you're interested in (\c B_LARGE_ICON or \c B_MINI_ICON)
*/
status_t
get_icon(const char *type, BBitmap *icon, icon_size which)
{
return get_icon_for_type(type, NULL, icon, which);
}
// get_icon
//! Fetches the vector icon associated with the given MIME type
/* \param type The mime type
\param data Pointer in which the allocated icon data is returned. You need to
free the buffer once you're done with it.
\param size Pointer in which the size of the icon data is returned.
*/
status_t
get_icon(const char *type, uint8** data, size_t* size)
{
return get_icon_for_type(type, NULL, data, size);
}
// get_icon_for_type
/*! \brief Fetches the large or mini icon used by an application of this type for files of the
given type.
The type of the \c BMimeType object is not required to actually be a subtype of
\c "application/"; that is the intended use however, and calling \c get_icon_for_type()
on a non-application type will likely return \c B_ENTRY_NOT_FOUND.
The icon is copied into the \c BBitmap pointed to by \c icon. The bitmap must
be the proper size: \c 32x32 for the large icon, \c 16x16 for the mini icon.
\param type The MIME type
\param fileType Pointer to a pre-allocated string containing the MIME type whose
custom icon you wish to fetch. If NULL, works just like get_icon().
\param icon Pointer to a pre-allocated \c BBitmap of proper size and colorspace into
which the icon is copied.
\param icon_size Value that specifies which icon to return. Currently \c B_LARGE_ICON
and \c B_MINI_ICON are supported.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type
- "error code": Failure
*/
status_t
get_icon_for_type(const char* type, const char* fileType, BBitmap* icon,
icon_size which)
{
if (!type || !icon)
return B_BAD_VALUE;
// open the node for the given type
BNode node;
ssize_t err = open_type(type, &node);
if (err < B_OK)
return (status_t)err;
// construct our attribute name
std::string vectorIconAttrName;
std::string smallIconAttrName;
std::string largeIconAttrName;
if (fileType) {
std::string lowerCaseFileType = BPrivate::Storage::to_lower(fileType);
vectorIconAttrName = kIconAttrPrefix + lowerCaseFileType;
smallIconAttrName = kMiniIconAttrPrefix + lowerCaseFileType;
largeIconAttrName = kLargeIconAttrPrefix + lowerCaseFileType;
} else {
vectorIconAttrName = kIconAttr;
smallIconAttrName = kMiniIconAttr;
largeIconAttrName = kLargeIconAttr;
}
return BIconUtils::GetIcon(&node, vectorIconAttrName.c_str(),
smallIconAttrName.c_str(), largeIconAttrName.c_str(),
which, icon);
// ssize_t err = type && icon ? B_OK : B_BAD_VALUE;
//
// // Figure out what kind of data we *should* find
// uint32 attrType = 0;
// ssize_t attrSize = 0;
// BRect bounds;
//
// if (!err) {
// switch (which) {
// case B_MINI_ICON:
// bounds.Set(0, 0, 15, 15);
// attrType = kMiniIconType;
// attrSize = 16 * 16;
// break;
// case B_LARGE_ICON:
// bounds.Set(0, 0, 31, 31);
// attrType = kLargeIconType;
// attrSize = 32 * 32;
// break;
// default:
// err = B_BAD_VALUE;
// break;
// }
// }
// // Construct our attribute name
// std::string attr;
// if (fileType) {
// attr = (which == B_MINI_ICON
// ? kMiniIconAttrPrefix
// : kLargeIconAttrPrefix)
// + BPrivate::Storage::to_lower(fileType);
// } else {
// attr = (which == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr;
// }
// // Check the icon and attribute to see if they match
// if (!err) {
// err = (icon->InitCheck() == B_OK
// && icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE;
// }
//
// BNode node;
// if (!err)
// err = open_type(type, &node);
//
// attr_info info;
// if (!err)
// err = node.GetAttrInfo(attr.c_str(), &info);
//
// if (!err)
// err = (attrType == info.type && attrSize == info.size) ? B_OK : B_BAD_VALUE;
// // read the attribute
// if (!err) {
// bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
// char *buffer = NULL;
// if (otherColorSpace) {
// // other color space than stored in attribute
// buffer = new(std::nothrow) char[attrSize];
// if (!buffer)
// err = B_NO_MEMORY;
// if (!err)
// err = node.ReadAttr(attr.c_str(), attrType, 0, buffer, attrSize);
// } else {
// // same color space, just read direct
// err = node.ReadAttr(attr.c_str(), attrType, 0, icon->Bits(), attrSize);
// }
// if (err >= 0)
// err = (err == attrSize) ? (status_t)B_OK : (status_t)B_FILE_ERROR;
// if (otherColorSpace) {
// if (!err) {
// err = icon->ImportBits(buffer, attrSize, B_ANY_BYTES_PER_ROW,
// 0, B_CMAP8);
// }
// delete[] buffer;
// }
// }
//
// return err;
}
// get_icon_for_type
/*! \brief Fetches the vector icon used by an application of this type for files of the
given type.
The type of the \c BMimeType object is not required to actually be a subtype of
\c "application/"; that is the intended use however, and calling \c get_icon_for_type()
on a non-application type will likely return \c B_ENTRY_NOT_FOUND.
The icon data is allocated and returned in \a data.
\param type The MIME type
\param fileType Pointer to a pre-allocated string containing the MIME type whose
custom icon you wish to fetch. If NULL, works just like get_icon().
\param data Pointer in which the icon data is returned on success.
\param size Pointer in which the size of the icon data is returned.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No vector icon exists for the given type
- "error code": Failure
*/
status_t
get_icon_for_type(const char* type, const char* fileType, uint8** data,
size_t* size)
{
if (!type || !data || !size)
return B_BAD_VALUE;
// open the node for the given type
BNode node;
ssize_t err = open_type(type, &node);
if (err < B_OK)
return (status_t)err;
// construct our attribute name
std::string iconAttrName;
if (fileType)
iconAttrName = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType);
else
iconAttrName = kIconAttr;
// get info about attribute for that name
attr_info info;
if (!err)
err = node.GetAttrInfo(iconAttrName.c_str(), &info);
// validate attribute type
if (!err)
err = (info.type == B_VECTOR_ICON_TYPE) ? B_OK : B_BAD_VALUE;
// allocate a buffer and read the attribute data into it
if (!err) {
uint8* buffer = new(std::nothrow) uint8[info.size];
if (!buffer)
err = B_NO_MEMORY;
if (!err) {
err = node.ReadAttr(iconAttrName.c_str(), B_VECTOR_ICON_TYPE,
0, buffer, info.size);
}
if (err >= 0)
err = (err == info.size) ? (ssize_t)B_OK : (ssize_t)B_FILE_ERROR;
if (!err) {
// success, set data pointer and size
*data = buffer;
*size = info.size;
} else {
delete[] buffer;
}
}
return err;
}
/*! \brief Fetches signature of the MIME type's preferred application for the
given action.
The string pointed to by \c signature must be long enough to
hold the short description; a length of \c B_MIME_TYPE_LENGTH is
recommended.
Currently, the only supported app verb is \c B_OPEN.
\param type The MIME type of interest
\param description Pointer to a pre-allocated string into which the
preferred application's signature is copied. If the function fails,
the contents of the string are undefined.
\param verb \c The action of interest
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No such preferred application exists
- "error code": Failure
*/
status_t
get_preferred_app(const char *type, char *signature, app_verb verb = B_OPEN)
{
// Since B_OPEN is the currently the only app_verb, it is essentially ignored
ssize_t err = read_mime_attr(type, kPreferredAppAttr, signature,
B_MIME_TYPE_LENGTH, kPreferredAppType);
return err >= 0 ? B_OK : err ;
}
/*! \brief Fetches the sniffer rule for the given MIME type.
\param type The MIME type of interest
\param result Pointer to a pre-allocated BString into which the type's
sniffer rule is copied.
\return
- \c B_OK: Success
- \c B_ENTRY_NOT_FOUND: No such preferred application exists
- "error code": Failure
*/
status_t
get_sniffer_rule(const char *type, BString *result)
{
return read_mime_attr_string(type, kSnifferRuleAttr, result);
}
status_t
get_supported_types(const char *type, BMessage *types)
{
status_t err = read_mime_attr_message(type, kSupportedTypesAttr, types);
if (err == B_ENTRY_NOT_FOUND) {
// return an empty message
types->MakeEmpty();
err = B_OK;
}
if (err == B_OK) {
types->what = 0;
err = types->AddString("type", type);
}
return err;
}
//! Checks if the given MIME type is present in the database
bool
is_installed(const char *type)
{
BNode node;
return open_type(type, &node) == B_OK;
}
/*! \brief Returns properly formatted raw bitmap data, ready to be shipped off
to the hacked up 4-parameter version of Database::SetIcon()
This function exists as something of a hack until an OBOS::BBitmap
implementation is available. It takes the given bitmap, converts it to the
B_CMAP8 color space if necessary and able, and returns said bitmap data in
a newly allocated array pointed to by the pointer that's pointed to by
\c data. The length of the array is stored in the integer pointed to by
\c dataSize. The array is allocated with \c new[], and it's your
responsibility to \c delete[] it when you're finished.
*/
status_t
get_icon_data(const BBitmap *icon, icon_size which, void **data,
int32 *dataSize)
{
if (icon == NULL || data == NULL || dataSize == 0
|| icon->InitCheck() != B_OK)
return B_BAD_VALUE;
BRect bounds;
BBitmap *icon8 = NULL;
void *srcData = NULL;
bool otherColorSpace = false;
// Figure out what kind of data we *should* have
switch (which) {
case B_MINI_ICON:
bounds.Set(0, 0, 15, 15);
break;
case B_LARGE_ICON:
bounds.Set(0, 0, 31, 31);
break;
default:
return B_BAD_VALUE;
}
// Check the icon
status_t err = icon->Bounds() == bounds ? B_OK : B_BAD_VALUE;
// Convert to B_CMAP8 if necessary
if (!err) {
otherColorSpace = (icon->ColorSpace() != B_CMAP8);
if (otherColorSpace) {
icon8 = new(std::nothrow) BBitmap(bounds, B_BITMAP_NO_SERVER_LINK,
B_CMAP8);
if (!icon8)
err = B_NO_MEMORY;
if (!err)
err = icon8->ImportBits(icon);
if (!err) {
srcData = icon8->Bits();
*dataSize = icon8->BitsLength();
}
} else {
srcData = icon->Bits();
*dataSize = icon->BitsLength();
}
}
// Alloc a new data buffer
if (!err) {
*data = new(std::nothrow) char[*dataSize];
if (!*data)
err = B_NO_MEMORY;
}
// Copy the data into it.
if (!err)
memcpy(*data, srcData, *dataSize);
if (otherColorSpace)
delete icon8;
return err;
}
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
+73 -410
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2006, Haiku. * Copyright 2002-2013, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -7,37 +7,16 @@
* Ingo Weinhold <ingo_weinhold@gmx.de> * Ingo Weinhold <ingo_weinhold@gmx.de>
*/ */
/*!
\file database_support.cpp
Private mime database functions and constants
*/
#include <AppMisc.h> #include <mime/database_support.h>
#include <DataIO.h>
#include <Directory.h> #include <pthread.h>
#include <File.h>
#include <Bitmap.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Entry.h>
#include <Message.h>
#include <Node.h>
#include <Path.h> #include <Path.h>
#include <storage_support.h>
#include <StringList.h>
#include <TypeConstants.h>
#include <fs_attr.h> // For struct attr_info #include <mime/DatabaseLocation.h>
#include <new> // For new(nothrow)
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <AutoDeleter.h>
#include "mime/database_support.h"
//#define DBG(x) x
#define DBG(x)
#define OUT printf
namespace BPrivate { namespace BPrivate {
@@ -109,12 +88,12 @@ static const directory_which kBaseDirectoryConstants[] = {
B_SYSTEM_DATA_DIRECTORY B_SYSTEM_DATA_DIRECTORY
}; };
static pthread_once_t sDatabaseDirectoryInitOnce = PTHREAD_ONCE_INIT; static pthread_once_t sDefaultDatabaseLocationInitOnce = PTHREAD_ONCE_INIT;
static BStringList sDatabaseDirectories; static DatabaseLocation sDefaultDatabaseLocation;
static void static void
init_database_directories() init_default_database_location()
{ {
for (size_t i = 0; for (size_t i = 0;
i < sizeof(kBaseDirectoryConstants) i < sizeof(kBaseDirectoryConstants)
@@ -129,410 +108,94 @@ init_database_directories()
continue; continue;
directoryPath += "/mime_db"; directoryPath += "/mime_db";
sDatabaseDirectories.Add(directoryPath); sDefaultDatabaseLocation.AddDirectory(directoryPath);
} }
} }
const BStringList& DatabaseLocation*
get_database_directories() default_database_location()
{ {
pthread_once(&sDatabaseDirectoryInitOnce, &init_database_directories); pthread_once(&sDefaultDatabaseLocationInitOnce,
return sDatabaseDirectories; &init_default_database_location);
return &sDefaultDatabaseLocation;
} }
BString /*! \brief Returns properly formatted raw bitmap data, ready to be shipped off
get_writable_database_directory() to the hacked up 4-parameter version of Database::SetIcon()
{
return get_database_directories().StringAt(0);
}
This function exists as something of a hack until an OBOS::BBitmap
static BString implementation is available. It takes the given bitmap, converts it to the
type_to_filename(const char* type, int32 index) B_CMAP8 color space if necessary and able, and returns said bitmap data in
{ a newly allocated array pointed to by the pointer that's pointed to by
BString path = get_database_directories().StringAt(index); \c data. The length of the array is stored in the integer pointed to by
return path << '/' << BPrivate::Storage::to_lower(type).c_str(); \c dataSize. The array is allocated with \c new[], and it's your
} responsibility to \c delete[] it when you're finished.
/*! Converts the given MIME type to an absolute path in the user writeable MIME
database directory.
*/
BString
type_to_writable_filename(const char* type)
{
return type_to_filename(type, 0);
}
static status_t
open_type(const char* type, BNode* _node, int32& _index)
{
const BStringList& directories = get_database_directories();
int32 count = directories.CountStrings();
for (int32 i = 0; i < count; i++) {
status_t error = _node->SetTo(type_to_filename(type, i));
attr_info attrInfo;
if (error == B_OK && _node->GetAttrInfo(kTypeAttr, &attrInfo) == B_OK) {
_index = i;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
static status_t
create_type_node(const char* type, BNode& _result)
{
const char* slash = strchr(type, '/');
BString superTypeName;
if (slash != NULL)
superTypeName.SetTo(type, slash - type);
else
superTypeName = type;
superTypeName.ToLower();
// open/create the directory for the supertype
BDirectory parent(get_writable_database_directory());
status_t error = parent.InitCheck();
if (error != B_OK)
return error;
BDirectory superTypeDirectory;
if (BEntry(&parent, superTypeName).Exists())
error = superTypeDirectory.SetTo(&parent, superTypeName);
else
error = parent.CreateDirectory(superTypeName, &superTypeDirectory);
if (error != B_OK)
return error;
// create the subtype
BFile subTypeFile;
if (slash != NULL) {
error = superTypeDirectory.CreateFile(BString(slash + 1).ToLower(),
&subTypeFile);
if (error != B_OK)
return error;
}
// assign the result
if (slash != NULL)
_result = subTypeFile;
else
_result = superTypeDirectory;
return _result.InitCheck();
}
static status_t
copy_type_node(BNode& source, const char* type, BNode& _target)
{
status_t error = create_type_node(type, _target);
if (error != B_OK)
return error;
// copy the attributes
MemoryDeleter bufferDeleter;
size_t bufferSize = 0;
source.RewindAttrs();
char attribute[B_ATTR_NAME_LENGTH];
while (source.GetNextAttrName(attribute) == B_OK) {
attr_info info;
error = source.GetAttrInfo(attribute, &info);
if (error != B_OK) {
syslog(LOG_ERR, "Failed to get info for attribute \"%s\" of MIME "
"type \"%s\": %s", attribute, type, strerror(error));
continue;
}
// resize our buffer, if necessary
if (info.size > bufferSize) {
bufferDeleter.SetTo(malloc(info.size));
if (bufferDeleter.Get() == NULL)
return B_NO_MEMORY;
bufferSize = info.size;
}
ssize_t bytesRead = source.ReadAttr(attribute, info.type, 0,
bufferDeleter.Get(), info.size);
if (bytesRead != info.size) {
syslog(LOG_ERR, "Failed to read attribute \"%s\" of MIME "
"type \"%s\": %s", attribute, type,
bytesRead < 0 ? strerror(bytesRead) : "short read");
continue;
}
ssize_t bytesWritten = _target.WriteAttr(attribute, info.type, 0,
bufferDeleter.Get(), info.size);
if (bytesWritten < 0) {
syslog(LOG_ERR, "Failed to write attribute \"%s\" of MIME "
"type \"%s\": %s", attribute, type,
bytesWritten < 0 ? strerror(bytesWritten) : "short write");
continue;
}
}
return B_OK;
}
// open_type
/*! \brief Opens a BNode on the given type, failing if the type has no
corresponding file in the database.
\param type The MIME type to open
\param result Pointer to a pre-allocated BNode into which
is opened on the given MIME type
*/ */
status_t status_t
open_type(const char *type, BNode *result) get_icon_data(const BBitmap *icon, icon_size which, void **data,
int32 *dataSize)
{ {
if (type == NULL || result == NULL) if (icon == NULL || data == NULL || dataSize == 0
|| icon->InitCheck() != B_OK)
return B_BAD_VALUE; return B_BAD_VALUE;
int32 index; BRect bounds;
return open_type(type, result, index); BBitmap *icon8 = NULL;
} void *srcData = NULL;
bool otherColorSpace = false;
// open_or_create_type // Figure out what kind of data we *should* have
/*! \brief Opens a BNode on the given type, creating a node of the switch (which) {
appropriate flavor if necessary. case B_MINI_ICON:
bounds.Set(0, 0, 15, 15);
All MIME types are converted to lowercase for use in the filesystem. break;
\param type The MIME type to open case B_LARGE_ICON:
\param result Pointer to a pre-allocated BNode into which bounds.Set(0, 0, 31, 31);
is opened on the given MIME type break;
*/ default:
status_t return B_BAD_VALUE;
open_or_create_type(const char *type, BNode *result, bool *didCreate)
{
if (didCreate)
*didCreate = false;
// See, if the type already exists.
int32 index;
status_t error = open_type(type, result, index);
if (error == B_OK) {
if (index == 0)
return B_OK;
// The caller wants a editable node, but the node found is not in the
// user's settings directory. Copy the node.
BNode nodeToClone(*result);
if (nodeToClone.InitCheck() != B_OK)
return nodeToClone.InitCheck();
error = copy_type_node(nodeToClone, type, *result);
if (error != B_OK) {
result->Unset();
return error;
}
if (didCreate != NULL)
*didCreate = true;
return error;
} }
// type doesn't exist yet -- create the respective node // Check the icon
error = create_type_node(type, *result); status_t err = icon->Bounds() == bounds ? B_OK : B_BAD_VALUE;
if (error != B_OK)
return error;
// write the type attribute // Convert to B_CMAP8 if necessary
error = result->WriteAttr(kTypeAttr, B_STRING_TYPE, 0, type,
strlen(type) + 1);
if (error != B_OK) {
result->Unset();
return error;
}
if (didCreate != NULL)
*didCreate = true;
return B_OK;
}
// read_mime_attr
/*! \brief Reads up to \c len bytes of the given data from the given attribute
for the given MIME type.
If no entry for the given type exists in the database, the function fails,
and the contents of \c data are undefined.
\param type The MIME type
\param attr The attribute name
\param data Pointer to a memory buffer into which the data should be copied
\param len The maximum number of bytes to read
\param datatype The expected data type
\return If successful, the number of bytes read is returned, otherwise, an
error code is returned.
*/
ssize_t
read_mime_attr(const char *type, const char *attr, void *data,
size_t len, type_code datatype)
{
BNode node;
ssize_t err = (type && attr && data ? B_OK : B_BAD_VALUE);
if (!err)
err = open_type(type, &node);
if (!err)
err = node.ReadAttr(attr, datatype, 0, data, len);
return err;
}
// read_mime_attr_message
/*! \brief Reads a flattened BMessage from the given attribute of the given
MIME type.
If no entry for the given type exists in the database, or if the data
stored in the attribute is not a flattened BMessage, the function fails
and the contents of \c msg are undefined.
\param type The MIME type
\param attr The attribute name
\param data Pointer to a pre-allocated BMessage into which the attribute
data is unflattened.
*/
status_t
read_mime_attr_message(const char *type, const char *attr, BMessage *msg)
{
BNode node;
attr_info info;
char *buffer = NULL;
ssize_t err = (type && attr && msg ? B_OK : B_BAD_VALUE);
if (!err)
err = open_type(type, &node);
if (!err)
err = node.GetAttrInfo(attr, &info);
if (!err)
err = info.type == B_MESSAGE_TYPE ? B_OK : B_BAD_VALUE;
if (!err) { if (!err) {
buffer = new(std::nothrow) char[info.size]; otherColorSpace = (icon->ColorSpace() != B_CMAP8);
if (!buffer) if (otherColorSpace) {
icon8 = new(std::nothrow) BBitmap(bounds, B_BITMAP_NO_SERVER_LINK,
B_CMAP8);
if (!icon8)
err = B_NO_MEMORY;
if (!err)
err = icon8->ImportBits(icon);
if (!err) {
srcData = icon8->Bits();
*dataSize = icon8->BitsLength();
}
} else {
srcData = icon->Bits();
*dataSize = icon->BitsLength();
}
}
// Alloc a new data buffer
if (!err) {
*data = new(std::nothrow) char[*dataSize];
if (!*data)
err = B_NO_MEMORY; err = B_NO_MEMORY;
} }
// Copy the data into it.
if (!err) if (!err)
err = node.ReadAttr(attr, B_MESSAGE_TYPE, 0, buffer, info.size); memcpy(*data, srcData, *dataSize);
if (err >= 0) if (otherColorSpace)
err = err == info.size ? (status_t)B_OK : (status_t)B_FILE_ERROR; delete icon8;
if (!err)
err = msg->Unflatten(buffer);
delete [] buffer;
return err; return err;
} }
// read_mime_attr_string
/*! \brief Reads a BString from the given attribute of the given
MIME type.
If no entry for the given type exists in the database, the function fails
and the contents of \c str are undefined.
\param type The MIME type
\param attr The attribute name
\param str Pointer to a pre-allocated BString into which the attribute
data stored.
*/
status_t
read_mime_attr_string(const char *type, const char *attr, BString *str)
{
BNode node;
status_t err = (type && attr && str ? B_OK : B_BAD_VALUE);
if (!err)
err = open_type(type, &node);
if (!err)
err = node.ReadAttrString(attr, str);
return err;
}
// write_mime_attr
/*! \brief Writes \c len bytes of the given data to the given attribute
for the given MIME type.
If no entry for the given type exists in the database, it is created.
\param type The MIME type
\param attr The attribute name
\param data Pointer to the data to write
\param len The number of bytes to write
\param datatype The data type of the given data
*/
status_t
write_mime_attr(const char *type, const char *attr, const void *data,
size_t len, type_code datatype, bool *didCreate)
{
BNode node;
status_t err = (type && attr && data ? B_OK : B_BAD_VALUE);
if (!err)
err = open_or_create_type(type, &node, didCreate);
if (!err) {
ssize_t bytes = node.WriteAttr(attr, datatype, 0, data, len);
if (bytes < B_OK)
err = bytes;
else
err = (bytes != (ssize_t)len ? (status_t)B_FILE_ERROR : (status_t)B_OK);
}
return err;
}
// write_mime_attr_message
/*! \brief Flattens the given \c BMessage and writes it to the given attribute
of the given MIME type.
If no entry for the given type exists in the database, it is created.
\param type The MIME type
\param attr The attribute name
\param msg The BMessage to flatten and write
*/
status_t
write_mime_attr_message(const char *type, const char *attr, const BMessage *msg, bool *didCreate)
{
BNode node;
BMallocIO data;
ssize_t bytes;
ssize_t err = (type && attr && msg ? B_OK : B_BAD_VALUE);
if (!err)
err = data.SetSize(msg->FlattenedSize());
if (!err)
err = msg->Flatten(&data, &bytes);
if (!err)
err = bytes == msg->FlattenedSize() ? B_OK : B_ERROR;
if (!err)
err = open_or_create_type(type, &node, didCreate);
if (!err)
err = node.WriteAttr(attr, B_MESSAGE_TYPE, 0, data.Buffer(), data.BufferLength());
if (err >= 0)
err = err == (ssize_t)data.BufferLength() ? (ssize_t)B_OK : (ssize_t)B_FILE_ERROR;
return err;
}
// delete_attribute
//! Deletes the given attribute for the given type
/*!
\param type The mime type
\param attr The attribute name
\return
- B_OK: success
- B_ENTRY_NOT_FOUND: no such type or attribute
- "error code": failure
*/
status_t
delete_attribute(const char *type, const char *attr)
{
status_t err = type ? B_OK : B_BAD_VALUE;
BNode node;
if (!err)
err = open_type(type, &node);
if (!err)
err = node.RemoveAttr(attr);
return err;
}
} // namespace Mime } // namespace Mime
} // namespace Storage } // namespace Storage
+4 -1
View File
@@ -21,6 +21,8 @@
#include <String.h> #include <String.h>
#include <TypeConstants.h> #include <TypeConstants.h>
#include <mime/database_support.h>
#include "CreateAppMetaMimeThread.h" #include "CreateAppMetaMimeThread.h"
#include "MessageDeliverer.h" #include "MessageDeliverer.h"
#include "MimeSnifferAddonManager.h" #include "MimeSnifferAddonManager.h"
@@ -56,7 +58,8 @@ init_mime_sniffer_add_on_manager()
MIMEManager::MIMEManager() MIMEManager::MIMEManager()
: :
BLooper("main_mime"), BLooper("main_mime"),
fDatabase(init_mime_sniffer_add_on_manager(), this), fDatabase(BPrivate::Storage::Mime::default_database_location(),
init_mime_sniffer_add_on_manager(), this),
fThreadManager() fThreadManager()
{ {
AddHandler(&fThreadManager); AddHandler(&fThreadManager);
@@ -23,6 +23,7 @@
#include <mime/Database.h> #include <mime/Database.h>
#include <mime/database_support.h> #include <mime/database_support.h>
#include <mime/DatabaseLocation.h>
namespace BPrivate { namespace BPrivate {
@@ -83,7 +84,7 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir)
mime.Install(); mime.Install();
BNode typeNode; BNode typeNode;
status = open_type(signature, &typeNode); status = fDatabase->Location()->OpenType(signature, typeNode);
if (status < B_OK) if (status < B_OK)
return status; return status;