Create MIMETypeLibrary for general MIME type detection

This commit is contained in:
sabrina-shanman 2018-11-29 16:46:08 -08:00
parent 2919097f29
commit 142e787a9c
2 changed files with 176 additions and 0 deletions

View file

@ -0,0 +1,85 @@
//
// MIMETypeLibrary.cpp
// libraries/shared/src/shared
//
// Created by Sabrina Shanman on 2018/11/29.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "MIMETypeLibrary.h"
MIMETypeLibrary::ID MIMETypeLibrary::registerMIMEType(const MIMEType& mimeType) {
ID id;
withWriteLock([&](){
id = nextID++;
_mimeTypes.emplace_back(id, mimeType);
});
return id;
}
void MIMETypeLibrary::unregisterMIMEType(const MIMETypeLibrary::ID& id) {
withWriteLock([&](){
for (auto it = _mimeTypes.begin(); it != _mimeTypes.end(); it++) {
if ((*it).id == id) {
_mimeTypes.erase(it);
break;
}
}
});
}
MIMEType MIMETypeLibrary::getMIMEType(const MIMETypeLibrary::ID& id) const {
return resultWithReadLock<MIMEType>([&](){
for (auto& supportedFormat : _mimeTypes) {
if (supportedFormat.id == id) {
return supportedFormat.mimeType;
}
}
return MIMEType::NONE;
});
}
MIMETypeLibrary::ID MIMETypeLibrary::findMatchingMIMEType(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url, const std::string& webMediaType) const {
return resultWithReadLock<MIMETypeLibrary::ID>([&](){
// Check file contents
for (auto& mimeType : _mimeTypes) {
for (auto& fileSignature : mimeType.mimeType.fileSignatures) {
auto testBytes = data.mid(fileSignature.byteOffset, (int)fileSignature.bytes.size()).toStdString();
if (testBytes == fileSignature.bytes) {
return mimeType.id;
}
}
}
// Check file extension
std::string urlString = url.path().toStdString();
std::size_t extensionSeparator = urlString.rfind('.');
if (extensionSeparator != std::string::npos) {
std::string detectedExtension = urlString.substr(extensionSeparator + 1);
for (auto& supportedFormat : _mimeTypes) {
for (auto& extension : supportedFormat.mimeType.extensions) {
if (extension == detectedExtension) {
return supportedFormat.id;
}
}
}
}
// Check web media type
if (webMediaType != "") {
for (auto& supportedFormat : _mimeTypes) {
for (auto& candidateWebMediaType : supportedFormat.mimeType.webMediaTypes) {
if (candidateWebMediaType == webMediaType) {
return supportedFormat.id;
}
}
}
}
// Supported file type not found.
return INVALID_ID;
});
}

View file

@ -0,0 +1,91 @@
//
// MIMETypeLibrary.h
// libraries/shared/src/shared
//
// Created by Sabrina Shanman on 2018/11/28.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_MIMETypeLibrary_h
#define hifi_MIMETypeLibrary_h
#include <vector>
#include <string>
#include <functional>
#include <mutex>
#include "HifiTypes.h"
#include "ReadWriteLockable.h"
// A short sequence of bytes, typically at the beginning of the file, which identifies the file format
class FileSignature {
public:
FileSignature(const std::string& bytes, int byteOffset) :
bytes(bytes),
byteOffset(byteOffset) {
}
FileSignature(const FileSignature& fileSignature) :
bytes(fileSignature.bytes),
byteOffset(fileSignature.byteOffset) {
}
std::string bytes;
int byteOffset;
};
// A named file extension with a list of known ways to positively identify the file type
class MIMEType {
public:
MIMEType(const std::string& name) :
name(name) {
}
MIMEType() {};
MIMEType(const MIMEType& mimeType) :
name(mimeType.name),
extensions(mimeType.extensions),
webMediaTypes(mimeType.webMediaTypes),
fileSignatures(mimeType.fileSignatures) {
}
static MIMEType NONE;
std::string name;
std::vector<std::string> extensions;
std::vector<std::string> webMediaTypes;
std::vector<FileSignature> fileSignatures;
};
MIMEType MIMEType::NONE = MIMEType("");
class MIMETypeLibrary : ReadWriteLockable {
public:
using ID = unsigned int;
static const ID INVALID_ID { 0 };
ID registerMIMEType(const MIMEType& mimeType);
void unregisterMIMEType(const ID& id);
MIMEType getMIMEType(const ID& id) const;
ID findMatchingMIMEType(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url, const std::string& webMediaType) const;
protected:
ID nextID { 1 };
class Entry {
public:
Entry(const ID& id, const MIMEType& mimeType) :
id(id),
mimeType(mimeType) {
}
ID id;
MIMEType mimeType;
};
std::vector<Entry> _mimeTypes;
};
#endif // hifi_MIMETypeLibrary_h