\file MimeType.cpp
BMimeType implementation.
*/
#include "MimeType.h"
#include <Bitmap.h>
#include <ctype.h>
#include <new>
#include <stdio.h>
#include <string.h>
using namespace BPrivate;
bool isValidMimeChar(const char ch);
status_t toLower(const char *str, char *result);
using namespace std;
const char *B_PEF_APP_MIME_TYPE = "application/x-be-executable";
const char *B_PE_APP_MIME_TYPE = "application/x-vnd.be-peexecutable";
const char *B_ELF_APP_MIME_TYPE = "application/x-vnd.be-elfexecutable";
const char *B_RESOURCE_MIME_TYPE = "application/x-be-resource";
const char *B_FILE_MIME_TYPE = "application/octet-stream";
const char *B_APP_MIME_TYPE = B_ELF_APP_MIME_TYPE;
*/
BMimeType::BMimeType()
: fType(NULL)
, fCStatus(B_NO_INIT)
{
}
MIME type.
The supplied string must specify a valid MIME type or supertype.
\see SetTo() for further information.
\param mimeType The MIME string.
*/
BMimeType::BMimeType(const char *mimeType)
: fType(NULL)
, fCStatus(B_NO_INIT)
{
SetTo(mimeType);
}
*/
BMimeType::~BMimeType()
{
Unset();
}
The supplied string must specify a valid MIME type or supertype.
Valid MIME types are given by the following grammar:
MIMEType ::= Supertype "/" [ Subtype ]
Supertype ::= "application" | "audio" | "image" | "message"
| "multipart" | "text" | "video"
Subtype ::= MIMEChar MIMEChar*
MIMEChar ::= any character except white spaces, CTLs and '/', '<', '>',
'@',, ',', ';', ':', '"', '(', ')', '[', ']', '?', '=', '\'
(Note: RFC1341 also forbits '.', but it is allowed here.)
Currently the supertype is not restricted to one of the seven types given,
but can be an arbitrary string (obeying the same rule as the subtype).
Nevertheless it is a very bad idea to use another supertype.
The supplied MIME string is copied; the caller retains the ownership.
\param mimeType The MIME string.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \c NULL or invalid \a mimeString.
- \c B_NO_MEMORY: Insufficient memory to copy the MIME string.
*/
status_t
BMimeType::SetTo(const char *mimeType)
{
if (!mimeType || !BMimeType::IsValid(mimeType)) {
fCStatus = B_BAD_VALUE;
} else {
Unset();
fType = new(std::nothrow) char[strlen(mimeType)+1];
if (fType) {
strcpy(fType, mimeType);
fCStatus = B_OK;
} else {
fCStatus = B_NO_MEMORY;
}
}
return fCStatus;
}
*/
void
BMimeType::Unset()
{
if (fType)
delete [] fType;
fType = NULL;
fCStatus = B_NO_INIT;
}
\return
- \c B_OK: The object is properly initialized.
- A specific error code otherwise.
*/
status_t
BMimeType::InitCheck() const
{
return fCStatus;
}
\return The MIME string, if the object is properly initialized, \c NULL
otherwise.
*/
const char *
BMimeType::Type() const
{
return fType;
}
\see SetTo() for further information.
\return \c true, if the object is properly initialized, \c false
otherwise.
*/
bool
BMimeType::IsValid() const
{
return InitCheck() == B_OK && BMimeType::IsValid(Type());
}
\return \c true, if the object is properly initialized and represents a
supertype, \c false otherwise.
*/
bool
BMimeType::IsSupertypeOnly() const
{
if (fCStatus == B_OK) {
int len = strlen(fType);
for (int i = 0; i < len; i++) {
if (fType[i] == '/')
return false;
}
return true;
} else
return false;
}
To remove the MIME type from the database, call \c Delete().
\return
- \c true: The MIME type is currently installed in the database
- \c false: The MIME type is not currently installed in the database
*/
The supplied object is initialized to this object's supertype. If this
BMimeType is not properly initialized, the supplied object will be Unset().
\param superType A pointer to the BMimeType object that shall be
initialized to this object's supertype.
\return
- \c B_OK: Everything went fine.
- \c B_BAD_VALUE: \c NULL \a superType, this object is not initialized,
or this object <i> is </i> a supertype.
*/
status_t
BMimeType::GetSupertype(BMimeType *superType) const
{
if (!superType)
return B_BAD_VALUE;
superType->Unset();
status_t err = (fCStatus == B_OK ? B_OK : B_BAD_VALUE);
if (!err) {
int len = strlen(fType);
int i;
for (i = 0; i < len; i++) {
if (fType[i] == '/')
break;
}
if (i == len)
err = B_BAD_VALUE;
else {
char superMime[B_MIME_TYPE_LENGTH];
strncpy(superMime, fType, i);
superMime[i] = 0;
err = superType->SetTo(superMime);
}
}
return err;
}
Two BMimeType objects are said to be equal, if they represent the same
MIME string, ignoring case, or if both are not initialized.
\param type The BMimeType to be compared with.
\return \c true, if the objects are equal, \c false otherwise.
*/
bool
BMimeType::operator==(const BMimeType &type) const
{
char lower1[B_MIME_TYPE_LENGTH];
char lower2[B_MIME_TYPE_LENGTH];
if (InitCheck() == B_OK && type.InitCheck() == B_OK) {
status_t err = toLower(Type(), lower1);
if (!err)
err = toLower(type.Type(), lower2);
if (!err)
err = (strcmp(lower1, lower2) == 0 ? B_OK : B_ERROR);
return err == B_OK;
} else if (InitCheck() == B_NO_INIT && type.InitCheck() == B_NO_INIT) {
return true;
} else {
return false;
}
}
A BMimeType objects equals a MIME string, if its MIME string equals the
latter one, ignoring case, or if it is uninitialized and the MIME string
is \c NULL.
\param type The MIME string to be compared with.
\return \c true, if the MIME types are equal, \c false otherwise.
*/
bool
BMimeType::operator==(const char *type) const
{
BMimeType mime;
if (type)
mime.SetTo(type);
return (*this) == mime;
}
supplied one.
\param type The MIME type.
\return \c true, if this MIME type is a supertype of or equals the
supplied one, \c false otherwise.
*/
bool
BMimeType::Contains(const BMimeType *type) const
{
if (!type)
return false;
if (*this == *type)
return true;
BMimeType super;
if (type->GetSupertype(&super) == B_OK && *this == super)
return true;
return false;
}
\see SetTo() for further information.
\return \c true, if the given string represents a valid MIME type.
*/
bool
BMimeType::IsValid(const char *string)
{
if (!string)
return false;
bool foundSlash = false;
int len = strlen(string);
if (len >= B_MIME_TYPE_LENGTH || len == 0)
return false;
for (int i = 0; i < len; i++) {
char ch = string[i];
if (ch == '/') {
if (foundSlash || i == 0 || i == len-1)
return false;
else
foundSlash = true;
} else if (!isValidMimeChar(ch)) {
return false;
}
}
return true;
}
bool isValidMimeChar(const char ch)
{
return ch > 32
&& ch != '/'
&& ch != '<'
&& ch != '>'
&& ch != '@'
&& ch != ','
&& ch != ';'
&& ch != ':'
&& ch != '"'
&& ch != '('
&& ch != ')'
&& ch != '['
&& ch != ']'
&& ch != '?'
&& ch != '='
&& ch != '\\'
&& ch != 127;
}
\deprecated This method has the same semantics as SetTo().
Use SetTo() instead.
*/
status_t
BMimeType::SetType(const char *mimeType)
{
return SetTo(mimeType);
}
status_t
BMimeType::GuessMimeType(const entry_ref *ref, BMimeType *type)
{
if (!ref || !type)
return B_BAD_VALUE;
BEntry entry;
status_t error = entry.SetTo(ref);
if (error != B_OK)
return error;
if (!entry.Exists())
return B_ENTRY_NOT_FOUND;
if (entry.IsDirectory())
return type->SetType("application/x-vnd.be-directory");
if (entry.IsSymLink())
return type->SetType("application/x-vnd.be-symlink");
if (!entry.IsFile())
return B_ERROR;
BFile file;
char buffer[4];
if (file.SetTo(ref, B_READ_ONLY) == B_OK
&& file.Read(buffer, 4) == 4) {
return GuessMimeType(buffer, 4, type);
}
return type->SetType(B_FILE_MIME_TYPE);
}
status_t
BMimeType::GuessMimeType(const void *_buffer, int32 length, BMimeType *type)
{
const uint8 *buffer = (const uint8*)_buffer;
if (!buffer || !type)
return B_BAD_VALUE;
if (length >= 4 && buffer[0] == 0x7f && buffer[1] == 'E' && buffer[2] == 'L'
&& buffer[3] == 'F') {
return type->SetType(B_ELF_APP_MIME_TYPE);
}
return type->SetType(B_FILE_MIME_TYPE);
}
status_t
BMimeType::GuessMimeType(const char *filename, BMimeType *type)
{
if (!filename || !type)
return B_BAD_VALUE;
entry_ref ref;
status_t error = get_ref_for_path(filename, &ref);
return (error == B_OK ? GuessMimeType(&ref, type) : error);
}
void BMimeType::_ReservedMimeType1() {}
void BMimeType::_ReservedMimeType2() {}
void BMimeType::_ReservedMimeType3() {}
*/
BMimeType &
BMimeType::operator=(const BMimeType &)
{
return *this;
}
*/
BMimeType::BMimeType(const BMimeType &)
{
}
status_t
toLower(const char *str, char *result) {
if (!str || !result)
return B_BAD_VALUE;
int len = strlen(str);
int i;
for (i = 0; i < len; i++)
result[i] = tolower(str[i]);
result[i] = 0;
return B_OK;
}