After implementing the BMimeType::GetInstalled[Super]Types()

functionality, it became apparent that some restructuring was
needed if I wanted to keep things clean and managble.
storage/MimeDatabase.{h,cpp} have been broken into:

storage/mime/database_support.{h,cpp}
+ MIME database constants
+ high-level database access functions like open_type(),
  read_mime_attr(), etc.

storage/mime/database_access.{h,cpp}
+ atomic read functions
+ is_installed()
+ get_icon_data()

storage/mime/Database.{h,cpp}
+ Mime::Database class, which is responsible for all write,
  non-atomic read, and mime monitor functionality.

storage/mime/InstalledTypes.{h,cpp}
+ Helper class for Mime::Database::GetInstalled[Super]Types()

storage/mime/Supertype.{h,cpp}
+ Helper class for Mime::InstalledTypes

I haven't merged my intial, somewhat cludgy GetInstalled[Super]Types
implementation into the new setup yet. That comes next, and it ought
to be a more graceful implementation now.

I also implemented BMimeType::Get/SetSupportingTypes(), though
they haven't been tested yet (sorry).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@862 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder
2002-08-24 05:04:02 +00:00
parent 1c4b41005c
commit e20a514ae9
15 changed files with 2476 additions and 110 deletions
+24 -22
View File
@@ -57,6 +57,7 @@ enum {
B_MIME_TYPE_CREATED = 0x00000100,
B_MIME_TYPE_DELETED = 0x00000200,
B_SNIFFER_RULE_CHANGED = 0x00000400,
B_SUPPORTED_TYPES_CHANGED = 0x00000800,
B_EVERYTHING_CHANGED = (int)0xFFFFFFFF
};
@@ -121,9 +122,9 @@ public:
status_t SetShortDescription(const char *description);
status_t SetLongDescription(const char *description);
static status_t GetInstalledSupertypes(BMessage *super_types);
static status_t GetInstalledSupertypes(BMessage *supertypes);
static status_t GetInstalledTypes(BMessage *types);
static status_t GetInstalledTypes(const char *super_type,
static status_t GetInstalledTypes(const char *supertype,
BMessage *subtypes);
static status_t GetWildcardApps(BMessage *wild_ones);
static bool IsValid(const char *mimeType);
@@ -156,15 +157,16 @@ public:
status_t SetType(const char *mimeType);
/* Brand new Delete() methods */
status_t DeleteIcon(icon_size size);
status_t DeletePreferredApp(app_verb verb = B_OPEN);
status_t DeleteAppHint();
status_t DeleteAttrInfo();
status_t DeleteFileExtensions();
status_t DeleteShortDescription();
status_t DeleteLongDescription();
status_t DeleteSnifferRule();
status_t DeleteFileExtensions();
status_t DeleteIcon(icon_size size);
status_t DeleteIconForType(const char *type, icon_size which);
status_t DeleteAppHint();
status_t DeletePreferredApp(app_verb verb = B_OPEN);
status_t DeleteSnifferRule();
status_t DeleteSupportedTypes();
private:
BMimeType(const char *mimeType, const char *mimePath);
@@ -192,24 +194,24 @@ private:
BMimeType &operator=(const BMimeType &);
BMimeType(const BMimeType &);
/*
void InitData(const char *type);
void InitData(const char *type);
status_t OpenFile(bool create_file = false, dev_t dev = -1) const;
status_t CloseFile() const;
// void InitData(const char *type);
// void InitData(const char *type);
// status_t OpenFile(bool create_file = false, dev_t dev = -1) const;
// status_t CloseFile() const;
status_t GetSupportedTypes(BMessage *types);
status_t SetSupportedTypes(const BMessage *types);
void MimeChanged(int32 w, const char *type = NULL,
bool large = true) const;
*/
// void MimeChanged(int32 w, const char *type = NULL,
// bool large = true) const;
char *fType;
BFile *fMeta;
BPrivate::MimeDatabase *fMimeDatabase; // Was: "void *_unused;"
entry_ref fRef;
int fWhere;
status_t fCStatus;
uint32 _reserved[3];
char *fType;
BFile *fMeta;
void *_unused;
entry_ref fRef;
int fWhere;
status_t fCStatus;
uint32 _reserved[3];
};
+100
View File
@@ -0,0 +1,100 @@
// mime/Database.h
#ifndef _MIME_DATABASE_H
#define _MIME_DATABASE_H
#include <mime/InstalledTypes.h>
#include <Mime.h>
#include <Messenger.h>
#include <StorageDefs.h>
#include <string>
#include <map>
#include <set>
class BNode;
class BBitmap;
class BMessage;
namespace BPrivate {
namespace Storage {
namespace Mime {
class Database {
public:
Database();
~Database();
status_t InitCheck() const;
// 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);
status_t SetShortDescription(const char *type, const char *description);
status_t SetLongDescription(const char *type, const char *description);
status_t SetFileExtensions(const char *type, const BMessage *extensions);
status_t SetIcon(const char *type, const void *data, size_t dataSize, icon_size which);
status_t SetIconForType(const char *type, const char *fileType, const void *data,
size_t dataSize, icon_size which);
status_t SetPreferredApp(const char *type, const char *signature, app_verb verb = B_OPEN);
// status_t SetSnifferRule(const char *);
status_t SetSupportedTypes(const char *type, const BMessage *types);
// Non-atomic Get()
status_t GetInstalledSupertypes(BMessage *super_types);
status_t GetInstalledTypes(BMessage *types);
status_t GetInstalledTypes(const char *super_type,
BMessage *subtypes);
status_t GetSupportingApps(const char *type, BMessage *signatures);
// Sniffer
// static status_t CheckSnifferRule(const char *rule, BString *parseError);
// static status_t GuessMimeType(const entry_ref *file, BMimeType *result);
// static status_t GuessMimeType(const void *buffer, int32 length,
// BMimeType *result);
// static status_t GuessMimeType(const char *filename, BMimeType *result);
// Monitor
status_t StartWatching(BMessenger target);
status_t StopWatching(BMessenger target);
// Delete()
status_t DeleteAppHint(const char *type);
status_t DeleteAttrInfo(const char *type);
status_t DeleteShortDescription(const char *type);
status_t DeleteLongDescription(const char *type);
status_t DeleteFileExtensions(const char *type);
status_t DeleteIcon(const char *type, icon_size size);
status_t DeleteIconForType(const char *type, const char *fileType, icon_size which);
status_t DeletePreferredApp(const char *type, app_verb verb = B_OPEN);
status_t DeleteSnifferRule(const char *type);
status_t DeleteSupportedTypes(const char *type);
private:
status_t SendInstallNotification(const char *type);
status_t SendDeleteNotification(const char *type);
status_t SendMonitorUpdate(int32 which, const char *type, const char *extraType,
bool largeIcon, int32 action);
status_t SendMonitorUpdate(int32 which, const char *type, const char *extraType,
int32 action);
status_t SendMonitorUpdate(int32 which, const char *type, bool largeIcon,
int32 action);
status_t SendMonitorUpdate(int32 which, const char *type,
int32 action);
status_t SendMonitorUpdate(BMessage &msg);
status_t fCStatus;
std::set<BMessenger> fMonitorSet;
InstalledTypes fInstalledTypes;
};
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
#endif // _MIME_DATABASE_H
@@ -0,0 +1,42 @@
// mime/InstalledTypes.h
#ifndef _MIME_INSTALLED_TYPES_H
#define _MIME_INSTALLED_TYPES_H
#include <mime/Supertype.h>
#include <SupportDefs.h>
#include <string>
#include <map>
class BMessage;
namespace BPrivate {
namespace Storage {
namespace Mime {
class InstalledTypes {
public:
InstalledTypes();
~InstalledTypes();
status_t GetInstalledTypes(BMessage *types);
status_t GetInstalledTypes(const char *supertype, BMessage *types);
status_t GetInstalledSupertypes(BMessage *types);
void AddType(const char *type);
void AddSupertype(const char *type);
void AddSubtype(const char *super, const char *sub);
private:
void FillMessageWithTypes(BMessage *msg);
void FillMessageWithSupertypes(BMessage *msg);
std::map<std::string, Supertype> fSupertypes;
BMessage *fCachedMessage;
};
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
#endif // _MIME_INSTALLED_TYPES_H
+34
View File
@@ -0,0 +1,34 @@
// mime/Supertype.h
#ifndef _MIME_SUPERTYPE_H
#define _MIME_SUPERTYPE_H
#include <SupportDefs.h>
#include <string>
#include <set>
class BMessage;
namespace BPrivate {
namespace Storage {
namespace Mime {
class Supertype {
public:
Supertype(const char *super);
~Supertype();
void AddSubtype(const char *sub);
void FillMessageWithTypes(BMessage *msg);
private:
std::set<std::string> fSubtypes;
BMessage *fCachedMessage;
std::string fType;
};
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
#endif // _MIME_SUPERTYPE_H
@@ -0,0 +1,39 @@
// mime/database_access.h
#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_for_type(const char *type, const char *fileType, BBitmap *icon,
icon_size which);
status_t get_preferred_app(const char *type, char *signature, app_verb verb);
status_t get_sniffer_rule(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
@@ -0,0 +1,71 @@
// mime/database_support.h
#ifndef _MIME_DATABASE_SUPPORT_H
#define _MIME_DATABASE_SUPPORT_H
#include <StorageDefs.h>
#include <string>
class BNode;
class BMessage;
namespace BPrivate {
namespace Storage {
namespace Mime {
// Database directory
extern const std::string kDatabaseDir;
// Attribute Prefixes
extern const char *kMiniIconAttrPrefix;
extern const char *kLargeIconAttrPrefix;
// Attribute names
extern const char *kFileTypeAttr;
extern const char *kTypeAttr;
extern const char *kAttrInfoAttr;
extern const char *kAppHintAttr;
extern const char *kShortDescriptionAttr;
extern const char *kLongDescriptionAttr;
extern const char *kFileExtensionsAttr;
extern const char *kMiniIconAttr;
extern const char *kLargeIconAttr;
extern const char *kPreferredAppAttr;
extern const char *kSnifferRuleAttr;
extern const char *kSupportedTypesAttr;
// Attribute Datatypes
extern const int32 kFileTypeType;
extern const int32 kTypeType;
extern const int32 kAppHintType;
extern const int32 kAttrInfoType;
extern const int32 kShortDescriptionType;
extern const int32 kLongDescriptionType;
extern const int32 kFileExtensionsType;
extern const int32 kMiniIconType;
extern const int32 kLargeIconType;
extern const int32 kPreferredAppType;
extern const int32 kSnifferRuleType;
extern const int32 kSupportedTypesType;
std::string type_to_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);
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 write_mime_attr(const char *type, const char *attr, const void *data,
size_t len, type_code datatype, bool *didCreate);
status_t write_mime_attr_message(const char *type, const char *attr,
const BMessage *msg, bool *didCreate);
status_t delete_attribute(const char *type, const char *attr);
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
#endif // _MIME_DATABASE_SUPPORT_H
+20 -10
View File
@@ -24,15 +24,16 @@ UsePublicHeaders [ FDirName add-ons file_system ] ;
# that can just be linked into libstorage.so and the
# registrar separately.
SEARCH_SOURCE += [ FDirName $(SUBDIR) sniffer ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) mime ] ;
SharedLibrary storage :
# storage
Directory.cpp
Entry.cpp
EntryList.cpp
File.cpp
FindDirectory.cpp
Mime.cpp
MimeDatabase.cpp
MimeType.cpp
Node.cpp
#NodeInfo.cpp
@@ -45,21 +46,30 @@ SharedLibrary storage :
ResourceItem.cpp
Resources.cpp
ResourceStrings.cpp
Err.cpp # Hack-o-rama
DisjList.cpp # Hack-o-rama
Pattern.cpp # Hack-o-rama
PatternList.cpp # Hack-o-rama
Parser.cpp # Hack-o-rama
Range.cpp # Hack-o-rama
RPattern.cpp # Hack-o-rama
RPatternList.cpp # Hack-o-rama
Rule.cpp # Hack-o-rama
Statable.cpp
SymLink.cpp
Volume.cpp
VolumeRoster.cpp
kernel_interface.POSIX.cpp
storage_support.cpp
# storage/sniffer
Err.cpp
DisjList.cpp
Pattern.cpp
PatternList.cpp
Parser.cpp
Range.cpp
RPattern.cpp
RPatternList.cpp
Rule.cpp
# storage/mime
Database.cpp
InstalledTypes.cpp
Supertype.cpp
database_access.cpp
database_support.cpp
;
LinkSharedOSLibs libstorage.so :
libopenbeos.so
+151 -53
View File
@@ -6,19 +6,20 @@
\file MimeType.cpp
BMimeType implementation.
*/
#include <MimeType.h>
#include "MimeType.h"
#include <Bitmap.h>
#include <mime/database_access.h>
#include <sniffer/Rule.h>
#include <sniffer/Parser.h>
#include <ctype.h> // For tolower()
#include <new.h> // For new(nothrow)
#include <stdio.h> // For printf()
#include <string.h> // For strncpy()
#include <MimeDatabase.h>
#include <RegistrarDefs.h>
#include <Roster.h> // For _send_to_roster_()
#include <sniffer/Rule.h>
#include <sniffer/Parser.h>
// Private helper functions
bool isValidMimeChar(const char ch);
status_t toLower(const char *str, char *result);
@@ -27,6 +28,7 @@ enum {
NOT_IMPLEMENTED = B_ERROR,
};
using namespace BPrivate::Storage::Mime;
const char *B_PEF_APP_MIME_TYPE = "application/x-be-executable";
const char *B_PE_APP_MIME_TYPE = "application/x-vnd.be-peexecutable";
@@ -43,7 +45,6 @@ const char *B_APP_MIME_TYPE = B_ELF_APP_MIME_TYPE;
BMimeType::BMimeType()
: fType(NULL)
, fCStatus(B_NO_INIT)
, fMimeDatabase(new(nothrow) BPrivate::MimeDatabase())
{
}
@@ -57,7 +58,6 @@ BMimeType::BMimeType()
BMimeType::BMimeType(const char *mimeType)
: fType(NULL)
, fCStatus(B_NO_INIT)
, fMimeDatabase(new(nothrow) BPrivate::MimeDatabase())
{
SetTo(mimeType);
}
@@ -68,7 +68,6 @@ BMimeType::BMimeType(const char *mimeType)
BMimeType::~BMimeType()
{
Unset();
delete fMimeDatabase;
}
// SetTo
@@ -98,8 +97,6 @@ BMimeType::SetTo(const char *mimeType)
{
if (!mimeType || !BMimeType::IsValid(mimeType)) {
fCStatus = B_BAD_VALUE;
} else if (!fMimeDatabase) {
fCStatus = B_NO_MEMORY;
} else {
Unset();
fType = new(nothrow) char[strlen(mimeType)+1];
@@ -193,7 +190,7 @@ BMimeType::IsSupertypeOnly() const
bool
BMimeType::IsInstalled() const
{
return InitCheck() == B_OK && fMimeDatabase->IsInstalled(Type());
return InitCheck() == B_OK && is_installed(Type());
}
// GetSupertype
@@ -388,7 +385,10 @@ BMimeType::Delete()
status_t
BMimeType::GetIcon(BBitmap *icon, icon_size size) const
{
return fMimeDatabase->GetIcon(Type(), icon, size);
status_t err = InitCheck();
if (!err)
err = get_icon(Type(), icon, size);
return err;
}
// GetPreferredApp
@@ -414,7 +414,10 @@ BMimeType::GetIcon(BBitmap *icon, icon_size size) const
status_t
BMimeType::GetPreferredApp(char *signature, app_verb verb) const
{
return fMimeDatabase->GetPreferredApp(Type(), signature, verb);
status_t err = InitCheck();
if (!err)
err = get_preferred_app(Type(), signature, verb);
return err;
}
// GetAttrInfo
@@ -470,7 +473,10 @@ BMimeType::GetPreferredApp(char *signature, app_verb verb) const
status_t
BMimeType::GetAttrInfo(BMessage *info) const
{
return fMimeDatabase->GetAttrInfo(Type(), info);
status_t err = InitCheck();
if (!err)
err = get_attr_info(Type(), info);
return err;
}
// GetFileExtensions
@@ -504,7 +510,10 @@ BMimeType::GetAttrInfo(BMessage *info) const
status_t
BMimeType::GetFileExtensions(BMessage *extensions) const
{
return fMimeDatabase->GetFileExtensions(Type(), extensions);
status_t err = InitCheck();
if (!err)
err = get_file_extensions(Type(), extensions);
return err;
}
// GetShortDescription
@@ -523,7 +532,10 @@ BMimeType::GetFileExtensions(BMessage *extensions) const
status_t
BMimeType::GetShortDescription(char *description) const
{
return fMimeDatabase->GetShortDescription(Type(), description);
status_t err = InitCheck();
if (!err)
err = get_short_description(Type(), description);
return err;
}
// GetLongDescription
@@ -542,7 +554,10 @@ BMimeType::GetShortDescription(char *description) const
status_t
BMimeType::GetLongDescription(char *description) const
{
return fMimeDatabase->GetLongDescription(Type(), description);
status_t err = InitCheck();
if (!err)
err = get_long_description(Type(), description);
return err;
}
// GetSupportingApps
@@ -908,9 +923,26 @@ BMimeType::SetLongDescription(const char *description)
- "error code": Failure
*/
status_t
BMimeType::GetInstalledSupertypes(BMessage *super_types)
BMimeType::GetInstalledSupertypes(BMessage *supertypes)
{
return NOT_IMPLEMENTED;
status_t err = supertypes ? B_OK : B_BAD_VALUE;
BMessage msg(B_REG_MIME_GET_INSTALLED_SUPERTYPES);
BMessage reply;
status_t result;
// Build and send the message, read the reply
if (!err)
err = _send_to_roster_(&msg, &reply, true);
if (!err)
err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE;
if (!err)
err = reply.FindInt32("result", &result);
if (!err)
err = result;
if (!err)
err = reply.FindMessage("types", supertypes);
return err;
}
// GetInstalledTypes
@@ -929,7 +961,7 @@ BMimeType::GetInstalledSupertypes(BMessage *super_types)
status_t
BMimeType::GetInstalledTypes(BMessage *types)
{
return NOT_IMPLEMENTED;
return GetInstalledTypes(NULL, types);
}
// GetInstalledTypes
@@ -948,9 +980,28 @@ BMimeType::GetInstalledTypes(BMessage *types)
- "error code": Failure
*/
status_t
BMimeType::GetInstalledTypes(const char *super_type, BMessage *subtypes)
BMimeType::GetInstalledTypes(const char *supertype, BMessage *types)
{
return NOT_IMPLEMENTED;
status_t err = types ? B_OK : B_BAD_VALUE;
BMessage msg(B_REG_MIME_GET_INSTALLED_TYPES);
BMessage reply;
status_t result;
// Build and send the message, read the reply
if (!err && supertype)
err = msg.AddString("supertype", supertype);
if (!err)
err = _send_to_roster_(&msg, &reply, true);
if (!err)
err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE;
if (!err)
err = reply.FindInt32("result", &result);
if (!err)
err = result;
if (!err)
err = reply.FindMessage("types", types);
return err;
}
// GetWildcardApps
@@ -1050,7 +1101,10 @@ bool isValidMimeChar(const char ch)
status_t
BMimeType::GetAppHint(entry_ref *ref) const
{
return fMimeDatabase->GetAppHint(Type(), ref);
status_t err = InitCheck();
if (!err)
err = get_app_hint(Type(), ref);
return err;
}
// SetAppHint
@@ -1136,7 +1190,7 @@ BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) cons
if (type) {
err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE;
if (!err)
err = fMimeDatabase->GetIconForType(Type(), type, icon, which);
err = get_icon_for_type(Type(), type, icon, which);
} else
err = GetIcon(icon, which);
return err;
@@ -1191,7 +1245,7 @@ BMimeType::SetIconForType(const char *type, const BBitmap *icon, icon_size which
err = msg.AddInt32("which", (type ? B_REG_MIME_ICON_FOR_TYPE : B_REG_MIME_ICON));
if (icon) {
if (!err)
err = BPrivate::MimeDatabase::GetIconData(icon, which, &data, &dataSize);
err = get_icon_data(icon, which, &data, &dataSize);
if (!err)
err = msg.AddData("icon data", B_RAW_TYPE, data, dataSize);
}
@@ -1470,20 +1524,12 @@ BMimeType::SetType(const char *mimeType)
SetTo(mimeType);
}
// DeleteIcon
//! Deletes the mime type's icon of given size
status_t
BMimeType::DeleteIcon(icon_size which)
{
return SetIcon(NULL, which);
}
// DeletePreferredApp
//! Deletes the mime type's preferred app for the given verb
// DeleteAppHint
//! Deletes the mime type's application hint
status_t
BMimeType::DeletePreferredApp(app_verb verb = B_OPEN)
BMimeType::DeleteAppHint()
{
return SetPreferredApp(NULL, verb);
return SetAppHint(NULL);
}
// DeleteAttrInfo
@@ -1494,14 +1540,6 @@ BMimeType::DeleteAttrInfo()
return SetAttrInfo(NULL);
}
// DeleteFileExtensions
//! Deletes the mime type's associated file extensions
status_t
BMimeType::DeleteFileExtensions()
{
return SetFileExtensions(NULL);
}
// DeleteShortDescription
//! Deletes the mime type's short description
status_t
@@ -1518,12 +1556,20 @@ BMimeType::DeleteLongDescription()
return SetLongDescription(NULL);
}
// DeleteSnifferRule
//! Deletes the mime type's sniffer rule
// DeleteFileExtensions
//! Deletes the mime type's associated file extensions
status_t
BMimeType::DeleteSnifferRule()
BMimeType::DeleteFileExtensions()
{
return SetSnifferRule(NULL);
return SetFileExtensions(NULL);
}
// DeleteIcon
//! Deletes the mime type's icon of given size
status_t
BMimeType::DeleteIcon(icon_size which)
{
return SetIcon(NULL, which);
}
// DeleteIconForType
@@ -1534,12 +1580,28 @@ BMimeType::DeleteIconForType(const char *type, icon_size which)
return SetIconForType(type, NULL, which);
}
// DeleteAppHint
//! Deletes the mime type's application hint
// DeletePreferredApp
//! Deletes the mime type's preferred app for the given verb
status_t
BMimeType::DeleteAppHint()
BMimeType::DeletePreferredApp(app_verb verb = B_OPEN)
{
return SetAppHint(NULL);
return SetPreferredApp(NULL, verb);
}
// DeleteSnifferRule
//! Deletes the mime type's sniffer rule
status_t
BMimeType::DeleteSnifferRule()
{
return SetSnifferRule(NULL);
}
// DeleteSupportedTypes
//! Deletes the mime type's supported types
status_t
BMimeType::DeleteSupportedTypes()
{
return SetSupportedTypes(NULL);
}
void BMimeType::_ReservedMimeType1() {}
@@ -1562,6 +1624,42 @@ BMimeType::BMimeType(const BMimeType &)
{
}
status_t
BMimeType::GetSupportedTypes(BMessage *types)
{
status_t err = InitCheck();
if (!err)
err = get_supported_types(Type(), types);
return err;
}
status_t
BMimeType::SetSupportedTypes(const BMessage *types)
{
status_t err = InitCheck();
BMessage msg(types ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM);
BMessage reply;
status_t result;
// Build and send the message, read the reply
if (!err)
err = msg.AddString("type", Type());
if (!err)
err = msg.AddInt32("which", B_REG_MIME_SUPPORTED_TYPES);
if (!err && types)
err = msg.AddMessage("types", types);
if (!err)
err = _send_to_roster_(&msg, &reply, true);
if (!err)
err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE;
if (!err)
err = reply.FindInt32("result", &result);
if (!err)
err = result;
return err;
}
// Returns a lowercase version of str in result. Result must
// be preallocated and is assumed to be of adequate length.
status_t
+752
View File
@@ -0,0 +1,752 @@
// mime/Database.cpp
#include <Application.h>
#include <Bitmap.h>
#include <DataIO.h>
#include <Directory.h>
#include <Entry.h>
#include <Message.h>
#include <mime/database_access.h>
#include <mime/database_support.h>
#include <MimeType.h>
#include <Node.h>
#include <Path.h>
#include <storage_support.h>
#include <TypeConstants.h>
#include <fs_attr.h> // For struct attr_info
#include <iostream>
#include <new> // For new(nothrow)
#include <stdio.h>
#include <string>
#include "mime/Database.h"
//#define DBG(x) x
#define DBG(x)
#define OUT printf
// icon types
enum {
B_MINI_ICON_TYPE = 'MICN',
B_LARGE_ICON_TYPE = 'ICON',
};
namespace BPrivate {
namespace Storage {
namespace Mime {
/*!
\class Database
\brief Mime::Database is the master of the MIME data base.
All write and non-atomic read accesses are carried out by this class.
Monitoring is handled by
\note No error checking (other than checks for NULL pointers) is performed
by this class on the mime type strings passed to it. It's assumed
that this sort of checking has been done beforehand.
*/
// constructor
/*! \brief Creates and initializes a MimeDatabase.
*/
Database::Database()
: fCStatus(B_NO_INIT)
{
// Do some really minor error checking
BEntry entry(kDatabaseDir.c_str());
fCStatus = entry.Exists() ? B_OK : B_BAD_VALUE;
}
// destructor
/*! \brief Frees all resources associated with this object.
*/
Database::~Database()
{
}
// InitCheck
/*! \brief Returns the initialization status of the object.
\return
- B_OK: success
- "error code": failure
*/
status_t
Database::InitCheck() const
{
return fCStatus;
}
// Install
/*! \brief Installs the given type in the database
\note The R5 version of this call returned an unreliable result if the
MIME type was already installed. Ours simply returns B_OK.
\param type Pointer to a NULL-terminated string containing the MIME type of interest
\param decsription Pointer to a NULL-terminated string containing the new long description
\return
- B_OK: success
- B_FILE_EXISTS: the type is already installed
- "error code": failure
*/
status_t
Database::Install(const char *type)
{
BEntry entry;
status_t err = (type ? B_OK : B_BAD_VALUE);
if (!err)
err = entry.SetTo(type_to_filename(type).c_str());
if (!err) {
if (entry.Exists())
err = B_FILE_EXISTS;
else {
bool didCreate = false;
BNode node;
err = open_or_create_type(type, &node, &didCreate);
}
}
return err;
}
// Delete
/*! \brief Removes the given type from the database
\param type Pointer to a NULL-terminated string containing the MIME type of interest
\return
- B_OK: success
- "error code": failure
*/
status_t
Database::Delete(const char *type)
{
BEntry entry;
status_t err = (type ? B_OK : B_BAD_VALUE);
if (!err)
err = entry.SetTo(type_to_filename(type).c_str());
if (!err)
err = entry.Remove();
if (!err)
err = SendDeleteNotification(type);
return err;
}
// SetAppHint
/*! \brief Sets the application hint for the given MIME type
\param type Pointer to a NULL-terminated string containing the MIME type of interest
\param decsription Pointer to an entry_ref containing the location of an application
that should be used when launching an application with this signature.
*/
status_t
Database::SetAppHint(const char *type, const entry_ref *ref)
{
DBG(OUT("Database::SetAppHint()\n"));
BPath path;
bool didCreate = false;
status_t err = (type && ref) ? B_OK : B_BAD_VALUE;
if (!err)
err = path.SetTo(ref);
if (!err)
err = write_mime_attr(type, kAppHintAttr, path.Path(), strlen(path.Path())+1,
kAppHintType, &didCreate);
if (!err)
err = SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
// SetAttrInfo
/*! \brief Stores a BMessage describing the format of attributes typically associated with
files of the given MIME type
See BMimeType::SetAttrInfo() for description of the expected message format.
The \c BMessage::what value is ignored.
\param info Pointer to a pre-allocated and properly formatted BMessage containing
information about the file attributes typically associated with the
MIME type.
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
Database::SetAttrInfo(const char *type, const BMessage *info)
{
DBG(OUT("Database::SetAttrInfo()\n"));
bool didCreate = false;
status_t err = (type && info) ? B_OK : B_BAD_VALUE;
if (!err)
err = write_mime_attr_message(type, kAttrInfoAttr, info, &didCreate);
if (!err)
err = SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
// SetShortDescription
/*! \brief Sets the short description for the given MIME type
\param type Pointer to a NULL-terminated string containing the MIME type of interest
\param decsription Pointer to a NULL-terminated string containing the new short description
*/
status_t
Database::SetShortDescription(const char *type, const char *description)
{
DBG(OUT("Database::SetShortDescription()\n"));
bool didCreate = false;
status_t err = (type && description && strlen(description) < B_MIME_TYPE_LENGTH) ? B_OK : B_BAD_VALUE;
if (!err)
err = write_mime_attr(type, kShortDescriptionAttr, description, strlen(description)+1,
kShortDescriptionType, &didCreate);
if (!err)
err = SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
// SetLongDescription
/*! \brief Sets the long description for the given MIME type
\param type Pointer to a NULL-terminated string containing the MIME type of interest
\param decsription Pointer to a NULL-terminated string containing the new long description
*/
status_t
Database::SetLongDescription(const char *type, const char *description)
{
DBG(OUT("Database::SetLongDescription()\n"));
bool didCreate = false;
status_t err = (type && description && strlen(description) < B_MIME_TYPE_LENGTH) ? B_OK : B_BAD_VALUE;
if (!err)
err = write_mime_attr(type, kLongDescriptionAttr, description, strlen(description)+1,
kLongDescriptionType, &didCreate);
if (!err)
err = SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
// SetFileExtensions
//! Sets the list of filename extensions associated with the MIME type
/*! The list of extensions is given in a pre-allocated BMessage pointed to by
the \c extensions parameter. Please see BMimeType::SetFileExtensions()
for a description of the expected message format.
\param extensions Pointer to a pre-allocated, properly formatted BMessage containing
the new list of file extensions to associate with this MIME type.
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
Database::SetFileExtensions(const char *type, const BMessage *extensions)
{
DBG(OUT("Database::SetFileExtensions()\n"));
bool didCreate = false;
status_t err = (type && extensions) ? B_OK : B_BAD_VALUE;
if (!err)
err = write_mime_attr_message(type, kFileExtensionsAttr, extensions, &didCreate);
if (!err)
err = SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
//! Sets the icon for the given mime type
/*! This is the version I would have used if I could have gotten a BBitmap
to the registrar somehow. Since R5::BBitmap::Instantiate is causing a
violent crash, I've copied most of the icon color conversion code into
Mime::get_icon_data() so BMimeType::SetIcon() can get at it.
Once we have a sufficiently complete OBOS::BBitmap implementation, we
ought to be able to use this version of SetIcon() again. At that point,
I'll add some real documentation.
*/
status_t
Database::SetIcon(const char *type, const void *data, size_t dataSize, icon_size which)
{
return SetIconForType(type, NULL, data, dataSize, which);
}
// SetIconForType
/*! \brief Sets 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 application-specific
icons are not expected to be present for non-application types.
The bitmap data pointed to by \c data must be of the proper size (\c 32x32
for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and the proper color
space (B_CMAP8).
\param type The MIME type
\param fileType The MIME type whose custom icon you wish to set.
\param data Pointer to an array of bitmap data of proper dimensions and color depth
\param dataSize The length of the array pointed to by \c data
\param size The size icon you're expecting (\c B_LARGE_ICON or \c B_MINI_ICON)
\return
- \c B_OK: Success
- "error code": Failure
*/
status_t
Database::SetIconForType(const char *type, const char *fileType, const void *data,
size_t dataSize, icon_size which)
{
ssize_t err = (type && data) ? B_OK : B_BAD_VALUE;
std::string attr;
int32 attrType;
int32 attrSize;
// Figure out what kind of data we *should* have
if (!err) {
switch (which) {
case B_MINI_ICON:
attrType = kMiniIconType;
attrSize = 16 * 16;
break;
case B_LARGE_ICON:
attrType = kLargeIconType;
attrSize = 32 * 32;
break;
default:
err = B_BAD_VALUE;
break;
}
}
// Construct our attribute name
if (fileType) {
attr = (which == B_MINI_ICON
? kMiniIconAttrPrefix
: kLargeIconAttrPrefix)
+ BPrivate::Storage::to_lower(fileType);
} else
attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr;
// Double check the data we've been given
if (!err)
err = dataSize == attrSize ? B_OK : B_BAD_VALUE;
// Write the icon data
BNode node;
bool didCreate = false;
if (!err)
err = open_or_create_type(type, &node, &didCreate);
if (!err)
err = node.WriteAttr(attr.c_str(), attrType, 0, data, attrSize);
if (err >= 0)
err = err == attrSize ? B_OK : B_FILE_ERROR;
return err;
}
// SetPreferredApp
/*! \brief Sets the signature of the preferred application for the given app verb
Currently, the only supported app verb is \c B_OPEN
\param type Pointer to a NULL-terminated string containing the MIME type of interest
\param signature Pointer to a NULL-terminated string containing the MIME signature
of the new preferred application
\param verb \c app_verb action for which the new preferred application is applicable
*/
status_t
Database::SetPreferredApp(const char *type, const char *signature, app_verb verb = B_OPEN)
{
DBG(OUT("Database::SetPreferredApp()\n"));
bool didCreate = false;
status_t err = (type && signature && strlen(signature) < B_MIME_TYPE_LENGTH) ? B_OK : B_BAD_VALUE;
if (!err)
err = write_mime_attr(type, kPreferredAppAttr, signature, strlen(signature)+1,
kPreferredAppType, &didCreate);
if (!err)
err = SendMonitorUpdate(B_PREFERRED_APP_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
// SetSupportedTypes
status_t
Database::SetSupportedTypes(const char *type, const BMessage *types)
{
DBG(OUT("Database::SetSupportedTypes()\n"));
bool didCreate = false;
status_t err = (type && types) ? B_OK : B_BAD_VALUE;
if (!err)
err = write_mime_attr_message(type, kSupportedTypesAttr, types, &didCreate);
if (!err)
err = SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type, B_META_MIME_MODIFIED);
return err;
}
status_t
Database::GetInstalledSupertypes(BMessage *supertypes)
{
// return fInstalledTypes.GetInstalledSupertypes(supertypes);
return B_ERROR;
}
status_t
Database::GetInstalledTypes(BMessage *types)
{
// return fInstalledTypes.GetInstalledTypes(types);
return B_ERROR;
}
status_t
Database::GetInstalledTypes(const char *supertype, BMessage *subtypes)
{
// return fInstalledTypes.GetInstalledTypes(supertype, subtypes);
return B_ERROR;
}
status_t
Database::GetSupportingApps(const char *type, BMessage *signatures)
{
return B_ERROR;
}
// StartWatching
//! Subscribes the given BMessenger to the MIME monitor service
/*! Notification messages will be sent with a \c BMessage::what value
of \c B_META_MIME_CHANGED. Notification messages have the following
fields:
<table>
<tr>
<td> Name </td>
<td> Type </td>
<td> Description </td>
</tr>
<tr>
<td> \c be:type </td>
<td> \c B_STRING_TYPE </td>
<td> The MIME type that was changed </td>
</tr>
<tr>
<td> \c be:which </td>
<td> \c B_INT32_TYPE </td>
<td> Bitmask describing which attributes were changed (see below) </td>
</tr>
<tr>
<td> \c be:extra_type </td>
<td> \c B_STRING_TYPE </td>
<td> Additional MIME type string (applicable to B_ICON_FOR_TYPE_CHANGED notifications only)</td>
</tr>
<tr>
<td> \c be:large_icon </td>
<td> \c B_BOOL_TYPE </td>
<td> \c true if the large icon was changed, \c false if the small icon
was changed (applicable to B_ICON_[FOR_TYPE_]CHANGED updates only) </td>
</tr>
</table>
The \c be:which field of the message describes which attributes were updated, and
may be the bitwise \c OR of any of the following values:
<table>
<tr>
<td> Value </td>
<td> Triggered By </td>
</tr>
<tr>
<td> \c B_ICON_CHANGED </td>
<td> \c BMimeType::SetIcon() </td>
</tr>
<tr>
<td> \c B_PREFERRED_APP_CHANGED </td>
<td> \c BMimeType::SetPreferredApp() </td>
</tr>
<tr>
<td> \c B_ATTR_INFO_CHANGED </td>
<td> \c BMimeType::SetAttrInfo() </td>
</tr>
<tr>
<td> \c B_FILE_EXTENSIONS_CHANGED </td>
<td> \c BMimeType::SetFileExtensions() </td>
</tr>
<tr>
<td> \c B_SHORT_DESCRIPTION_CHANGED </td>
<td> \c BMimeType::SetShortDescription() </td>
</tr>
<tr>
<td> \c B_LONG_DESCRIPTION_CHANGED </td>
<td> \c BMimeType::SetLongDescription() </td>
</tr>
<tr>
<td> \c B_ICON_FOR_TYPE_CHANGED </td>
<td> \c BMimeType::SetIconForType() </td>
</tr>
<tr>
<td> \c B_APP_HINT_CHANGED </td>
<td> \c BMimeType::SetAppHint() </td>
</tr>
</table>
\param target The \c BMessenger to subscribe to the MIME monitor service
*/
status_t
Database::StartWatching(BMessenger target)
{
DBG(OUT("Database::StartWatching()\n"));
status_t err = target.IsValid() ? B_OK : B_BAD_VALUE;
if (!err)
fMonitorSet.insert(target);
return err;
}
// StartWatching
//! Unsubscribes the given BMessenger from the MIME monitor service
/*! \param target The \c BMessenger to unsubscribe
*/
status_t
Database::StopWatching(BMessenger target)
{
DBG(OUT("Database::StopWatching()\n"));
status_t err = fMonitorSet.find(target) != fMonitorSet.end() ? B_OK : B_ENTRY_NOT_FOUND;
if (!err)
fMonitorSet.erase(target);
return err;
}
status_t
Database::DeleteAppHint(const char *type)
{
status_t err = delete_attribute(type, kAppHintAttr);
if (!err)
err = SendMonitorUpdate(B_APP_HINT_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteAttrInfo(const char *type)
{
status_t err = delete_attribute(type, kAttrInfoAttr);
if (!err)
err = SendMonitorUpdate(B_ATTR_INFO_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteShortDescription(const char *type)
{
status_t err = delete_attribute(type, kShortDescriptionAttr);
if (!err)
err = SendMonitorUpdate(B_SHORT_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteLongDescription(const char *type)
{
status_t err = delete_attribute(type, kLongDescriptionAttr);
if (!err)
err = SendMonitorUpdate(B_LONG_DESCRIPTION_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteFileExtensions(const char *type)
{
status_t err = delete_attribute(type, kFileExtensionsAttr);
if (!err)
err = SendMonitorUpdate(B_FILE_EXTENSIONS_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteIcon(const char *type, icon_size which)
{
const char *attr = which == B_MINI_ICON ? kMiniIconAttr : kLargeIconAttr;
status_t err = delete_attribute(type, attr);
if (!err)
err = SendMonitorUpdate(B_ICON_CHANGED, type, which, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteIconForType(const char *type, const char *fileType, icon_size which)
{
std::string attr;
status_t err = fileType ? B_OK : B_BAD_VALUE;
if (!err) {
attr = (which == B_MINI_ICON ? kMiniIconAttrPrefix : kLargeIconAttrPrefix) + BPrivate::Storage::to_lower(fileType);
err = delete_attribute(type, attr.c_str());
}
if (!err)
err = SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType,
which == B_LARGE_ICON, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeletePreferredApp(const char *type, app_verb verb = B_OPEN)
{
status_t err;
switch (verb) {
case B_OPEN:
err = delete_attribute(type, kPreferredAppAttr);
break;
default:
err = B_BAD_VALUE;
break;
}
/*! \todo The R5 monitor makes no note of which app_verb value was updated. If
additional app_verb values besides \c B_OPEN are someday added, the format
of the MIME monitor messages will need to be augmented.
*/
if (!err)
err = SendMonitorUpdate(B_PREFERRED_APP_CHANGED, type, B_META_MIME_DELETED);
}
status_t
Database::DeleteSnifferRule(const char *type)
{
status_t err = delete_attribute(type, kSnifferRuleAttr);
if (!err)
err = SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::DeleteSupportedTypes(const char *type)
{
status_t err = delete_attribute(type, kSupportedTypesAttr);
if (!err)
err = SendMonitorUpdate(B_SUPPORTED_TYPES_CHANGED, type, B_META_MIME_DELETED);
return err;
}
status_t
Database::SendInstallNotification(const char *type)
{
// fInstalledTypes.AddType(type);
status_t err = SendMonitorUpdate(B_MIME_TYPE_CREATED, type, B_META_MIME_MODIFIED);
return err;
}
status_t
Database::SendDeleteNotification(const char *type)
{
// Tell the backend first
// fInstalledTypes.RemoveType(type);
status_t err = SendMonitorUpdate(B_MIME_TYPE_DELETED, type, B_META_MIME_MODIFIED);
return err;
}
// SendMonitorUpdate
/*! \brief Sends an update notification to all BMessengers that have
subscribed to the MIME Monitor service
\param type The MIME type that was updated
\param which Bitmask describing which attribute was updated
\param extraType The MIME type to which the change is applies
\param largeIcon \true if the the large icon was updated, \false if the
small icon was updated
*/
status_t
Database::SendMonitorUpdate(int32 which, const char *type, const char *extraType, bool largeIcon, int32 action) {
BMessage msg(B_META_MIME_CHANGED);
status_t err;
err = msg.AddInt32("be:which", which);
if (!err)
err = msg.AddString("be:type", type);
if (!err)
err = msg.AddString("be:extra_type", extraType);
if (!err)
err = msg.AddBool("be:large_icon", largeIcon);
if (!err)
err = msg.AddInt32("be:action", action);
if (!err)
err = SendMonitorUpdate(msg);
return err;
}
// SendMonitorUpdate
/*! \brief Sends an update notification to all BMessengers that have
subscribed to the MIME Monitor service
\param type The MIME type that was updated
\param which Bitmask describing which attribute was updated
\param extraType The MIME type to which the change is applies
*/
status_t
Database::SendMonitorUpdate(int32 which, const char *type, const char *extraType, int32 action) {
BMessage msg(B_META_MIME_CHANGED);
status_t err;
err = msg.AddInt32("be:which", which);
if (!err)
err = msg.AddString("be:type", type);
if (!err)
err = msg.AddString("be:extra_type", extraType);
if (!err)
err = msg.AddInt32("be:action", action);
if (!err)
err = SendMonitorUpdate(msg);
return err;
}
// SendMonitorUpdate
/*! \brief Sends an update notification to all BMessengers that have
subscribed to the MIME Monitor service
\param type The MIME type that was updated
\param which Bitmask describing which attribute was updated
\param largeIcon \true if the the large icon was updated, \false if the
small icon was updated
*/
status_t
Database::SendMonitorUpdate(int32 which, const char *type, bool largeIcon, int32 action) {
BMessage msg(B_META_MIME_CHANGED);
status_t err;
err = msg.AddInt32("be:which", which);
if (!err)
err = msg.AddString("be:type", type);
if (!err)
err = msg.AddBool("be:large_icon", largeIcon);
if (!err)
err = msg.AddInt32("be:action", action);
if (!err)
err = SendMonitorUpdate(msg);
return err;
}
// SendMonitorUpdate
/*! \brief Sends an update notification to all BMessengers that have
subscribed to the MIME Monitor service
\param type The MIME type that was updated
\param which Bitmask describing which attribute was updated
*/
status_t
Database::SendMonitorUpdate(int32 which, const char *type, int32 action) {
BMessage msg(B_META_MIME_CHANGED);
status_t err;
err = msg.AddInt32("be:which", which);
if (!err)
err = msg.AddString("be:type", type);
if (!err)
err = msg.AddInt32("be:action", action);
if (!err)
err = SendMonitorUpdate(msg);
return err;
}
// SendMonitorUpdate
/*! \brief Sends an update notification to all BMessengers that have subscribed to
the MIME Monitor service
\param BMessage A preformatted MIME monitor message to be sent to all subscribers
*/
status_t
Database::SendMonitorUpdate(BMessage &msg) {
DBG(OUT("Database::SendMonitorUpdate(BMessage&)\n"));
status_t err;
std::set<BMessenger>::const_iterator i;
for (i = fMonitorSet.begin(); i != fMonitorSet.end(); i++) {
status_t err = (*i).SendMessage(&msg, (BHandler*)NULL);
if (err)
DBG(OUT("Database::SendMonitorUpdate(BMessage&): BMessenger::SendMessage failed, %p\n", err));
}
DBG(OUT("Database::SendMonitorUpdate(BMessage&) done\n"));
err = B_OK;
return err;
}
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
+414
View File
@@ -0,0 +1,414 @@
// mime/InstalledTypes.cpp
#include "mime/InstalledTypes.h"
#include <Message.h>
#include <stdio.h>
#define DBG(x) x
//#define DBG(x)
#define OUT printf
namespace BPrivate {
namespace Storage {
namespace Mime {
InstalledTypes::InstalledTypes()
: fCachedMessage(NULL)
{
}
InstalledTypes::~InstalledTypes()
{
delete fCachedMessage;
}
/*
MimeDatabaseBackend::MimeDatabaseBackend()
: fCachedInstalledTypesMessage(NULL)
, fCachedInstalledSupertypesMessage(NULL)
{
}
MimeDatabaseBackend::~MimeDatabaseBackend()
{
delete fCachedInstalledTypesMessage;
delete fCachedInstalledSupertypesMessage;
}
status_t
MimeDatabaseBackend::GetInstalledTypes(BMessage *types)
{
DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(1)\n"));
status_t err = types ? B_OK : B_BAD_VALUE;
if (!err) {
if (!fCachedInstalledTypesMessage) {
if (fInstalledTypes.begin() == fInstalledTypes.end())
err = BuildInstalledTypesList(&fCachedInstalledTypesMessage);
else
err = BuildInstalledTypesMessage(&fCachedInstalledTypesMessage);
}
*types = *fCachedInstalledTypesMessage;
}
DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(1) done\n"));
return err;
}
status_t
MimeDatabaseBackend::GetInstalledTypes(const char *supertype, BMessage *types)
{
DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(2)\n"));
status_t err = supertype && types && BMimeType::IsValid(supertype) ? B_OK : B_BAD_VALUE;
// Types are not case sensitive, so we always use lowercase
char lowertype[B_PATH_NAME_LENGTH+1];
BPrivate::Storage::to_lower(supertype, lowertype);
installed_subtypes_info *info;
// See if we need to build the main list
if (!err && fSupertypesMap.empty())
err = BuildInstalledTypesList();
// See if the supertype even exists
if (!err) {
std::map<std::string, installed_subtypes_info>::iterator i = fSupertypesMap.find(supertype);
err = i != fSupertypesMap.end() ? B_OK : B_BAD_VALUE;
if (!err)
info = &(i->second);
}
// Make sure there's a cached message waiting for us
if (!err && !info->cached_message)
err = BuildInstalledTypesMessage(info->subtypes, &(info->cached_message));
// Copy the message into the result
if (!err)
*types = *info->cached_message;
DBG(OUT("MimeDatabaseBackend::GetInstalledTypes(2) done\n"));
return err;
}
status_t
MimeDatabaseBackend::GetInstalledSupertypes(BMessage *types)
{
DBG(OUT("MimeDatabaseBackend::GetInstalledSupertypes()\n"));
status_t err = types ? B_OK : B_BAD_VALUE;
// See if we need to build the main list
if (!err && fSupertypesMap.empty())
err = BuildInstalledTypesList();
// Make sure there's a cached message waiting for us
if (!err && !fCachedInstalledSupertypesMessage)
err = BuildInstalledSupertypesMessage(fSupertypesMap, &fCachedInstalledSupertypesMessage);
// Copy the message into the result
if (!err)
*types = *fCachedInstalledSupertypesMessage;
DBG(OUT("MimeDatabaseBackend::GetInstalledSupertypes() done\n"));
return err;
}
status_t
MimeDatabaseBackend::GetSupportingApps(const char *type, BMessage *signatures)
{
return B_ERROR; // not implemented
}
void
MimeDatabaseBackend::InstallType(const char *type)
{
DBG(OUT("MimeDatabaseBackend::InstallType()\n"));
if (fInstalledTypes.empty())
return;
// Remove any cached messages
if (fCachedInstalledTypesMessage) {
delete fCachedInstalledTypesMessage;
fCachedInstalledTypesMessage = NULL;
}
if (fCachedInstalledSupertypesMessage) {
delete fCachedInstalledSupertypesMessage;
fCachedInstalledSupertypesMessage = NULL;
}
char lowertype[B_PATH_NAME_LENGTH+1];
char supertype[B_PATH_NAME_LENGTH+1];
Storage::to_lower(type, lowertype);
fInstalledTypes.insert(lowertype);
BMimeType mime(lowertype);
BMimeType super;
status_t err = mime.InitCheck();
if (!err)
err = mime.GetSupertype(&super);
if (!err) {
Storage::to_lower(super.Type(), supertype);
installed_subtypes_info &info = fSupertypesMap[supertype];
delete info.cached_message;
info.cached_message = NULL;
info.subtypes.insert(lowertype);
}
DBG(OUT("MimeDatabaseBackend::InstallType() done\n"));
}
void
MimeDatabaseBackend::DeleteType(const char *type)
{
if (fInstalledTypes.empty())
return;
printf("fuCK\n");
// Remove any cached messages
if (fCachedInstalledTypesMessage) {
delete fCachedInstalledTypesMessage;
fCachedInstalledTypesMessage = NULL;
}
printf("fuCK\n");
if (fCachedInstalledSupertypesMessage) {
delete fCachedInstalledSupertypesMessage;
fCachedInstalledSupertypesMessage = NULL;
}
printf("fuCK\n");
char lowertype[B_PATH_NAME_LENGTH+1];
char supertype[B_PATH_NAME_LENGTH+1];
printf("fuCK\n");
Storage::to_lower(type, lowertype);
fInstalledTypes.erase(lowertype);
printf("fuCK\n");
BMimeType mime(lowertype);
BMimeType super;
printf("fuCK\n");
status_t err = mime.InitCheck();
printf("fuCK\n");
if (!err)
err = mime.GetSupertype(&super);
printf("fuCK\n");
if (!err) {
Storage::to_lower(super.Type(), supertype);
installed_subtypes_info &info = fSupertypesMap[supertype];
printf("fuCK\n");
delete info.cached_message;
printf("fuCK\n");
info.cached_message = NULL;
printf("fuCK\n");
info.subtypes.erase(lowertype);
}
printf("fuCK\n");
}
// BuildInstalledTypesList()
//! Builds an initial installed types list and (optionally) an installed types BMessage
status_t
MimeDatabaseBackend::BuildInstalledTypesList(BMessage **types)
{
BMessage *msg;
if (types) {
*types = new BMessage;
msg = *types;
} else
msg = NULL;
BDirectory root;
status_t err = root.SetTo(MimeDatabase::kDatabaseDir.c_str());
if (!err) {
root.Rewind();
while (true) {
BEntry entry;
err = root.GetNextEntry(&entry);
if (err) {
// If we've come to the end of list, it's not an error
if (err == B_ENTRY_NOT_FOUND)
err = B_OK;
break;
} else {
// Check that this entry is both a directory and a valid MIME string
char supertype[B_PATH_NAME_LENGTH+1];
if (entry.IsDirectory()
&& entry.GetName(supertype) == B_OK
&& BMimeType::IsValid(supertype))
{
// Make sure our string is all lowercase
BPrivate::Storage::to_lower(supertype);
// Add this supertype
fInstalledTypes.insert(supertype);
fSupertypesMap[supertype] = installed_subtypes_info();
installed_subtypes_info &info = fSupertypesMap[supertype];
if (msg)
msg->AddString("types", supertype);
// Now iterate through this supertype directory and add
// all of its subtypes
BDirectory dir;
if (dir.SetTo(&entry) == B_OK) {
dir.Rewind();
while (true) {
BEntry subEntry;
err = dir.GetNextEntry(&subEntry);
if (err) {
// If we've come to the end of list, it's not an error
if (err == B_ENTRY_NOT_FOUND)
err = B_OK;
break;
} else {
// Get the subtype's name
char subtype[B_PATH_NAME_LENGTH+1];
char mimetype[B_PATH_NAME_LENGTH+1];
if (subEntry.GetName(subtype) == B_OK) {
BPrivate::Storage::to_lower(subtype);
sprintf(mimetype, "%s/%s", supertype, subtype);
// Add the subtype
if (BMimeType::IsValid(mimetype)) {
fInstalledTypes.insert(mimetype);
info.subtypes.insert(mimetype);
if (msg)
msg->AddString("types", mimetype);
}
}
}
}
} else {
DBG(OUT("MimeDatabaseBackend::BuildInstalledTypesList(): "
"Failed opening supertype directory '%s'\n",
supertype));
}
}
}
}
} else {
DBG(OUT("MimeDatabaseBackend::BuildInstalledTypesList(): "
"Failed opening mime database directory '%s'\n",
MimeDatabase::kDatabaseDir.c_str()));
}
return err;
}
status_t
MimeDatabaseBackend::BuildInstalledTypesMessage(BMessage **result)
{
status_t err = result ? B_OK : B_BAD_VALUE;
// Alloc the message
if (!err) {
*result = new BMessage;
if (!(*result))
err = B_NO_MEMORY;
}
// Fill with types
if (!err) {
BMessage &msg = **result;
std::set<std::string>::const_iterator i;
for (i = fInstalledTypes.begin(); i != fInstalledTypes.end(); i++)
msg.AddString("types", (*i).c_str());
}
return err;
}
status_t
MimeDatabaseBackend::BuildInstalledTypesMessage(const std::set<std::string> &set, BMessage **result)
{
status_t err = result ? B_OK : B_BAD_VALUE;
// Alloc the message
if (!err) {
*result = new BMessage;
if (!(*result))
err = B_NO_MEMORY;
}
// Fill with types
if (!err) {
BMessage &msg = **result;
std::set<std::string>::const_iterator i;
for (i = set.begin(); i != set.end(); i++)
msg.AddString("types", (*i).c_str());
}
return err;
}
status_t
MimeDatabaseBackend::BuildInstalledSupertypesMessage(const std::map<std::string, installed_subtypes_info> &map, BMessage **result)
{
status_t err = result ? B_OK : B_BAD_VALUE;
// Alloc the message
if (!err) {
*result = new BMessage;
if (!(*result))
err = B_NO_MEMORY;
}
// Fill with types
if (!err) {
BMessage &msg = **result;
std::map<std::string, installed_subtypes_info>::const_iterator i;
for (i = map.begin(); i != map.end(); i++)
msg.AddString("super_types", (i->first).c_str());
}
return err;
}
status_t
MimeDatabaseBackend::BuildInstalledTypesList(const char *supertype, BMessage **types)
{
return B_ERROR;
// I'm not going to work on this function anymore until we
// get to optimization, as BuildInstalledTypesList(Bmessage**)
// handles this already (just not as efficiently if we only
// want to build the types for a single supertype). I have
// no idea if this function works, as I've never tried it.
BMessage *msg;
if (types) {
*types = new BMessage;
msg = *types;
} else
msg = NULL;
status_t err = supertype && BMimeType::IsValid(supertype) ? B_OK : B_BAD_VALUE;
// Check that this entry is both a directory and a valid MIME string
if (!err)
{
// Make sure our string is all lowercase
BPrivate::Storage::to_lower(supertype);
// Clear any previous subtype info struct
fSupertypesMap[supertype] = installed_subtypes_info();
installed_subtypes_info &info = fSupertypesMap[supertype];
// Iterate through the supertype directory and add
// all of its subtypes
BDirectory super;
if (super.SetTo((MimeDatabase::kDatabaseDir + supertype).c_str()) == B_OK) {
super.Rewind();
while (true) {
BEntry entry;
err = super.GetNextEntry(&entry);
if (err) {
// If we've come to the end of list, it's not an error
if (err == B_ENTRY_NOT_FOUND)
err = B_OK;
break;
} else {
// Get the subtype's name
char subtype[B_PATH_NAME_LENGTH+1];
char mimetype[B_PATH_NAME_LENGTH+1];
if (entry.GetName(subtype) == B_OK) {
BPrivate::Storage::to_lower(subtype);
sprintf(mimetype, "%s/%s", supertype, subtype);
// Add the subtype
if (BMimeType::IsValid(mimetype)) {
fInstalledTypes.insert(mimetype);
info.subtypes.insert(mimetype);
if (msg)
msg->AddString("types", mimetype);
}
}
}
}
} else {
DBG(OUT("MimeDatabaseBackend::BuildInstalledTypesList(): "
"Failed opening supertype directory '%s'\n",
supertype));
}
}
}
*/
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
+33
View File
@@ -0,0 +1,33 @@
// mime/Supertype.cpp
#include "mime/Supertype.h"
#include <Message.h>
#include <stdio.h>
#define DBG(x) x
//#define DBG(x)
#define OUT printf
namespace BPrivate {
namespace Storage {
namespace Mime {
Supertype::Supertype(const char *super)
: fCachedMessage(NULL)
, fType(super)
{
}
Supertype::~Supertype()
{
delete fCachedMessage;
}
} // namespace Mime
} // namespace Storage
} // namespace BPrivate
+425
View File
@@ -0,0 +1,425 @@
// mime/Database.cpp
#include <Bitmap.h>
#include <Entry.h>
#include <Message.h>
#include <mime/database_support.h>
#include <Node.h>
#include <Path.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>
#include "mime/database_access.h"
//#define DBG(x) x
#define DBG(x)
#define OUT printf
namespace BPrivate {
namespace Storage {
namespace Mime {
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
// get_app_hint
//! 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)
{
char path[B_MIME_TYPE_LENGTH+1];
BEntry entry;
ssize_t err = ref ? B_OK : B_BAD_VALUE;
if (!err)
err = read_mime_attr(type, kAppHintAttr, path, B_MIME_TYPE_LENGTH, kAppHintType);
if (err >= 0)
err = entry.SetTo(path);
if (!err)
err = entry.GetRef(ref);
return err;
}
// get_attr_info
/*! \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) {
info->what = 233; // Don't know why, but that's what R5 does.
err = info->AddString("type", type);
}
return err;
}
// get_short_description
//! 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+1 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+1 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 ;
}
// get_file_extensions
//! 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) {
extensions->what = 234; // Don't know why, but that's what R5 does.
err = extensions->AddString("type", type);
}
return err;
}
// get_icon
//! 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_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 type 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)
{
std::string attr;
attr_info info;
ssize_t err;
BNode node;
uint32 attrType;
size_t attrSize;
BRect bounds;
char *buffer;
err = type && icon ? B_OK : B_BAD_VALUE;
// Figure out what kind of data we *should* find
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
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;
if (!err)
err = open_type(type, &node);
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;
ssize_t read;
if (otherColorSpace) {
// other color space than stored in attribute
buffer = new(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) ? B_OK : B_FILE_ERROR;
if (otherColorSpace) {
if (!err) {
icon->SetBits(buffer, attrSize, 0, B_CMAP8);
err = icon->InitCheck();
}
delete[] buffer;
}
}
return err;
}
// get_preferred_app
//! 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+1 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 ;
}
// get_supported_types
status_t
get_supported_types(const char *type, BMessage *types)
{
status_t err = read_mime_attr_message(type, kSupportedTypesAttr, types);
if (!err) {
types->what = 0;
err = types->AddString("type", type);
}
return err;
}
// is_installed
//! 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;
}
// get_icon_data
/*! \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)
{
ssize_t err = (icon && data && dataSize && icon->InitCheck() == B_OK) ? B_OK : B_BAD_VALUE;
BRect bounds;
BBitmap *icon8 = NULL;
void *srcData = NULL;
bool otherColorSpace = false;
// Figure out what kind of data we *should* have
if (!err) {
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:
err = B_BAD_VALUE;
break;
}
}
// Check the icon
if (!err)
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(nothrow) BBitmap(bounds, B_CMAP8);
if (!icon8)
err = B_NO_MEMORY;
if (!err) {
switch (icon->ColorSpace()) {
case B_RGB32:
{
// Set each pixel individually, since SetBits() for B_RGB32 takes
// 24-bit rgb pixel data...
char *bgra = (char*)icon->Bits();
for (uint32 i = 0; i*4+3 < icon->BitsLength(); bgra += 4, i++) {
char rgb[3];
rgb[0] = bgra[2]; // red
rgb[1] = bgra[1]; // green
rgb[2] = bgra[0]; // blue
icon8->SetBits(rgb, 3, i, B_RGB32);
}
break;
}
case B_GRAY1:
{
icon8->SetBits(icon->Bits(), icon->BitsLength(), 0, B_GRAY1);
break;
}
default:
err = B_BAD_VALUE;
}
if (!err)
err = icon8->InitCheck(); // I don't think this is actually useful, even if SetBits() fails...
}
if (!err) {
srcData = icon8->Bits();
*dataSize = icon8->BitsLength();
}
} else {
srcData = icon->Bits();
*dataSize = icon->BitsLength();
}
}
// Alloc a new data buffer
if (!err) {
*data = new(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
+304
View File
@@ -0,0 +1,304 @@
// database_support.cpp
#include <DataIO.h>
#include <Directory.h>
#include <Entry.h>
#include <Message.h>
#include <Node.h>
#include <Path.h>
#include <storage_support.h>
#include <TypeConstants.h>
#include <fs_attr.h> // For struct attr_info
#include <new> // For new(nothrow)
#include <stdio.h>
#include <string>
#include "mime/database_support.h"
//#define DBG(x) x
#define DBG(x)
#define OUT printf
// icon types (which really ought to be publicly or semi-publicly declared somewhere...)
enum {
B_MINI_ICON_TYPE = 'MICN',
B_LARGE_ICON_TYPE = 'ICON',
};
namespace BPrivate {
namespace Storage {
namespace Mime {
//const char* MimeDatabase::kDefaultDatabaseDir = "/boot/home/config/settings/beos_mime";
const std::string kDatabaseDir = "/boot/home/config/settings/obos_mime";
#define ATTR_PREFIX "META:"
#define MINI_ICON_ATTR_PREFIX ATTR_PREFIX "M:"
#define LARGE_ICON_ATTR_PREFIX ATTR_PREFIX "L:"
const char *kMiniIconAttrPrefix = MINI_ICON_ATTR_PREFIX;
const char *kLargeIconAttrPrefix = LARGE_ICON_ATTR_PREFIX;
// attribute names
const char *kFileTypeAttr = "BEOS:TYPE";
const char *kTypeAttr = ATTR_PREFIX "TYPE";
const char *kAppHintAttr = ATTR_PREFIX "PPATH";
const char *kAttrInfoAttr = ATTR_PREFIX "ATTR_INFO";
const char *kShortDescriptionAttr = ATTR_PREFIX "S:DESC";
const char *kLongDescriptionAttr = ATTR_PREFIX "L:DESC";
const char *kFileExtensionsAttr = ATTR_PREFIX "EXTENS";
const char *kMiniIconAttr = MINI_ICON_ATTR_PREFIX "STD_ICON";
const char *kLargeIconAttr = LARGE_ICON_ATTR_PREFIX "STD_ICON";
const char *kPreferredAppAttr = ATTR_PREFIX "PREF_APP";
const char *kSnifferRuleAttr = ATTR_PREFIX "SNIFF_RULE";
const char *kSupportedTypesAttr = ATTR_PREFIX "FILE_TYPES";
// attribute data types (as used in the R5 database)
const int32 kFileTypeType = 'MIMS'; // B_MIME_STRING_TYPE
const int32 kTypeType = B_STRING_TYPE;
const int32 kAppHintType = 'MPTH';
const int32 kAttrInfoType = B_MESSAGE_TYPE;
const int32 kShortDescriptionType = 'MSDC';
const int32 kLongDescriptionType = 'MLDC';
const int32 kFileExtensionsType = B_MESSAGE_TYPE;
const int32 kMiniIconType = B_MINI_ICON_TYPE;
const int32 kLargeIconType = B_LARGE_ICON_TYPE;
const int32 kPreferredAppType = 'MSIG';
const int32 kSnifferRuleType = B_STRING_TYPE;
const int32 kSupportedTypesType = B_MESSAGE_TYPE;
// type_to_filename
//! Converts the given MIME type to an absolute path in the MIME database.
std::string
type_to_filename(const char *type)
{
return kDatabaseDir + "/" + BPrivate::Storage::to_lower(type);
}
// open_type
/*! \brief Opens a BNode on the given type, failing if the type has no
corresponding file in the database.
\param type The MIME type to open
\param result Pointer to a pre-allocated BNode into which
is opened on the given MIME type
*/
status_t
open_type(const char *type, BNode *result)
{
status_t err = (type && result ? B_OK : B_BAD_VALUE);
if (!err)
err = result->SetTo(type_to_filename(type).c_str());
return err;
}
// 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;
std::string filename;
std::string typeLower = BPrivate::Storage::to_lower(type);
status_t err = (type && result ? B_OK : B_BAD_VALUE);
if (!err) {
filename = type_to_filename(type);
err = result->SetTo(filename.c_str());
}
if (err == B_ENTRY_NOT_FOUND) {
// Figure out what type of node we need to create
// + Supertype == directory
// + Non-supertype == file
int32 pos = typeLower.find_first_of('/');
if (pos == std::string::npos) {
// Supertype == directory
BDirectory parent(kDatabaseDir.c_str());
err = parent.InitCheck();
if (!err)
err = parent.CreateDirectory(typeLower.c_str(), NULL);
} else {
// Non-supertype == file
std::string super(typeLower, 0, pos);
std::string sub(typeLower, pos+1);
BDirectory parent((kDatabaseDir + "/" + super).c_str());
err = parent.InitCheck();
if (!err)
err = parent.CreateFile(sub.c_str(), NULL);
}
// Now try opening again
err = result->SetTo(filename.c_str());
if (!err && didCreate)
*didCreate = true;
}
return err;
}
// read_mime_attr
/*! \brief Reads up to \c len bytes of the given data from the given attribute
for the given MIME type.
If no entry for the given type exists in the database, the function fails,
and the contents of \c data are undefined.
\param type The MIME type
\param attr The attribute name
\param data Pointer to a memory buffer into which the data should be copied
\param len The maximum number of bytes to read
\param datatype The expected data type
\return If successful, the number of bytes read is returned, otherwise, an
error code is returned.
*/
ssize_t
read_mime_attr(const char *type, const char *attr, void *data,
size_t len, type_code datatype)
{
BNode node;
ssize_t err = (type && attr && data ? B_OK : B_BAD_VALUE);
if (!err)
err = open_type(type, &node);
if (!err)
err = node.ReadAttr(attr, datatype, 0, data, len);
return err;
}
// read_mime_attr_message
/*! \brief Reads a flattened BMessage from the given attribute of the given
MIME type.
If no entry for the given type exists in the database, or if the data
stored in the attribute is not a flattened BMessage, the function fails
and the contents of \c msg are undefined.
\param type The MIME type
\param attr The attribute name
\param data Pointer to a pre-allocated BMessage into which the attribute
data is unflattened.
*/
status_t
read_mime_attr_message(const char *type, const char *attr, BMessage *msg)
{
BNode node;
attr_info info;
char *buffer = NULL;
ssize_t err = (type && attr && msg ? B_OK : B_BAD_VALUE);
if (!err)
err = open_type(type, &node);
if (!err)
err = node.GetAttrInfo(attr, &info);
if (!err)
err = info.type == B_MESSAGE_TYPE ? B_OK : B_BAD_VALUE;
if (!err) {
buffer = new(nothrow) char[info.size];
if (!buffer)
err = B_NO_MEMORY;
}
if (!err)
err = node.ReadAttr(attr, B_MESSAGE_TYPE, 0, buffer, info.size);
if (err >= 0)
err = err == info.size ? B_OK : B_FILE_ERROR;
if (!err)
err = msg->Unflatten(buffer);
delete [] buffer;
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 != len ? B_FILE_ERROR : 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 == data.BufferLength() ? B_OK : 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
} // namespace BPrivate
+65 -23
View File
@@ -23,7 +23,7 @@
*/
MIMEManager::MIMEManager()
: BLooper("main_mime")
, fMimeDatabase()
, fDatabase()
{
}
@@ -61,8 +61,8 @@ MIMEManager::MessageReceived(BMessage *message)
err = message->FindMessenger("target", &messenger);
if (!err) {
err = message->what == B_REG_MIME_START_WATCHING
? fMimeDatabase.StartWatching(messenger)
: fMimeDatabase.StopWatching(messenger);
? fDatabase.StartWatching(messenger)
: fDatabase.StopWatching(messenger);
}
reply.what = B_REG_RESULT;
@@ -78,13 +78,43 @@ MIMEManager::MessageReceived(BMessage *message)
err = message->FindString("type", &type);
if (!err)
err = message->what == B_REG_MIME_INSTALL
? fMimeDatabase.Install(type)
: fMimeDatabase.Delete(type);
? fDatabase.Install(type)
: fDatabase.Delete(type);
reply.what = B_REG_RESULT;
reply.AddInt32("result", err);
message->SendReply(&reply, this);
break;
}
case B_REG_MIME_GET_INSTALLED_TYPES:
{
BMessage types;
const char *supertype;
err = message->FindString("supertype", &supertype);
if (err == B_NAME_NOT_FOUND)
err = fDatabase.GetInstalledTypes(&types);
else if (!err)
err = fDatabase.GetInstalledTypes(supertype, &types);
reply.what = B_REG_RESULT;
reply.AddInt32("result", err);
reply.AddMessage("types", &types);
message->SendReply(&reply, this);
break;
}
case B_REG_MIME_GET_INSTALLED_SUPERTYPES:
{
BMessage types;
err = fDatabase.GetInstalledSupertypes(&types);
reply.what = B_REG_RESULT;
reply.AddInt32("result", err);
reply.AddMessage("types", &types);
message->SendReply(&reply, this);
break;
}
default:
printf("MIMEMan: msg->what == %.4s\n", &(message->what));
@@ -112,7 +142,7 @@ MIMEManager::HandleSetParam(BMessage *message)
entry_ref ref;
err = message->FindRef("app hint", &ref);
if (!err)
err = fMimeDatabase.SetAppHint(type, &ref);
err = fDatabase.SetAppHint(type, &ref);
break;
}
@@ -121,7 +151,7 @@ MIMEManager::HandleSetParam(BMessage *message)
BMessage info;
err = message->FindMessage("attr info", &info);
if (!err)
err = fMimeDatabase.SetAttrInfo(type, &info);
err = fDatabase.SetAttrInfo(type, &info);
break;
}
@@ -134,8 +164,8 @@ MIMEManager::HandleSetParam(BMessage *message)
err = message->FindString("description", &description);
if (!err)
err = (isLong
? fMimeDatabase.SetLongDescription(type, description)
: fMimeDatabase.SetShortDescription(type, description));
? fDatabase.SetLongDescription(type, description)
: fDatabase.SetShortDescription(type, description));
break;
}
@@ -144,11 +174,10 @@ MIMEManager::HandleSetParam(BMessage *message)
BMessage extensions;
err = message->FindMessage("extensions", &extensions);
if (!err)
err = fMimeDatabase.SetFileExtensions(type, &extensions);
err = fDatabase.SetFileExtensions(type, &extensions);
break;
}
case B_REG_MIME_ICON:
case B_REG_MIME_ICON_FOR_TYPE:
{
@@ -163,11 +192,11 @@ MIMEManager::HandleSetParam(BMessage *message)
if (!err)
err = message->FindString("file type", &fileType);
if (!err)
err = fMimeDatabase.SetIconForType(type, fileType, data,
err = fDatabase.SetIconForType(type, fileType, data,
dataSize, (icon_size)size);
} else {
if (!err)
err = fMimeDatabase.SetIcon(type, data, dataSize,
err = fDatabase.SetIcon(type, data, dataSize,
(icon_size)size);
}
break;
@@ -182,10 +211,19 @@ MIMEManager::HandleSetParam(BMessage *message)
if (!err)
err = message->FindInt32("app verb", &verb);
if (!err)
err = fMimeDatabase.SetPreferredApp(type, signature, (app_verb)verb);
err = fDatabase.SetPreferredApp(type, signature, (app_verb)verb);
break;
}
case B_REG_MIME_SUPPORTED_TYPES:
{
BMessage types;
err = message->FindMessage("types", &types);
if (!err)
err = fDatabase.SetSupportedTypes(type, &types);
break;
}
default:
err = B_BAD_VALUE;
break;
@@ -214,11 +252,11 @@ MIMEManager::HandleDeleteParam(BMessage *message)
if (!err) {
switch (which) {
case B_REG_MIME_APP_HINT:
err = fMimeDatabase.DeleteAppHint(type);
err = fDatabase.DeleteAppHint(type);
break;
case B_REG_MIME_ATTR_INFO:
err = fMimeDatabase.DeleteAttrInfo(type);
err = fDatabase.DeleteAttrInfo(type);
break;
case B_REG_MIME_DESCRIPTION:
@@ -227,13 +265,13 @@ MIMEManager::HandleDeleteParam(BMessage *message)
err = message->FindBool("long", &isLong);
if (!err)
err = isLong
? fMimeDatabase.DeleteLongDescription(type)
: fMimeDatabase.DeleteShortDescription(type);
? fDatabase.DeleteLongDescription(type)
: fDatabase.DeleteShortDescription(type);
break;
}
case B_REG_MIME_FILE_EXTENSIONS:
err = fMimeDatabase.DeleteFileExtensions(type);
err = fDatabase.DeleteFileExtensions(type);
break;
case B_REG_MIME_ICON:
@@ -246,10 +284,10 @@ MIMEManager::HandleDeleteParam(BMessage *message)
if (!err)
err = message->FindString("file type", &fileType);
if (!err)
err = fMimeDatabase.DeleteIconForType(type, fileType, (icon_size)size);
err = fDatabase.DeleteIconForType(type, fileType, (icon_size)size);
} else {
if (!err)
err = fMimeDatabase.DeleteIcon(type, (icon_size)size);
err = fDatabase.DeleteIcon(type, (icon_size)size);
}
break;
}
@@ -259,12 +297,16 @@ MIMEManager::HandleDeleteParam(BMessage *message)
int32 verb;
err = message->FindInt32("app verb", &verb);
if (!err)
err = fMimeDatabase.DeletePreferredApp(type, (app_verb)verb);
err = fDatabase.DeletePreferredApp(type, (app_verb)verb);
break;
}
case B_REG_MIME_SNIFFER_RULE:
err = fMimeDatabase.DeleteSnifferRule(type);
err = fDatabase.DeleteSnifferRule(type);
break;
case B_REG_MIME_SUPPORTED_TYPES:
err = fDatabase.DeleteSupportedTypes(type);
break;
default:
+2 -2
View File
@@ -4,7 +4,7 @@
#define MIME_MANAGER_H
#include <Looper.h>
#include <MimeDatabase.h>
#include <mime/Database.h>
class MIMEManager : public BLooper {
public:
@@ -16,7 +16,7 @@ private:
void HandleSetParam(BMessage *message);
void HandleDeleteParam(BMessage *message);
BPrivate::MimeDatabase fMimeDatabase;
BPrivate::Storage::Mime::Database fDatabase;
};
#endif // MIME_MANAGER_H