repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / kits / storage / Mime.cpp
blobaca9e2535620f1a10acd2f55328a4ddba0623c63
1 /*
2 * Copyright 2002-2008, Haiku Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Tyler Dauwalder
7 * Ingo Weinhold, bonefish@users.sf.net
8 * Axel Dörfler, axeld@pinc-software.de
9 */
12 #include <errno.h>
13 #include <new>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17 #include <unistd.h>
19 #include <AutoDeleter.h>
20 #include <Bitmap.h>
21 #include <Drivers.h>
22 #include <Entry.h>
23 #include <File.h>
24 #include <FindDirectory.h>
25 #include <fs_attr.h>
26 #include <fs_info.h>
27 #include <IconUtils.h>
28 #include <Mime.h>
29 #include <MimeType.h>
30 #include <Node.h>
31 #include <Path.h>
32 #include <RegistrarDefs.h>
33 #include <Roster.h>
34 #include <RosterPrivate.h>
37 using namespace BPrivate;
39 enum {
40 NOT_IMPLEMENTED = B_ERROR,
44 // Helper function that contacts the registrar for mime update calls
45 status_t
46 do_mime_update(int32 what, const char* path, int recursive,
47 int synchronous, int force)
49 BEntry root;
50 entry_ref ref;
52 status_t err = root.SetTo(path ? path : "/");
53 if (!err)
54 err = root.GetRef(&ref);
55 if (!err) {
56 BMessage msg(what);
57 BMessage reply;
58 status_t result;
60 // Build and send the message, read the reply
61 if (!err)
62 err = msg.AddRef("entry", &ref);
63 if (!err)
64 err = msg.AddBool("recursive", recursive);
65 if (!err)
66 err = msg.AddBool("synchronous", synchronous);
67 if (!err)
68 err = msg.AddInt32("force", force);
69 if (!err)
70 err = BRoster::Private().SendTo(&msg, &reply, true);
71 if (!err)
72 err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE;
73 if (!err)
74 err = reply.FindInt32("result", &result);
75 if (!err)
76 err = result;
78 return err;
82 // Updates the MIME information (i.e MIME type) for one or more files.
83 int
84 update_mime_info(const char* path, int recursive, int synchronous, int force)
86 // Force recursion when given a NULL path
87 if (!path)
88 recursive = true;
90 return do_mime_update(B_REG_MIME_UPDATE_MIME_INFO, path, recursive,
91 synchronous, force);
95 // Creates a MIME database entry for one or more applications.
96 status_t
97 create_app_meta_mime(const char* path, int recursive, int synchronous,
98 int force)
100 // Force recursion when given a NULL path
101 if (!path)
102 recursive = true;
104 return do_mime_update(B_REG_MIME_CREATE_APP_META_MIME, path, recursive,
105 synchronous, force);
109 // Retrieves an icon associated with a given device.
110 status_t
111 get_device_icon(const char* device, void* icon, int32 size)
113 if (device == NULL || icon == NULL
114 || (size != B_LARGE_ICON && size != B_MINI_ICON))
115 return B_BAD_VALUE;
117 int fd = open(device, O_RDONLY);
118 if (fd < 0)
119 return errno;
121 // ToDo: The mounted directories for volumes can also have META:X:STD_ICON
122 // attributes. Should those attributes override the icon returned by
123 // ioctl(,B_GET_ICON,)?
124 device_icon iconData = {size, icon};
125 if (ioctl(fd, B_GET_ICON, &iconData) != 0) {
126 // legacy icon was not available, try vector icon
127 close(fd);
129 uint8* data;
130 size_t dataSize;
131 type_code type;
132 status_t status = get_device_icon(device, &data, &dataSize, &type);
133 if (status == B_OK) {
134 BBitmap* icon32 = new(std::nothrow) BBitmap(
135 BRect(0, 0, size - 1, size - 1), B_BITMAP_NO_SERVER_LINK,
136 B_RGBA32);
137 BBitmap* icon8 = new(std::nothrow) BBitmap(
138 BRect(0, 0, size - 1, size - 1), B_BITMAP_NO_SERVER_LINK,
139 B_CMAP8);
141 ArrayDeleter<uint8> dataDeleter(data);
142 ObjectDeleter<BBitmap> icon32Deleter(icon32);
143 ObjectDeleter<BBitmap> icon8Deleter(icon8);
145 if (icon32 == NULL || icon32->InitCheck() != B_OK || icon8 == NULL
146 || icon8->InitCheck() != B_OK) {
147 return B_NO_MEMORY;
150 status = BIconUtils::GetVectorIcon(data, dataSize, icon32);
151 if (status == B_OK)
152 status = BIconUtils::ConvertToCMAP8(icon32, icon8);
153 if (status == B_OK)
154 memcpy(icon, icon8->Bits(), icon8->BitsLength());
156 return status;
158 return errno;
161 close(fd);
162 return B_OK;
166 // Retrieves an icon associated with a given device.
167 status_t
168 get_device_icon(const char* device, BBitmap* icon, icon_size which)
170 // check parameters
171 if (device == NULL || icon == NULL)
172 return B_BAD_VALUE;
174 uint8* data;
175 size_t size;
176 type_code type;
177 status_t status = get_device_icon(device, &data, &size, &type);
178 if (status == B_OK) {
179 status = BIconUtils::GetVectorIcon(data, size, icon);
180 delete[] data;
181 return status;
184 // Vector icon was not available, try old one
186 BRect rect;
187 if (which == B_MINI_ICON)
188 rect.Set(0, 0, 15, 15);
189 else if (which == B_LARGE_ICON)
190 rect.Set(0, 0, 31, 31);
192 BBitmap* bitmap = icon;
193 int32 iconSize = which;
195 if (icon->ColorSpace() != B_CMAP8
196 || (which != B_MINI_ICON && which != B_LARGE_ICON)) {
197 if (which < B_LARGE_ICON)
198 iconSize = B_MINI_ICON;
199 else
200 iconSize = B_LARGE_ICON;
202 bitmap = new(std::nothrow) BBitmap(
203 BRect(0, 0, iconSize - 1, iconSize -1), B_BITMAP_NO_SERVER_LINK,
204 B_CMAP8);
205 if (bitmap == NULL || bitmap->InitCheck() != B_OK) {
206 delete bitmap;
207 return B_NO_MEMORY;
211 // get the icon, convert temporary data into bitmap if necessary
212 status = get_device_icon(device, bitmap->Bits(), iconSize);
213 if (status == B_OK && icon != bitmap)
214 status = BIconUtils::ConvertFromCMAP8(bitmap, icon);
216 if (icon != bitmap)
217 delete bitmap;
219 return status;
223 status_t
224 get_device_icon(const char* device, uint8** _data, size_t* _size,
225 type_code* _type)
227 if (device == NULL || _data == NULL || _size == NULL || _type == NULL)
228 return B_BAD_VALUE;
230 int fd = open(device, O_RDONLY);
231 if (fd < 0)
232 return errno;
234 // Try to get the icon by name first
236 char name[B_FILE_NAME_LENGTH];
237 if (ioctl(fd, B_GET_ICON_NAME, name) >= 0) {
238 status_t status = get_named_icon(name, _data, _size, _type);
239 if (status == B_OK) {
240 close(fd);
241 return B_OK;
245 // Getting the named icon failed, try vector icon next
247 // NOTE: The actual icon size is unknown as of yet. After the first call
248 // to B_GET_VECTOR_ICON, the actual size is known and the final buffer
249 // is allocated with the correct size. If the buffer needed to be
250 // larger, then the temporary buffer above will not yet contain the
251 // valid icon data. In that case, a second call to B_GET_VECTOR_ICON
252 // retrieves it into the final buffer.
253 uint8 data[8192];
254 device_icon iconData = {sizeof(data), data};
255 status_t status = ioctl(fd, B_GET_VECTOR_ICON, &iconData,
256 sizeof(device_icon));
257 if (status != 0)
258 status = errno;
260 if (status == B_OK) {
261 *_data = new(std::nothrow) uint8[iconData.icon_size];
262 if (*_data == NULL)
263 status = B_NO_MEMORY;
266 if (status == B_OK) {
267 if (iconData.icon_size > (int32)sizeof(data)) {
268 // the stack buffer does not contain the data, see NOTE above
269 iconData.icon_data = *_data;
270 status = ioctl(fd, B_GET_VECTOR_ICON, &iconData,
271 sizeof(device_icon));
272 if (status != 0)
273 status = errno;
274 } else
275 memcpy(*_data, data, iconData.icon_size);
277 *_size = iconData.icon_size;
278 *_type = B_VECTOR_ICON_TYPE;
281 // TODO: also support getting the old icon?
282 close(fd);
283 return status;
287 status_t
288 get_named_icon(const char* name, BBitmap* icon, icon_size which)
290 // check parameters
291 if (name == NULL || icon == NULL)
292 return B_BAD_VALUE;
294 BRect rect;
295 if (which == B_MINI_ICON)
296 rect.Set(0, 0, 15, 15);
297 else if (which == B_LARGE_ICON)
298 rect.Set(0, 0, 31, 31);
299 else
300 return B_BAD_VALUE;
302 if (icon->Bounds() != rect)
303 return B_BAD_VALUE;
305 uint8* data;
306 size_t size;
307 type_code type;
308 status_t status = get_named_icon(name, &data, &size, &type);
309 if (status == B_OK) {
310 status = BIconUtils::GetVectorIcon(data, size, icon);
311 delete[] data;
314 return status;
318 status_t
319 get_named_icon(const char* name, uint8** _data, size_t* _size, type_code* _type)
321 if (name == NULL || _data == NULL || _size == NULL || _type == NULL)
322 return B_BAD_VALUE;
324 directory_which kWhich[] = {
325 B_USER_NONPACKAGED_DATA_DIRECTORY,
326 B_USER_DATA_DIRECTORY,
327 B_SYSTEM_NONPACKAGED_DATA_DIRECTORY,
328 B_SYSTEM_DATA_DIRECTORY,
331 status_t status = B_ENTRY_NOT_FOUND;
332 BFile file;
333 off_t size;
335 for (uint32 i = 0; i < sizeof(kWhich) / sizeof(kWhich[0]); i++) {
336 BPath path;
337 if (find_directory(kWhich[i], &path) != B_OK)
338 continue;
340 path.Append("icons");
341 path.Append(name);
343 status = file.SetTo(path.Path(), B_READ_ONLY);
344 if (status == B_OK) {
345 status = file.GetSize(&size);
346 if (size > 1024 * 1024)
347 status = B_ERROR;
349 if (status == B_OK)
350 break;
353 if (status != B_OK)
354 return status;
356 *_data = new(std::nothrow) uint8[size];
357 if (*_data == NULL)
358 return B_NO_MEMORY;
360 if (file.Read(*_data, size) != size) {
361 delete[] *_data;
362 return B_ERROR;
365 *_size = size;
366 *_type = B_VECTOR_ICON_TYPE;
367 // TODO: for now
369 return B_OK;