xref: /haiku/src/servers/registrar/mime/UpdateMimeInfoThread.cpp (revision e7c8829c5d8e5d34a2a1e111f1c06aceff256013)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //---------------------------------------------------------------------
5 /*!
6 	\file UpdateMimeInfoThread.h
7 	UpdateMimeInfoThread implementation
8 */
9 
10 #include "UpdateMimeInfoThread.h"
11 
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <AppFileInfo.h>
16 #include <Bitmap.h>
17 #include <fs_attr.h>
18 #include <Message.h>
19 #include <MimeType.h>
20 #include <mime/database_support.h>
21 #include <Node.h>
22 
23 namespace BPrivate {
24 namespace Storage {
25 namespace Mime {
26 
27 static const char *kAppFlagsAttribute			= "BEOS:APP_FLAGS";
28 
29 // update_icon
30 static status_t
31 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
32 	const char *type, BBitmap &icon, icon_size iconSize)
33 {
34 	status_t err = appFileInfoRead.GetIconForType(type, &icon, iconSize);
35 	if (err == B_OK)
36 		err = appFileInfoWrite.SetIconForType(type, &icon, iconSize);
37 	else if (err == B_ENTRY_NOT_FOUND)
38 		err = appFileInfoWrite.SetIconForType(type, NULL, iconSize);
39 	return err;
40 }
41 
42 // update_icon
43 static status_t
44 update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite,
45 	const char *type)
46 {
47 	uint8* data = NULL;
48 	size_t size = 0;
49 
50 	status_t err = appFileInfoRead.GetIconForType(type, &data, &size);
51 	if (err == B_OK)
52 		err = appFileInfoWrite.SetIconForType(type, data, size);
53 	else if (err == B_ENTRY_NOT_FOUND)
54 		err = appFileInfoWrite.SetIconForType(type, NULL, size);
55 
56 	free(data);
57 
58 	return err;
59 }
60 
61 // is_shared_object_mime_type
62 static bool
63 is_shared_object_mime_type(BMimeType &type)
64 {
65 	return (type == B_APP_MIME_TYPE);
66 }
67 
68 
69 // constructor
70 //! Creates a new UpdateMimeInfoThread object
71 UpdateMimeInfoThread::UpdateMimeInfoThread(const char *name, int32 priority,
72 	Database *database, BMessenger managerMessenger, const entry_ref *root,
73 	bool recursive, int32 force, BMessage *replyee)
74 	: MimeUpdateThread(name, priority, database, managerMessenger, root,
75 		recursive, force, replyee)
76 {
77 }
78 
79 // DoMimeUpdate
80 /*! \brief Performs an update_mime_info() update on the given entry
81 
82 	If the entry has no \c BEOS:TYPE attribute, or if \c fForce is true, the
83 	entry is sniffed and its \c BEOS:TYPE attribute is set accordingly.
84 */
85 status_t
86 UpdateMimeInfoThread::DoMimeUpdate(const entry_ref *entry, bool *entryIsDir)
87 {
88 	status_t err = entry ? B_OK : B_BAD_VALUE;
89 	bool updateType = false;
90 	bool updateAppInfo = false;
91 	BNode node;
92 
93 	if (!err)
94 		err = node.SetTo(entry);
95 	if (!err && entryIsDir)
96 		*entryIsDir = node.IsDirectory();
97 	if (!err) {
98 		// If not forced, only update if the entry has no file type attribute
99 		attr_info info;
100 		if (fForce == B_UPDATE_MIME_INFO_FORCE_UPDATE_ALL
101 			|| node.GetAttrInfo(kFileTypeAttr, &info) == B_ENTRY_NOT_FOUND) {
102 			updateType = true;
103 		}
104 		updateAppInfo = (updateType
105 			|| fForce == B_UPDATE_MIME_INFO_FORCE_KEEP_TYPE);
106 	}
107 
108 	// guess the MIME type
109 	BMimeType type;
110 	if (!err && (updateType || updateAppInfo)) {
111 		err = BMimeType::GuessMimeType(entry, &type);
112 		if (!err)
113 			err = type.InitCheck();
114 	}
115 
116 	// update the MIME type
117 	if (!err && updateType) {
118 		const char *typeStr = type.Type();
119 		ssize_t len = strlen(typeStr)+1;
120 		ssize_t bytes = node.WriteAttr(kFileTypeAttr, kFileTypeType, 0, typeStr,
121 			len);
122 		if (bytes < B_OK)
123 			err = bytes;
124 		else
125 			err = (bytes != len ? (status_t)B_FILE_ERROR : (status_t)B_OK);
126 	}
127 
128 	// update the app file info attributes, if this is a shared object
129 	BFile file;
130 	BAppFileInfo appFileInfoRead;
131 	BAppFileInfo appFileInfoWrite;
132 	if (!err && updateAppInfo && node.IsFile()
133 		&& is_shared_object_mime_type(type)
134 		&& file.SetTo(entry, B_READ_WRITE) == B_OK
135 		&& appFileInfoRead.SetTo(&file) == B_OK
136 		&& appFileInfoWrite.SetTo(&file) == B_OK) {
137 
138 		// we read from resources and write to attributes
139 		appFileInfoRead.SetInfoLocation(B_USE_RESOURCES);
140 		appFileInfoWrite.SetInfoLocation(B_USE_ATTRIBUTES);
141 
142 		// signature
143 		char signature[B_MIME_TYPE_LENGTH];
144 		err = appFileInfoRead.GetSignature(signature);
145 		if (err == B_OK)
146 			err = appFileInfoWrite.SetSignature(signature);
147 		else if (err == B_ENTRY_NOT_FOUND)
148 			err = appFileInfoWrite.SetSignature(NULL);
149 		if (err != B_OK)
150 			return err;
151 
152 		// app flags
153 		uint32 appFlags;
154 		err = appFileInfoRead.GetAppFlags(&appFlags);
155 		if (err == B_OK) {
156 			err = appFileInfoWrite.SetAppFlags(appFlags);
157 		} else if (err == B_ENTRY_NOT_FOUND) {
158 			file.RemoveAttr(kAppFlagsAttribute);
159 			err = B_OK;
160 		}
161 		if (err != B_OK)
162 			return err;
163 
164 		// supported types
165 		BMessage supportedTypes;
166 		bool hasSupportedTypes = false;
167 		err = appFileInfoRead.GetSupportedTypes(&supportedTypes);
168 		if (err == B_OK) {
169 			err = appFileInfoWrite.SetSupportedTypes(&supportedTypes);
170 			hasSupportedTypes = true;
171 		} else if (err == B_ENTRY_NOT_FOUND)
172 			err = appFileInfoWrite.SetSupportedTypes(NULL);
173 		if (err != B_OK)
174 			return err;
175 
176 		// vector icon
177 		err = update_icon(appFileInfoRead, appFileInfoWrite, NULL);
178 		if (err != B_OK)
179 			return err;
180 
181 		// small icon
182 		BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK,
183 			B_CMAP8);
184 		if (smallIcon.InitCheck() != B_OK)
185 			return smallIcon.InitCheck();
186 		err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, smallIcon,
187 			B_MINI_ICON);
188 		if (err != B_OK)
189 			return err;
190 
191 		// large icon
192 		BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK,
193 			B_CMAP8);
194 		if (largeIcon.InitCheck() != B_OK)
195 			return largeIcon.InitCheck();
196 		err = update_icon(appFileInfoRead, appFileInfoWrite, NULL, largeIcon,
197 			B_LARGE_ICON);
198 		if (err != B_OK)
199 			return err;
200 
201 		// version infos
202 		const version_kind versionKinds[]
203 			= {B_APP_VERSION_KIND, B_SYSTEM_VERSION_KIND};
204 		for (int i = 0; i < 2; i++) {
205 			version_kind kind = versionKinds[i];
206 			version_info versionInfo;
207 			err = appFileInfoRead.GetVersionInfo(&versionInfo, kind);
208 			if (err == B_OK)
209 				err = appFileInfoWrite.SetVersionInfo(&versionInfo, kind);
210 			else if (err == B_ENTRY_NOT_FOUND)
211 				err = appFileInfoWrite.SetVersionInfo(NULL, kind);
212 			if (err != B_OK)
213 				return err;
214 		}
215 
216 		// icons for supported types
217 		if (hasSupportedTypes) {
218 			const char *supportedType;
219 			for (int32 i = 0;
220 				 supportedTypes.FindString("types", i, &supportedType) == B_OK;
221 				 i++) {
222 				// vector icon
223 				err = update_icon(appFileInfoRead, appFileInfoWrite,
224 					supportedType);
225 				if (err != B_OK)
226 					return err;
227 
228 				// small icon
229 				err = update_icon(appFileInfoRead, appFileInfoWrite,
230 					supportedType, smallIcon, B_MINI_ICON);
231 				if (err != B_OK)
232 					return err;
233 
234 				// large icon
235 				err = update_icon(appFileInfoRead, appFileInfoWrite,
236 					supportedType, largeIcon, B_LARGE_ICON);
237 				if (err != B_OK)
238 					return err;
239 			}
240 		}
241 	}
242 
243 	return err;
244 }
245 
246 }	// namespace Mime
247 }	// namespace Storage
248 }	// namespace BPrivate
249 
250