1/*
2 * Copyright 2002-2013, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Tyler Dauwalder
7 *		Ingo Weinhold <ingo_weinhold@gmx.de>
8 */
9
10
11#include <mime/database_support.h>
12
13#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
14#	include <pthread.h>
15#endif
16
17#include <new>
18
19#include <Bitmap.h>
20#include <FindDirectory.h>
21#include <Path.h>
22
23#include <mime/DatabaseLocation.h>
24
25
26namespace BPrivate {
27namespace Storage {
28namespace Mime {
29
30
31#define ATTR_PREFIX "META:"
32#define MINI_ICON_ATTR_PREFIX ATTR_PREFIX "M:"
33#define LARGE_ICON_ATTR_PREFIX ATTR_PREFIX "L:"
34
35const char *kMiniIconAttrPrefix		= MINI_ICON_ATTR_PREFIX;
36const char *kLargeIconAttrPrefix	= LARGE_ICON_ATTR_PREFIX;
37const char *kIconAttrPrefix			= ATTR_PREFIX;
38
39// attribute names
40const char *kFileTypeAttr			= "BEOS:TYPE";
41const char *kTypeAttr				= ATTR_PREFIX "TYPE";
42const char *kAppHintAttr			= ATTR_PREFIX "PPATH";
43const char *kAttrInfoAttr			= ATTR_PREFIX "ATTR_INFO";
44const char *kShortDescriptionAttr	= ATTR_PREFIX "S:DESC";
45const char *kLongDescriptionAttr	= ATTR_PREFIX "L:DESC";
46const char *kFileExtensionsAttr		= ATTR_PREFIX "EXTENS";
47const char *kMiniIconAttr			= MINI_ICON_ATTR_PREFIX "STD_ICON";
48const char *kLargeIconAttr			= LARGE_ICON_ATTR_PREFIX "STD_ICON";
49const char *kIconAttr				= ATTR_PREFIX "ICON";
50const char *kPreferredAppAttr		= ATTR_PREFIX "PREF_APP";
51const char *kSnifferRuleAttr		= ATTR_PREFIX "SNIFF_RULE";
52const char *kSupportedTypesAttr		= ATTR_PREFIX "FILE_TYPES";
53
54// attribute data types (as used in the R5 database)
55const int32 kFileTypeType			= 'MIMS';	// B_MIME_STRING_TYPE
56const int32 kTypeType				= B_STRING_TYPE;
57const int32 kAppHintType			= 'MPTH';
58const int32 kAttrInfoType			= B_MESSAGE_TYPE;
59const int32 kShortDescriptionType	= 'MSDC';
60const int32 kLongDescriptionType	= 'MLDC';
61const int32 kFileExtensionsType		= B_MESSAGE_TYPE;
62const int32 kMiniIconType			= B_MINI_ICON_TYPE;
63const int32 kLargeIconType			= B_LARGE_ICON_TYPE;
64const int32 kIconType				= B_VECTOR_ICON_TYPE;
65const int32 kPreferredAppType		= 'MSIG';
66const int32 kSnifferRuleType		= B_STRING_TYPE;
67const int32 kSupportedTypesType		= B_MESSAGE_TYPE;
68
69// Message fields
70const char *kApplicationsField				= "applications";
71const char *kExtensionsField				= "extensions";
72const char *kSupertypesField				= "super_types";
73const char *kSupportingAppsSubCountField	= "be:sub";
74const char *kSupportingAppsSuperCountField	= "be:super";
75const char *kTypesField						= "types";
76
77// Mime types
78const char *kGenericFileType	= "application/octet-stream";
79const char *kDirectoryType		= "application/x-vnd.Be-directory";
80const char *kSymlinkType		= "application/x-vnd.Be-symlink";
81const char *kMetaMimeType		= "application/x-vnd.Be-meta-mime";
82
83// Error codes
84const status_t kMimeGuessFailureError	= B_ERRORS_END+1;
85
86
87#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
88
89
90static const directory_which kBaseDirectoryConstants[] = {
91	B_USER_SETTINGS_DIRECTORY,
92	B_USER_NONPACKAGED_DATA_DIRECTORY,
93	B_USER_DATA_DIRECTORY,
94	B_SYSTEM_NONPACKAGED_DATA_DIRECTORY,
95	B_SYSTEM_DATA_DIRECTORY
96};
97
98static pthread_once_t sDefaultDatabaseLocationInitOnce = PTHREAD_ONCE_INIT;
99static DatabaseLocation* sDefaultDatabaseLocation = NULL;
100
101
102static void
103init_default_database_location()
104{
105	static DatabaseLocation databaseLocation;
106	sDefaultDatabaseLocation = &databaseLocation;
107
108	for (size_t i = 0;
109		i < sizeof(kBaseDirectoryConstants)
110			/ sizeof(kBaseDirectoryConstants[0]); i++) {
111		BString directoryPath;
112		BPath path;
113		if (find_directory(kBaseDirectoryConstants[i], &path) == B_OK)
114			directoryPath = path.Path();
115		else if (i == 0)
116			directoryPath = "/boot/home/config/settings";
117		else
118			continue;
119
120		directoryPath += "/mime_db";
121		databaseLocation.AddDirectory(directoryPath);
122	}
123}
124
125
126DatabaseLocation*
127default_database_location()
128{
129	pthread_once(&sDefaultDatabaseLocationInitOnce,
130		&init_default_database_location);
131	return sDefaultDatabaseLocation;
132}
133
134
135#else	// building for the host platform
136
137
138DatabaseLocation*
139default_database_location()
140{
141	// Should never actually be used, but make it valid, anyway.
142	static DatabaseLocation location;
143	if (location.Directories().IsEmpty())
144		location.AddDirectory("/tmp");
145	return &location;
146}
147
148
149#endif
150
151
152/*! \brief Returns properly formatted raw bitmap data, ready to be shipped off
153	to the hacked up 4-parameter version of Database::SetIcon()
154
155	BBitmap implemented.  This function takes the given bitmap, converts it to the
156	B_CMAP8 color space if necessary and able, and returns said bitmap data in
157	a newly allocated array pointed to by the pointer that's pointed to by
158	\c data. The length of the array is stored in the integer pointed to by
159	\c dataSize. The array is allocated with \c new[], and it's your
160	responsibility to \c delete[] it when you're finished.
161*/
162status_t
163get_icon_data(const BBitmap *icon, icon_size which, void **data,
164	int32 *dataSize)
165{
166	if (icon == NULL || data == NULL || dataSize == 0
167		|| icon->InitCheck() != B_OK)
168		return B_BAD_VALUE;
169
170	BRect bounds;
171	BBitmap *icon8 = NULL;
172	void *srcData = NULL;
173	bool otherColorSpace = false;
174
175	// Figure out what kind of data we *should* have
176	switch (which) {
177		case B_MINI_ICON:
178			bounds.Set(0, 0, 15, 15);
179			break;
180		case B_LARGE_ICON:
181			bounds.Set(0, 0, 31, 31);
182			break;
183		default:
184			return B_BAD_VALUE;
185	}
186
187	// Check the icon
188	status_t err = icon->Bounds() == bounds ? B_OK : B_BAD_VALUE;
189
190	// Convert to B_CMAP8 if necessary
191	if (!err) {
192		otherColorSpace = (icon->ColorSpace() != B_CMAP8);
193		if (otherColorSpace) {
194			icon8 = new(std::nothrow) BBitmap(bounds, B_BITMAP_NO_SERVER_LINK,
195				B_CMAP8);
196			if (!icon8)
197				err = B_NO_MEMORY;
198			if (!err)
199				err = icon8->ImportBits(icon);
200			if (!err) {
201				srcData = icon8->Bits();
202				*dataSize = icon8->BitsLength();
203			}
204		} else {
205			srcData = icon->Bits();
206			*dataSize = icon->BitsLength();
207		}
208	}
209
210	// Alloc a new data buffer
211	if (!err) {
212		*data = new(std::nothrow) char[*dataSize];
213		if (!*data)
214			err = B_NO_MEMORY;
215	}
216
217	// Copy the data into it.
218	if (!err)
219		memcpy(*data, srcData, *dataSize);
220	if (otherColorSpace)
221		delete icon8;
222	return err;
223}
224
225
226} // namespace Mime
227} // namespace Storage
228} // namespace BPrivate
229
230