1/*
2 * Copyright 2002-2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Tyler Dauwalder
7 *		Axel D��rfler, axeld@pinc-software.de
8 */
9
10
11#include "CreateAppMetaMimeThread.h"
12
13#include <stdio.h>
14#include <stdlib.h>
15
16#include <AppFileInfo.h>
17#include <Bitmap.h>
18#include <fs_attr.h>
19#include <MimeType.h>
20#include <Node.h>
21#include <Path.h>
22#include <String.h>
23
24#include <mime/database_support.h>
25
26#include "Database.h"
27
28
29namespace BPrivate {
30namespace Storage {
31namespace Mime {
32
33
34CreateAppMetaMimeThread::CreateAppMetaMimeThread(const char *name,
35	int32 priority, Database *database, BMessenger managerMessenger,
36	const entry_ref *root, bool recursive, int32 force, BMessage *replyee)
37	: MimeUpdateThread(name, priority, database, managerMessenger, root,
38		recursive, force, replyee)
39{
40}
41
42
43status_t
44CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir)
45{
46	if (ref == NULL)
47		return B_BAD_VALUE;
48
49	BNode typeNode;
50
51	BFile file;
52	status_t status = file.SetTo(ref, B_READ_ONLY | O_NOTRAVERSE);
53	if (status < B_OK)
54		return status;
55
56	bool isDir = file.IsDirectory();
57	if (_entryIsDir != NULL)
58		*_entryIsDir = isDir;
59
60	if (isDir || !file.IsFile())
61		return B_OK;
62
63	BAppFileInfo appInfo(&file);
64	status = appInfo.InitCheck();
65	if (status < B_OK)
66		return status;
67
68	// Read the app sig (which consequently keeps us from updating
69	// non-applications, since we get an error if the file has no
70	// app sig)
71	BString signature;
72	status = file.ReadAttrString("BEOS:APP_SIG", &signature);
73	if (status < B_OK)
74		return B_BAD_TYPE;
75
76	// Init our various objects
77
78	BMimeType mime;
79	status = mime.SetTo(signature.String());
80	if (status < B_OK)
81		return status;
82
83	InstallNotificationDeferrer _(fDatabase, signature.String());
84
85	if (!mime.IsInstalled())
86		mime.Install();
87
88	BString path = "/";
89	path.Append(signature);
90	path.ToLower();
91		// Signatures and MIME types are case insensitive, but we want to
92		// preserve the case wherever possible
93	path.Prepend(get_database_directory().c_str());
94
95	status = typeNode.SetTo(path.String());
96	if (status < B_OK)
97		return status;
98
99	// Preferred App
100	attr_info info;
101	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK))
102		status = mime.SetPreferredApp(signature.String());
103
104	// Short Description (name of the application)
105	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK))
106		status = mime.SetShortDescription(ref->name);
107
108	// App Hint
109	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK))
110		status = mime.SetAppHint(ref);
111
112	// Vector Icon
113	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) {
114		uint8* data = NULL;
115		size_t size = 0;
116		if (appInfo.GetIcon(&data, &size) == B_OK) {
117			status = mime.SetIcon(data, size);
118			free(data);
119		}
120	}
121	// Mini Icon
122	BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
123	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) {
124		if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK)
125			status = mime.SetIcon(&miniIcon, B_MINI_ICON);
126	}
127	// Large Icon
128	BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
129	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) {
130		if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK)
131			status = mime.SetIcon(&largeIcon, B_LARGE_ICON);
132	}
133
134	// Supported Types
135	bool setSupportedTypes = false;
136	BMessage supportedTypes;
137	if (status == B_OK && (fForce || typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) {
138		if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK)
139			setSupportedTypes = true;
140	}
141
142	// defer notifications for supported types
143	const char* type;
144	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
145		fDatabase->DeferInstallNotification(type);
146
147	// set supported types
148	if (setSupportedTypes)
149		status = mime.SetSupportedTypes(&supportedTypes);
150
151	// Icons for supported types
152	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) {
153		// vector icon
154		uint8* data = NULL;
155		size_t size = 0;
156		if (status == B_OK && appInfo.GetIconForType(type, &data, &size) == B_OK) {
157			status = mime.SetIconForType(type, data, size);
158			free(data);
159		}
160		// mini icon
161		if (status == B_OK && appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK)
162			status = mime.SetIconForType(type, &miniIcon, B_MINI_ICON);
163		// large icon
164		if (status == B_OK && appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK)
165			status = mime.SetIconForType(type, &largeIcon, B_LARGE_ICON);
166	}
167
168	// undefer notifications for supported types
169	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
170		fDatabase->UndeferInstallNotification(type);
171
172	return status;
173}
174
175}	// namespace Mime
176}	// namespace Storage
177}	// namespace BPrivate
178
179