From 98da112ccabc1bb25391a79e3effa70cd8747c15 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 25 Aug 2002 22:49:22 +0000 Subject: [PATCH] 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 --- headers/os/storage/AppFileInfo.h | 10 +- src/kits/storage/AppFileInfo.cpp | 792 ++++++++++++++++++++++++++++++- 2 files changed, 777 insertions(+), 25 deletions(-) diff --git a/headers/os/storage/AppFileInfo.h b/headers/os/storage/AppFileInfo.h index b88999e497..7694ef97af 100644 --- a/headers/os/storage/AppFileInfo.h +++ b/headers/os/storage/AppFileInfo.h @@ -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; diff --git a/src/kits/storage/AppFileInfo.cpp b/src/kits/storage/AppFileInfo.cpp index d66a15b5d6..7476f57a25 100644 --- a/src/kits/storage/AppFileInfo.cpp +++ b/src/kits/storage/AppFileInfo.cpp @@ -1,6 +1,48 @@ // BAppFileInfo.cpp +#include +#include +#include + #include +#include +#include +#include +#include +#include +#include +#include +#include + +// 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 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::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; +} +