1/*
2 * Copyright 2002-2013, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Tyler Dauwalder
7 *		Axel D��rfler, axeld@pinc-software.de
8 *		Ingo Weinhold, ingo_weinhold@gmx.de
9 */
10
11
12#include <mime/AppMetaMimeCreator.h>
13
14#include <stdlib.h>
15
16#include <AppFileInfo.h>
17#include <Bitmap.h>
18#include <File.h>
19#include <fs_attr.h>
20#include <Message.h>
21#include <MimeType.h>
22#include <String.h>
23
24#include <AutoLocker.h>
25#include <mime/Database.h>
26#include <mime/database_support.h>
27#include <mime/DatabaseLocation.h>
28
29
30namespace BPrivate {
31namespace Storage {
32namespace Mime {
33
34
35AppMetaMimeCreator::AppMetaMimeCreator(Database* database,
36	DatabaseLocker* databaseLocker, int32 force)
37	:
38	MimeEntryProcessor(database, databaseLocker, force)
39{
40}
41
42
43AppMetaMimeCreator::~AppMetaMimeCreator()
44{
45}
46
47
48status_t
49AppMetaMimeCreator::Do(const entry_ref& entry, bool* _entryIsDir)
50{
51	BFile file;
52	status_t status = file.SetTo(&entry, 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	if (!BMimeType::IsValid(signature))
77		return B_BAD_TYPE;
78
79	InstallNotificationDeferrer _(fDatabase, signature.String());
80
81	if (!fDatabase->Location()->IsInstalled(signature)) {
82		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
83		fDatabase->Install(signature);
84	}
85
86	BNode typeNode;
87	status = fDatabase->Location()->OpenType(signature, typeNode);
88	if (status != B_OK)
89		return status;
90
91	// Preferred App
92	attr_info info;
93	if (status == B_OK
94		&& (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) {
95		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
96		status = fDatabase->SetPreferredApp(signature, signature);
97	}
98
99	// Short Description (name of the application)
100	if (status == B_OK
101		&& (fForce
102			|| typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) {
103		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
104		status = fDatabase->SetShortDescription(signature, entry.name);
105	}
106
107	// App Hint
108	if (status == B_OK
109		&& (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) {
110		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
111		status = fDatabase->SetAppHint(signature, &entry);
112	}
113
114	// Vector Icon
115	if (status == B_OK
116		&& (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) {
117		uint8* data = NULL;
118		size_t size = 0;
119		if (appInfo.GetIcon(&data, &size) == B_OK) {
120			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
121			status = fDatabase->SetIcon(signature, data, size);
122			free(data);
123		}
124	}
125	// Mini Icon
126	BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
127	if (status == B_OK
128		&& (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) {
129		if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) {
130			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
131			status = fDatabase->SetIcon(signature, &miniIcon, B_MINI_ICON);
132		}
133	}
134	// Large Icon
135	BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
136	if (status == B_OK
137		&& (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) {
138		if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) {
139			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
140			status = fDatabase->SetIcon(signature, &largeIcon, B_LARGE_ICON);
141		}
142	}
143
144	// Supported Types
145	bool setSupportedTypes = false;
146	BMessage supportedTypes;
147	if (status == B_OK
148		&& (fForce
149			|| typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) {
150		if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK)
151			setSupportedTypes = true;
152	}
153
154	// defer notifications for supported types
155	const char* type;
156	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
157		fDatabase->DeferInstallNotification(type);
158
159	// set supported types
160	if (setSupportedTypes) {
161		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
162		status = fDatabase->SetSupportedTypes(signature, &supportedTypes, true);
163	}
164
165	// Icons for supported types
166	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK;
167		 i++) {
168		// vector icon
169		uint8* data = NULL;
170		size_t size = 0;
171		if (status == B_OK
172			&& appInfo.GetIconForType(type, &data, &size) == B_OK) {
173			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
174			status = fDatabase->SetIconForType(signature, type, data, size);
175			free(data);
176		}
177		// mini icon
178		if (status == B_OK
179			&& appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) {
180			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
181			status = fDatabase->SetIconForType(signature, type, &miniIcon,
182				B_MINI_ICON);
183		}
184		// large icon
185		if (status == B_OK
186			&& appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) {
187			AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
188			status = fDatabase->SetIconForType(signature, type, &largeIcon,
189				B_LARGE_ICON);
190		}
191	}
192
193	// undefer notifications for supported types
194	for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++)
195		fDatabase->UndeferInstallNotification(type);
196
197	return status;
198}
199
200
201} // namespace Mime
202} // namespace Storage
203} // namespace BPrivate
204