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
update_icon(BAppFileInfo & appFileInfoRead,BAppFileInfo & appFileInfoWrite,const char * type,BBitmap & icon,icon_size iconSize)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
update_icon(BAppFileInfo & appFileInfoRead,BAppFileInfo & appFileInfoWrite,const char * type)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
is_shared_object_mime_type(const BString & type)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
MimeInfoUpdater(Database * database,DatabaseLocker * databaseLocker,int32 force)77 MimeInfoUpdater::MimeInfoUpdater(Database* database,
78 DatabaseLocker* databaseLocker, int32 force)
79 :
80 MimeEntryProcessor(database, databaseLocker, force)
81 {
82 }
83
84
~MimeInfoUpdater()85 MimeInfoUpdater::~MimeInfoUpdater()
86 {
87 }
88
89
90 status_t
Do(const entry_ref & entry,bool * _entryIsDir)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