xref: /haiku/src/kits/storage/mime/MimeInfoUpdater.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2002-2014, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Tyler Dauwalder
7  *		Rene Gollent, rene@gollent.com.
8  *		Michael Lotz, mmlr@mlotz.ch
9  *		Jonas Sundström, jonas@kirilla.com
10  *		Ingo Weinhold, ingo_weinhold@gmx.de
11  */
12 
13 
14 #include <mime/MimeInfoUpdater.h>
15 
16 #include <stdlib.h>
17 
18 #include <AppFileInfo.h>
19 #include <Bitmap.h>
20 #include <File.h>
21 #include <fs_attr.h>
22 #include <MimeType.h>
23 #include <String.h>
24 
25 #include <AutoLocker.h>
26 #include <mime/Database.h>
27 #include <mime/database_support.h>
28 
29 
30 static const char *kAppFlagsAttribute = "BEOS:APP_FLAGS";
31 
32 
33 static status_t
34 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
35 	const char *type, BBitmap &icon, icon_size iconSize)
36 {
37 	status_t err = appFileInfoRead.GetIconForType(type, &icon, iconSize);
38 	if (err == B_OK)
39 		err = appFileInfoWrite.SetIconForType(type, &icon, iconSize, false);
40 	else if (err == B_ENTRY_NOT_FOUND)
41 		err = appFileInfoWrite.SetIconForType(type, NULL, iconSize, false);
42 	return err;
43 }
44 
45 
46 static status_t
47 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
48 	const char *type)
49 {
50 	uint8* data = NULL;
51 	size_t size = 0;
52 
53 	status_t err = appFileInfoRead.GetIconForType(type, &data, &size);
54 	if (err == B_OK)
55 		err = appFileInfoWrite.SetIconForType(type, data, size, false);
56 	else if (err == B_ENTRY_NOT_FOUND)
57 		err = appFileInfoWrite.SetIconForType(type, NULL, size, false);
58 
59 	free(data);
60 
61 	return err;
62 }
63 
64 
65 static bool
66 is_shared_object_mime_type(const BString &type)
67 {
68 	return type.ICompare(B_APP_MIME_TYPE) == 0;
69 }
70 
71 
72 namespace BPrivate {
73 namespace Storage {
74 namespace Mime {
75 
76 
77 MimeInfoUpdater::MimeInfoUpdater(Database* database,
78 	DatabaseLocker* databaseLocker, int32 force)
79 	:
80 	MimeEntryProcessor(database, databaseLocker, force)
81 {
82 }
83 
84 
85 MimeInfoUpdater::~MimeInfoUpdater()
86 {
87 }
88 
89 
90 status_t
91 MimeInfoUpdater::Do(const entry_ref& entry, bool* _entryIsDir)
92 {
93 	bool updateType = false;
94 	bool updateAppInfo = false;
95 	BNode node;
96 
97 	status_t err = node.SetTo(&entry);
98 	if (!err && _entryIsDir)
99 		*_entryIsDir = node.IsDirectory();
100 	if (!err) {
101 		// If not forced, only update if the entry has no file type attribute
102 		attr_info info;
103 		if (fForce == B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL
104 			|| node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND) {
105 			updateType = true;
106 		}
107 		updateAppInfo = (updateType
108 			|| fForce == B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE);
109 	}
110 
111 	// guess the MIME type
112 	BString type;
113 	if (!err && (updateType || updateAppInfo)) {
114 		AutoLocker<DatabaseLocker> databaseLocker(fDatabaseLocker);
115 		err = fDatabase->GuessMimeType(&entry, &type);
116 	}
117 
118 	// update the MIME type
119 	if (!err && updateType) {
120 		ssize_t len = type.Length() + 1;
121 		ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, type,
122 			len);
123 		if (bytes < B_OK)
124 			err = bytes;
125 		else
126 			err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK);
127 	}
128 
129 	// update the app file info attributes, if this is a shared object
130 	BFile file;
131 	BAppFileInfo appFileInfoRead;
132 	BAppFileInfo appFileInfoWrite;
133 	if (!err && updateAppInfo && node.IsFile()
134 		&& is_shared_object_mime_type(type)
135 		&& (err = file.SetTo(&entry, B_READ_WRITE)) == B_OK
136 		&& (err = appFileInfoRead.SetTo(&file)) == B_OK
137 		&& (err = appFileInfoWrite.SetTo(&file)) == B_OK) {
138 
139 		// we read from resources and write to attributes
140 		appFileInfoRead.SetInfoLocation(B_USE_RESOURCES);
141 		appFileInfoWrite.SetInfoLocation(B_USE_ATTRIBUTES);
142 
143 		// signature
144 		char signature[B_MIME_TYPE_LENGTH];
145 		err = appFileInfoRead.GetSignature(signature);
146 		if (err == B_OK)
147 			err = appFileInfoWrite.SetSignature(signature);
148 		else if (err == B_ENTRY_NOT_FOUND)
149 			err = appFileInfoWrite.SetSignature(NULL);
150 		if (err != B_OK)
151 			return err;
152 
153 		// catalog entry
154 		char catalogEntry[B_MIME_TYPE_LENGTH * 3];
155 		err = appFileInfoRead.GetCatalogEntry(catalogEntry);
156 		if (err == B_OK)
157 			err = appFileInfoWrite.SetCatalogEntry(catalogEntry);
158 		else if (err == B_ENTRY_NOT_FOUND)
159 			err = appFileInfoWrite.SetCatalogEntry(NULL);
160 		if (err != B_OK)
161 			return err;
162 
163 		// app flags
164 		uint32 appFlags;
165 		err = appFileInfoRead.GetAppFlags(&appFlags);
166 		if (err == B_OK) {
167 			err = appFileInfoWrite.SetAppFlags(appFlags);
168 		} else if (err == B_ENTRY_NOT_FOUND) {
169 			file.RemoveAttr(kAppFlagsAttribute);
170 			err = B_OK;
171 		}
172 		if (err != B_OK)
173 			return err;
174 
175 		// supported types
176 		BMessage supportedTypes;
177 		bool hasSupportedTypes = false;
178 		err = appFileInfoRead.GetSupportedTypes(&supportedTypes);
179 		if (err == B_OK) {
180 			err = appFileInfoWrite.SetSupportedTypes(&supportedTypes, false,
181 				false);
182 			hasSupportedTypes = true;
183 		} else if (err == B_ENTRY_NOT_FOUND)
184 			err = appFileInfoWrite.SetSupportedTypes(NULL, false, false);
185 		if (err != B_OK)
186 			return err;
187 
188 		// vector icon
189 		err = update_icon(appFileInfoRead, appFileInfoWrite, NULL);
190 		if (err != B_OK)
191 			return err;
192 
193 		// small icon
194 		BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK,
195 			B_CMAP8);
196 		if (smallIcon.InitCheck() != B_OK)
197 			return smallIcon.InitCheck();
198 		err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon,
199 			B_MINI_ICON);
200 		if (err != B_OK)
201 			return err;
202 
203 		// large icon
204 		BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK,
205 			B_CMAP8);
206 		if (largeIcon.InitCheck() != B_OK)
207 			return largeIcon.InitCheck();
208 		err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon,
209 			B_LARGE_ICON);
210 		if (err != B_OK)
211 			return err;
212 
213 		// version infos
214 		const version_kind versionKinds[]
215 			= {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND};
216 		for (int i = 0; i < 2; i++) {
217 			version_kind kind = versionKinds[i];
218 			version_info versionInfo;
219 			err = appFileInfoRead.GetVersionInfo(&versionInfo, kind);
220 			if (err == B_OK)
221 				err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind);
222 			else if (err == B_ENTRY_NOT_FOUND)
223 				err = appFileInfoWrite.SetVersionInfo(NULL, kind);
224 			if (err != B_OK)
225 				return err;
226 		}
227 
228 		// icons for supported types
229 		if (hasSupportedTypes) {
230 			const char *supportedType;
231 			for (int32 i = 0;
232 				 supportedTypes.FindString("types", i, &supportedType) == B_OK;
233 				 i++) {
234 				// vector icon
235 				err = update_icon(appFileInfoRead, appFileInfoWrite,
236 					supportedType);
237 				if (err != B_OK)
238 					return err;
239 
240 				// small icon
241 				err = update_icon(appFileInfoRead, appFileInfoWrite,
242 					supportedType, smallIcon, B_MINI_ICON);
243 				if (err != B_OK)
244 					return err;
245 
246 				// large icon
247 				err = update_icon(appFileInfoRead, appFileInfoWrite,
248 					supportedType, largeIcon, B_LARGE_ICON);
249 				if (err != B_OK)
250 					return err;
251 			}
252 		}
253 	}
254 
255 	return err;
256 }
257 
258 
259 } // namespace Mime
260 } // namespace Storage
261 } // namespace BPrivate
262