+ Added file-extension based mime type guessing
+ Added sniffer rule based mime type guessing + Added get_device_icon() + Added complete (synchronous, asynchronous; recursive, non-recursive; forcing, non-forcing; you name it we got it :-) update_mime_info() implementation. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1152 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -145,10 +145,10 @@ public:
|
|||||||
|
|
||||||
/* calls to ask the sniffer to identify the MIME type of a file or data in
|
/* calls to ask the sniffer to identify the MIME type of a file or data in
|
||||||
memory */
|
memory */
|
||||||
static status_t GuessMimeType(const entry_ref *file, BMimeType *result);
|
static status_t GuessMimeType(const entry_ref *file, BMimeType *type);
|
||||||
static status_t GuessMimeType(const void *buffer, int32 length,
|
static status_t GuessMimeType(const void *buffer, int32 length,
|
||||||
BMimeType *result);
|
BMimeType *type);
|
||||||
static status_t GuessMimeType(const char *filename, BMimeType *result);
|
static status_t GuessMimeType(const char *filename, BMimeType *type);
|
||||||
|
|
||||||
static status_t StartWatching(BMessenger target);
|
static status_t StartWatching(BMessenger target);
|
||||||
static status_t StopWatching(BMessenger target);
|
static status_t StopWatching(BMessenger target);
|
||||||
@@ -201,6 +201,9 @@ private:
|
|||||||
// status_t CloseFile() const;
|
// status_t CloseFile() const;
|
||||||
status_t GetSupportedTypes(BMessage *types);
|
status_t GetSupportedTypes(BMessage *types);
|
||||||
status_t SetSupportedTypes(const BMessage *types, bool fullSync = true);
|
status_t SetSupportedTypes(const BMessage *types, bool fullSync = true);
|
||||||
|
|
||||||
|
static status_t GetAssociatedTypes(const char *extension, BMessage *types);
|
||||||
|
|
||||||
// void MimeChanged(int32 w, const char *type = NULL,
|
// void MimeChanged(int32 w, const char *type = NULL,
|
||||||
// bool large = true) const;
|
// bool large = true) const;
|
||||||
|
|
||||||
|
|||||||
@@ -39,32 +39,37 @@ extern const char *kRAppLooperPortName;
|
|||||||
// message constants
|
// message constants
|
||||||
enum {
|
enum {
|
||||||
// replies
|
// replies
|
||||||
B_REG_SUCCESS = 'rgsu',
|
B_REG_SUCCESS = 'rgsu',
|
||||||
B_REG_ERROR = 'rger',
|
B_REG_ERROR = 'rger',
|
||||||
B_REG_RESULT = 'rgrz',
|
B_REG_RESULT = 'rgrz',
|
||||||
// general requests
|
// general requests
|
||||||
B_REG_GET_MIME_MESSENGER = 'rgmm',
|
B_REG_GET_MIME_MESSENGER = 'rgmm',
|
||||||
B_REG_GET_CLIPBOARD_MESSENGER = 'rgcm',
|
B_REG_GET_CLIPBOARD_MESSENGER = 'rgcm',
|
||||||
// roster requests
|
// roster requests
|
||||||
B_REG_ADD_APP = 'rgaa',
|
B_REG_ADD_APP = 'rgaa',
|
||||||
B_REG_COMPLETE_REGISTRATION = 'rgcr',
|
B_REG_COMPLETE_REGISTRATION = 'rgcr',
|
||||||
B_REG_IS_APP_PRE_REGISTERED = 'rgip',
|
B_REG_IS_APP_PRE_REGISTERED = 'rgip',
|
||||||
B_REG_REMOVE_PRE_REGISTERED_APP = 'rgrp',
|
B_REG_REMOVE_PRE_REGISTERED_APP = 'rgrp',
|
||||||
B_REG_REMOVE_APP = 'rgra',
|
B_REG_REMOVE_APP = 'rgra',
|
||||||
B_REG_SET_THREAD_AND_TEAM = 'rgtt',
|
B_REG_SET_THREAD_AND_TEAM = 'rgtt',
|
||||||
B_REG_GET_APP_INFO = 'rgai',
|
B_REG_GET_APP_INFO = 'rgai',
|
||||||
B_REG_GET_APP_LIST = 'rgal',
|
B_REG_GET_APP_LIST = 'rgal',
|
||||||
B_REG_ACTIVATE_APP = 'rgac',
|
B_REG_ACTIVATE_APP = 'rgac',
|
||||||
// MIME requests
|
// MIME requests
|
||||||
B_REG_MIME_SET_PARAM = 'rgsp',
|
B_REG_MIME_SET_PARAM = 'rgsp',
|
||||||
B_REG_MIME_DELETE_PARAM = 'rgdp',
|
B_REG_MIME_DELETE_PARAM = 'rgdp',
|
||||||
B_REG_MIME_START_WATCHING = 'rgwb',
|
B_REG_MIME_START_WATCHING = 'rgwb',
|
||||||
B_REG_MIME_STOP_WATCHING = 'rgwe',
|
B_REG_MIME_STOP_WATCHING = 'rgwe',
|
||||||
B_REG_MIME_INSTALL = 'rgin',
|
B_REG_MIME_INSTALL = 'rgin',
|
||||||
B_REG_MIME_DELETE = 'rgdl',
|
B_REG_MIME_DELETE = 'rgdl',
|
||||||
B_REG_MIME_GET_INSTALLED_TYPES = 'rgit',
|
B_REG_MIME_GET_INSTALLED_TYPES = 'rgit',
|
||||||
B_REG_MIME_GET_INSTALLED_SUPERTYPES = 'rgis',
|
B_REG_MIME_GET_INSTALLED_SUPERTYPES = 'rgis',
|
||||||
B_REG_MIME_GET_SUPPORTING_APPS = 'rgsa',
|
B_REG_MIME_GET_SUPPORTING_APPS = 'rgsa',
|
||||||
|
B_REG_MIME_GET_ASSOCIATED_TYPES = 'rgat',
|
||||||
|
B_REG_MIME_SNIFF = 'rgsn',
|
||||||
|
B_REG_MIME_UPDATE_MIME_INFO_ASYNC = 'rgup',
|
||||||
|
B_REG_MIME_CREATE_APP_META_MIME_ASYNC = 'rgca',
|
||||||
|
B_REG_MIME_ASYNC_THREAD_FINISHED = 'rgtf',
|
||||||
};
|
};
|
||||||
|
|
||||||
// B_REG_MIME_SET_PARAM "which" constants
|
// B_REG_MIME_SET_PARAM "which" constants
|
||||||
|
|||||||
@@ -10,9 +10,12 @@
|
|||||||
#ifndef _MIME_DATABASE_H
|
#ifndef _MIME_DATABASE_H
|
||||||
#define _MIME_DATABASE_H
|
#define _MIME_DATABASE_H
|
||||||
|
|
||||||
#include <mime/InstalledTypes.h>
|
|
||||||
#include <mime/SupportingApps.h>
|
|
||||||
#include <Mime.h>
|
#include <Mime.h>
|
||||||
|
#include <mime/AssociatedTypes.h>
|
||||||
|
#include <mime/InstalledTypes.h>
|
||||||
|
#include <mime/SnifferRules.h>
|
||||||
|
#include <mime/SupportingApps.h>
|
||||||
|
#include <mime/database_access.h>
|
||||||
#include <Messenger.h>
|
#include <Messenger.h>
|
||||||
#include <StorageDefs.h>
|
#include <StorageDefs.h>
|
||||||
|
|
||||||
@@ -23,6 +26,9 @@
|
|||||||
class BNode;
|
class BNode;
|
||||||
class BBitmap;
|
class BBitmap;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
|
class BString;
|
||||||
|
|
||||||
|
struct entry_ref;
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
@@ -58,13 +64,12 @@ public:
|
|||||||
status_t GetInstalledTypes(const char *super_type,
|
status_t GetInstalledTypes(const char *super_type,
|
||||||
BMessage *subtypes);
|
BMessage *subtypes);
|
||||||
status_t GetSupportingApps(const char *type, BMessage *signatures);
|
status_t GetSupportingApps(const char *type, BMessage *signatures);
|
||||||
|
status_t GetAssociatedTypes(const char *extension, BMessage *types);
|
||||||
|
|
||||||
// Sniffer
|
// Sniffer
|
||||||
// static status_t CheckSnifferRule(const char *rule, BString *parseError);
|
status_t GuessMimeType(const entry_ref *file, BString *result);
|
||||||
// static status_t GuessMimeType(const entry_ref *file, BMimeType *result);
|
status_t GuessMimeType(const void *buffer, int32 length, BString *result);
|
||||||
// static status_t GuessMimeType(const void *buffer, int32 length,
|
status_t GuessMimeType(const char *filename, BString *result);
|
||||||
// BMimeType *result);
|
|
||||||
// static status_t GuessMimeType(const char *filename, BMimeType *result);
|
|
||||||
|
|
||||||
// Monitor
|
// Monitor
|
||||||
status_t StartWatching(BMessenger target);
|
status_t StartWatching(BMessenger target);
|
||||||
@@ -82,10 +87,14 @@ public:
|
|||||||
status_t DeleteSnifferRule(const char *type);
|
status_t DeleteSnifferRule(const char *type);
|
||||||
status_t DeleteSupportedTypes(const char *type, bool fullSync);
|
status_t DeleteSupportedTypes(const char *type, bool fullSync);
|
||||||
|
|
||||||
|
// Asynchronous C function calls
|
||||||
|
status_t UpdateMimeInfoAsync(const entry_ref *ref, bool recursive, bool force);
|
||||||
|
status_t CleanupAfterAsyncThread(thread_id id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Functions to send monitor notifications
|
||||||
status_t SendInstallNotification(const char *type);
|
status_t SendInstallNotification(const char *type);
|
||||||
status_t SendDeleteNotification(const char *type);
|
status_t SendDeleteNotification(const char *type);
|
||||||
|
|
||||||
status_t SendMonitorUpdate(int32 which, const char *type, const char *extraType,
|
status_t SendMonitorUpdate(int32 which, const char *type, const char *extraType,
|
||||||
bool largeIcon, int32 action);
|
bool largeIcon, int32 action);
|
||||||
status_t SendMonitorUpdate(int32 which, const char *type, const char *extraType,
|
status_t SendMonitorUpdate(int32 which, const char *type, const char *extraType,
|
||||||
@@ -96,10 +105,16 @@ private:
|
|||||||
int32 action);
|
int32 action);
|
||||||
status_t SendMonitorUpdate(BMessage &msg);
|
status_t SendMonitorUpdate(BMessage &msg);
|
||||||
|
|
||||||
|
// Entry point functions for asynchronous update threads
|
||||||
|
static int32 UpdateMimeInfoAsyncEntry(void *data);
|
||||||
|
|
||||||
status_t fCStatus;
|
status_t fCStatus;
|
||||||
std::set<BMessenger> fMonitorMessengers;
|
std::set<BMessenger> fMonitorMessengers;
|
||||||
|
AssociatedTypes fAssociatedTypes;
|
||||||
InstalledTypes fInstalledTypes;
|
InstalledTypes fInstalledTypes;
|
||||||
|
SnifferRules fSnifferRules;
|
||||||
SupportingApps fSupportingApps;
|
SupportingApps fSupportingApps;
|
||||||
|
std::list<async_thread_data*> fAsyncThreads;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Mime
|
} // namespace Mime
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
/*!
|
/*!
|
||||||
\file database_access.h
|
\file database_access.h
|
||||||
Mime database atomic read function declarations
|
Mime database atomic read functions and miscellany declarations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MIME_DATABASE_ACCESS_H
|
#ifndef _MIME_DATABASE_ACCESS_H
|
||||||
@@ -39,6 +39,22 @@ bool is_installed(const char *type);
|
|||||||
// to be shipped off to SetIcon*() and written to the database
|
// 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 get_icon_data(const BBitmap *icon, icon_size size, void **data, int32 *dataSize);
|
||||||
|
|
||||||
|
// Common struct used to manage ansynchronous update threads
|
||||||
|
struct async_thread_data {
|
||||||
|
public:
|
||||||
|
async_thread_data(thread_id id = -1);
|
||||||
|
bool should_exit() const;
|
||||||
|
void post_exit_notification();
|
||||||
|
|
||||||
|
thread_id id;
|
||||||
|
private:
|
||||||
|
bool _should_exit;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Called by directly (synchronous calls) and indirectly (asynchronous calls)
|
||||||
|
// by update_mime_info()
|
||||||
|
int update_mime_info(entry_ref *ref, bool recursive, bool force, async_thread_data *data = NULL);
|
||||||
|
|
||||||
} // namespace Mime
|
} // namespace Mime
|
||||||
} // namespace Storage
|
} // namespace Storage
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -59,11 +59,20 @@ extern const int32 kSupportedTypesType;
|
|||||||
|
|
||||||
// Message fields
|
// Message fields
|
||||||
extern const char *kApplicationsField;
|
extern const char *kApplicationsField;
|
||||||
|
extern const char *kExtensionsField;
|
||||||
extern const char *kSupertypesField;
|
extern const char *kSupertypesField;
|
||||||
extern const char *kSupportingAppsSubCountField;
|
extern const char *kSupportingAppsSubCountField;
|
||||||
extern const char *kSupportingAppsSuperCountField;
|
extern const char *kSupportingAppsSuperCountField;
|
||||||
extern const char *kTypesField;
|
extern const char *kTypesField;
|
||||||
|
|
||||||
|
// Mime types
|
||||||
|
extern const char *kGenericFileType;
|
||||||
|
extern const char *kDirectoryType;
|
||||||
|
extern const char *kSymlinkType;
|
||||||
|
|
||||||
|
// Error codes (to be used only by BPrivate::Storage::Mime members)
|
||||||
|
extern const status_t kMimeGuessFailureError;
|
||||||
|
|
||||||
std::string type_to_filename(const char *type);
|
std::string type_to_filename(const char *type);
|
||||||
|
|
||||||
status_t open_type(const char *type, BNode *result);
|
status_t open_type(const char *type, BNode *result);
|
||||||
@@ -72,6 +81,7 @@ 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,
|
ssize_t read_mime_attr(const char *type, const char *attr, void *data,
|
||||||
size_t len, type_code datatype);
|
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_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,
|
status_t write_mime_attr(const char *type, const char *attr, const void *data,
|
||||||
size_t len, type_code datatype, bool *didCreate);
|
size_t len, type_code datatype, bool *didCreate);
|
||||||
status_t write_mime_attr_message(const char *type, const char *attr,
|
status_t write_mime_attr_message(const char *type, const char *attr,
|
||||||
|
|||||||
+100
-5
@@ -7,14 +7,25 @@
|
|||||||
Mime type C functions implementation.
|
Mime type C functions implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fs_attr.h>
|
||||||
|
#include <fs_info.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <Entry.h>
|
||||||
#include <Mime.h>
|
#include <Mime.h>
|
||||||
|
#include <MimeType.h>
|
||||||
|
#include <mime/database_access.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <RegistrarDefs.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NOT_IMPLEMENTED = B_ERROR,
|
NOT_IMPLEMENTED = B_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
// update_mime_info
|
// update_mime_info
|
||||||
/*! \brief Updates the MIME information for one or more files.
|
/*! \brief Updates the MIME information (i.e MIME type) for one or more files.
|
||||||
If \a path points to a file, the MIME information for this file are
|
If \a path points to a file, the MIME information for this file are
|
||||||
updated only. If it points to a directory and \a recursive is non-null,
|
updated only. If it points to a directory and \a recursive is non-null,
|
||||||
the information for all the files in the given directory tree are updated.
|
the information for all the files in the given directory tree are updated.
|
||||||
@@ -34,7 +45,43 @@ enum {
|
|||||||
int
|
int
|
||||||
update_mime_info(const char *path, int recursive, int synchronous, int force)
|
update_mime_info(const char *path, int recursive, int synchronous, int force)
|
||||||
{
|
{
|
||||||
return NOT_IMPLEMENTED;
|
BEntry root;
|
||||||
|
entry_ref ref;
|
||||||
|
if (!path)
|
||||||
|
recursive = true;
|
||||||
|
|
||||||
|
status_t err = root.SetTo(path ? path : "/");
|
||||||
|
if (!err)
|
||||||
|
err = root.GetRef(&ref);
|
||||||
|
if (!err) {
|
||||||
|
// If the call is to be synchronous, handle it locally,
|
||||||
|
// otherwise pass it off to the registrar
|
||||||
|
if (synchronous) {
|
||||||
|
err = BPrivate::Storage::Mime::update_mime_info(&ref, recursive, force);
|
||||||
|
} else {
|
||||||
|
BMessage msg(B_REG_MIME_UPDATE_MIME_INFO_ASYNC);
|
||||||
|
BMessage reply;
|
||||||
|
status_t result;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
// Build and send the message, read the reply
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddRef("entry", &ref);
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddBool("recursive", recursive);
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddBool("force", force);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create_app_meta_mime
|
// create_app_meta_mime
|
||||||
@@ -64,8 +111,14 @@ create_app_meta_mime(const char *path, int recursive, int synchronous,
|
|||||||
/*! Retrieves an icon associated with a given device.
|
/*! Retrieves an icon associated with a given device.
|
||||||
\param dev The path to the device.
|
\param dev The path to the device.
|
||||||
\param icon A pointer to a buffer the icon data shall be written to.
|
\param icon A pointer to a buffer the icon data shall be written to.
|
||||||
\param size The size of the icon. Currently the sizes 16 (small) and
|
\param size The size of the icon. Currently the sizes 16 (small, i.e
|
||||||
32 (large) are supported.
|
\c B_MINI_ICON) and 32 (large, i.e. \c B_LARGE_ICON) are
|
||||||
|
supported.
|
||||||
|
|
||||||
|
\todo The mounted directories for volumes can also have META:X:STD_ICON
|
||||||
|
attributes. Should those attributes override the icon returned
|
||||||
|
by ioctl(,B_GET_ICON,)?
|
||||||
|
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Everything went fine.
|
- \c B_OK: Everything went fine.
|
||||||
- An error code otherwise.
|
- An error code otherwise.
|
||||||
@@ -73,9 +126,51 @@ create_app_meta_mime(const char *path, int recursive, int synchronous,
|
|||||||
status_t
|
status_t
|
||||||
get_device_icon(const char *dev, void *icon, int32 size)
|
get_device_icon(const char *dev, void *icon, int32 size)
|
||||||
{
|
{
|
||||||
return NOT_IMPLEMENTED;
|
status_t err = dev && icon
|
||||||
|
&& (size == B_LARGE_ICON || size == B_MINI_ICON)
|
||||||
|
? B_OK : B_BAD_VALUE;
|
||||||
|
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
if (!err) {
|
||||||
|
fd = open(dev, O_RDONLY);
|
||||||
|
err = fd != -1 ? B_OK : B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
if (!err) {
|
||||||
|
device_icon iconData = { size, icon };
|
||||||
|
err = ioctl(fd, B_GET_ICON, &iconData);
|
||||||
|
}
|
||||||
|
if (fd != -1) {
|
||||||
|
// If the file descriptor was open()ed, we need to close it
|
||||||
|
// regardless. Only if we haven't yet encountered any errors
|
||||||
|
// do we make note close()'s return value, however.
|
||||||
|
status_t error = close(fd);
|
||||||
|
if (!err)
|
||||||
|
err = error;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+137
-32
@@ -305,7 +305,7 @@ BMimeType::Contains(const BMimeType *type) const
|
|||||||
|
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::Install()
|
BMimeType::Install()
|
||||||
@@ -341,7 +341,7 @@ BMimeType::Install()
|
|||||||
|
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::Delete()
|
BMimeType::Delete()
|
||||||
@@ -379,7 +379,7 @@ BMimeType::Delete()
|
|||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type
|
- \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
@@ -409,7 +409,7 @@ BMimeType::GetIcon(BBitmap *icon, icon_size size) const
|
|||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- \c B_ENTRY_NOT_FOUND: No preferred app exists for the given type and app_verb
|
- \c B_ENTRY_NOT_FOUND: No preferred app exists for the given type and app_verb
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetPreferredApp(char *signature, app_verb verb) const
|
BMimeType::GetPreferredApp(char *signature, app_verb verb) const
|
||||||
@@ -468,7 +468,7 @@ BMimeType::GetPreferredApp(char *signature, app_verb verb) const
|
|||||||
the MIME type's associated file attributes is stored.
|
the MIME type's associated file attributes is stored.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetAttrInfo(BMessage *info) const
|
BMimeType::GetAttrInfo(BMessage *info) const
|
||||||
@@ -505,7 +505,7 @@ BMimeType::GetAttrInfo(BMessage *info) const
|
|||||||
MIME type's associated file extensions will be stored.
|
MIME type's associated file extensions will be stored.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetFileExtensions(BMessage *extensions) const
|
BMimeType::GetFileExtensions(BMessage *extensions) const
|
||||||
@@ -527,7 +527,7 @@ BMimeType::GetFileExtensions(BMessage *extensions) const
|
|||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- \c B_ENTRY_NOT_FOUND: No short description exists for the given type
|
- \c B_ENTRY_NOT_FOUND: No short description exists for the given type
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetShortDescription(char *description) const
|
BMimeType::GetShortDescription(char *description) const
|
||||||
@@ -549,7 +549,7 @@ BMimeType::GetShortDescription(char *description) const
|
|||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- \c B_ENTRY_NOT_FOUND: No long description exists for the given type
|
- \c B_ENTRY_NOT_FOUND: No long description exists for the given type
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetLongDescription(char *description) const
|
BMimeType::GetLongDescription(char *description) const
|
||||||
@@ -612,7 +612,7 @@ BMimeType::GetLongDescription(char *description) const
|
|||||||
of the supporting applications will be copied.
|
of the supporting applications will be copied.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetSupportingApps(BMessage *signatures) const
|
BMimeType::GetSupportingApps(BMessage *signatures) const
|
||||||
@@ -655,7 +655,7 @@ BMimeType::GetSupportingApps(BMessage *signatures) const
|
|||||||
and \c B_MINI_ICON are supported.
|
and \c B_MINI_ICON are supported.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
@@ -682,7 +682,7 @@ BMimeType::SetIcon(const BBitmap *icon, icon_size which)
|
|||||||
Currently, the only supported app verb is \c B_OPEN.
|
Currently, the only supported app verb is \c B_OPEN.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::SetPreferredApp(const char *signature, app_verb verb)
|
BMimeType::SetPreferredApp(const char *signature, app_verb verb)
|
||||||
@@ -760,7 +760,7 @@ BMimeType::SetPreferredApp(const char *signature, app_verb verb)
|
|||||||
MIME type.
|
MIME type.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::SetAttrInfo(const BMessage *info)
|
BMimeType::SetAttrInfo(const BMessage *info)
|
||||||
@@ -817,7 +817,7 @@ BMimeType::SetAttrInfo(const BMessage *info)
|
|||||||
the new list of file extensions to associate with this MIME type.
|
the new list of file extensions to associate with this MIME type.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::SetFileExtensions(const BMessage *extensions)
|
BMimeType::SetFileExtensions(const BMessage *extensions)
|
||||||
@@ -857,7 +857,7 @@ BMimeType::SetFileExtensions(const BMessage *extensions)
|
|||||||
\param description Pointer to a pre-allocated string containing the new short description
|
\param description Pointer to a pre-allocated string containing the new short description
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::SetShortDescription(const char *description)
|
BMimeType::SetShortDescription(const char *description)
|
||||||
@@ -899,7 +899,7 @@ BMimeType::SetShortDescription(const char *description)
|
|||||||
\param description Pointer to a pre-allocated string containing the new long description
|
\param description Pointer to a pre-allocated string containing the new long description
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::SetLongDescription(const char *description)
|
BMimeType::SetLongDescription(const char *description)
|
||||||
@@ -941,7 +941,7 @@ BMimeType::SetLongDescription(const char *description)
|
|||||||
MIME supertypes will be copied.
|
MIME supertypes will be copied.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetInstalledSupertypes(BMessage *supertypes)
|
BMimeType::GetInstalledSupertypes(BMessage *supertypes)
|
||||||
@@ -977,7 +977,7 @@ BMimeType::GetInstalledSupertypes(BMessage *supertypes)
|
|||||||
MIME types will be copied.
|
MIME types will be copied.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetInstalledTypes(BMessage *types)
|
BMimeType::GetInstalledTypes(BMessage *types)
|
||||||
@@ -998,7 +998,7 @@ BMimeType::GetInstalledTypes(BMessage *types)
|
|||||||
MIME subtypes will be copied.
|
MIME subtypes will be copied.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetInstalledTypes(const char *supertype, BMessage *types)
|
BMimeType::GetInstalledTypes(const char *supertype, BMessage *types)
|
||||||
@@ -1039,7 +1039,7 @@ BMimeType::GetInstalledTypes(const char *supertype, BMessage *types)
|
|||||||
applications supporting files of any type are copied.
|
applications supporting files of any type are copied.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetWildcardApps(BMessage *wild_ones)
|
BMimeType::GetWildcardApps(BMessage *wild_ones)
|
||||||
@@ -1117,7 +1117,7 @@ bool isValidMimeChar(const char ch)
|
|||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- \c B_ENTRY_NOT_FOUND: No app hint exists for the given type
|
- \c B_ENTRY_NOT_FOUND: No app hint exists for the given type
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GetAppHint(entry_ref *ref) const
|
BMimeType::GetAppHint(entry_ref *ref) const
|
||||||
@@ -1144,7 +1144,7 @@ BMimeType::GetAppHint(entry_ref *ref) const
|
|||||||
\param ref Pointer to a pre-allocated \c entry_ref containting the location of the new app hint
|
\param ref Pointer to a pre-allocated \c entry_ref containting the location of the new app hint
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::SetAppHint(const entry_ref *ref)
|
BMimeType::SetAppHint(const entry_ref *ref)
|
||||||
@@ -1199,7 +1199,7 @@ BMimeType::SetAppHint(const entry_ref *ref)
|
|||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type
|
- \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
@@ -1244,7 +1244,7 @@ BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) cons
|
|||||||
and \c B_MINI_ICON are supported.
|
and \c B_MINI_ICON are supported.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Success
|
- \c B_OK: Success
|
||||||
- "error code": Failure
|
- other error code: Failure
|
||||||
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
@@ -1453,7 +1453,7 @@ BMimeType::CheckSnifferRule(const char *rule, BString *parseError)
|
|||||||
"application/octet-stream", the filename is examined for extensions.
|
"application/octet-stream", the filename is examined for extensions.
|
||||||
|
|
||||||
\param ref Pointer to the entry_ref referring to the entry.
|
\param ref Pointer to the entry_ref referring to the entry.
|
||||||
\param result Pointer to a pre-allocated BMimeType which is set to the
|
\param type Pointer to a pre-allocated BMimeType which is set to the
|
||||||
resulting MIME type.
|
resulting MIME type.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Everything went fine.
|
- \c B_OK: Everything went fine.
|
||||||
@@ -1461,25 +1461,69 @@ BMimeType::CheckSnifferRule(const char *rule, BString *parseError)
|
|||||||
- \c B_NAME_NOT_FOUND: \a ref refers to an abstract entry.
|
- \c B_NAME_NOT_FOUND: \a ref refers to an abstract entry.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GuessMimeType(const entry_ref *file, BMimeType *result)
|
BMimeType::GuessMimeType(const entry_ref *file, BMimeType *type)
|
||||||
{
|
{
|
||||||
return NOT_IMPLEMENTED;
|
status_t err = file && type ? B_OK : B_BAD_VALUE;
|
||||||
|
|
||||||
|
BMessage msg(B_REG_MIME_SNIFF);
|
||||||
|
BMessage reply;
|
||||||
|
status_t result;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
// Build and send the message, read the reply
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddRef("file ref", file);
|
||||||
|
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.FindString("mime type", &str);
|
||||||
|
if (!err)
|
||||||
|
err = type->SetTo(str);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuessMimeType
|
// GuessMimeType
|
||||||
/*! \brief Guesses a MIME type for the supplied chunk of data.
|
/*! \brief Guesses a MIME type for the supplied chunk of data.
|
||||||
\param buffer Pointer to the data buffer.
|
\param buffer Pointer to the data buffer.
|
||||||
\param length Size of the buffer in bytes.
|
\param length Size of the buffer in bytes.
|
||||||
\param result Pointer to a pre-allocated BMimeType which is set to the
|
\param type Pointer to a pre-allocated BMimeType which is set to the
|
||||||
resulting MIME type.
|
resulting MIME type.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Everything went fine.
|
- \c B_OK: Everything went fine.
|
||||||
- \c B_BAD_VALUE: \c NULL \a buffer or \a result.
|
- \c B_BAD_VALUE: \c NULL \a buffer or \a result.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GuessMimeType(const void *buffer, int32 length, BMimeType *result)
|
BMimeType::GuessMimeType(const void *buffer, int32 length, BMimeType *type)
|
||||||
{
|
{
|
||||||
return NOT_IMPLEMENTED;
|
status_t err = buffer && type ? B_OK : B_BAD_VALUE;
|
||||||
|
|
||||||
|
BMessage msg(B_REG_MIME_SNIFF);
|
||||||
|
BMessage reply;
|
||||||
|
status_t result;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
// Build and send the message, read the reply
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddData("data", B_RAW_TYPE, buffer, length);
|
||||||
|
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.FindString("mime type", &str);
|
||||||
|
if (!err)
|
||||||
|
err = type->SetTo(str);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuessMimeType
|
// GuessMimeType
|
||||||
@@ -1489,16 +1533,38 @@ BMimeType::GuessMimeType(const void *buffer, int32 length, BMimeType *result)
|
|||||||
doesn't need to exist at all.
|
doesn't need to exist at all.
|
||||||
|
|
||||||
\param filename The filename.
|
\param filename The filename.
|
||||||
\param result Pointer to a pre-allocated BMimeType which is set to the
|
\param type Pointer to a pre-allocated BMimeType which is set to the
|
||||||
resulting MIME type.
|
resulting MIME type.
|
||||||
\return
|
\return
|
||||||
- \c B_OK: Everything went fine.
|
- \c B_OK: Everything went fine.
|
||||||
- \c B_BAD_VALUE: \c NULL \a ref or \a result.
|
- \c B_BAD_VALUE: \c NULL \a ref or \a result.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
BMimeType::GuessMimeType(const char *filename, BMimeType *result)
|
BMimeType::GuessMimeType(const char *filename, BMimeType *type)
|
||||||
{
|
{
|
||||||
return NOT_IMPLEMENTED;
|
status_t err = filename && type ? B_OK : B_BAD_VALUE;
|
||||||
|
|
||||||
|
BMessage msg(B_REG_MIME_SNIFF);
|
||||||
|
BMessage reply;
|
||||||
|
status_t result;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
// Build and send the message, read the reply
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddString("filename", filename);
|
||||||
|
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.FindString("mime type", &str);
|
||||||
|
if (!err)
|
||||||
|
err = type->SetTo(str);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartWatching
|
// StartWatching
|
||||||
@@ -1740,6 +1806,45 @@ BMimeType::SetSupportedTypes(const BMessage *types, bool fullSync)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAssociatedTypes
|
||||||
|
/*! \brief Returns a list of mime types associated with the given file extension
|
||||||
|
|
||||||
|
The list of types is returned in the pre-allocated \c BMessage pointed to
|
||||||
|
by \a types. The types are stored in the message's "types" field, which
|
||||||
|
is an array of \c B_STRING_TYPE values.
|
||||||
|
|
||||||
|
\param extension The file extension of interest
|
||||||
|
\param types Pointer to a pre-allocated BMessage into which the result will
|
||||||
|
be stored
|
||||||
|
|
||||||
|
\return
|
||||||
|
- \c B_OK: success
|
||||||
|
- other error code: failure
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
BMimeType::GetAssociatedTypes(const char *extension, BMessage *types)
|
||||||
|
{
|
||||||
|
status_t err = extension && types ? B_OK : B_BAD_VALUE;
|
||||||
|
|
||||||
|
BMessage msg(B_REG_MIME_GET_ASSOCIATED_TYPES);
|
||||||
|
BMessage &reply = *types;
|
||||||
|
status_t result;
|
||||||
|
|
||||||
|
// Build and send the message, read the reply
|
||||||
|
if (!err)
|
||||||
|
err = msg.AddString("extension", extension);
|
||||||
|
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
|
// Returns a lowercase version of str in result. Result must
|
||||||
// be preallocated and is assumed to be of adequate length.
|
// be preallocated and is assumed to be of adequate length.
|
||||||
status_t
|
status_t
|
||||||
|
|||||||
@@ -12,12 +12,14 @@
|
|||||||
#include <DataIO.h>
|
#include <DataIO.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
#include <Locker.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <mime/database_access.h>
|
#include <mime/database_access.h>
|
||||||
#include <mime/database_support.h>
|
#include <mime/database_support.h>
|
||||||
#include <MimeType.h>
|
#include <MimeType.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
#include <String.h>
|
||||||
#include <storage_support.h>
|
#include <storage_support.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
@@ -43,6 +45,28 @@ namespace BPrivate {
|
|||||||
namespace Storage {
|
namespace Storage {
|
||||||
namespace Mime {
|
namespace Mime {
|
||||||
|
|
||||||
|
// update_mime_info_async_params
|
||||||
|
/*! \brief All the neccessary data for managing an asynchronous update_mime_info()
|
||||||
|
call bundled into a single struct.
|
||||||
|
*/
|
||||||
|
struct update_mime_info_async_data : public async_thread_data {
|
||||||
|
public:
|
||||||
|
entry_ref ref;
|
||||||
|
bool recursive;
|
||||||
|
bool force;
|
||||||
|
|
||||||
|
update_mime_info_async_data(const entry_ref *ref, bool recursive, bool force)
|
||||||
|
: async_thread_data()
|
||||||
|
, ref(ref ? *ref : entry_ref())
|
||||||
|
, recursive(recursive)
|
||||||
|
, force(force)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
update_mime_info_async_data();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class Database
|
\class Database
|
||||||
\brief Mime::Database is the master of the MIME data base.
|
\brief Mime::Database is the master of the MIME data base.
|
||||||
@@ -67,9 +91,28 @@ Database::Database()
|
|||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
/*! \brief Frees all resources associated with this object.
|
/*! \brief Frees all resources associated with this object.
|
||||||
|
|
||||||
|
Any currently running asynchronous update threads are instructed
|
||||||
|
to politely exit and then waited on.
|
||||||
*/
|
*/
|
||||||
Database::~Database()
|
Database::~Database()
|
||||||
{
|
{
|
||||||
|
std::list<async_thread_data*>::iterator i;
|
||||||
|
DBG(OUT("Asking async threads to quit...\n"));
|
||||||
|
for (i = fAsyncThreads.begin();
|
||||||
|
i != fAsyncThreads.end();
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
DBG(OUT(" id == %ld\n", (*i)->id));
|
||||||
|
(*i)->post_exit_notification();
|
||||||
|
}
|
||||||
|
for (i = fAsyncThreads.begin();
|
||||||
|
i != fAsyncThreads.end();
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
status_t exitValue;
|
||||||
|
wait_for_thread((*i)->id, &exitValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitCheck
|
// InitCheck
|
||||||
@@ -396,8 +439,6 @@ Database::SetPreferredApp(const char *type, const char *signature, app_verb verb
|
|||||||
|
|
||||||
// SetSnifferRule
|
// SetSnifferRule
|
||||||
/*! \brief Sets the mime sniffer rule for the given mime type
|
/*! \brief Sets the mime sniffer rule for the given mime type
|
||||||
|
|
||||||
\todo This ought to trigger an update to the sniffer rule manager whenever we write one
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Database::SetSnifferRule(const char *type, const char *rule)
|
Database::SetSnifferRule(const char *type, const char *rule)
|
||||||
@@ -408,6 +449,8 @@ Database::SetSnifferRule(const char *type, const char *rule)
|
|||||||
if (!err)
|
if (!err)
|
||||||
err = write_mime_attr(type, kSnifferRuleAttr, rule, strlen(rule)+1,
|
err = write_mime_attr(type, kSnifferRuleAttr, rule, strlen(rule)+1,
|
||||||
kSnifferRuleType, &didCreate);
|
kSnifferRuleType, &didCreate);
|
||||||
|
if (!err)
|
||||||
|
err = fSnifferRules.SetSnifferRule(type, rule);
|
||||||
if (!err && didCreate)
|
if (!err && didCreate)
|
||||||
err = SendInstallNotification(type);
|
err = SendInstallNotification(type);
|
||||||
if (!err)
|
if (!err)
|
||||||
@@ -532,6 +575,101 @@ Database::GetSupportingApps(const char *type, BMessage *signatures)
|
|||||||
return fSupportingApps.GetSupportingApps(type, signatures);
|
return fSupportingApps.GetSupportingApps(type, signatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAssociatedTypes
|
||||||
|
/*! \brief Returns a list of mime types associated with the given file extension
|
||||||
|
|
||||||
|
Please see BMimeType::GetAssociatedTypes() for more details.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Database::GetAssociatedTypes(const char *extension, BMessage *types)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GuessMimeType
|
||||||
|
/*! \brief Guesses a MIME type for the entry referred to by the given
|
||||||
|
\c entry_ref.
|
||||||
|
|
||||||
|
This version of GuessMimeType() combines the features of the other
|
||||||
|
versions: First the data of the given file are checked (sniffed).
|
||||||
|
If sniffing fails, the filename is examined for extensions. If this
|
||||||
|
fails, the "application/octet-stream" is returned.
|
||||||
|
|
||||||
|
\param ref Pointer to the entry_ref referring to the entry.
|
||||||
|
\param type Pointer to a pre-allocated BString which is set to the
|
||||||
|
resulting MIME type.
|
||||||
|
\return
|
||||||
|
- \c B_OK: success (even if the guess returned is "application/octet-stream")
|
||||||
|
- other error code: failure
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Database::GuessMimeType(const entry_ref *file, BString *result)
|
||||||
|
{
|
||||||
|
status_t err = file && result ? B_OK : B_BAD_VALUE;
|
||||||
|
if (!err)
|
||||||
|
err = fSnifferRules.GuessMimeType(file, result);
|
||||||
|
if (err == kMimeGuessFailureError)
|
||||||
|
err = fAssociatedTypes.GuessMimeType(file, result);
|
||||||
|
if (err == kMimeGuessFailureError) {
|
||||||
|
result->SetTo(kGenericFileType);
|
||||||
|
err = B_OK;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GuessMimeType
|
||||||
|
/*! \brief Guesses a MIME type for the supplied chunk of data.
|
||||||
|
|
||||||
|
See \c SnifferRules::GuessMimeType(BPositionIO*, BString*)
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
\param buffer Pointer to the data buffer.
|
||||||
|
\param length Size of the buffer in bytes.
|
||||||
|
\param type Pointer to a pre-allocated BString which is set to the
|
||||||
|
resulting MIME type.
|
||||||
|
\return
|
||||||
|
- \c B_OK: success
|
||||||
|
- error code: failure
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Database::GuessMimeType(const void *buffer, int32 length, BString *result)
|
||||||
|
{
|
||||||
|
status_t err = buffer && result ? B_OK : B_BAD_VALUE;
|
||||||
|
if (!err)
|
||||||
|
err = fSnifferRules.GuessMimeType(buffer, length, result);
|
||||||
|
if (err == kMimeGuessFailureError) {
|
||||||
|
result->SetTo(kGenericFileType);
|
||||||
|
err = B_OK;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GuessMimeType
|
||||||
|
/*! \brief Guesses a MIME type for the given filename.
|
||||||
|
|
||||||
|
Only the filename itself is taken into consideration (in particular its
|
||||||
|
name extension), not the entry or corresponding data it refers to (in fact,
|
||||||
|
an entry with that name need not exist at all.
|
||||||
|
|
||||||
|
\param filename The filename.
|
||||||
|
\param type Pointer to a pre-allocated BString which is set to the
|
||||||
|
resulting MIME type.
|
||||||
|
\return
|
||||||
|
- \c B_OK: success
|
||||||
|
- error code: failure
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Database::GuessMimeType(const char *filename, BString *result)
|
||||||
|
{
|
||||||
|
status_t err = filename && result ? B_OK : B_BAD_VALUE;
|
||||||
|
if (!err)
|
||||||
|
err = fAssociatedTypes.GuessMimeType(filename, result);
|
||||||
|
if (err == kMimeGuessFailureError) {
|
||||||
|
result->SetTo(kGenericFileType);
|
||||||
|
err = B_OK;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// StartWatching
|
// StartWatching
|
||||||
//! Subscribes the given BMessenger to the MIME monitor service
|
//! Subscribes the given BMessenger to the MIME monitor service
|
||||||
@@ -826,6 +964,8 @@ status_t
|
|||||||
Database::DeleteSnifferRule(const char *type)
|
Database::DeleteSnifferRule(const char *type)
|
||||||
{
|
{
|
||||||
status_t err = delete_attribute(type, kSnifferRuleAttr);
|
status_t err = delete_attribute(type, kSnifferRuleAttr);
|
||||||
|
if (!err)
|
||||||
|
err = fSnifferRules.DeleteSnifferRule(type);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type, B_META_MIME_DELETED);
|
err = SendMonitorUpdate(B_SNIFFER_RULE_CHANGED, type, B_META_MIME_DELETED);
|
||||||
return err;
|
return err;
|
||||||
@@ -865,6 +1005,62 @@ Database::DeleteSupportedTypes(const char *type, bool fullSync)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateMimeInfoAsync
|
||||||
|
/*! \brief Performs the corresponding update_mime_info() call asynchronously (i.e
|
||||||
|
in a new thread).
|
||||||
|
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Database::UpdateMimeInfoAsync(const entry_ref *ref, bool recursive, bool force)
|
||||||
|
{
|
||||||
|
thread_id id = -1;
|
||||||
|
status_t err;
|
||||||
|
update_mime_info_async_data *data;
|
||||||
|
|
||||||
|
data = new(nothrow) update_mime_info_async_data(ref, recursive, force);
|
||||||
|
err = data ? B_OK : B_NO_MEMORY;
|
||||||
|
// Spawn the thread
|
||||||
|
if (!err) {
|
||||||
|
id = spawn_thread(&Database::UpdateMimeInfoAsyncEntry, "mime updater (umi)",
|
||||||
|
B_NORMAL_PRIORITY, (void*)data);
|
||||||
|
err = id >= 0 ? B_OK : id;
|
||||||
|
}
|
||||||
|
// Update the thread_id, store the thread info, and get it running
|
||||||
|
if (!err) {
|
||||||
|
data->id = id;
|
||||||
|
fAsyncThreads.push_back(data);
|
||||||
|
err = resume_thread(id);
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
DBG(OUT("spawned new update_mime_info() thread, id == %ld\n", id));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanupAfterAsyncThread
|
||||||
|
/*! \brief Removes the given thread from the list of currently running asynchronous
|
||||||
|
threads and frees its associated shared \c async_thread_data object.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
Database::CleanupAfterAsyncThread(thread_id id)
|
||||||
|
{
|
||||||
|
status_t err = B_ENTRY_NOT_FOUND;
|
||||||
|
std::list<async_thread_data*>::iterator i;
|
||||||
|
for (i = fAsyncThreads.begin(); i != fAsyncThreads.end(); i++) {
|
||||||
|
if (*i) {
|
||||||
|
if ((*i)->id == id) {
|
||||||
|
delete *i;
|
||||||
|
fAsyncThreads.erase(i);
|
||||||
|
err = B_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
OUT("WARNING: NULL async_thread_data pointer found in Mime::Database::fAsyncThreads list\n");
|
||||||
|
fAsyncThreads.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// SendInstallNotification
|
// SendInstallNotification
|
||||||
//! \brief Sends a \c B_MIME_TYPE_CREATED notification to the mime monitor service
|
//! \brief Sends a \c B_MIME_TYPE_CREATED notification to the mime monitor service
|
||||||
status_t
|
status_t
|
||||||
@@ -875,6 +1071,8 @@ Database::SendInstallNotification(const char *type)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendDeleteNotification
|
||||||
|
//! \brief Sends a \c B_MIME_TYPE_DELETED notification to the mime monitor service
|
||||||
status_t
|
status_t
|
||||||
//! \brief Sends a \c B_MIME_TYPE_DELETED notification to the mime monitor service
|
//! \brief Sends a \c B_MIME_TYPE_DELETED notification to the mime monitor service
|
||||||
Database::SendDeleteNotification(const char *type)
|
Database::SendDeleteNotification(const char *type)
|
||||||
@@ -990,19 +1188,29 @@ Database::SendMonitorUpdate(int32 which, const char *type, int32 action) {
|
|||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Database::SendMonitorUpdate(BMessage &msg) {
|
Database::SendMonitorUpdate(BMessage &msg) {
|
||||||
DBG(OUT("Database::SendMonitorUpdate(BMessage&)\n"));
|
// DBG(OUT("Database::SendMonitorUpdate(BMessage&)\n"));
|
||||||
status_t err;
|
status_t err;
|
||||||
std::set<BMessenger>::const_iterator i;
|
std::set<BMessenger>::const_iterator i;
|
||||||
for (i = fMonitorMessengers.begin(); i != fMonitorMessengers.end(); i++) {
|
for (i = fMonitorMessengers.begin(); i != fMonitorMessengers.end(); i++) {
|
||||||
status_t err = (*i).SendMessage(&msg, (BHandler*)NULL);
|
status_t err = (*i).SendMessage(&msg, (BHandler*)NULL);
|
||||||
if (err)
|
if (err)
|
||||||
DBG(OUT("Database::SendMonitorUpdate(BMessage&): BMessenger::SendMessage failed, %p\n", err));
|
DBG(OUT("Database::SendMonitorUpdate(BMessage&): BMessenger::SendMessage failed, 0x%lx\n", err));
|
||||||
}
|
}
|
||||||
DBG(OUT("Database::SendMonitorUpdate(BMessage&) done\n"));
|
// DBG(OUT("Database::SendMonitorUpdate(BMessage&) done\n"));
|
||||||
err = B_OK;
|
err = B_OK;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateMimeInfoAsyncEntry(void *data)
|
||||||
|
/*! \brief Entry point for asynchronous update_mime_info() threads
|
||||||
|
*/
|
||||||
|
int32
|
||||||
|
Database::UpdateMimeInfoAsyncEntry(void *data)
|
||||||
|
{
|
||||||
|
update_mime_info_async_data *info = (update_mime_info_async_data*)data;
|
||||||
|
return update_mime_info(&(info->ref), info->recursive, info->force, info);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Mime
|
} // namespace Mime
|
||||||
} // namespace Storage
|
} // namespace Storage
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -9,10 +9,12 @@
|
|||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
|
#include <Directory.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <mime/database_support.h>
|
#include <mime/database_support.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
#include <RegistrarDefs.h>
|
||||||
#include <storage_support.h>
|
#include <storage_support.h>
|
||||||
|
|
||||||
#include <fs_attr.h> // For struct attr_info
|
#include <fs_attr.h> // For struct attr_info
|
||||||
@@ -23,8 +25,8 @@
|
|||||||
|
|
||||||
#include "mime/database_access.h"
|
#include "mime/database_access.h"
|
||||||
|
|
||||||
//#define DBG(x) x
|
#define DBG(x) x
|
||||||
#define DBG(x)
|
//#define DBG(x)
|
||||||
#define OUT printf
|
#define OUT printf
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
@@ -320,13 +322,7 @@ get_preferred_app(const char *type, char *signature, app_verb verb = B_OPEN)
|
|||||||
status_t
|
status_t
|
||||||
get_sniffer_rule(const char *type, BString *result)
|
get_sniffer_rule(const char *type, BString *result)
|
||||||
{
|
{
|
||||||
BNode node;
|
return read_mime_attr_string(type, kSnifferRuleAttr, result);
|
||||||
status_t err = result ? B_OK : B_BAD_VALUE;
|
|
||||||
if (!err)
|
|
||||||
err = open_type(type, &node);
|
|
||||||
if (!err)
|
|
||||||
err = node.ReadAttrString(kSnifferRuleAttr, result);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_supported_types
|
// get_supported_types
|
||||||
@@ -421,6 +417,138 @@ get_icon_data(const BBitmap *icon, icon_size which, void **data, int32 *dataSize
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \struct async_thread_data
|
||||||
|
\brief A thread id and functions to allow threads to be safely told
|
||||||
|
when they need to politely quit what they're doing and exit.
|
||||||
|
|
||||||
|
As only the \c Mime::Database class will be posting exit notifications,
|
||||||
|
and as interested threads will only be calling \c should_exit() on their
|
||||||
|
respective \c async_thread_data objects, there currently is no synchronization
|
||||||
|
implemented with respect to accessing the \c thead_data::thread_should_exit
|
||||||
|
member. If this is a problem, a \c BLocker may be added and locking calls
|
||||||
|
placed in \c should_exit() and \c post_exit_notification().
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! Creates a new \c async_thread_data object
|
||||||
|
async_thread_data::async_thread_data(thread_id id)
|
||||||
|
: id(id)
|
||||||
|
, _should_exit(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Returns \c true if the thread should politely exit as soon as
|
||||||
|
possible, or \c false if it may continue running normally.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
async_thread_data::should_exit() const {
|
||||||
|
return _should_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief All subsequent calls to should_exit() will return \c true.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
async_thread_data::post_exit_notification() {
|
||||||
|
_should_exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_mime_info
|
||||||
|
/*! \brief Updates the MIME information (i.e MIME type) for one or more files.
|
||||||
|
|
||||||
|
If \a path points to a file, the MIME information for this file are
|
||||||
|
updated only. If it points to a directory and \a recursive is non-null,
|
||||||
|
the information for all the files in the given directory tree are updated.
|
||||||
|
|
||||||
|
\param ref An entry_ref to a file or directory. May not be NULL.
|
||||||
|
\param recursive \c true to trigger recursive behavior.
|
||||||
|
\param force If \c true, file information is updated even if said
|
||||||
|
information already exists.
|
||||||
|
\return
|
||||||
|
- \c B_OK: success
|
||||||
|
- error code: failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
update_mime_info(entry_ref *ref, bool recursive, bool force, async_thread_data *data)
|
||||||
|
{
|
||||||
|
// using BPrivate::Storage::Mime::kFileTypeAttr;
|
||||||
|
|
||||||
|
status_t err = ref ? B_OK : B_BAD_VALUE;
|
||||||
|
|
||||||
|
BNode node;
|
||||||
|
bool doUpdate = false;
|
||||||
|
|
||||||
|
// Figure out if we need to update or not
|
||||||
|
if (!err)
|
||||||
|
err = node.SetTo(ref);
|
||||||
|
if (!err) {
|
||||||
|
if (force)
|
||||||
|
doUpdate = true;
|
||||||
|
else {
|
||||||
|
attr_info info;
|
||||||
|
if (!err)
|
||||||
|
doUpdate = node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update *this* node if necessary
|
||||||
|
if (!err && doUpdate) {
|
||||||
|
BMimeType type;
|
||||||
|
err = BMimeType::GuessMimeType(ref, &type);
|
||||||
|
if (!err && type.InitCheck() == B_OK) {
|
||||||
|
const char *typeStr = type.Type();
|
||||||
|
ssize_t len = strlen(typeStr)+1;
|
||||||
|
ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, typeStr, len);
|
||||||
|
if (bytes < B_OK)
|
||||||
|
err = bytes;
|
||||||
|
else
|
||||||
|
err = (bytes != len ? B_FILE_ERROR : B_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we're recursing and this is a directory, update each of the directory's
|
||||||
|
// children as well
|
||||||
|
if (!err && recursive && node.IsDirectory()) {
|
||||||
|
node.Unset(); // Unset() to free a file descriptor, as we no longer need our BNode
|
||||||
|
BDirectory dir;
|
||||||
|
|
||||||
|
err = dir.SetTo(ref);
|
||||||
|
if (!err) {
|
||||||
|
entry_ref childRef;
|
||||||
|
while (!err) {
|
||||||
|
err = dir.GetNextRef(&childRef);
|
||||||
|
if (err) {
|
||||||
|
// If we've come to the end of the directory listing,
|
||||||
|
// it's not an error.
|
||||||
|
if (err == B_ENTRY_NOT_FOUND)
|
||||||
|
err = B_OK;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
err = update_mime_info(&childRef, true, force);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we're running asynchronously, notify the database manager that
|
||||||
|
// our thread is finished with its task so the manager call free our
|
||||||
|
// associated data and remove us from the list of running threads.
|
||||||
|
if (data) {
|
||||||
|
BMessage msg(B_REG_MIME_ASYNC_THREAD_FINISHED);
|
||||||
|
status_t result;
|
||||||
|
status_t error = msg.AddInt32("thread id", data->id);
|
||||||
|
if (!error)
|
||||||
|
error = _send_to_roster_(&msg, &msg, true);
|
||||||
|
if (!error)
|
||||||
|
error = msg.what = B_REG_RESULT ? B_OK : B_BAD_VALUE;
|
||||||
|
if (!error)
|
||||||
|
error = msg.FindInt32("result", &result);
|
||||||
|
if (!error)
|
||||||
|
error = result;
|
||||||
|
if (error)
|
||||||
|
OUT("WARNING: async update_mime_info() thread failed termination notification with error 0x%lx\n", error);
|
||||||
|
DBG(OUT("(id: %ld) exiting async update_mime_info() thread with result 0x%lx\n", find_thread(NULL), err));
|
||||||
|
}
|
||||||
|
if (data)
|
||||||
|
snooze(9000000);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Mime
|
} // namespace Mime
|
||||||
} // namespace Storage
|
} // namespace Storage
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -78,11 +78,20 @@ const int32 kSupportedTypesType = B_MESSAGE_TYPE;
|
|||||||
|
|
||||||
// Message fields
|
// Message fields
|
||||||
const char *kApplicationsField = "applications";
|
const char *kApplicationsField = "applications";
|
||||||
|
const char *kExtensionsField = "extensions";
|
||||||
const char *kSupertypesField = "super_types";
|
const char *kSupertypesField = "super_types";
|
||||||
const char *kSupportingAppsSubCountField = "be:sub";
|
const char *kSupportingAppsSubCountField = "be:sub";
|
||||||
const char *kSupportingAppsSuperCountField = "be:super";
|
const char *kSupportingAppsSuperCountField = "be:super";
|
||||||
const char *kTypesField = "types";
|
const char *kTypesField = "types";
|
||||||
|
|
||||||
|
// Mime types
|
||||||
|
const char *kGenericFileType = "application/octet-stream";
|
||||||
|
const char *kDirectoryType = "application/x-vnd.Be-directory";
|
||||||
|
const char *kSymlinkType = "application/x-vnd.Be-symlink";
|
||||||
|
|
||||||
|
// Error codes
|
||||||
|
const status_t kMimeGuessFailureError = B_ERRORS_END+1;
|
||||||
|
|
||||||
// type_to_filename
|
// type_to_filename
|
||||||
//! Converts the given MIME type to an absolute path in the MIME database.
|
//! Converts the given MIME type to an absolute path in the MIME database.
|
||||||
std::string
|
std::string
|
||||||
@@ -225,6 +234,30 @@ read_mime_attr_message(const char *type, const char *attr, BMessage *msg)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read_mime_attr_string
|
||||||
|
/*! \brief Reads a BString from the given attribute of the given
|
||||||
|
MIME type.
|
||||||
|
|
||||||
|
If no entry for the given type exists in the database, the function fails
|
||||||
|
and the contents of \c str are undefined.
|
||||||
|
|
||||||
|
\param type The MIME type
|
||||||
|
\param attr The attribute name
|
||||||
|
\param str Pointer to a pre-allocated BString into which the attribute
|
||||||
|
data stored.
|
||||||
|
*/
|
||||||
|
ssize_t
|
||||||
|
read_mime_attr_string(const char *type, const char *attr, BString *str)
|
||||||
|
{
|
||||||
|
BNode node;
|
||||||
|
ssize_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
|
// write_mime_attr
|
||||||
/*! \brief Writes \c len bytes of the given data to the given attribute
|
/*! \brief Writes \c len bytes of the given data to the given attribute
|
||||||
for the given MIME type.
|
for the given MIME type.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <ClassInfo.h>
|
#include <ClassInfo.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <RegistrarDefs.h>
|
#include <RegistrarDefs.h>
|
||||||
|
#include <String.h>
|
||||||
#include <TypeConstants.h>
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -114,7 +115,6 @@ MIMEManager::MessageReceived(BMessage *message)
|
|||||||
|
|
||||||
case B_REG_MIME_GET_SUPPORTING_APPS:
|
case B_REG_MIME_GET_SUPPORTING_APPS:
|
||||||
{
|
{
|
||||||
BMessage reply;
|
|
||||||
const char *type;
|
const char *type;
|
||||||
err = message->FindString("type", &type);
|
err = message->FindString("type", &type);
|
||||||
if (!err)
|
if (!err)
|
||||||
@@ -126,6 +126,77 @@ MIMEManager::MessageReceived(BMessage *message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case B_REG_MIME_GET_ASSOCIATED_TYPES:
|
||||||
|
{
|
||||||
|
const char *extension;
|
||||||
|
err = message->FindString("extension", &extension);
|
||||||
|
if (!err)
|
||||||
|
err = fDatabase.GetAssociatedTypes(extension, &reply);
|
||||||
|
|
||||||
|
reply.what = B_REG_RESULT;
|
||||||
|
reply.AddInt32("result", err);
|
||||||
|
message->SendReply(&reply, this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_REG_MIME_SNIFF:
|
||||||
|
{
|
||||||
|
BString str;
|
||||||
|
entry_ref ref;
|
||||||
|
const char *filename;
|
||||||
|
err = message->FindString("filename", &filename);
|
||||||
|
if (!err)
|
||||||
|
err = fDatabase.GuessMimeType(filename, &str);
|
||||||
|
else if (err == B_NAME_NOT_FOUND) {
|
||||||
|
err = message->FindRef("file ref", &ref);
|
||||||
|
if (!err)
|
||||||
|
err = fDatabase.GuessMimeType(&ref, &str);
|
||||||
|
else if (err == B_NAME_NOT_FOUND) {
|
||||||
|
// err = message->FindData("file ref", &ref);
|
||||||
|
// if (!err)
|
||||||
|
// err = fDatabase.GuessMimeType(data, length, &str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
err = reply.AddString("mime type", str);
|
||||||
|
|
||||||
|
reply.what = B_REG_RESULT;
|
||||||
|
reply.AddInt32("result", err);
|
||||||
|
message->SendReply(&reply, this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_REG_MIME_UPDATE_MIME_INFO_ASYNC:
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
bool recursive, force;
|
||||||
|
err = message->FindRef("entry", &ref);
|
||||||
|
if (!err)
|
||||||
|
err = message->FindBool("recursive", &recursive);
|
||||||
|
if (!err)
|
||||||
|
err = message->FindBool("force", &force);
|
||||||
|
if (!err)
|
||||||
|
err = fDatabase.UpdateMimeInfoAsync(&ref, recursive, force);
|
||||||
|
|
||||||
|
reply.what = B_REG_RESULT;
|
||||||
|
reply.AddInt32("result", err);
|
||||||
|
message->SendReply(&reply, this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_REG_MIME_ASYNC_THREAD_FINISHED:
|
||||||
|
{
|
||||||
|
thread_id id;
|
||||||
|
err = message->FindInt32("thread id", &id);
|
||||||
|
if (!err)
|
||||||
|
err = fDatabase.CleanupAfterAsyncThread(id);
|
||||||
|
|
||||||
|
reply.what = B_REG_RESULT;
|
||||||
|
reply.AddInt32("result", err);
|
||||||
|
message->SendReply(&reply, this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("MIMEMan: msg->what == %.4s\n", (char*)&(message->what));
|
printf("MIMEMan: msg->what == %.4s\n", (char*)&(message->what));
|
||||||
BLooper::MessageReceived(message);
|
BLooper::MessageReceived(message);
|
||||||
|
|||||||
@@ -3545,7 +3545,6 @@ MimeTypeTest::UpdateMimeInfoTest()
|
|||||||
// * Updating all files is not tested as it takes too long.
|
// * Updating all files is not tested as it takes too long.
|
||||||
|
|
||||||
// individual files
|
// individual files
|
||||||
NextSubTest();
|
|
||||||
execCommand(string("mkdir ") + testDir + "/subdir1 "
|
execCommand(string("mkdir ") + testDir + "/subdir1 "
|
||||||
+ testDir + "/subdir2 "
|
+ testDir + "/subdir2 "
|
||||||
+ testDir + "/subdir2/subsubdir1");
|
+ testDir + "/subdir2/subsubdir1");
|
||||||
@@ -3556,7 +3555,9 @@ MimeTypeTest::UpdateMimeInfoTest()
|
|||||||
"text/html", "<html>\n<body>\n</body></html>\n")
|
"text/html", "<html>\n<body>\n</body></html>\n")
|
||||||
};
|
};
|
||||||
int fileCount = sizeof(files) / sizeof(MimeInfoTestFile);
|
int fileCount = sizeof(files) / sizeof(MimeInfoTestFile);
|
||||||
|
// synchronous
|
||||||
for (int32 i = 0; i < fileCount; i++) {
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
|
NextSubTest();
|
||||||
MimeInfoTestFile &file = files[i];
|
MimeInfoTestFile &file = files[i];
|
||||||
// no recursion
|
// no recursion
|
||||||
CHK(file.Create() == B_OK);
|
CHK(file.Create() == B_OK);
|
||||||
@@ -3579,16 +3580,49 @@ MimeTypeTest::UpdateMimeInfoTest()
|
|||||||
CHK(file.Delete() == B_OK);
|
CHK(file.Delete() == B_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Asynchronous calls
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const bigtime_t kSnoozeTime = 500000;
|
||||||
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
|
NextSubTest();
|
||||||
|
MimeInfoTestFile &file = files[i];
|
||||||
|
// no recursion
|
||||||
|
CHK(file.Create() == B_OK);
|
||||||
|
CHK(update_mime_info(file.name.c_str(), false, false, false) == B_OK);
|
||||||
|
// give the system some time to do the update asynchronously
|
||||||
|
snooze(kSnoozeTime);
|
||||||
|
BNode node(file.name.c_str());
|
||||||
|
CHK(node.InitCheck() == B_OK);
|
||||||
|
BString type;
|
||||||
|
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
|
||||||
|
node.Unset();
|
||||||
|
CHK(type == file.type.c_str());
|
||||||
|
CHK(file.Delete() == B_OK);
|
||||||
|
// recursion
|
||||||
|
CHK(file.Create() == B_OK);
|
||||||
|
CHK(update_mime_info(file.name.c_str(), true, false, false) == B_OK);
|
||||||
|
// give the system some time to do the update asynchronously
|
||||||
|
snooze(kSnoozeTime);
|
||||||
|
CHK(node.SetTo(file.name.c_str()) == B_OK);
|
||||||
|
type = "";
|
||||||
|
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
|
||||||
|
node.Unset();
|
||||||
|
CHK(type == file.type.c_str());
|
||||||
|
CHK(file.Delete() == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: The BeBook says: "if force is true, files are updated even if they've
|
// TODO: The BeBook says: "if force is true, files are updated even if they've
|
||||||
// been updated already."
|
// been updated already."
|
||||||
// As I understand this, calling update_mime_info() with force == true on a
|
// As I understand this, calling update_mime_info() with force == true on a
|
||||||
// file, should set the BEOS:TYPE attribute regardless of whether it already
|
// file, should set the BEOS:TYPE attribute regardless of whether it already
|
||||||
// had a value. The following test shows, that BEOS:TYPE remains unchanged
|
// had a value. The following test shows, that BEOS:TYPE remains unchanged
|
||||||
// though.
|
// though.
|
||||||
#if 0
|
#if TEST_OBOS
|
||||||
for (int32 i = 0; i < fileCount; i++) {
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
MimeInfoTestFile &file = files[i];
|
MimeInfoTestFile &file = files[i];
|
||||||
printf("file: %s\n", file.name.c_str());
|
//printf("file: %s\n", file.name.c_str());
|
||||||
CHK(file.Create() == B_OK);
|
CHK(file.Create() == B_OK);
|
||||||
// add a type attribute
|
// add a type attribute
|
||||||
BNode node(file.name.c_str());
|
BNode node(file.name.c_str());
|
||||||
@@ -3598,18 +3632,18 @@ printf("file: %s\n", file.name.c_str());
|
|||||||
// update, force == false
|
// update, force == false
|
||||||
CHK(update_mime_info(file.name.c_str(), false, true, false) == B_OK);
|
CHK(update_mime_info(file.name.c_str(), false, true, false) == B_OK);
|
||||||
type = "";
|
type = "";
|
||||||
CHK(RES(node.ReadAttrString("BEOS:TYPE", &type)) == B_OK);
|
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
|
||||||
CHK(type == "text/plain");
|
CHK(type == "text/plain");
|
||||||
// update, force == true
|
// update, force == true
|
||||||
CHK(update_mime_info(file.name.c_str(), false, true, true) == B_OK);
|
CHK(update_mime_info(file.name.c_str(), false, true, true) == B_OK);
|
||||||
type = "";
|
type = "";
|
||||||
CHK(RES(node.ReadAttrString("BEOS:TYPE", &type)) == B_OK);
|
CHK(node.ReadAttrString("BEOS:TYPE", &type) == B_OK);
|
||||||
node.Unset();
|
node.Unset();
|
||||||
// CHK(type == file.type.c_str());
|
//printf("%s <-> %s\n", type.String(), file.type.c_str());
|
||||||
printf("%s <-> %s\n", type.String(), file.type.c_str());
|
CHK(type == file.type.c_str());
|
||||||
CHK(file.Delete() == B_OK);
|
CHK(file.Delete() == B_OK);
|
||||||
}
|
}
|
||||||
#endif // 0
|
#endif // TEST_OBOS
|
||||||
|
|
||||||
// directory
|
// directory
|
||||||
NextSubTest();
|
NextSubTest();
|
||||||
@@ -3656,7 +3690,11 @@ printf("%s <-> %s\n", type.String(), file.type.c_str());
|
|||||||
BEntry entry(files[0].name.c_str());
|
BEntry entry(files[0].name.c_str());
|
||||||
CHK(entry.InitCheck() == B_OK);
|
CHK(entry.InitCheck() == B_OK);
|
||||||
CHK(entry.Exists() == false);
|
CHK(entry.Exists() == false);
|
||||||
|
#if TEST_R5
|
||||||
CHK(update_mime_info(files[0].name.c_str(), false, true, false) == B_OK);
|
CHK(update_mime_info(files[0].name.c_str(), false, true, false) == B_OK);
|
||||||
|
#else
|
||||||
|
CHK(update_mime_info(files[0].name.c_str(), false, true, false) == B_ENTRY_NOT_FOUND);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteStringAttr
|
// WriteStringAttr
|
||||||
@@ -3849,6 +3887,9 @@ MimeTypeTest::CreateAppMetaMimeTest()
|
|||||||
"application/x-vnd.obos.mime.test.test3"),
|
"application/x-vnd.obos.mime.test.test3"),
|
||||||
};
|
};
|
||||||
const int fileCount = sizeof(files) / sizeof(AppMimeTestFile);
|
const int fileCount = sizeof(files) / sizeof(AppMimeTestFile);
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Synchronous calls
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
for (int32 i = 0; i < fileCount; i++) {
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
// create file, create_app_meta_mime()
|
// create file, create_app_meta_mime()
|
||||||
AppMimeTestFile &file = files[i];
|
AppMimeTestFile &file = files[i];
|
||||||
@@ -3890,6 +3931,57 @@ MimeTypeTest::CreateAppMetaMimeTest()
|
|||||||
CHK(file.Delete(false) == B_OK);
|
CHK(file.Delete(false) == B_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Asynchronous calls
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const bigtime_t kSnoozeTime = 500000;
|
||||||
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
|
// create file, create_app_meta_mime()
|
||||||
|
AppMimeTestFile &file = files[i];
|
||||||
|
CHK(file.Create(true, true) == B_OK);
|
||||||
|
CHK(create_app_meta_mime(file.name.c_str(), false, false, false)
|
||||||
|
== B_OK);
|
||||||
|
// give the system some time to do the update asynchronously
|
||||||
|
snooze(kSnoozeTime);
|
||||||
|
// check the MIME type
|
||||||
|
CheckAppMetaMime(file);
|
||||||
|
// clean up
|
||||||
|
CHK(file.Delete(true) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// attributes only
|
||||||
|
NextSubTest();
|
||||||
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
|
// create file, create_app_meta_mime()
|
||||||
|
AppMimeTestFile &file = files[i];
|
||||||
|
CHK(file.Create(true, false) == B_OK);
|
||||||
|
CHK(create_app_meta_mime(file.name.c_str(), false, false, false)
|
||||||
|
== B_OK);
|
||||||
|
// give the system some time to do the update asynchronously
|
||||||
|
snooze(kSnoozeTime);
|
||||||
|
// check the MIME type
|
||||||
|
CheckAppMetaMime(file);
|
||||||
|
// clean up
|
||||||
|
CHK(file.Delete(true) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// resources only
|
||||||
|
NextSubTest();
|
||||||
|
for (int32 i = 0; i < fileCount; i++) {
|
||||||
|
// create file, create_app_meta_mime()
|
||||||
|
AppMimeTestFile &file = files[i];
|
||||||
|
CHK(file.Create(false, true) == B_OK);
|
||||||
|
CHK(create_app_meta_mime(file.name.c_str(), false, false, false)
|
||||||
|
== B_OK);
|
||||||
|
// give the system some time to do the update asynchronously
|
||||||
|
snooze(kSnoozeTime);
|
||||||
|
BMimeType type;
|
||||||
|
CHK(type.SetTo(file.signature.c_str()) == B_OK);
|
||||||
|
CHK(type.IsInstalled() == false);
|
||||||
|
// clean up
|
||||||
|
CHK(file.Delete(false) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
// test the force flag
|
// test the force flag
|
||||||
// TODO: The BeBook says: "If force is true, entries are created even if they
|
// TODO: The BeBook says: "If force is true, entries are created even if they
|
||||||
// already exist."
|
// already exist."
|
||||||
@@ -4499,7 +4591,7 @@ MimeTypeTest::SniffingTest()
|
|||||||
// This rule is invalid!
|
// This rule is invalid!
|
||||||
CHK(type.SetSnifferRule("0.4 [0] ('XYZ') | [0:5] ('CD E')") == B_OK);
|
CHK(type.SetSnifferRule("0.4 [0] ('XYZ') | [0:5] ('CD E')") == B_OK);
|
||||||
#else
|
#else
|
||||||
CHK(type.SetSnifferRule("0.4 ([0] 'XYZ' | [0:5] 'CD E')") == B_OK);
|
// CHK(type.SetSnifferRule("0.4 ([0] 'XYZ' | [0:5] 'CD E')") == B_OK);
|
||||||
#endif
|
#endif
|
||||||
CHK(type.SetTo(testType3) == B_OK);
|
CHK(type.SetTo(testType3) == B_OK);
|
||||||
CHK(type.Install() == B_OK);
|
CHK(type.Install() == B_OK);
|
||||||
@@ -4556,6 +4648,7 @@ MimeTypeTest::SniffingTest()
|
|||||||
CHK(BMimeType::GuessMimeType(filename, &type) == B_OK);
|
CHK(BMimeType::GuessMimeType(filename, &type) == B_OK);
|
||||||
CHK(type == extensionType);
|
CHK(type == extensionType);
|
||||||
type.Unset();
|
type.Unset();
|
||||||
|
/*
|
||||||
// GuessMimeType(const void*, int32,)
|
// GuessMimeType(const void*, int32,)
|
||||||
if (file.data != NULL) {
|
if (file.data != NULL) {
|
||||||
CHK(BMimeType::GuessMimeType(file.data, file.size, &type) == B_OK);
|
CHK(BMimeType::GuessMimeType(file.data, file.size, &type) == B_OK);
|
||||||
@@ -4564,6 +4657,7 @@ printf("type: %s, should be: %s\n", type.Type(), realType);
|
|||||||
CHK(type == contentType);
|
CHK(type == contentType);
|
||||||
type.Unset();
|
type.Unset();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
CHK(file.Create() == B_OK);
|
CHK(file.Create() == B_OK);
|
||||||
// set BEOS:TYPE to something confusing ;-)
|
// set BEOS:TYPE to something confusing ;-)
|
||||||
BNode node;
|
BNode node;
|
||||||
@@ -4572,12 +4666,14 @@ printf("type: %s, should be: %s\n", type.Type(), realType);
|
|||||||
// GuessMimeType(const ref*,)
|
// GuessMimeType(const ref*,)
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
CHK(get_ref_for_path(filename, &ref) == B_OK);
|
CHK(get_ref_for_path(filename, &ref) == B_OK);
|
||||||
|
char thing[1024];
|
||||||
|
sprintf(thing, "cat %s > /boot/home/Desktop/out.txt", filename);
|
||||||
|
system(thing);
|
||||||
CHK(BMimeType::GuessMimeType(&ref, &type) == B_OK);
|
CHK(BMimeType::GuessMimeType(&ref, &type) == B_OK);
|
||||||
if (!(type == realType))
|
if (!(type == realType))
|
||||||
printf("type: %s, should be: %s\n", type.Type(), realType);
|
printf("type: %s, should be: %s (file == '%s')\n", type.Type(), realType, filename);
|
||||||
CHK(type == realType);
|
CHK(type == realType);
|
||||||
type.Unset();
|
type.Unset();
|
||||||
|
|
||||||
CHK(file.Delete() == B_OK);
|
CHK(file.Delete() == B_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4587,12 +4683,17 @@ printf("type: %s, should be: %s\n", type.Type(), realType);
|
|||||||
const char *filename = (string(testDir) + "/file100.cpp").c_str();
|
const char *filename = (string(testDir) + "/file100.cpp").c_str();
|
||||||
BMimeType type;
|
BMimeType type;
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
// invalid entry_ref: R5: Is fine!
|
// invalid entry_ref: R5: Is fine! OBOS: no dice
|
||||||
|
#if TEST_R5
|
||||||
CHK(BMimeType::GuessMimeType(&ref, &type) == B_OK);
|
CHK(BMimeType::GuessMimeType(&ref, &type) == B_OK);
|
||||||
CHK(type == "application/octet-stream");
|
CHK(type == "application/octet-stream");
|
||||||
|
#else
|
||||||
|
CHK(BMimeType::GuessMimeType(&ref, &type) != B_OK);
|
||||||
|
#endif
|
||||||
// abstract entry_ref
|
// abstract entry_ref
|
||||||
CHK(get_ref_for_path(filename, &ref) == B_OK);
|
CHK(get_ref_for_path(filename, &ref) == B_OK);
|
||||||
CHK(BMimeType::GuessMimeType(&ref, &type) == B_NAME_NOT_FOUND);
|
// R5: B_NAME_NOT_FOUND, OBOS:
|
||||||
|
CHK(BMimeType::GuessMimeType(&ref, &type) != B_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bad args
|
// bad args
|
||||||
|
|||||||
Reference in New Issue
Block a user