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:
@@ -21,12 +21,15 @@ namespace BPrivate {
|
||||
namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
|
||||
class DatabaseLocation;
|
||||
class MimeSniffer;
|
||||
|
||||
|
||||
class AssociatedTypes {
|
||||
public:
|
||||
AssociatedTypes(MimeSniffer* mimeSniffer);
|
||||
AssociatedTypes(DatabaseLocation* databaseLocation,
|
||||
MimeSniffer* mimeSniffer);
|
||||
~AssociatedTypes();
|
||||
|
||||
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
|
||||
|
||||
private:
|
||||
MimeSniffer* fMimeSniffer;
|
||||
bool fHaveDoneFullBuild;
|
||||
DatabaseLocation* fDatabaseLocation;
|
||||
MimeSniffer* fMimeSniffer;
|
||||
bool fHaveDoneFullBuild;
|
||||
};
|
||||
|
||||
} // namespace Mime
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <StorageDefs.h>
|
||||
|
||||
#include <mime/AssociatedTypes.h>
|
||||
#include <mime/database_access.h>
|
||||
#include <mime/InstalledTypes.h>
|
||||
#include <mime/SnifferRules.h>
|
||||
#include <mime/SupportingApps.h>
|
||||
@@ -36,8 +35,11 @@ namespace BPrivate {
|
||||
namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
|
||||
class DatabaseLocation;
|
||||
class MimeSniffer;
|
||||
|
||||
|
||||
// types of mime update functions that may be run asynchronously
|
||||
typedef enum {
|
||||
B_REG_UPDATE_MIME_INFO,
|
||||
@@ -49,16 +51,18 @@ class Database {
|
||||
class NotificationListener;
|
||||
|
||||
public:
|
||||
Database(MimeSniffer* mimeSniffer,
|
||||
Database(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer,
|
||||
NotificationListener* notificationListener);
|
||||
~Database();
|
||||
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
DatabaseLocation* Location() const { return fLocation; }
|
||||
|
||||
// Type management
|
||||
status_t Install(const char *type);
|
||||
status_t Delete(const char *type);
|
||||
|
||||
|
||||
// Set()
|
||||
status_t SetAppHint(const char *type, const entry_ref *ref);
|
||||
status_t SetAttrInfo(const char *type, const BMessage *info);
|
||||
@@ -142,6 +146,7 @@ class Database {
|
||||
|
||||
private:
|
||||
status_t fStatus;
|
||||
DatabaseLocation* fLocation;
|
||||
NotificationListener* fNotificationListener;
|
||||
std::set<BMessenger> fMonitorMessengers;
|
||||
AssociatedTypes fAssociatedTypes;
|
||||
|
||||
@@ -17,12 +17,16 @@ namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
|
||||
class DatabaseLocation;
|
||||
|
||||
|
||||
class DatabaseDirectory : public BMergedDirectory {
|
||||
public:
|
||||
DatabaseDirectory();
|
||||
virtual ~DatabaseDirectory();
|
||||
|
||||
status_t Init(const char* superType = NULL);
|
||||
status_t Init(DatabaseLocation* databaseLocation,
|
||||
const char* superType = NULL);
|
||||
|
||||
protected:
|
||||
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 Mime {
|
||||
|
||||
|
||||
class DatabaseLocation;
|
||||
|
||||
|
||||
class InstalledTypes {
|
||||
public:
|
||||
InstalledTypes();
|
||||
InstalledTypes(DatabaseLocation* databaseLocation);
|
||||
~InstalledTypes();
|
||||
|
||||
status_t GetInstalledTypes(BMessage *types);
|
||||
@@ -55,6 +59,8 @@ class InstalledTypes {
|
||||
|
||||
status_t _BuildInstalledTypesList();
|
||||
|
||||
private:
|
||||
DatabaseLocation* fDatabaseLocation;
|
||||
std::map<std::string, Supertype> fSupertypes;
|
||||
BMessage *fCachedMessage;
|
||||
BMessage *fCachedSupertypesMessage;
|
||||
|
||||
@@ -25,12 +25,14 @@ namespace Sniffer {
|
||||
|
||||
namespace Mime {
|
||||
|
||||
|
||||
class DatabaseLocation;
|
||||
class MimeSniffer;
|
||||
|
||||
|
||||
class SnifferRules {
|
||||
public:
|
||||
SnifferRules(MimeSniffer* mimeSniffer);
|
||||
SnifferRules(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer);
|
||||
~SnifferRules();
|
||||
|
||||
status_t GuessMimeType(const entry_ref *ref, BString *type);
|
||||
@@ -59,9 +61,10 @@ private:
|
||||
std::list<sniffer_rule> fRuleList;
|
||||
|
||||
private:
|
||||
MimeSniffer* fMimeSniffer;
|
||||
ssize_t fMaxBytesNeeded;
|
||||
bool fHaveDoneFullBuild;
|
||||
DatabaseLocation* fDatabaseLocation;
|
||||
MimeSniffer* fMimeSniffer;
|
||||
ssize_t fMaxBytesNeeded;
|
||||
bool fHaveDoneFullBuild;
|
||||
};
|
||||
|
||||
} // namespace Mime
|
||||
|
||||
@@ -22,11 +22,15 @@ namespace BPrivate {
|
||||
namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
|
||||
class DatabaseLocation;
|
||||
|
||||
|
||||
class SupportingApps {
|
||||
public:
|
||||
SupportingApps();
|
||||
SupportingApps(DatabaseLocation* databaseLocation);
|
||||
~SupportingApps();
|
||||
|
||||
|
||||
status_t GetSupportingApps(const char *type, BMessage *apps);
|
||||
|
||||
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> > fStrandedTypes; // app sig => set of no longer supported types for whom the
|
||||
// given app is still listed as a supporting app
|
||||
|
||||
private:
|
||||
DatabaseLocation* fDatabaseLocation;
|
||||
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
|
||||
@@ -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.
|
||||
*/
|
||||
#ifndef _MIME_DATABASE_SUPPORT_H
|
||||
#define _MIME_DATABASE_SUPPORT_H
|
||||
|
||||
|
||||
#include <StorageDefs.h>
|
||||
#include <String.h>
|
||||
#include <Mime.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
class BNode;
|
||||
class BMessage;
|
||||
class BStringList;
|
||||
class BBitmap;
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
namespace Storage {
|
||||
namespace Mime {
|
||||
|
||||
// Database directory
|
||||
const BStringList& get_database_directories();
|
||||
BString get_writable_database_directory();
|
||||
|
||||
class DatabaseLocation;
|
||||
|
||||
|
||||
// Attribute Prefixes
|
||||
extern const char *kMiniIconAttrPrefix;
|
||||
@@ -75,24 +73,18 @@ extern const char *kMetaMimeType;
|
||||
// Error codes (to be used only by BPrivate::Storage::Mime members)
|
||||
extern const status_t kMimeGuessFailureError;
|
||||
|
||||
BString type_to_writable_filename(const char *type);
|
||||
|
||||
status_t open_type(const char *type, BNode *result);
|
||||
status_t open_or_create_type(const char *type, BNode *result, bool *didCreate);
|
||||
DatabaseLocation* default_database_location();
|
||||
|
||||
ssize_t read_mime_attr(const char *type, const char *attr, void *data,
|
||||
size_t len, type_code datatype);
|
||||
status_t read_mime_attr_message(const char *type, const char *attr, BMessage *msg);
|
||||
status_t read_mime_attr_string(const char *type, const char *attr, BString *str);
|
||||
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);
|
||||
// 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);
|
||||
|
||||
status_t delete_attribute(const char *type, const char *attr);
|
||||
|
||||
} // namespace Mime
|
||||
} // namespace Storage
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
#endif // _MIME_DATABASE_SUPPORT_H
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <IconUtils.h>
|
||||
#include <Mime.h>
|
||||
#include <MimeType.h>
|
||||
#include <mime/database_access.h>
|
||||
#include <Node.h>
|
||||
#include <Path.h>
|
||||
#include <RegistrarDefs.h>
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
#include "MimeType.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <mime/database_access.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
#include <sniffer/Rule.h>
|
||||
#include <sniffer/Parser.h>
|
||||
|
||||
@@ -176,7 +177,8 @@ BMimeType::IsSupertypeOnly() const
|
||||
bool
|
||||
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
|
||||
BMimeType::GetIcon(BBitmap *icon, icon_size size) const
|
||||
{
|
||||
if (icon == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_icon(Type(), icon, size);
|
||||
err = default_database_location()->GetIcon(Type(), *icon, size);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -319,9 +324,12 @@ BMimeType::GetIcon(BBitmap *icon, icon_size size) const
|
||||
status_t
|
||||
BMimeType::GetIcon(uint8** data, size_t* size) const
|
||||
{
|
||||
if (data == NULL || size == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_icon(Type(), data, size);
|
||||
err = default_database_location()->GetIcon(Type(), *data, *size);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -333,8 +341,10 @@ status_t
|
||||
BMimeType::GetPreferredApp(char *signature, app_verb verb) const
|
||||
{
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_preferred_app(Type(), signature, verb);
|
||||
if (!err) {
|
||||
err = default_database_location()->GetPreferredApp(Type(), signature,
|
||||
verb);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -345,9 +355,12 @@ BMimeType::GetPreferredApp(char *signature, app_verb verb) const
|
||||
status_t
|
||||
BMimeType::GetAttrInfo(BMessage *info) const
|
||||
{
|
||||
if (info == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_attr_info(Type(), info);
|
||||
err = default_database_location()->GetAttributesInfo(Type(), *info);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -358,9 +371,14 @@ BMimeType::GetAttrInfo(BMessage *info) const
|
||||
status_t
|
||||
BMimeType::GetFileExtensions(BMessage *extensions) const
|
||||
{
|
||||
if (extensions == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_file_extensions(Type(), extensions);
|
||||
if (!err) {
|
||||
err = default_database_location()->GetFileExtensions(Type(),
|
||||
*extensions);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -371,8 +389,10 @@ status_t
|
||||
BMimeType::GetShortDescription(char *description) const
|
||||
{
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_short_description(Type(), description);
|
||||
if (!err) {
|
||||
err = default_database_location()->GetShortDescription(Type(),
|
||||
description);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -383,8 +403,10 @@ status_t
|
||||
BMimeType::GetLongDescription(char *description) const
|
||||
{
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_long_description(Type(), description);
|
||||
if (!err) {
|
||||
err = default_database_location()->GetLongDescription(Type(),
|
||||
description);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -703,9 +725,12 @@ BMimeType::IsValid(const char *string)
|
||||
status_t
|
||||
BMimeType::GetAppHint(entry_ref *ref) const
|
||||
{
|
||||
if (ref == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_app_hint(Type(), ref);
|
||||
err = default_database_location()->GetAppHint(Type(), *ref);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -745,13 +770,18 @@ BMimeType::SetAppHint(const entry_ref *ref)
|
||||
status_t
|
||||
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,
|
||||
// we need to make sure the give type is valid.
|
||||
status_t err;
|
||||
if (type) {
|
||||
err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE;
|
||||
if (!err)
|
||||
err = get_icon_for_type(Type(), type, icon, which);
|
||||
if (!err) {
|
||||
err = default_database_location()->GetIconForType(Type(), type,
|
||||
*icon, which);
|
||||
}
|
||||
} else
|
||||
err = GetIcon(icon, which);
|
||||
|
||||
@@ -764,6 +794,9 @@ BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) cons
|
||||
status_t
|
||||
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,
|
||||
// we need to make sure the give type is valid.
|
||||
if (type == NULL)
|
||||
@@ -772,7 +805,8 @@ BMimeType::GetIconForType(const char *type, uint8** _data, size_t* _size) const
|
||||
if (!BMimeType::IsValid(type))
|
||||
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
|
||||
BMimeType::GetSnifferRule(BString *result) const
|
||||
{
|
||||
if (result == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_sniffer_rule(Type(), result);
|
||||
err = default_database_location()->GetSnifferRule(Type(), *result);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1096,9 +1133,12 @@ BMimeType::BMimeType(const BMimeType &)
|
||||
status_t
|
||||
BMimeType::GetSupportedTypes(BMessage *types)
|
||||
{
|
||||
if (types == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t err = InitCheck();
|
||||
if (!err)
|
||||
err = get_supported_types(Type(), types);
|
||||
err = default_database_location()->GetSupportedTypes(Type(), *types);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <Message.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseDirectory.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
#include <mime/MimeSniffer.h>
|
||||
#include <MimeType.h>
|
||||
#include <Path.h>
|
||||
@@ -40,8 +41,10 @@ namespace Mime {
|
||||
|
||||
// Constructor
|
||||
//! Constructs a new AssociatedTypes object
|
||||
AssociatedTypes::AssociatedTypes(MimeSniffer* mimeSniffer)
|
||||
AssociatedTypes::AssociatedTypes(DatabaseLocation* databaseLocation,
|
||||
MimeSniffer* mimeSniffer)
|
||||
:
|
||||
fDatabaseLocation(databaseLocation),
|
||||
fMimeSniffer(mimeSniffer),
|
||||
fHaveDoneFullBuild(false)
|
||||
{
|
||||
@@ -333,7 +336,7 @@ AssociatedTypes::BuildAssociatedTypesTable()
|
||||
fAssociatedTypes.clear();
|
||||
|
||||
DatabaseDirectory root;
|
||||
status_t err = root.Init();
|
||||
status_t err = root.Init(fDatabaseLocation);
|
||||
if (!err) {
|
||||
root.Rewind();
|
||||
while (true) {
|
||||
@@ -357,7 +360,7 @@ AssociatedTypes::BuildAssociatedTypesTable()
|
||||
// First, iterate through this supertype directory and process
|
||||
// all of its subtypes
|
||||
DatabaseDirectory dir;
|
||||
if (dir.Init(supertype) == B_OK) {
|
||||
if (dir.Init(fDatabaseLocation, supertype) == B_OK) {
|
||||
dir.Rewind();
|
||||
while (true) {
|
||||
BEntry subEntry;
|
||||
@@ -424,7 +427,8 @@ AssociatedTypes::ProcessType(const char *type)
|
||||
if (!err) {
|
||||
// Read in the list of file extension types
|
||||
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
|
||||
// file extensions for the mime type and adding the mime type
|
||||
// to the list of associated types for each file extension
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include <AutoLocker.h>
|
||||
#include <mime/database_access.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
#include <storage_support.h>
|
||||
|
||||
|
||||
@@ -64,18 +64,21 @@ Database::NotificationListener::~NotificationListener()
|
||||
// constructor
|
||||
/*! \brief Creates and initializes a Mime::Database object.
|
||||
*/
|
||||
Database::Database(MimeSniffer* mimeSniffer,
|
||||
Database::Database(DatabaseLocation* databaseLocation, MimeSniffer* mimeSniffer,
|
||||
NotificationListener* notificationListener)
|
||||
:
|
||||
fStatus(B_NO_INIT),
|
||||
fLocation(databaseLocation),
|
||||
fNotificationListener(notificationListener),
|
||||
fAssociatedTypes(mimeSniffer),
|
||||
fSnifferRules(mimeSniffer),
|
||||
fAssociatedTypes(databaseLocation, mimeSniffer),
|
||||
fInstalledTypes(databaseLocation),
|
||||
fSnifferRules(databaseLocation, mimeSniffer),
|
||||
fSupportingApps(databaseLocation),
|
||||
fDeferredInstallNotificationsLocker("deferred install notifications"),
|
||||
fDeferredInstallNotifications()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -116,14 +119,14 @@ Database::Install(const char *type)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
BEntry entry;
|
||||
status_t err = entry.SetTo(type_to_writable_filename(type));
|
||||
status_t err = entry.SetTo(fLocation->WritablePathForType(type));
|
||||
if (!err) {
|
||||
if (entry.Exists())
|
||||
err = B_FILE_EXISTS;
|
||||
else {
|
||||
bool didCreate = false;
|
||||
BNode node;
|
||||
err = open_or_create_type(type, &node, &didCreate);
|
||||
err = fLocation->OpenOrCreateType(type, node, &didCreate);
|
||||
if (!err && didCreate) {
|
||||
fInstalledTypes.AddType(type);
|
||||
_SendInstallNotification(type);
|
||||
@@ -148,7 +151,7 @@ Database::Delete(const char *type)
|
||||
|
||||
// Open the type
|
||||
BEntry entry;
|
||||
status_t status = entry.SetTo(type_to_writable_filename(type));
|
||||
status_t status = entry.SetTo(fLocation->WritablePathForType(type));
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
@@ -198,7 +201,7 @@ Database::_SetStringValue(const char *type, int32 what, const char* attribute,
|
||||
return B_BAD_VALUE;
|
||||
|
||||
char oldValue[maxLength];
|
||||
status_t status = read_mime_attr(type, attribute, oldValue,
|
||||
status_t status = fLocation->ReadAttribute(type, attribute, oldValue,
|
||||
maxLength, attributeType);
|
||||
if (status >= B_OK && !strcmp(value, oldValue)) {
|
||||
// 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;
|
||||
status = write_mime_attr(type, attribute, value, length + 1,
|
||||
status = fLocation->WriteAttribute(type, attribute, value, length + 1,
|
||||
attributeType, &didCreate);
|
||||
|
||||
if (status == B_OK) {
|
||||
@@ -267,7 +270,8 @@ Database::SetAttrInfo(const char *type, const BMessage *info)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
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 (didCreate)
|
||||
_SendInstallNotification(type);
|
||||
@@ -334,8 +338,8 @@ Database::SetFileExtensions(const char *type, const BMessage *extensions)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
bool didCreate = false;
|
||||
status_t status = write_mime_attr_message(type, kFileExtensionsAttr,
|
||||
extensions, &didCreate);
|
||||
status_t status = fLocation->WriteMessageAttribute(type,
|
||||
kFileExtensionsAttr, *extensions, &didCreate);
|
||||
|
||||
if (status == B_OK) {
|
||||
if (didCreate) {
|
||||
@@ -439,7 +443,7 @@ Database::SetIconForType(const char *type, const char *fileType,
|
||||
BNode node;
|
||||
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)
|
||||
return err;
|
||||
|
||||
@@ -500,7 +504,7 @@ Database::SetIconForType(const char *type, const char *fileType,
|
||||
BNode node;
|
||||
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)
|
||||
return err;
|
||||
|
||||
@@ -556,8 +560,8 @@ Database::SetSnifferRule(const char *type, const char *rule)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
bool didCreate = false;
|
||||
status_t status = write_mime_attr(type, kSnifferRuleAttr, rule, strlen(rule) + 1,
|
||||
kSnifferRuleType, &didCreate);
|
||||
status_t status = fLocation->WriteAttribute(type, kSnifferRuleAttr, rule,
|
||||
strlen(rule) + 1, kSnifferRuleType, &didCreate);
|
||||
|
||||
if (status == B_OK)
|
||||
status = fSnifferRules.SetSnifferRule(type, rule);
|
||||
@@ -597,7 +601,7 @@ Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSy
|
||||
// Install the types
|
||||
const char *supportedType;
|
||||
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)
|
||||
break;
|
||||
|
||||
@@ -610,8 +614,8 @@ Database::SetSupportedTypes(const char *type, const BMessage *types, bool fullSy
|
||||
|
||||
// Write the attr
|
||||
bool didCreate = false;
|
||||
status_t status = write_mime_attr_message(type, kSupportedTypesAttr, types,
|
||||
&didCreate);
|
||||
status_t status = fLocation->WriteMessageAttribute(type,
|
||||
kSupportedTypesAttr, *types, &didCreate);
|
||||
|
||||
// Notify the monitor if we created the type when we opened it
|
||||
if (status != B_OK)
|
||||
@@ -976,7 +980,7 @@ Database::StopWatching(BMessenger target)
|
||||
status_t
|
||||
Database::DeleteAppHint(const char *type)
|
||||
{
|
||||
status_t status = delete_attribute(type, kAppHintAttr);
|
||||
status_t status = fLocation->DeleteAttribute(type, kAppHintAttr);
|
||||
if (status == B_OK)
|
||||
_SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_DELETED);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -998,7 +1002,7 @@ Database::DeleteAppHint(const char *type)
|
||||
status_t
|
||||
Database::DeleteAttrInfo(const char *type)
|
||||
{
|
||||
status_t status = delete_attribute(type, kAttrInfoAttr);
|
||||
status_t status = fLocation->DeleteAttribute(type, kAttrInfoAttr);
|
||||
if (status == B_OK)
|
||||
_SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_DELETED);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -1020,7 +1024,7 @@ Database::DeleteAttrInfo(const char *type)
|
||||
status_t
|
||||
Database::DeleteShortDescription(const char *type)
|
||||
{
|
||||
status_t status = delete_attribute(type, kShortDescriptionAttr);
|
||||
status_t status = fLocation->DeleteAttribute(type, kShortDescriptionAttr);
|
||||
if (status == B_OK)
|
||||
_SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -1042,7 +1046,7 @@ Database::DeleteShortDescription(const char *type)
|
||||
status_t
|
||||
Database::DeleteLongDescription(const char *type)
|
||||
{
|
||||
status_t status = delete_attribute(type, kLongDescriptionAttr);
|
||||
status_t status = fLocation->DeleteAttribute(type, kLongDescriptionAttr);
|
||||
if (status == B_OK)
|
||||
_SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -1064,7 +1068,7 @@ Database::DeleteLongDescription(const char *type)
|
||||
status_t
|
||||
Database::DeleteFileExtensions(const char *type)
|
||||
{
|
||||
status_t status = delete_attribute(type, kFileExtensionsAttr);
|
||||
status_t status = fLocation->DeleteAttribute(type, kFileExtensionsAttr);
|
||||
if (status == B_OK)
|
||||
_SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_DELETED);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -1088,7 +1092,7 @@ status_t
|
||||
Database::DeleteIcon(const char *type, icon_size which)
|
||||
{
|
||||
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)
|
||||
_SendMonitorUpdate(B_ICON_CHANGED, type, which, B_META_MIME_DELETED);
|
||||
else if (status == B_ENTRY_NOT_FOUND)
|
||||
@@ -1111,7 +1115,7 @@ status_t
|
||||
Database::DeleteIcon(const char *type)
|
||||
{
|
||||
// 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) {
|
||||
_SendMonitorUpdate(B_ICON_CHANGED, type, B_LARGE_ICON,
|
||||
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
|
||||
? 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) {
|
||||
_SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
|
||||
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?
|
||||
// (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) {
|
||||
_SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
|
||||
true, B_META_MIME_DELETED);
|
||||
@@ -1209,7 +1213,7 @@ Database::DeletePreferredApp(const char *type, app_verb verb)
|
||||
|
||||
switch (verb) {
|
||||
case B_OPEN:
|
||||
status = delete_attribute(type, kPreferredAppAttr);
|
||||
status = fLocation->DeleteAttribute(type, kPreferredAppAttr);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1242,7 +1246,7 @@ Database::DeletePreferredApp(const char *type, app_verb verb)
|
||||
status_t
|
||||
Database::DeleteSnifferRule(const char *type)
|
||||
{
|
||||
status_t status = delete_attribute(type, kSnifferRuleAttr);
|
||||
status_t status = fLocation->DeleteAttribute(type, kSnifferRuleAttr);
|
||||
if (status == B_OK) {
|
||||
status = fSnifferRules.DeleteSnifferRule(type);
|
||||
if (status == B_OK) {
|
||||
@@ -1274,7 +1278,7 @@ Database::DeleteSnifferRule(const char *type)
|
||||
status_t
|
||||
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,
|
||||
// do so even if the supported types attribute didn't exist, as
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <StringList.h>
|
||||
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
@@ -34,14 +35,14 @@ DatabaseDirectory::~DatabaseDirectory()
|
||||
|
||||
|
||||
status_t
|
||||
DatabaseDirectory::Init(const char* superType)
|
||||
DatabaseDirectory::Init(DatabaseLocation* databaseLocation,
|
||||
const char* superType)
|
||||
{
|
||||
status_t error = BMergedDirectory::Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
const BStringList& directories
|
||||
= BPrivate::Storage::Mime::get_database_directories();
|
||||
const BStringList& directories = databaseLocation->Directories();
|
||||
int32 count = directories.CountStrings();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BString directory = directories.StringAt(i);
|
||||
|
||||
@@ -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
|
||||
@@ -40,8 +40,9 @@ namespace Mime {
|
||||
*/
|
||||
|
||||
//! Constructs a new InstalledTypes object
|
||||
InstalledTypes::InstalledTypes()
|
||||
InstalledTypes::InstalledTypes(DatabaseLocation* databaseLocation)
|
||||
:
|
||||
fDatabaseLocation(databaseLocation),
|
||||
fCachedMessage(NULL),
|
||||
fCachedSupertypesMessage(NULL),
|
||||
fHaveDoneFullBuild(false)
|
||||
@@ -385,7 +386,7 @@ InstalledTypes::_BuildInstalledTypesList()
|
||||
|
||||
DatabaseDirectory root;
|
||||
if (!err)
|
||||
err = root.Init();
|
||||
err = root.Init(fDatabaseLocation);
|
||||
if (!err) {
|
||||
root.Rewind();
|
||||
while (true) {
|
||||
@@ -417,7 +418,7 @@ InstalledTypes::_BuildInstalledTypesList()
|
||||
// Now iterate through this supertype directory and add
|
||||
// all of its subtypes
|
||||
DatabaseDirectory dir;
|
||||
if (dir.Init(supertype) == B_OK) {
|
||||
if (dir.Init(fDatabaseLocation, supertype) == B_OK) {
|
||||
dir.Rewind();
|
||||
while (true) {
|
||||
BEntry subEntry;
|
||||
|
||||
@@ -13,7 +13,7 @@ StaticLibrary libstorage_kit_mime.a :
|
||||
AssociatedTypes.cpp
|
||||
Database.cpp
|
||||
DatabaseDirectory.cpp
|
||||
database_access.cpp
|
||||
DatabaseLocation.cpp
|
||||
database_support.cpp
|
||||
InstalledTypes.cpp
|
||||
MimeSniffer.cpp
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <MimeType.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseDirectory.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
#include <mime/MimeSniffer.h>
|
||||
#include <sniffer/Parser.h>
|
||||
#include <sniffer/Rule.h>
|
||||
@@ -112,8 +113,10 @@ bool operator<(SnifferRules::sniffer_rule &left, SnifferRules::sniffer_rule &rig
|
||||
|
||||
// Constructor
|
||||
//! Constructs a new SnifferRules object
|
||||
SnifferRules::SnifferRules(MimeSniffer* mimeSniffer)
|
||||
SnifferRules::SnifferRules(DatabaseLocation* databaseLocation,
|
||||
MimeSniffer* mimeSniffer)
|
||||
:
|
||||
fDatabaseLocation(databaseLocation),
|
||||
fMimeSniffer(mimeSniffer),
|
||||
fMaxBytesNeeded(0),
|
||||
fHaveDoneFullBuild(false)
|
||||
@@ -338,7 +341,7 @@ SnifferRules::BuildRuleList()
|
||||
ssize_t bytesNeeded = 0;
|
||||
DatabaseDirectory root;
|
||||
|
||||
status_t err = root.Init();
|
||||
status_t err = root.Init(fDatabaseLocation);
|
||||
if (!err) {
|
||||
root.Rewind();
|
||||
while (true) {
|
||||
@@ -362,7 +365,7 @@ SnifferRules::BuildRuleList()
|
||||
// First, iterate through this supertype directory and process
|
||||
// all of its subtypes
|
||||
DatabaseDirectory dir;
|
||||
if (dir.Init(supertype) == B_OK) {
|
||||
if (dir.Init(fDatabaseLocation, supertype) == B_OK) {
|
||||
dir.Rewind();
|
||||
while (true) {
|
||||
BEntry subEntry;
|
||||
@@ -562,8 +565,10 @@ SnifferRules::ProcessType(const char *type, ssize_t *bytesNeeded)
|
||||
if (!err)
|
||||
err = rule.rule ? B_OK : B_NO_MEMORY;
|
||||
// Read the attr
|
||||
if (!err)
|
||||
err = read_mime_attr_string(type, kSnifferRuleAttr, &str);
|
||||
if (!err) {
|
||||
err = fDatabaseLocation->ReadStringAttribute(type, kSnifferRuleAttr,
|
||||
str);
|
||||
}
|
||||
// Parse the rule
|
||||
if (!err) {
|
||||
err = Sniffer::parse(str.String(), rule.rule, &errorMsg);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseDirectory.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
#include <storage_support.h>
|
||||
|
||||
|
||||
@@ -42,8 +43,10 @@ namespace Mime {
|
||||
|
||||
// Constructor
|
||||
//! Constructs a new SupportingApps object
|
||||
SupportingApps::SupportingApps()
|
||||
: fHaveDoneFullBuild(false)
|
||||
SupportingApps::SupportingApps(DatabaseLocation* databaseLocation)
|
||||
:
|
||||
fDatabaseLocation(databaseLocation),
|
||||
fHaveDoneFullBuild(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -266,7 +269,7 @@ SupportingApps::BuildSupportingAppsTable()
|
||||
fStrandedTypes.clear();
|
||||
|
||||
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
|
||||
if (status == B_OK) {
|
||||
@@ -290,8 +293,8 @@ SupportingApps::BuildSupportingAppsTable()
|
||||
&appSignature) >= B_OK) {
|
||||
// Read in the list of supported types
|
||||
BMessage msg;
|
||||
if (read_mime_attr_message(appSignature.String(), kSupportedTypesAttr,
|
||||
&msg) == B_OK) {
|
||||
if (fDatabaseLocation->ReadMessageAttribute(appSignature,
|
||||
kSupportedTypesAttr, msg) == B_OK) {
|
||||
// Iterate through the supported types, adding them to the list of
|
||||
// supported types for the application and adding the application's
|
||||
// signature to the list of supporting apps for each type
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006, Haiku.
|
||||
* Copyright 2002-2013, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -7,37 +7,16 @@
|
||||
* Ingo Weinhold <ingo_weinhold@gmx.de>
|
||||
*/
|
||||
|
||||
/*!
|
||||
\file database_support.cpp
|
||||
Private mime database functions and constants
|
||||
*/
|
||||
|
||||
#include <AppMisc.h>
|
||||
#include <DataIO.h>
|
||||
#include <Directory.h>
|
||||
#include <File.h>
|
||||
#include <mime/database_support.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Entry.h>
|
||||
#include <Message.h>
|
||||
#include <Node.h>
|
||||
#include <Path.h>
|
||||
#include <storage_support.h>
|
||||
#include <StringList.h>
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include <fs_attr.h> // For struct attr_info
|
||||
#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
|
||||
#include <mime/DatabaseLocation.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
@@ -109,12 +88,12 @@ static const directory_which kBaseDirectoryConstants[] = {
|
||||
B_SYSTEM_DATA_DIRECTORY
|
||||
};
|
||||
|
||||
static pthread_once_t sDatabaseDirectoryInitOnce = PTHREAD_ONCE_INIT;
|
||||
static BStringList sDatabaseDirectories;
|
||||
static pthread_once_t sDefaultDatabaseLocationInitOnce = PTHREAD_ONCE_INIT;
|
||||
static DatabaseLocation sDefaultDatabaseLocation;
|
||||
|
||||
|
||||
static void
|
||||
init_database_directories()
|
||||
init_default_database_location()
|
||||
{
|
||||
for (size_t i = 0;
|
||||
i < sizeof(kBaseDirectoryConstants)
|
||||
@@ -129,410 +108,94 @@ init_database_directories()
|
||||
continue;
|
||||
|
||||
directoryPath += "/mime_db";
|
||||
sDatabaseDirectories.Add(directoryPath);
|
||||
sDefaultDatabaseLocation.AddDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const BStringList&
|
||||
get_database_directories()
|
||||
DatabaseLocation*
|
||||
default_database_location()
|
||||
{
|
||||
pthread_once(&sDatabaseDirectoryInitOnce, &init_database_directories);
|
||||
return sDatabaseDirectories;
|
||||
pthread_once(&sDefaultDatabaseLocationInitOnce,
|
||||
&init_default_database_location);
|
||||
return &sDefaultDatabaseLocation;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
get_writable_database_directory()
|
||||
{
|
||||
return get_database_directories().StringAt(0);
|
||||
}
|
||||
/*! \brief Returns properly formatted raw bitmap data, ready to be shipped off
|
||||
to the hacked up 4-parameter version of Database::SetIcon()
|
||||
|
||||
|
||||
static BString
|
||||
type_to_filename(const char* type, int32 index)
|
||||
{
|
||||
BString path = get_database_directories().StringAt(index);
|
||||
return path << '/' << BPrivate::Storage::to_lower(type).c_str();
|
||||
}
|
||||
|
||||
|
||||
/*! 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
|
||||
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
|
||||
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;
|
||||
|
||||
int32 index;
|
||||
return open_type(type, result, index);
|
||||
}
|
||||
BRect bounds;
|
||||
BBitmap *icon8 = NULL;
|
||||
void *srcData = NULL;
|
||||
bool otherColorSpace = false;
|
||||
|
||||
// open_or_create_type
|
||||
/*! \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 result Pointer to a pre-allocated BNode into which
|
||||
is opened on the given MIME type
|
||||
*/
|
||||
status_t
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
// type doesn't exist yet -- create the respective node
|
||||
error = create_type_node(type, *result);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// Check the icon
|
||||
status_t err = icon->Bounds() == bounds ? B_OK : B_BAD_VALUE;
|
||||
|
||||
// write the type attribute
|
||||
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;
|
||||
// Convert to B_CMAP8 if necessary
|
||||
if (!err) {
|
||||
buffer = new(std::nothrow) char[info.size];
|
||||
if (!buffer)
|
||||
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)
|
||||
err = node.ReadAttr(attr, B_MESSAGE_TYPE, 0, buffer, info.size);
|
||||
if (err >= 0)
|
||||
err = err == info.size ? (status_t)B_OK : (status_t)B_FILE_ERROR;
|
||||
if (!err)
|
||||
err = msg->Unflatten(buffer);
|
||||
delete [] buffer;
|
||||
memcpy(*data, srcData, *dataSize);
|
||||
if (otherColorSpace)
|
||||
delete icon8;
|
||||
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 Storage
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <String.h>
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include <mime/database_support.h>
|
||||
|
||||
#include "CreateAppMetaMimeThread.h"
|
||||
#include "MessageDeliverer.h"
|
||||
#include "MimeSnifferAddonManager.h"
|
||||
@@ -56,7 +58,8 @@ init_mime_sniffer_add_on_manager()
|
||||
MIMEManager::MIMEManager()
|
||||
:
|
||||
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()
|
||||
{
|
||||
AddHandler(&fThreadManager);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <mime/Database.h>
|
||||
#include <mime/database_support.h>
|
||||
#include <mime/DatabaseLocation.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
@@ -83,7 +84,7 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir)
|
||||
mime.Install();
|
||||
|
||||
BNode typeNode;
|
||||
status = open_type(signature, &typeNode);
|
||||
status = fDatabase->Location()->OpenType(signature, typeNode);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user