PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/src/kits/storage/Mime.cpp

http://github.com/Barrett17/Haiku-services-branch
C++ | 373 lines | 267 code | 66 blank | 40 comment | 124 complexity | 62c5f64420300202864f3aba2c14e2ef MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, LGPL-2.0, LGPL-2.1, BSD-2-Clause, ISC, Apache-2.0, AGPL-1.0, MIT, MPL-2.0-no-copyleft-exception, Unlicense, BSD-3-Clause, LGPL-3.0
  1. /*
  2. * Copyright 2002-2008, Haiku Inc.
  3. * Distributed under the terms of the MIT License.
  4. *
  5. * Authors:
  6. * Tyler Dauwalder
  7. * Ingo Weinhold, bonefish@users.sf.net
  8. * Axel Dörfler, axeld@pinc-software.de
  9. */
  10. /*!
  11. \file Mime.cpp
  12. Mime type C functions implementation.
  13. */
  14. #include <errno.h>
  15. #include <new>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/ioctl.h>
  19. #include <unistd.h>
  20. #include <AutoDeleter.h>
  21. #include <Bitmap.h>
  22. #include <Drivers.h>
  23. #include <Entry.h>
  24. #include <File.h>
  25. #include <FindDirectory.h>
  26. #include <fs_attr.h>
  27. #include <fs_info.h>
  28. #include <IconUtils.h>
  29. #include <Mime.h>
  30. #include <MimeType.h>
  31. #include <mime/database_access.h>
  32. #include <Node.h>
  33. #include <Path.h>
  34. #include <RegistrarDefs.h>
  35. #include <Roster.h>
  36. #include <RosterPrivate.h>
  37. using namespace BPrivate;
  38. enum {
  39. NOT_IMPLEMENTED = B_ERROR,
  40. };
  41. // Helper function that contacts the registrar for mime update calls
  42. status_t
  43. do_mime_update(int32 what, const char *path, int recursive,
  44. int synchronous, int force)
  45. {
  46. BEntry root;
  47. entry_ref ref;
  48. status_t err = root.SetTo(path ? path : "/");
  49. if (!err)
  50. err = root.GetRef(&ref);
  51. if (!err) {
  52. BMessage msg(what);
  53. BMessage reply;
  54. status_t result;
  55. // Build and send the message, read the reply
  56. if (!err)
  57. err = msg.AddRef("entry", &ref);
  58. if (!err)
  59. err = msg.AddBool("recursive", recursive);
  60. if (!err)
  61. err = msg.AddBool("synchronous", synchronous);
  62. if (!err)
  63. err = msg.AddInt32("force", force);
  64. if (!err)
  65. err = BRoster::Private().SendTo(&msg, &reply, true);
  66. if (!err)
  67. err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE;
  68. if (!err)
  69. err = reply.FindInt32("result", &result);
  70. if (!err)
  71. err = result;
  72. }
  73. return err;
  74. }
  75. // Updates the MIME information (i.e MIME type) for one or more files.
  76. int
  77. update_mime_info(const char *path, int recursive, int synchronous, int force)
  78. {
  79. // Force recursion when given a NULL path
  80. if (!path)
  81. recursive = true;
  82. return do_mime_update(B_REG_MIME_UPDATE_MIME_INFO, path, recursive,
  83. synchronous, force);
  84. }
  85. // Creates a MIME database entry for one or more applications.
  86. status_t
  87. create_app_meta_mime(const char *path, int recursive, int synchronous,
  88. int force)
  89. {
  90. // Force recursion when given a NULL path
  91. if (!path)
  92. recursive = true;
  93. return do_mime_update(B_REG_MIME_CREATE_APP_META_MIME, path, recursive,
  94. synchronous, force);
  95. }
  96. // Retrieves an icon associated with a given device.
  97. status_t
  98. get_device_icon(const char *device, void *icon, int32 size)
  99. {
  100. if (device == NULL || icon == NULL
  101. || (size != B_LARGE_ICON && size != B_MINI_ICON))
  102. return B_BAD_VALUE;
  103. int fd = open(device, O_RDONLY);
  104. if (fd < 0)
  105. return errno;
  106. // ToDo: The mounted directories for volumes can also have META:X:STD_ICON
  107. // attributes. Should those attributes override the icon returned by
  108. // ioctl(,B_GET_ICON,)?
  109. device_icon iconData = {size, icon};
  110. if (ioctl(fd, B_GET_ICON, &iconData) != 0) {
  111. // legacy icon was not available, try vector icon
  112. close(fd);
  113. uint8* data;
  114. size_t dataSize;
  115. type_code type;
  116. status_t status = get_device_icon(device, &data, &dataSize, &type);
  117. if (status == B_OK) {
  118. BBitmap* icon32 = new(std::nothrow) BBitmap(
  119. BRect(0, 0, size - 1, size - 1), B_BITMAP_NO_SERVER_LINK,
  120. B_RGBA32);
  121. BBitmap* icon8 = new(std::nothrow) BBitmap(
  122. BRect(0, 0, size - 1, size - 1), B_BITMAP_NO_SERVER_LINK,
  123. B_CMAP8);
  124. ArrayDeleter<uint8> dataDeleter(data);
  125. ObjectDeleter<BBitmap> icon32Deleter(icon32);
  126. ObjectDeleter<BBitmap> icon8Deleter(icon8);
  127. if (icon32 == NULL || icon32->InitCheck() != B_OK || icon8 == NULL
  128. || icon8->InitCheck() != B_OK) {
  129. return B_NO_MEMORY;
  130. }
  131. status = BIconUtils::GetVectorIcon(data, dataSize, icon32);
  132. if (status == B_OK)
  133. status = BIconUtils::ConvertToCMAP8(icon32, icon8);
  134. if (status == B_OK)
  135. memcpy(icon, icon8->Bits(), icon8->BitsLength());
  136. return status;
  137. }
  138. return errno;
  139. }
  140. close(fd);
  141. return B_OK;
  142. }
  143. // Retrieves an icon associated with a given device.
  144. status_t
  145. get_device_icon(const char *device, BBitmap *icon, icon_size which)
  146. {
  147. // check parameters
  148. if (device == NULL || icon == NULL)
  149. return B_BAD_VALUE;
  150. uint8* data;
  151. size_t size;
  152. type_code type;
  153. status_t status = get_device_icon(device, &data, &size, &type);
  154. if (status == B_OK) {
  155. status = BIconUtils::GetVectorIcon(data, size, icon);
  156. delete[] data;
  157. return status;
  158. }
  159. // Vector icon was not available, try old one
  160. BRect rect;
  161. if (which == B_MINI_ICON)
  162. rect.Set(0, 0, 15, 15);
  163. else if (which == B_LARGE_ICON)
  164. rect.Set(0, 0, 31, 31);
  165. BBitmap* bitmap = icon;
  166. int32 iconSize = which;
  167. if (icon->ColorSpace() != B_CMAP8
  168. || (which != B_MINI_ICON && which != B_LARGE_ICON)) {
  169. if (which < B_LARGE_ICON)
  170. iconSize = B_MINI_ICON;
  171. else
  172. iconSize = B_LARGE_ICON;
  173. bitmap = new(std::nothrow) BBitmap(
  174. BRect(0, 0, iconSize - 1, iconSize -1), B_BITMAP_NO_SERVER_LINK,
  175. B_CMAP8);
  176. if (bitmap == NULL || bitmap->InitCheck() != B_OK) {
  177. delete bitmap;
  178. return B_NO_MEMORY;
  179. }
  180. }
  181. // get the icon, convert temporary data into bitmap if necessary
  182. status = get_device_icon(device, bitmap->Bits(), iconSize);
  183. if (status == B_OK && icon != bitmap)
  184. status = BIconUtils::ConvertFromCMAP8(bitmap, icon);
  185. if (icon != bitmap)
  186. delete bitmap;
  187. return status;
  188. }
  189. status_t
  190. get_device_icon(const char *device, uint8** _data, size_t* _size,
  191. type_code* _type)
  192. {
  193. if (device == NULL || _data == NULL || _size == NULL || _type == NULL)
  194. return B_BAD_VALUE;
  195. int fd = open(device, O_RDONLY);
  196. if (fd < 0)
  197. return errno;
  198. // Try to get the icon by name first
  199. char name[B_FILE_NAME_LENGTH];
  200. if (ioctl(fd, B_GET_ICON_NAME, name) >= 0) {
  201. status_t status = get_named_icon(name, _data, _size, _type);
  202. if (status == B_OK) {
  203. close(fd);
  204. return B_OK;
  205. }
  206. }
  207. // Getting the named icon failed, try vector icon next
  208. // NOTE: The actual icon size is unknown as of yet. After the first call
  209. // to B_GET_VECTOR_ICON, the actual size is known and the final buffer
  210. // is allocated with the correct size. If the buffer needed to be
  211. // larger, then the temporary buffer above will not yet contain the
  212. // valid icon data. In that case, a second call to B_GET_VECTOR_ICON
  213. // retrieves it into the final buffer.
  214. uint8 data[8192];
  215. device_icon iconData = {sizeof(data), data};
  216. status_t status = ioctl(fd, B_GET_VECTOR_ICON, &iconData,
  217. sizeof(device_icon));
  218. if (status != 0)
  219. status = errno;
  220. if (status == B_OK) {
  221. *_data = new(std::nothrow) uint8[iconData.icon_size];
  222. if (*_data == NULL)
  223. status = B_NO_MEMORY;
  224. }
  225. if (status == B_OK) {
  226. if (iconData.icon_size > (int32)sizeof(data)) {
  227. // the stack buffer does not contain the data, see NOTE above
  228. iconData.icon_data = *_data;
  229. status = ioctl(fd, B_GET_VECTOR_ICON, &iconData,
  230. sizeof(device_icon));
  231. if (status != 0)
  232. status = errno;
  233. } else
  234. memcpy(*_data, data, iconData.icon_size);
  235. *_size = iconData.icon_size;
  236. *_type = B_VECTOR_ICON_TYPE;
  237. }
  238. // TODO: also support getting the old icon?
  239. close(fd);
  240. return status;
  241. }
  242. status_t
  243. get_named_icon(const char* name, BBitmap* icon, icon_size which)
  244. {
  245. // check parameters
  246. if (name == NULL || icon == NULL)
  247. return B_BAD_VALUE;
  248. BRect rect;
  249. if (which == B_MINI_ICON)
  250. rect.Set(0, 0, 15, 15);
  251. else if (which == B_LARGE_ICON)
  252. rect.Set(0, 0, 31, 31);
  253. else
  254. return B_BAD_VALUE;
  255. if (icon->Bounds() != rect)
  256. return B_BAD_VALUE;
  257. uint8* data;
  258. size_t size;
  259. type_code type;
  260. status_t status = get_named_icon(name, &data, &size, &type);
  261. if (status == B_OK)
  262. status = BIconUtils::GetVectorIcon(data, size, icon);
  263. delete[] data;
  264. return status;
  265. }
  266. status_t
  267. get_named_icon(const char* name, uint8** _data, size_t* _size, type_code* _type)
  268. {
  269. if (name == NULL || _data == NULL || _size == NULL || _type == NULL)
  270. return B_BAD_VALUE;
  271. directory_which kWhich[] = {
  272. B_USER_DATA_DIRECTORY,
  273. B_COMMON_DATA_DIRECTORY,
  274. B_BEOS_DATA_DIRECTORY,
  275. };
  276. status_t status = B_ENTRY_NOT_FOUND;
  277. BFile file;
  278. off_t size;
  279. for (uint32 i = 0; i < sizeof(kWhich) / sizeof(kWhich[0]); i++) {
  280. BPath path;
  281. if (find_directory(kWhich[i], &path) != B_OK)
  282. continue;
  283. path.Append("icons");
  284. path.Append(name);
  285. status = file.SetTo(path.Path(), B_READ_ONLY);
  286. if (status == B_OK) {
  287. status = file.GetSize(&size);
  288. if (size > 1024 * 1024)
  289. status = B_ERROR;
  290. }
  291. if (status == B_OK)
  292. break;
  293. }
  294. if (status != B_OK)
  295. return status;
  296. *_data = new(std::nothrow) uint8[size];
  297. if (*_data == NULL)
  298. return B_NO_MEMORY;
  299. if (file.Read(*_data, size) != size) {
  300. delete[] *_data;
  301. return B_ERROR;
  302. }
  303. *_size = size;
  304. *_type = B_VECTOR_ICON_TYPE;
  305. // TODO: for now
  306. return B_OK;
  307. }