Complete implementation. The 'supporting types' methods are untested as they need BMimeType/registar support. SetSupportedTypes() may need some adjustions when that is available.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@880 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2002-08-25 22:49:22 +00:00
parent 821e6e16f2
commit 98da112cca
2 changed files with 777 additions and 25 deletions
+9 -1
View File
@@ -107,7 +107,15 @@ private:
// status_t UpdateMetaMime(const char *path, bool force,
// uint32 *changesMask) const;
// bool IsApp();
// status_t GetMetaMime(BMimeType *meta) const;
status_t GetMetaMime(BMimeType *meta) const;
status_t _ReadData(const char *name, int32 id, type_code type,
void *buffer, size_t bufferSize,
size_t &bytesRead, void **allocatedBuffer = NULL) const;
status_t _WriteData(const char *name, int32 id, type_code type,
const void *buffer, size_t bufferSize,
bool findID = false);
status_t _RemoveData(const char *name, type_code type);
BResources *fResources;
info_location fWhere;
+768 -24
View File
@@ -1,6 +1,48 @@
// BAppFileInfo.cpp
#include <new>
#include <set>
#include <string>
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <File.h>
#include <fs_attr.h>
#include <MimeType.h>
#include <RegistrarDefs.h>
#include <Resources.h>
#include <Roster.h>
#include <String.h>
// attributes
static const char *kTypeAttribute = "BEOS:TYPE";
static const char *kSignatureAttribute = "BEOS:APP_SIG";
static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS";
static const char *kSupportedTypesAttribute = "BEOS:FILE_TYPES";
static const char *kVersionInfoAttribute = "BEOS:APP_VERSION";
static const char *kMiniIconAttribute = "BEOS:M:";
static const char *kLargeIconAttribute = "BEOS:L:";
static const char *kStandardIconType = "STD_ICON";
// resource IDs
static const int32 kTypeResourceID = 2;
static const int32 kSignatureResourceID = 1;
static const int32 kAppFlagsResourceID = 1;
static const int32 kSupportedTypesResourceID = 1;
static const int32 kMiniIconResourceID = 101;
static const int32 kLargeIconResourceID = 101;
static const int32 kVersionInfoResourceID = 1;
static const int32 kMiniIconForTypeResourceID = 0;
static const int32 kLargeIconForTypeResourceID = 0;
// type codes
enum {
B_APP_FLAGS_TYPE = 'APPF',
B_MINI_ICON_TYPE = 'MICN',
B_LARGE_ICON_TYPE = 'ICON',
B_VERSION_INFO_TYPE = 'APPV',
};
enum {
NOT_IMPLEMENTED = B_ERROR,
@@ -29,6 +71,7 @@ BAppFileInfo::BAppFileInfo(BFile *file)
: fResources(NULL),
fWhere(B_USE_BOTH_LOCATIONS)
{
SetTo(file);
}
// destructor
@@ -38,6 +81,8 @@ BAppFileInfo::BAppFileInfo(BFile *file)
*/
BAppFileInfo::~BAppFileInfo()
{
if (fResources)
delete fResources;
}
// SetTo
@@ -56,7 +101,40 @@ BAppFileInfo::~BAppFileInfo()
status_t
BAppFileInfo::SetTo(BFile *file)
{
return NOT_IMPLEMENTED;
// unset the old file
BNodeInfo::SetTo(NULL);
if (fResources) {
delete fResources;
fResources = NULL;
}
// check param
status_t error = (file && file->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// create resources
if (error == B_OK) {
fResources = new(nothrow) BResources();
if (fResources)
error = fResources->SetTo(file);
else
error = B_NO_MEMORY;
}
// set node info
if (error == B_OK)
error = BNodeInfo::SetTo(file);
// clean up on error
if (error != B_OK) {
if (fResources) {
delete fResources;
fResources = NULL;
}
if (InitCheck() == B_OK)
BNodeInfo::SetTo(NULL);
}
// set data location
if (error == B_OK)
SetInfoLocation(B_USE_BOTH_LOCATIONS);
// set error
fCStatus = error;
return error;
}
// GetType
@@ -78,7 +156,24 @@ BAppFileInfo::SetTo(BFile *file)
status_t
BAppFileInfo::GetType(char *type) const
{
return NOT_IMPLEMENTED;
// check param and initialization
status_t error = (type ? B_OK : B_BAD_VALUE);
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// read the data
size_t read = 0;
if (error == B_OK) {
error = _ReadData(kTypeAttribute, kTypeResourceID, B_MIME_STRING_TYPE,
type, B_MIME_TYPE_LENGTH, read);
}
// check the read data -- null terminate the string
if (error == B_OK && type[read - 1] != '\0') {
if (read == B_MIME_TYPE_LENGTH)
error = B_ERROR;
else
type[read] = '\0';
}
return error;
}
// SetType
@@ -98,7 +193,25 @@ BAppFileInfo::GetType(char *type) const
status_t
BAppFileInfo::SetType(const char *type)
{
return NOT_IMPLEMENTED;
// check initialization
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
if (error == B_OK) {
if (type) {
// check param
size_t typeLen = strlen(type);
if (error == B_OK && typeLen >= B_MIME_TYPE_LENGTH)
error = B_BAD_VALUE;
// write the data
if (error == B_OK) {
error = _WriteData(kTypeAttribute, kTypeResourceID,
B_MIME_STRING_TYPE, type, typeLen + 1);
}
} else
error = _RemoveData(kTypeAttribute, B_MIME_STRING_TYPE);
}
return error;
}
// GetSignature
@@ -120,7 +233,25 @@ BAppFileInfo::SetType(const char *type)
status_t
BAppFileInfo::GetSignature(char *signature) const
{
return NOT_IMPLEMENTED;
// check param and initialization
status_t error = (signature ? B_OK : B_BAD_VALUE);
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// read the data
size_t read = 0;
if (error == B_OK) {
error = _ReadData(kSignatureAttribute, kSignatureResourceID,
B_MIME_STRING_TYPE, signature, B_MIME_TYPE_LENGTH,
read);
}
// check the read data -- null terminate the string
if (error == B_OK && signature[read - 1] != '\0') {
if (read == B_MIME_TYPE_LENGTH)
error = B_ERROR;
else
signature[read] = '\0';
}
return error;
}
// SetSignature
@@ -140,7 +271,26 @@ BAppFileInfo::GetSignature(char *signature) const
status_t
BAppFileInfo::SetSignature(const char *signature)
{
return NOT_IMPLEMENTED;
// check initialization
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
if (error == B_OK) {
if (signature) {
// check param
size_t signatureLen = strlen(signature);
if (error == B_OK && signatureLen >= B_MIME_TYPE_LENGTH)
error = B_BAD_VALUE;
// write the data
if (error == B_OK) {
error = _WriteData(kSignatureAttribute, kSignatureResourceID,
B_MIME_STRING_TYPE, signature,
signatureLen + 1);
}
} else
error = _RemoveData(kSignatureAttribute, B_MIME_STRING_TYPE);
}
return error;
}
// GetAppFlags
@@ -160,7 +310,21 @@ BAppFileInfo::SetSignature(const char *signature)
status_t
BAppFileInfo::GetAppFlags(uint32 *flags) const
{
return NOT_IMPLEMENTED;
// check param and initialization
status_t error = (flags ? B_OK : B_BAD_VALUE);
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// read the data
size_t read = 0;
if (error == B_OK) {
error = _ReadData(kAppFlagsAttribute, kAppFlagsResourceID,
B_APP_FLAGS_TYPE, flags, sizeof(uint32),
read);
}
// check the read data
if (error == B_OK && read != sizeof(uint32))
error = B_ERROR;
return error;
}
// SetAppFlags
@@ -174,7 +338,18 @@ BAppFileInfo::GetAppFlags(uint32 *flags) const
status_t
BAppFileInfo::SetAppFlags(uint32 flags)
{
return NOT_IMPLEMENTED;
// check initialization
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
if (error == B_OK) {
// write the data
if (error == B_OK) {
error = _WriteData(kAppFlagsAttribute, kAppFlagsResourceID,
B_APP_FLAGS_TYPE, &flags, sizeof(uint32));
}
}
return error;
}
// GetSupportedTypes
@@ -197,7 +372,24 @@ BAppFileInfo::SetAppFlags(uint32 flags)
status_t
BAppFileInfo::GetSupportedTypes(BMessage *types) const
{
return NOT_IMPLEMENTED;
// check param and initialization
status_t error = (types ? B_OK : B_BAD_VALUE);
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// read the data
size_t read = 0;
void *buffer = NULL;
if (error == B_OK) {
error = _ReadData(kSupportedTypesAttribute, kSupportedTypesResourceID,
B_MESSAGE_TYPE, NULL, 0, read, &buffer);
}
// unflatten the buffer
if (error == B_OK)
error = types->Unflatten((const char*)buffer);
// clean up
if (buffer)
free(buffer);
return error;
}
// SetSupportedTypes
@@ -229,13 +421,99 @@ BAppFileInfo::GetSupportedTypes(BMessage *types) const
status_t
BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
{
return NOT_IMPLEMENTED;
// check initialization
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
BMimeType mimeType;
if (error == B_OK)
error = GetMetaMime(&mimeType);
if (error == B_OK) {
if (types) {
// check param
ssize_t size = types->FlattenedSize();
if (size < 0)
error = size;
// allocate a buffer for the flattened data
char *buffer = NULL;
if (error == B_OK) {
buffer = new(nothrow) char[size];
if (!buffer)
error = B_NO_MEMORY;
}
// flatten the message
if (error == B_OK)
error = types->Flatten(buffer, size);
// write the data
if (error == B_OK) {
error = _WriteData(kSupportedTypesAttribute,
kSupportedTypesResourceID, B_MESSAGE_TYPE,
buffer, size);
}
// clean up
if (buffer)
delete[] buffer;
} else
error = _RemoveData(kSupportedTypesAttribute, B_MESSAGE_TYPE);
// update the MIME database, if the app signature is installed
if (mimeType.IsInstalled()) {
// create a set of the removed types
set<string> oldTypes;
if (syncAll) {
BMessage oldTypeMsg;
error = mimeType.GetSupportedTypes(&oldTypeMsg);
// add all formerly supported types to the set
if (error == B_OK) {
BString type;
for (int32 i = 0;
oldTypeMsg.FindString("types", i, &type) == B_OK;
i++) {
oldTypes.insert(string(type.ToLower().String()));
}
}
// remove the newly supported types from the set
if (error == B_OK && types) {
BString type;
for (int32 i = 0;
types->FindString("types", i, &type) == B_OK;
i++) {
oldTypes.erase(string(type.ToLower().String()));
}
}
}
// create and send the message
if (error == B_OK && oldTypes.size() > 0) {
BMessage message(B_REG_MIME_UNSUPPORT_TYPES);
error = message.AddString("type", mimeType.Type());
for (set<string>::iterator it = oldTypes.begin();
error == B_OK && it != oldTypes.end();
it++) {
error = message.AddString("unsupported_types",
it->c_str());
}
BMessage reply;
if (error == B_OK)
error = _send_to_roster_(&message, &reply, true);
if (error == B_OK)
error = (reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE);
status_t result;
if (error == B_OK)
error = reply.FindInt32("result", &result);
if (error == B_OK)
error = result;
}
// set the type's supported types
if (error == B_OK)
error = mimeType.SetSupportedTypes(types);
}
}
return error;
}
// SetSupportedTypes
/*! \brief Sets the MIME types supported by the application.
This method is a short-hand for SetSupportedTypes(types, true).
This method is a short-hand for SetSupportedTypes(types, false).
\see SetSupportedType(const BMessage*, bool) for detailed information.
\param types The supported types to be assigned to the file.
@@ -248,7 +526,7 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types, bool syncAll)
status_t
BAppFileInfo::SetSupportedTypes(const BMessage *types)
{
return NOT_IMPLEMENTED;
return SetSupportedTypes(types, false);
}
// IsSupportedType
@@ -264,7 +542,27 @@ BAppFileInfo::SetSupportedTypes(const BMessage *types)
bool
BAppFileInfo::IsSupportedType(const char *type) const
{
return false; // not implemented
status_t error = (type ? B_OK : B_BAD_VALUE);
// get the supported types
BMessage types;
if (error == B_OK)
error = GetSupportedTypes(&types);
// turn type into a BMimeType
BMimeType mimeType;
if (error == B_OK)
error = mimeType.SetTo(type);
// iterate through the supported types
bool found = false;
if (error == B_OK) {
const char *supportedType;
for (int32 i = 0;
!found && types.FindString("types", i, &supportedType) == B_OK;
i++) {
found = !strcmp(supportedType, "application/octet-stream")
|| BMimeType(supportedType).Contains(&mimeType);
}
}
return found;
}
// Supports
@@ -282,7 +580,22 @@ BAppFileInfo::IsSupportedType(const char *type) const
bool
BAppFileInfo::Supports(BMimeType *type) const
{
return false; // not implemented
status_t error = (type && type->InitCheck() == B_OK ? B_OK : B_BAD_VALUE);
// get the supported types
BMessage types;
if (error == B_OK)
error = GetSupportedTypes(&types);
// iterate through the supported types
bool found = false;
if (error == B_OK) {
const char *supportedType;
for (int32 i = 0;
!found && types.FindString("types", i, &supportedType) == B_OK;
i++) {
found = BMimeType(supportedType).Contains(type);
}
}
return found;
}
// GetIcon
@@ -302,7 +615,7 @@ BAppFileInfo::Supports(BMimeType *type) const
status_t
BAppFileInfo::GetIcon(BBitmap *icon, icon_size which) const
{
return NOT_IMPLEMENTED;
return GetIconForType(NULL, icon, which);
}
// SetIcon
@@ -324,7 +637,7 @@ BAppFileInfo::GetIcon(BBitmap *icon, icon_size which) const
status_t
BAppFileInfo::SetIcon(const BBitmap *icon, icon_size which)
{
return NOT_IMPLEMENTED;
return SetIconForType(NULL, icon, which);
}
// GetVersionInfo
@@ -344,7 +657,38 @@ BAppFileInfo::SetIcon(const BBitmap *icon, icon_size which)
status_t
BAppFileInfo::GetVersionInfo(version_info *info, version_kind kind) const
{
return NOT_IMPLEMENTED;
// check params and initialization
status_t error = (info ? B_OK : B_BAD_VALUE);
int32 index = 0;
if (error == B_OK) {
switch (kind) {
case B_APP_VERSION_KIND:
index = 0;
break;
case B_SYSTEM_VERSION_KIND:
index = 1;
break;
default:
error = B_BAD_VALUE;
break;
}
}
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// read the data
size_t read = 0;
version_info infos[2];
if (error == B_OK) {
error = _ReadData(kVersionInfoAttribute, kVersionInfoResourceID,
B_VERSION_INFO_TYPE, infos,
2 * sizeof(version_info), read);
}
// check the read data -- null terminate the string
if (error == B_OK && read != 2 * sizeof(version_info))
error = B_ERROR;
if (error == B_OK)
*info = infos[index];
return error;
}
// SetVersionInfo
@@ -365,12 +709,55 @@ BAppFileInfo::GetVersionInfo(version_info *info, version_kind kind) const
status_t
BAppFileInfo::SetVersionInfo(const version_info *info, version_kind kind)
{
return NOT_IMPLEMENTED;
// check initialization
status_t error = B_OK;
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
if (error == B_OK) {
if (info) {
// check param
int32 index = 0;
if (error == B_OK) {
switch (kind) {
case B_APP_VERSION_KIND:
index = 0;
break;
case B_SYSTEM_VERSION_KIND:
index = 1;
break;
default:
error = B_BAD_VALUE;
break;
}
}
// read both infos
version_info infos[2];
if (error == B_OK) {
size_t read;
_ReadData(kVersionInfoAttribute, kVersionInfoResourceID,
B_VERSION_INFO_TYPE, infos,
2 * sizeof(version_info), read);
}
infos[index] = *info;
// write the data
if (error == B_OK) {
error = _WriteData(kVersionInfoAttribute,
kVersionInfoResourceID,
B_VERSION_INFO_TYPE, infos,
2 * sizeof(version_info));
}
} else
error = _RemoveData(kVersionInfoAttribute, B_VERSION_INFO_TYPE);
}
return error;
}
// GetIconForType
/*! \brief Gets the icon the application provides for a given MIME type.
\param type The MIME type in question.
If \a type is \c NULL, the application's icon is retrieved.
\param type The MIME type in question. May be \c NULL.
\param icon A pointer to a pre-allocated BBitmap of the correct dimension
to store the requested icon (16x16 for the mini and 32x32 for the
large icon).
@@ -379,7 +766,7 @@ BAppFileInfo::SetVersionInfo(const version_info *info, version_kind kind)
\return
- \c B_OK: Everything went fine.
- \c B_NO_INIT: The object is not properly initialized.
- \c B_BAD_VALUE: \c NULL \a type or \a icon, unsupported icon size
- \c B_BAD_VALUE: \c NULL \a icon, unsupported icon size
\a which or bitmap dimensions (\a icon) and icon size (\a which) do
not match.
- other error codes
@@ -388,15 +775,88 @@ status_t
BAppFileInfo::GetIconForType(const char *type, BBitmap *icon,
icon_size which) const
{
return NOT_IMPLEMENTED;
status_t error = B_OK;
// set some icon size related variables
BString attributeString;
BRect bounds;
uint32 attrType;
size_t attrSize;
switch (which) {
case B_MINI_ICON:
attributeString = kMiniIconAttribute;
bounds.Set(0, 0, 15, 15);
attrType = B_MINI_ICON_TYPE;
attrSize = 16 * 16;
break;
case B_LARGE_ICON:
attributeString = kLargeIconAttribute;
bounds.Set(0, 0, 31, 31);
attrType = B_LARGE_ICON_TYPE;
attrSize = 32 * 32;
break;
default:
error = B_BAD_VALUE;
break;
}
// check type param
if (error == B_OK) {
if (type) {
if (strlen(type) >= B_MIME_TYPE_LENGTH)
error = B_BAD_VALUE;
} else
type = kStandardIconType;
}
if (error == B_OK)
attributeString += type;
const char *attribute = attributeString.String();
// check parameter and initialization
if (error == B_OK
&& (!icon || icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
error = B_BAD_VALUE;
}
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// read the data
if (error == B_OK) {
bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
char *buffer = NULL;
size_t read;
if (otherColorSpace) {
// other color space than stored in attribute
buffer = new(nothrow) char[attrSize];
if (!buffer)
error = B_NO_MEMORY;
if (error == B_OK) {
error = _ReadData(attribute, -1, attrType, buffer, attrSize,
read);
}
} else {
error = _ReadData(attribute, -1, attrType, icon->Bits(), attrSize,
read);
}
if (error == B_OK && read != attrSize)
error = B_ERROR;
if (otherColorSpace) {
// other color space than stored in attribute
if (error == B_OK)
icon->SetBits(buffer, attrSize, 0, B_CMAP8);
delete[] buffer;
}
}
return error;
}
// SetIconForType
/*! \brief Sets the icon the application provides for a given MIME type.
If \a type is \c NULL, the application's icon is set.
If \a icon is \c NULL the icon is unset.
\param type The MIME type in question.
If the file has a signature, then the icon is also set on the MIME type.
If the type for the signature has not been installed yet, it is installed
before.
\param type The MIME type in question. May be \c NULL.
\param icon A pointer to the BBitmap containing the icon to be set.
May be \c NULL.
\param which Specifies the size of the icon to be set: \c B_MINI_ICON
@@ -412,7 +872,80 @@ status_t
BAppFileInfo::SetIconForType(const char *type, const BBitmap *icon,
icon_size which)
{
return NOT_IMPLEMENTED;
status_t error = B_OK;
// set some icon size related variables
BString attributeString;
BRect bounds;
uint32 attrType;
size_t attrSize;
int32 resourceID;
switch (which) {
case B_MINI_ICON:
attributeString = kMiniIconAttribute;
bounds.Set(0, 0, 15, 15);
attrType = B_MINI_ICON_TYPE;
attrSize = 16 * 16;
resourceID = (type ? kMiniIconForTypeResourceID
: kMiniIconResourceID);
break;
case B_LARGE_ICON:
attributeString = kLargeIconAttribute;
bounds.Set(0, 0, 31, 31);
attrType = B_LARGE_ICON_TYPE;
attrSize = 32 * 32;
resourceID = (type ? kLargeIconForTypeResourceID
: kLargeIconResourceID);
break;
default:
error = B_BAD_VALUE;
break;
}
// check type param
if (error == B_OK) {
if (type) {
if (strlen(type) >= B_MIME_TYPE_LENGTH)
error = B_BAD_VALUE;
else
attributeString += type;
} else
attributeString += kStandardIconType;
}
const char *attribute = attributeString.String();
// check parameter and initialization
if (error == B_OK && icon
&& (icon->InitCheck() != B_OK || icon->Bounds() != bounds)) {
error = B_BAD_VALUE;
}
if (error == B_OK && InitCheck() != B_OK)
error = B_NO_INIT;
// write/remove the attribute
if (error == B_OK) {
if (icon) {
bool otherColorSpace = (icon->ColorSpace() != B_CMAP8);
if (otherColorSpace) {
BBitmap bitmap(bounds, B_CMAP8);
error = bitmap.InitCheck();
if (error == B_OK) {
bitmap.SetBits(icon->Bits(), 0, attrSize, B_CMAP8);
error = _WriteData(attribute, resourceID, attrType,
bitmap.Bits(), attrSize, true);
}
} else {
error = _WriteData(attribute, resourceID, attrType,
icon->Bits(), attrSize, true);
}
} else // no icon given => remove
error = _RemoveData(attribute, attrType);
}
// set the attribute on the MIME type, if the file has a signature
BMimeType mimeType;
if (error == B_OK && GetMetaMime(&mimeType) == B_OK) {
if (!mimeType.IsInstalled())
error = mimeType.Install();
if (error == B_OK)
error = mimeType.SetIconForType(type, icon, which);
}
return error;
}
// SetInfoLocation
@@ -428,6 +961,7 @@ BAppFileInfo::SetIconForType(const char *type, const BBitmap *icon,
void
BAppFileInfo::SetInfoLocation(info_location location)
{
fWhere = location;
}
// IsUsingAttributes
@@ -439,7 +973,7 @@ BAppFileInfo::SetInfoLocation(info_location location)
bool
BAppFileInfo::IsUsingAttributes() const
{
return false; // not implemented
return (fWhere & B_USE_ATTRIBUTES);
}
// IsUsingResources
@@ -451,7 +985,7 @@ BAppFileInfo::IsUsingAttributes() const
bool
BAppFileInfo::IsUsingResources() const
{
return false; // not implemented
return (fWhere & B_USE_RESOURCES);
}
// FBC
@@ -475,3 +1009,213 @@ BAppFileInfo::BAppFileInfo(const BAppFileInfo &)
{
}
// GetMetaMime
/*! \brief Initializes a BMimeType to the file's signature.
The parameter \a meta is not checked.
\param meta A pointer to a pre-allocated BMimeType that shall be
initialized to the file's signature.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \c NULL \a meta
- \c B_ENTRY_NOT_FOUND: The file has not signature or the signature is
( not installed in the MIME database.)
no valid MIME string.
- other error codes
*/
status_t
BAppFileInfo::GetMetaMime(BMimeType *meta) const
{
char signature[B_MIME_TYPE_LENGTH];
status_t error = GetSignature(signature);
if (error == B_OK)
error = meta->SetTo(signature);
if (error == B_OK && !meta->IsValid())
error = B_BAD_VALUE;
return error;
}
// _ReadData
/*! \brief Reads data from an attribute or resource.
The data are read from the location specified by \a fWhere.
The object must be properly initialized. The parameters are NOT checked.
\param name The name of the attribute/resource to be read.
\param id The resource ID of the resource to be read. Is ignored, when
< 0.
\param type The type of the attribute/resource to be read.
\param buffer A pre-allocated buffer for the data to be read.
\param bufferSize The size of the supplied buffer.
\param bytesRead A reference parameter, set to the number of bytes
actually read.
\param allocatedBuffer If not \c NULL, the method allocates a buffer
large enough too store the whole data and writes a pointer to it
into this variable. If \c NULL, the supplied buffer is used.
\return
- \c B_OK: Everything went fine.
- error code
*/
status_t
BAppFileInfo::_ReadData(const char *name, int32 id, type_code type,
void *buffer, size_t bufferSize,
size_t &bytesRead, void **allocatedBuffer) const
{
status_t error = B_OK;
if (allocatedBuffer)
buffer = NULL;
if (IsUsingAttributes()) {
// get an attribute info
attr_info info;
if (error == B_OK)
error = fNode->GetAttrInfo(name, &info);
// check type and size, allocate a buffer, if required
if (error == B_OK && info.type != type)
error = B_BAD_VALUE;
if (allocatedBuffer) {
buffer = malloc(info.size);
if (!buffer)
error = B_NO_MEMORY;
bufferSize = info.size;
}
if (error == B_OK && bufferSize < info.size)
error = B_BAD_VALUE;
// read the data
if (error == B_OK) {
ssize_t read = fNode->ReadAttr(name, type, 0, buffer, info.size);
if (read < 0)
error = read;
else if (read != info.size)
error = B_ERROR;
else
bytesRead = read;
}
} else if (IsUsingResources()) {
// get a resource info
int32 idFound;
size_t sizeFound;
if (error == B_OK) {
if (!fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
error = B_ENTRY_NOT_FOUND;
}
// check id and size, allocate a buffer, if required
if (error == B_OK && id >= 0 && idFound != id)
error = B_ENTRY_NOT_FOUND;
if (allocatedBuffer) {
buffer = malloc(sizeFound);
if (!buffer)
error = B_NO_MEMORY;
bufferSize = sizeFound;
}
if (error == B_OK && bufferSize < sizeFound)
error = B_BAD_VALUE;
// load resource
const void *resourceData = NULL;
if (error == B_OK) {
resourceData = fResources->LoadResource(type, name, &bytesRead);
if (resourceData && sizeFound == bytesRead)
memcpy(buffer, resourceData, bytesRead);
else
error = B_ERROR;
}
} else
error = B_BAD_VALUE;
// return the allocated buffer, or free it on error
if (allocatedBuffer) {
if (error == B_OK)
*allocatedBuffer = buffer;
else
free(buffer);
}
return error;
}
// _WriteData
/*! \brief Writes data to an attribute or resource.
The data are written to the location(s) specified by \a fWhere.
The object must be properly initialized. The parameters are NOT checked.
\param name The name of the attribute/resource to be written.
\param id The resource ID of the resource to be written.
\param type The type of the attribute/resource to be written.
\param buffer A buffer containing the data to be written.
\param bufferSize The size of the supplied buffer.
\param findID If set to \c true use the ID that is already assigned to the
\a name / \a type pair or take the first unused ID >= \a id.
If \c false, \a id is used.
If \a id is already in use and .
\return
- \c B_OK: Everything went fine.
- error code
*/
status_t
BAppFileInfo::_WriteData(const char *name, int32 id, type_code type,
const void *buffer, size_t bufferSize, bool findID)
{
status_t error = B_OK;
// write to attribute
if (IsUsingAttributes() && error == B_OK) {
ssize_t written = fNode->WriteAttr(name, type, 0, buffer, bufferSize);
if (written < 0)
error = written;
else if (written != (ssize_t)bufferSize)
error = B_ERROR;
}
// write to resource
if (IsUsingResources() && error == B_OK) {
if (findID) {
// get the resource info
int32 idFound;
size_t sizeFound;
if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
id = idFound;
else {
// type-name pair doesn't exist yet -- find unused ID
while (fResources->HasResource(type, id))
id++;
}
}
error = fResources->AddResource(type, id, buffer, bufferSize, name);
}
return error;
}
// _RemoveData
/*! \brief Removes an attribute or resource.
The removal location is specified by \a fWhere.
The object must be properly initialized. The parameters are NOT checked.
\param name The name of the attribute/resource to be remove.
\param type The type of the attribute/resource to be removed.
\return
- \c B_OK: Everything went fine.
- error code
*/
status_t
BAppFileInfo::_RemoveData(const char *name, type_code type)
{
status_t error = B_OK;
// remove the attribute
if (IsUsingAttributes() && error == B_OK) {
error = fNode->RemoveAttr(name);
// It's no error, if there has been no attribute.
if (error == B_ENTRY_NOT_FOUND)
error = B_OK;
}
// remove the resource
if (IsUsingResources() && error == B_OK) {
// get a resource info
int32 idFound;
size_t sizeFound;
if (fResources->GetResourceInfo(type, name, &idFound, &sizeFound))
error = fResources->RemoveResource(type, idFound);
}
return error;
}