1338b8dc3SIngo Weinhold//----------------------------------------------------------------------
2338b8dc3SIngo Weinhold//  This software is part of the OpenBeOS distribution and is covered
3b6f76ebeSAugustin Cavalier//  by the MIT License.
4338b8dc3SIngo Weinhold//---------------------------------------------------------------------
5338b8dc3SIngo Weinhold/*!
6338b8dc3SIngo Weinhold	\file MimeType.cpp
7338b8dc3SIngo Weinhold	BMimeType implementation.
8338b8dc3SIngo Weinhold*/
9338b8dc3SIngo Weinhold#include "MimeType.h"
10338b8dc3SIngo Weinhold
11338b8dc3SIngo Weinhold#include <Bitmap.h>
12338b8dc3SIngo Weinhold
13338b8dc3SIngo Weinhold#include <ctype.h>			// For tolower()
14338b8dc3SIngo Weinhold#include <new>			// For new(nothrow)
15338b8dc3SIngo Weinhold#include <stdio.h>			// For printf()
16338b8dc3SIngo Weinhold#include <string.h>			// For strncpy()
17338b8dc3SIngo Weinhold
18338b8dc3SIngo Weinholdusing namespace BPrivate;
19338b8dc3SIngo Weinhold
20338b8dc3SIngo Weinhold// Private helper functions
21338b8dc3SIngo Weinholdbool isValidMimeChar(const char ch);
22338b8dc3SIngo Weinholdstatus_t toLower(const char *str, char *result);
23338b8dc3SIngo Weinhold
24338b8dc3SIngo Weinhold//using namespace BPrivate::Storage::Mime;
25338b8dc3SIngo Weinholdusing namespace std;
26338b8dc3SIngo Weinhold
27338b8dc3SIngo Weinholdconst char *B_PEF_APP_MIME_TYPE		= "application/x-be-executable";
28338b8dc3SIngo Weinholdconst char *B_PE_APP_MIME_TYPE		= "application/x-vnd.be-peexecutable";
29338b8dc3SIngo Weinholdconst char *B_ELF_APP_MIME_TYPE		= "application/x-vnd.be-elfexecutable";
30338b8dc3SIngo Weinholdconst char *B_RESOURCE_MIME_TYPE	= "application/x-be-resource";
31338b8dc3SIngo Weinholdconst char *B_FILE_MIME_TYPE		= "application/octet-stream";
32338b8dc3SIngo Weinhold// Might be defined platform depended, but ELF will certainly be the common
33338b8dc3SIngo Weinhold// format for all platforms anyway.
34338b8dc3SIngo Weinholdconst char *B_APP_MIME_TYPE			= B_ELF_APP_MIME_TYPE;
35338b8dc3SIngo Weinhold
36338b8dc3SIngo Weinhold// constructor
37338b8dc3SIngo Weinhold/*!	\brief Creates an uninitialized BMimeType object.
38338b8dc3SIngo Weinhold*/
39338b8dc3SIngo WeinholdBMimeType::BMimeType()
40338b8dc3SIngo Weinhold	: fType(NULL)
41338b8dc3SIngo Weinhold	, fCStatus(B_NO_INIT)
42338b8dc3SIngo Weinhold{
43338b8dc3SIngo Weinhold}
44338b8dc3SIngo Weinhold
45338b8dc3SIngo Weinhold// constructor
46338b8dc3SIngo Weinhold/*!	\brief Creates a BMimeType object and initializes it to the supplied
47338b8dc3SIngo Weinhold	MIME type.
48338b8dc3SIngo Weinhold	The supplied string must specify a valid MIME type or supertype.
49338b8dc3SIngo Weinhold	\see SetTo() for further information.
50338b8dc3SIngo Weinhold	\param mimeType The MIME string.
51338b8dc3SIngo Weinhold*/
52338b8dc3SIngo WeinholdBMimeType::BMimeType(const char *mimeType)
53338b8dc3SIngo Weinhold	: fType(NULL)
54338b8dc3SIngo Weinhold	, fCStatus(B_NO_INIT)
55338b8dc3SIngo Weinhold{
56338b8dc3SIngo Weinhold	SetTo(mimeType);
57338b8dc3SIngo Weinhold}
58338b8dc3SIngo Weinhold
59338b8dc3SIngo Weinhold// destructor
60338b8dc3SIngo Weinhold/*!	\brief Frees all resources associated with this object.
61338b8dc3SIngo Weinhold*/
62338b8dc3SIngo WeinholdBMimeType::~BMimeType()
63338b8dc3SIngo Weinhold{
64338b8dc3SIngo Weinhold	Unset();
65338b8dc3SIngo Weinhold}
66338b8dc3SIngo Weinhold
67338b8dc3SIngo Weinhold// SetTo
68338b8dc3SIngo Weinhold/*!	\brief Initializes this object to the supplied MIME type.
69338b8dc3SIngo Weinhold	The supplied string must specify a valid MIME type or supertype.
70338b8dc3SIngo Weinhold	Valid MIME types are given by the following grammar:
71338b8dc3SIngo Weinhold	MIMEType	::= Supertype "/" [ Subtype ]
72338b8dc3SIngo Weinhold	Supertype	::= "application" | "audio" | "image" | "message"
73338b8dc3SIngo Weinhold					| "multipart" | "text" | "video"
74338b8dc3SIngo Weinhold	Subtype		::= MIMEChar MIMEChar*
75338b8dc3SIngo Weinhold	MIMEChar	::= any character except white spaces, CTLs and '/', '<', '>',
76338b8dc3SIngo Weinhold					'@',, ',', ';', ':', '"', '(', ')', '[', ']', '?', '=', '\'
77338b8dc3SIngo Weinhold					(Note: RFC1341 also forbits '.', but it is allowed here.)
78338b8dc3SIngo Weinhold
79338b8dc3SIngo Weinhold	Currently the supertype is not restricted to one of the seven types given,
80338b8dc3SIngo Weinhold	but can be an arbitrary string (obeying the same rule as the subtype).
81338b8dc3SIngo Weinhold	Nevertheless it is a very bad idea to use another supertype.
82338b8dc3SIngo Weinhold	The supplied MIME string is copied; the caller retains the ownership.
83338b8dc3SIngo Weinhold	\param mimeType The MIME string.
84338b8dc3SIngo Weinhold	\return
85338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
86338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL or invalid \a mimeString.
87338b8dc3SIngo Weinhold	- \c B_NO_MEMORY: Insufficient memory to copy the MIME string.
88338b8dc3SIngo Weinhold*/
89338b8dc3SIngo Weinholdstatus_t
90338b8dc3SIngo WeinholdBMimeType::SetTo(const char *mimeType)
91338b8dc3SIngo Weinhold{
92338b8dc3SIngo Weinhold	if (!mimeType || !BMimeType::IsValid(mimeType)) {
93338b8dc3SIngo Weinhold		fCStatus = B_BAD_VALUE;
94338b8dc3SIngo Weinhold	} else {
95338b8dc3SIngo Weinhold		Unset();
96338b8dc3SIngo Weinhold		fType = new(std::nothrow) char[strlen(mimeType)+1];
97338b8dc3SIngo Weinhold		if (fType) {
98338b8dc3SIngo Weinhold			strcpy(fType, mimeType);
99338b8dc3SIngo Weinhold			fCStatus = B_OK;
100338b8dc3SIngo Weinhold		} else {
101338b8dc3SIngo Weinhold			fCStatus = B_NO_MEMORY;
102338b8dc3SIngo Weinhold		}
103338b8dc3SIngo Weinhold	}
104338b8dc3SIngo Weinhold	return fCStatus;
105338b8dc3SIngo Weinhold}
106338b8dc3SIngo Weinhold
107338b8dc3SIngo Weinhold// Unset
108338b8dc3SIngo Weinhold/*!	\brief Returns the object to an uninitialized state.
109338b8dc3SIngo Weinhold*/
110338b8dc3SIngo Weinholdvoid
111338b8dc3SIngo WeinholdBMimeType::Unset()
112338b8dc3SIngo Weinhold{
113338b8dc3SIngo Weinhold	if (fType)
114338b8dc3SIngo Weinhold		delete [] fType;
115338b8dc3SIngo Weinhold	fType = NULL;
116338b8dc3SIngo Weinhold	fCStatus = B_NO_INIT;
117338b8dc3SIngo Weinhold}
118338b8dc3SIngo Weinhold
119338b8dc3SIngo Weinhold// InitCheck
120338b8dc3SIngo Weinhold/*!	Returns the result of the most recent constructor or SetTo() call.
121338b8dc3SIngo Weinhold	\return
122338b8dc3SIngo Weinhold	- \c B_OK: The object is properly initialized.
123338b8dc3SIngo Weinhold	- A specific error code otherwise.
124338b8dc3SIngo Weinhold*/
125338b8dc3SIngo Weinholdstatus_t
126338b8dc3SIngo WeinholdBMimeType::InitCheck() const
127338b8dc3SIngo Weinhold{
128338b8dc3SIngo Weinhold	return fCStatus;
129338b8dc3SIngo Weinhold}
130338b8dc3SIngo Weinhold
131338b8dc3SIngo Weinhold// Type
132338b8dc3SIngo Weinhold/*!	\brief Returns the MIME string represented by this object.
133338b8dc3SIngo Weinhold	\return The MIME string, if the object is properly initialized, \c NULL
134338b8dc3SIngo Weinhold			otherwise.
135338b8dc3SIngo Weinhold*/
136338b8dc3SIngo Weinholdconst char *
137338b8dc3SIngo WeinholdBMimeType::Type() const
138338b8dc3SIngo Weinhold{
139338b8dc3SIngo Weinhold	return fType;
140338b8dc3SIngo Weinhold}
141338b8dc3SIngo Weinhold
142338b8dc3SIngo Weinhold// IsValid
143338b8dc3SIngo Weinhold/*!	\brief Returns whether the object represents a valid MIME type.
144338b8dc3SIngo Weinhold	\see SetTo() for further information.
145338b8dc3SIngo Weinhold	\return \c true, if the object is properly initialized, \c false
146338b8dc3SIngo Weinhold			otherwise.
147338b8dc3SIngo Weinhold*/
148338b8dc3SIngo Weinholdbool
149338b8dc3SIngo WeinholdBMimeType::IsValid() const
150338b8dc3SIngo Weinhold{
151338b8dc3SIngo Weinhold	return InitCheck() == B_OK && BMimeType::IsValid(Type());
152338b8dc3SIngo Weinhold}
153338b8dc3SIngo Weinhold
154338b8dc3SIngo Weinhold// IsSupertypeOnly
155338b8dc3SIngo Weinhold/*!	\brief Returns whether this objects represents a supertype.
156338b8dc3SIngo Weinhold	\return \c true, if the object is properly initialized and represents a
157338b8dc3SIngo Weinhold			supertype, \c false otherwise.
158338b8dc3SIngo Weinhold*/
159338b8dc3SIngo Weinholdbool
160338b8dc3SIngo WeinholdBMimeType::IsSupertypeOnly() const
161338b8dc3SIngo Weinhold{
162338b8dc3SIngo Weinhold	if (fCStatus == B_OK) {
163338b8dc3SIngo Weinhold		// We assume here fCStatus will be B_OK *only* if
164338b8dc3SIngo Weinhold		// the MIME string is valid
165338b8dc3SIngo Weinhold		int len = strlen(fType);
166338b8dc3SIngo Weinhold		for (int i = 0; i < len; i++) {
167338b8dc3SIngo Weinhold			if (fType[i] == '/')
168338b8dc3SIngo Weinhold				return false;
169338b8dc3SIngo Weinhold		}
170338b8dc3SIngo Weinhold		return true;
171338b8dc3SIngo Weinhold	} else
172338b8dc3SIngo Weinhold		return false;
173338b8dc3SIngo Weinhold}
174338b8dc3SIngo Weinhold
175338b8dc3SIngo Weinhold// IsInstalled
176338b8dc3SIngo Weinhold//! Returns whether or not this type is currently installed in the MIME database
177338b8dc3SIngo Weinhold/*! To add the MIME type to the database, call \c Install().
178338b8dc3SIngo Weinhold	To remove the MIME type from the database, call \c Delete().
179338b8dc3SIngo Weinhold
180338b8dc3SIngo Weinhold	\return
181338b8dc3SIngo Weinhold	- \c true: The MIME type is currently installed in the database
182338b8dc3SIngo Weinhold	- \c false: The MIME type is not currently installed in the database
183338b8dc3SIngo Weinhold*/
184338b8dc3SIngo Weinhold// bool
185338b8dc3SIngo Weinhold// BMimeType::IsInstalled() const
186338b8dc3SIngo Weinhold// {
187338b8dc3SIngo Weinhold// 	return InitCheck() == B_OK && is_installed(Type());
188338b8dc3SIngo Weinhold// }
189338b8dc3SIngo Weinhold
190338b8dc3SIngo Weinhold// GetSupertype
191338b8dc3SIngo Weinhold/*!	\brief Returns the supertype of the MIME type represented by this object.
192338b8dc3SIngo Weinhold	The supplied object is initialized to this object's supertype. If this
193338b8dc3SIngo Weinhold	BMimeType is not properly initialized, the supplied object will be Unset().
194338b8dc3SIngo Weinhold	\param superType A pointer to the BMimeType object that shall be
195338b8dc3SIngo Weinhold		   initialized to this object's supertype.
196338b8dc3SIngo Weinhold	\return
197338b8dc3SIngo Weinhold	- \c B_OK: Everything went fine.
198338b8dc3SIngo Weinhold	- \c B_BAD_VALUE: \c NULL \a superType, this object is not initialized,
199338b8dc3SIngo Weinhold	  or this object <i> is </i> a supertype.
200338b8dc3SIngo Weinhold*/
201338b8dc3SIngo Weinholdstatus_t
202338b8dc3SIngo WeinholdBMimeType::GetSupertype(BMimeType *superType) const
203338b8dc3SIngo Weinhold{
204338b8dc3SIngo Weinhold	if (!superType)
205338b8dc3SIngo Weinhold		return B_BAD_VALUE;
206338b8dc3SIngo Weinhold	superType->Unset();
207338b8dc3SIngo Weinhold
208338b8dc3SIngo Weinhold	status_t err = (fCStatus == B_OK ? B_OK : B_BAD_VALUE);
209338b8dc3SIngo Weinhold	if (!err) {
210338b8dc3SIngo Weinhold		int len = strlen(fType);
211338b8dc3SIngo Weinhold		int i;
212338b8dc3SIngo Weinhold		for (i = 0; i < len; i++) {
213338b8dc3SIngo Weinhold			if (fType[i] == '/')
214338b8dc3SIngo Weinhold				break;
215338b8dc3SIngo Weinhold		}
216338b8dc3SIngo Weinhold		if (i == len)
217338b8dc3SIngo Weinhold			err = B_BAD_VALUE;		// IsSupertypeOnly() == true
218338b8dc3SIngo Weinhold		else {
219338b8dc3SIngo Weinhold			char superMime[B_MIME_TYPE_LENGTH];
220338b8dc3SIngo Weinhold			strncpy(superMime, fType, i);
221338b8dc3SIngo Weinhold			superMime[i] = 0;
222338b8dc3SIngo Weinhold			err = superType->SetTo(superMime);
223338b8dc3SIngo Weinhold		}
224338b8dc3SIngo Weinhold	}
225338b8dc3SIngo Weinhold	return err;
226338b8dc3SIngo Weinhold}
227338b8dc3SIngo Weinhold
228338b8dc3SIngo Weinhold// ==
229338b8dc3SIngo Weinhold/*!	\brief Returns whether this and the supplied MIME type are equal.
230338b8dc3SIngo Weinhold	Two BMimeType objects are said to be equal, if they represent the same
231338b8dc3SIngo Weinhold	MIME string, ignoring case, or if both are not initialized.
232338b8dc3SIngo Weinhold	\param type The BMimeType to be compared with.
233338b8dc3SIngo Weinhold	\return \c true, if the objects are equal, \c false otherwise.
234338b8dc3SIngo Weinhold*/
235338b8dc3SIngo Weinholdbool
236338b8dc3SIngo WeinholdBMimeType::operator==(const BMimeType &type) const
237338b8dc3SIngo Weinhold{
238338b8dc3SIngo Weinhold	char lower1[B_MIME_TYPE_LENGTH];
239338b8dc3SIngo Weinhold	char lower2[B_MIME_TYPE_LENGTH];
240338b8dc3SIngo Weinhold
241338b8dc3SIngo Weinhold	if (InitCheck() == B_OK && type.InitCheck() == B_OK) {
242338b8dc3SIngo Weinhold		status_t err = toLower(Type(), lower1);
243338b8dc3SIngo Weinhold		if (!err)
244338b8dc3SIngo Weinhold			err = toLower(type.Type(), lower2);
245338b8dc3SIngo Weinhold		if (!err)
246338b8dc3SIngo Weinhold			err = (strcmp(lower1, lower2) == 0 ? B_OK : B_ERROR);
247338b8dc3SIngo Weinhold		return err == B_OK;
248338b8dc3SIngo Weinhold	} else if (InitCheck() == B_NO_INIT && type.InitCheck() == B_NO_INIT) {
249338b8dc3SIngo Weinhold		return true;
250338b8dc3SIngo Weinhold	} else {
251338b8dc3SIngo Weinhold		return false;
252338b8dc3SIngo Weinhold	}
253338b8dc3SIngo Weinhold}
254338b8dc3SIngo Weinhold
255338b8dc3SIngo Weinhold// ==
256338b8dc3SIngo Weinhold/*!	\brief Returns whether this and the supplied MIME type are equal.
257338b8dc3SIngo Weinhold	A BMimeType objects equals a MIME string, if its MIME string equals the
258338b8dc3SIngo Weinhold	latter one, ignoring case, or if it is uninitialized and the MIME string
259338b8dc3SIngo Weinhold	is \c NULL.
260338b8dc3SIngo Weinhold	\param type The MIME string to be compared with.
261338b8dc3SIngo Weinhold	\return \c true, if the MIME types are equal, \c false otherwise.
262338b8dc3SIngo Weinhold*/
263338b8dc3SIngo Weinholdbool
264338b8dc3SIngo WeinholdBMimeType::operator==(const char *type) const
265338b8dc3SIngo Weinhold{
266338b8dc3SIngo Weinhold	BMimeType mime;
267338b8dc3SIngo Weinhold	if (type)
268338b8dc3SIngo Weinhold		mime.SetTo(type);
269338b8dc3SIngo Weinhold	return (*this) == mime;
270338b8dc3SIngo Weinhold}
271338b8dc3SIngo Weinhold
272338b8dc3SIngo Weinhold// Contains
273338b8dc3SIngo Weinhold/*!	\brief Returns whether this MIME type is a supertype of or equals the
274338b8dc3SIngo Weinhold	supplied one.
275338b8dc3SIngo Weinhold	\param type The MIME type.
276338b8dc3SIngo Weinhold	\return \c true, if this MIME type is a supertype of or equals the
277338b8dc3SIngo Weinhold			supplied one, \c false otherwise.
278338b8dc3SIngo Weinhold*/
279338b8dc3SIngo Weinholdbool
280338b8dc3SIngo WeinholdBMimeType::Contains(const BMimeType *type) const
281338b8dc3SIngo Weinhold{
282338b8dc3SIngo Weinhold	if (!type)
283338b8dc3SIngo Weinhold		return false;
284338b8dc3SIngo Weinhold	if (*this == *type)
285338b8dc3SIngo Weinhold		return true;
286338b8dc3SIngo Weinhold	BMimeType super;
287338b8dc3SIngo Weinhold	if (type->GetSupertype(&super) == B_OK && *this == super)
288338b8dc3SIngo Weinhold		return true;
289338b8dc3SIngo Weinhold	return false;
290338b8dc3SIngo Weinhold}
291338b8dc3SIngo Weinhold
292338b8dc3SIngo Weinhold// IsValid
293338b8dc3SIngo Weinhold/*!	\brief Returns whether the given string represents a valid MIME type.
294338b8dc3SIngo Weinhold	\see SetTo() for further information.
295338b8dc3SIngo Weinhold	\return \c true, if the given string represents a valid MIME type.
296338b8dc3SIngo Weinhold*/
297338b8dc3SIngo Weinholdbool
298338b8dc3SIngo WeinholdBMimeType::IsValid(const char *string)
299338b8dc3SIngo Weinhold{
300338b8dc3SIngo Weinhold	if (!string)
301338b8dc3SIngo Weinhold		return false;
302338b8dc3SIngo Weinhold
303338b8dc3SIngo Weinhold	bool foundSlash = false;
304338b8dc3SIngo Weinhold	int len = strlen(string);
305338b8dc3SIngo Weinhold	if (len >= B_MIME_TYPE_LENGTH || len == 0)
306338b8dc3SIngo Weinhold		return false;
307338b8dc3SIngo Weinhold
308338b8dc3SIngo Weinhold	for (int i = 0; i < len; i++) {
309338b8dc3SIngo Weinhold		char ch = string[i];
310338b8dc3SIngo Weinhold		if (ch == '/') {
311338b8dc3SIngo Weinhold			if (foundSlash || i == 0 || i == len-1)
312338b8dc3SIngo Weinhold				return false;
313338b8dc3SIngo Weinhold			else
314338b8dc3SIngo Weinhold				foundSlash = true;
315338b8dc3SIngo Weinhold		} else if (!isValidMimeChar(ch)) {
316338b8dc3SIngo Weinhold			return false;
317338b8dc3SIngo Weinhold		}
318338b8dc3SIngo Weinhold	}
319338b8dc3SIngo Weinhold	return true;
320338b8dc3SIngo Weinhold}
321338b8dc3SIngo Weinhold
322338b8dc3SIngo Weinholdbool isValidMimeChar(const char ch)
323338b8dc3SIngo Weinhold{
324338b8dc3SIngo Weinhold	return    ch > 32		// Handles white space and most CTLs
325338b8dc3SIngo Weinhold	       && ch != '/'
326338b8dc3SIngo Weinhold	       && ch != '<'
327338b8dc3SIngo Weinhold	       && ch != '>'
328338b8dc3SIngo Weinhold	       && ch != '@'
329338b8dc3SIngo Weinhold	       && ch != ','
330338b8dc3SIngo Weinhold	       && ch != ';'
331338b8dc3SIngo Weinhold	       && ch != ':'
332338b8dc3SIngo Weinhold	       && ch != '"'
333338b8dc3SIngo Weinhold	       && ch != '('
334338b8dc3SIngo Weinhold	       && ch != ')'
335338b8dc3SIngo Weinhold	       && ch != '['
336338b8dc3SIngo Weinhold	       && ch != ']'
337338b8dc3SIngo Weinhold	       && ch != '?'
338338b8dc3SIngo Weinhold	       && ch != '='
339338b8dc3SIngo Weinhold	       && ch != '\\'
340338b8dc3SIngo Weinhold	       && ch != 127;	// DEL
341338b8dc3SIngo Weinhold}
342338b8dc3SIngo Weinhold
343338b8dc3SIngo Weinhold// SetType
344338b8dc3SIngo Weinhold/*!	\brief Initializes this object to the supplied MIME type.
345338b8dc3SIngo Weinhold	\deprecated This method has the same semantics as SetTo().
346338b8dc3SIngo Weinhold				Use SetTo() instead.
347338b8dc3SIngo Weinhold*/
348338b8dc3SIngo Weinholdstatus_t
349338b8dc3SIngo WeinholdBMimeType::SetType(const char *mimeType)
350338b8dc3SIngo Weinhold{
351338b8dc3SIngo Weinhold	return SetTo(mimeType);
352338b8dc3SIngo Weinhold}
353338b8dc3SIngo Weinhold
35415285cb0SIngo Weinhold// GuessMimeType
35515285cb0SIngo Weinholdstatus_t
35615285cb0SIngo WeinholdBMimeType::GuessMimeType(const entry_ref *ref, BMimeType *type)
35715285cb0SIngo Weinhold{
35815285cb0SIngo Weinhold	if (!ref || !type)
35915285cb0SIngo Weinhold		return B_BAD_VALUE;
36015285cb0SIngo Weinhold
36115285cb0SIngo Weinhold	// get BEntry
36215285cb0SIngo Weinhold	BEntry entry;
36315285cb0SIngo Weinhold	status_t error = entry.SetTo(ref);
36415285cb0SIngo Weinhold	if (error != B_OK)
36515285cb0SIngo Weinhold		return error;
36615285cb0SIngo Weinhold
36715285cb0SIngo Weinhold	// does entry exist?
36815285cb0SIngo Weinhold	if (!entry.Exists())
36915285cb0SIngo Weinhold		return B_ENTRY_NOT_FOUND;
37015285cb0SIngo Weinhold
37115285cb0SIngo Weinhold	// check entry type
37215285cb0SIngo Weinhold	if (entry.IsDirectory())
37315285cb0SIngo Weinhold		return type->SetType("application/x-vnd.be-directory");
37415285cb0SIngo Weinhold	if (entry.IsSymLink())
37515285cb0SIngo Weinhold		return type->SetType("application/x-vnd.be-symlink");
37615285cb0SIngo Weinhold	if (!entry.IsFile())
37715285cb0SIngo Weinhold		return B_ERROR;
37815285cb0SIngo Weinhold
37915285cb0SIngo Weinhold	// we have a file, read the first 4 bytes
38015285cb0SIngo Weinhold	BFile file;
38115285cb0SIngo Weinhold	char buffer[4];
38215285cb0SIngo Weinhold	if (file.SetTo(ref, B_READ_ONLY) == B_OK
38315285cb0SIngo Weinhold		&& file.Read(buffer, 4) == 4) {
38415285cb0SIngo Weinhold		return GuessMimeType(buffer, 4, type);
38515285cb0SIngo Weinhold	}
38615285cb0SIngo Weinhold
38715285cb0SIngo Weinhold	// we couldn't open or read the file
38815285cb0SIngo Weinhold	return type->SetType(B_FILE_MIME_TYPE);
38915285cb0SIngo Weinhold}
39015285cb0SIngo Weinhold
39115285cb0SIngo Weinhold// GuessMimeType
39215285cb0SIngo Weinholdstatus_t
39315285cb0SIngo WeinholdBMimeType::GuessMimeType(const void *_buffer, int32 length, BMimeType *type)
39415285cb0SIngo Weinhold{
39515285cb0SIngo Weinhold	const uint8 *buffer = (const uint8*)_buffer;
39615285cb0SIngo Weinhold	if (!buffer || !type)
39715285cb0SIngo Weinhold		return B_BAD_VALUE;
39815285cb0SIngo Weinhold
39915285cb0SIngo Weinhold	// we only know ELF files
40015285cb0SIngo Weinhold	if (length >= 4 && buffer[0] == 0x7f && buffer[1] == 'E' && buffer[2] == 'L'
40115285cb0SIngo Weinhold		&&  buffer[3] == 'F') {
40215285cb0SIngo Weinhold		return type->SetType(B_ELF_APP_MIME_TYPE);
40315285cb0SIngo Weinhold	}
40415285cb0SIngo Weinhold
40515285cb0SIngo Weinhold	return type->SetType(B_FILE_MIME_TYPE);
40615285cb0SIngo Weinhold}
40715285cb0SIngo Weinhold
40815285cb0SIngo Weinhold// GuessMimeType
40915285cb0SIngo Weinholdstatus_t
41015285cb0SIngo WeinholdBMimeType::GuessMimeType(const char *filename, BMimeType *type)
41115285cb0SIngo Weinhold{
41215285cb0SIngo Weinhold	if (!filename || !type)
41315285cb0SIngo Weinhold		return B_BAD_VALUE;
41415285cb0SIngo Weinhold
41515285cb0SIngo Weinhold	entry_ref ref;
41615285cb0SIngo Weinhold	status_t error = get_ref_for_path(filename, &ref);
41715285cb0SIngo Weinhold	return (error == B_OK ? GuessMimeType(&ref, type) : error);
41815285cb0SIngo Weinhold}
41915285cb0SIngo Weinhold
420338b8dc3SIngo Weinholdvoid BMimeType::_ReservedMimeType1() {}
421338b8dc3SIngo Weinholdvoid BMimeType::_ReservedMimeType2() {}
422338b8dc3SIngo Weinholdvoid BMimeType::_ReservedMimeType3() {}
423338b8dc3SIngo Weinhold
424338b8dc3SIngo Weinhold// =
425338b8dc3SIngo Weinhold/*!	\brief Unimplemented assignment operator.
426338b8dc3SIngo Weinhold*/
427338b8dc3SIngo WeinholdBMimeType &
428338b8dc3SIngo WeinholdBMimeType::operator=(const BMimeType &)
429338b8dc3SIngo Weinhold{
430338b8dc3SIngo Weinhold	return *this;	// not implemented
431338b8dc3SIngo Weinhold}
432338b8dc3SIngo Weinhold
433338b8dc3SIngo Weinhold// copy constructor
434338b8dc3SIngo Weinhold/*!	\brief Unimplemented copy constructor.
435338b8dc3SIngo Weinhold*/
436338b8dc3SIngo WeinholdBMimeType::BMimeType(const BMimeType &)
437338b8dc3SIngo Weinhold{
438338b8dc3SIngo Weinhold}
439338b8dc3SIngo Weinhold
440338b8dc3SIngo Weinhold
441338b8dc3SIngo Weinhold// Returns a lowercase version of str in result. Result must
442338b8dc3SIngo Weinhold// be preallocated and is assumed to be of adequate length.
443338b8dc3SIngo Weinholdstatus_t
444338b8dc3SIngo WeinholdtoLower(const char *str, char *result) {
445338b8dc3SIngo Weinhold	if (!str || !result)
446338b8dc3SIngo Weinhold		return B_BAD_VALUE;
447338b8dc3SIngo Weinhold	int len = strlen(str);
448338b8dc3SIngo Weinhold	int i;
449338b8dc3SIngo Weinhold	for (i = 0; i < len; i++)
450338b8dc3SIngo Weinhold		result[i] = tolower(str[i]);
451338b8dc3SIngo Weinhold	result[i] = 0;
452338b8dc3SIngo Weinhold	return B_OK;
453338b8dc3SIngo Weinhold}
454338b8dc3SIngo Weinhold
455338b8dc3SIngo Weinhold
456338b8dc3SIngo Weinhold