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