#include <mime/MimeInfoUpdater.h>
#include <stdlib.h>
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <File.h>
#include <fs_attr.h>
#include <MimeType.h>
#include <String.h>
#include <AutoLocker.h>
#include <mime/Database.h>
#include <mime/database_support.h>
static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS";
static status_t
update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
const char *type, BBitmap &icon, icon_size iconSize)
{
status_t err = appFileInfoRead.GetIconForType(type, &icon, iconSize);
if (err == B_OK)
err = appFileInfoWrite.SetIconForType(type, &icon, iconSize, false);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetIconForType(type, NULL, iconSize, false);
return err;
}
static status_t
update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
const char *type)
{
uint8* data = NULL;
size_t size = 0;
status_t err = appFileInfoRead.GetIconForType(type, &data, &size);
if (err == B_OK)
err = appFileInfoWrite.SetIconForType(type, data, size, false);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetIconForType(type, NULL, size, false);
free(data);
return err;
}
static bool
is_shared_object_mime_type(const BString &type)
{
return type.ICompare(B_APP_MIME_TYPE) == 0;
}
namespace BPrivate {
namespace Storage {
namespace Mime {
MimeInfoUpdater::MimeInfoUpdater(Database* database,
DatabaseLocker* databaseLocker, int32 force)
:
MimeEntryProcessor(database, databaseLocker, force)
{
}
MimeInfoUpdater::~MimeInfoUpdater()
{
}
status_t
MimeInfoUpdater::Do(const entry_ref& entry, bool* _entryIsDir)
{
bool updateType = false;
bool updateAppInfo = false;
BNode node;
status_t err = node.SetTo(&entry);
if (!err && _entryIsDir)
*_entryIsDir = node.IsDirectory();
if (!err) {
attr_info info;
if (fForce == B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL
|| node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND) {
updateType = true;
}
updateAppInfo = (updateType
|| fForce == B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE);
}
BString type;
if (!err && (updateType || updateAppInfo)) {
AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
err = fDatabase->GuessMimeType(&entry, &type);
}
if (!err && updateType) {
ssize_t len = type.Length() + 1;
ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, type,
len);
if (bytes < B_OK)
err = bytes;
else
err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK);
}
BFile file;
BAppFileInfo appFileInfoRead;
BAppFileInfo appFileInfoWrite;
if (!err && updateAppInfo && node.IsFile()
&& is_shared_object_mime_type(type)
&& (err = file.SetTo(&entry, B_READ_WRITE)) == B_OK
&& (err = appFileInfoRead.SetTo(&file)) == B_OK
&& (err = appFileInfoWrite.SetTo(&file)) == B_OK) {
appFileInfoRead.SetInfoLocation(B_USE_RESOURCES);
appFileInfoWrite.SetInfoLocation(B_USE_ATTRIBUTES);
char signature[B_MIME_TYPE_LENGTH];
err = appFileInfoRead.GetSignature(signature);
if (err == B_OK)
err = appFileInfoWrite.SetSignature(signature);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetSignature(NULL);
if (err != B_OK)
return err;
char catalogEntry[B_MIME_TYPE_LENGTH * 3];
err = appFileInfoRead.GetCatalogEntry(catalogEntry);
if (err == B_OK)
err = appFileInfoWrite.SetCatalogEntry(catalogEntry);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetCatalogEntry(NULL);
if (err != B_OK)
return err;
uint32 appFlags;
err = appFileInfoRead.GetAppFlags(&appFlags);
if (err == B_OK) {
err = appFileInfoWrite.SetAppFlags(appFlags);
} else if (err == B_ENTRY_NOT_FOUND) {
file.RemoveAttr(kAppFlagsAttribute);
err = B_OK;
}
if (err != B_OK)
return err;
BMessage supportedTypes;
bool hasSupportedTypes = false;
err = appFileInfoRead.GetSupportedTypes(&supportedTypes);
if (err == B_OK) {
err = appFileInfoWrite.SetSupportedTypes(&supportedTypes, false,
false);
hasSupportedTypes = true;
} else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetSupportedTypes(NULL, false, false);
if (err != B_OK)
return err;
err = update_icon(appFileInfoRead, appFileInfoWrite, NULL);
if (err != B_OK)
return err;
BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK,
B_CMAP8);
if (smallIcon.InitCheck() != B_OK)
return smallIcon.InitCheck();
err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon,
B_MINI_ICON);
if (err != B_OK)
return err;
BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK,
B_CMAP8);
if (largeIcon.InitCheck() != B_OK)
return largeIcon.InitCheck();
err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon,
B_LARGE_ICON);
if (err != B_OK)
return err;
const version_kind versionKinds[]
= {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND};
for (int i = 0; i < 2; i++) {
version_kind kind = versionKinds[i];
version_info versionInfo;
err = appFileInfoRead.GetVersionInfo(&versionInfo, kind);
if (err == B_OK)
err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind);
else if (err == B_ENTRY_NOT_FOUND)
err = appFileInfoWrite.SetVersionInfo(NULL, kind);
if (err != B_OK)
return err;
}
if (hasSupportedTypes) {
const char *supportedType;
for (int32 i = 0;
supportedTypes.FindString("types", i, &supportedType) == B_OK;
i++) {
err = update_icon(appFileInfoRead, appFileInfoWrite,
supportedType);
if (err != B_OK)
return err;
err = update_icon(appFileInfoRead, appFileInfoWrite,
supportedType, smallIcon, B_MINI_ICON);
if (err != B_OK)
return err;
err = update_icon(appFileInfoRead, appFileInfoWrite,
supportedType, largeIcon, B_LARGE_ICON);
if (err != B_OK)
return err;
}
}
}
return err;
}
}
}
}