summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/Mime.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xbmc/utils/Mime.cpp700
1 files changed, 700 insertions, 0 deletions
diff --git a/xbmc/utils/Mime.cpp b/xbmc/utils/Mime.cpp
new file mode 100644
index 0000000..576e499
--- /dev/null
+++ b/xbmc/utils/Mime.cpp
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Mime.h"
+
+#include "FileItem.h"
+#include "URIUtils.h"
+#include "URL.h"
+#include "filesystem/CurlFile.h"
+#include "music/tags/MusicInfoTag.h"
+#include "utils/StringUtils.h"
+#include "video/VideoInfoTag.h"
+
+#include <algorithm>
+
+const std::map<std::string, std::string> CMime::m_mimetypes = {
+ {{"3dm", "x-world/x-3dmf"},
+ {"3dmf", "x-world/x-3dmf"},
+ {"3fr", "image/3fr"},
+ {"a", "application/octet-stream"},
+ {"aab", "application/x-authorware-bin"},
+ {"aam", "application/x-authorware-map"},
+ {"aas", "application/x-authorware-seg"},
+ {"abc", "text/vnd.abc"},
+ {"acgi", "text/html"},
+ {"afl", "video/animaflex"},
+ {"ai", "application/postscript"},
+ {"aif", "audio/aiff"},
+ {"aifc", "audio/x-aiff"},
+ {"aiff", "audio/aiff"},
+ {"aim", "application/x-aim"},
+ {"aip", "text/x-audiosoft-intra"},
+ {"ani", "application/x-navi-animation"},
+ {"aos", "application/x-nokia-9000-communicator-add-on-software"},
+ {"apng", "image/apng"},
+ {"aps", "application/mime"},
+ {"arc", "application/octet-stream"},
+ {"arj", "application/arj"},
+ {"art", "image/x-jg"},
+ {"arw", "image/arw"},
+ {"asf", "video/x-ms-asf"},
+ {"asm", "text/x-asm"},
+ {"asp", "text/asp"},
+ {"asx", "video/x-ms-asf"},
+ {"au", "audio/basic"},
+ {"avi", "video/avi"},
+ {"avs", "video/avs-video"},
+ {"bcpio", "application/x-bcpio"},
+ {"bin", "application/octet-stream"},
+ {"bm", "image/bmp"},
+ {"bmp", "image/bmp"},
+ {"boo", "application/book"},
+ {"book", "application/book"},
+ {"boz", "application/x-bzip2"},
+ {"bsh", "application/x-bsh"},
+ {"bz", "application/x-bzip"},
+ {"bz2", "application/x-bzip2"},
+ {"c", "text/plain"},
+ {"c++", "text/plain"},
+ {"cat", "application/vnd.ms-pki.seccat"},
+ {"cc", "text/plain"},
+ {"ccad", "application/clariscad"},
+ {"cco", "application/x-cocoa"},
+ {"cdf", "application/cdf"},
+ {"cer", "application/pkix-cert"},
+ {"cer", "application/x-x509-ca-cert"},
+ {"cha", "application/x-chat"},
+ {"chat", "application/x-chat"},
+ {"class", "application/java"},
+ {"com", "application/octet-stream"},
+ {"conf", "text/plain"},
+ {"cpio", "application/x-cpio"},
+ {"cpp", "text/x-c"},
+ {"cpt", "application/x-cpt"},
+ {"crl", "application/pkcs-crl"},
+ {"crt", "application/pkix-cert"},
+ {"cr2", "image/cr2"},
+ {"crw", "image/crw"},
+ {"csh", "application/x-csh"},
+ {"css", "text/css"},
+ {"cxx", "text/plain"},
+ {"dcr", "application/x-director"},
+ {"deepv", "application/x-deepv"},
+ {"def", "text/plain"},
+ {"der", "application/x-x509-ca-cert"},
+ {"dif", "video/x-dv"},
+ {"dir", "application/x-director"},
+ {"dl", "video/dl"},
+ {"divx", "video/x-msvideo"},
+ {"dng", "image/dng"},
+ {"doc", "application/msword"},
+ {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
+ {"dot", "application/msword"},
+ {"dp", "application/commonground"},
+ {"drw", "application/drafting"},
+ {"dump", "application/octet-stream"},
+ {"dv", "video/x-dv"},
+ {"dvi", "application/x-dvi"},
+ {"dwf", "model/vnd.dwf"},
+ {"dwg", "image/vnd.dwg"},
+ {"dxf", "image/vnd.dwg"},
+ {"dxr", "application/x-director"},
+ {"el", "text/x-script.elisp"},
+ {"elc", "application/x-elc"},
+ {"env", "application/x-envoy"},
+ {"eps", "application/postscript"},
+ {"erf", "image/erf"},
+ {"es", "application/x-esrehber"},
+ {"etx", "text/x-setext"},
+ {"evy", "application/envoy"},
+ {"exe", "application/octet-stream"},
+ {"f", "text/x-fortran"},
+ {"f77", "text/x-fortran"},
+ {"f90", "text/x-fortran"},
+ {"fdf", "application/vnd.fdf"},
+ {"fif", "image/fif"},
+ {"flac", "audio/flac"},
+ {"fli", "video/fli"},
+ {"flo", "image/florian"},
+ {"flv", "video/x-flv"},
+ {"flx", "text/vnd.fmi.flexstor"},
+ {"fmf", "video/x-atomic3d-feature"},
+ {"for", "text/plain"},
+ {"for", "text/x-fortran"},
+ {"fpx", "image/vnd.fpx"},
+ {"frl", "application/freeloader"},
+ {"funk", "audio/make"},
+ {"g", "text/plain"},
+ {"g3", "image/g3fax"},
+ {"gif", "image/gif"},
+ {"gl", "video/x-gl"},
+ {"gsd", "audio/x-gsm"},
+ {"gsm", "audio/x-gsm"},
+ {"gsp", "application/x-gsp"},
+ {"gss", "application/x-gss"},
+ {"gtar", "application/x-gtar"},
+ {"gz", "application/x-compressed"},
+ {"gzip", "application/x-gzip"},
+ {"h", "text/plain"},
+ {"hdf", "application/x-hdf"},
+ {"heic", "image/heic"},
+ {"heif", "image/heif"},
+ {"help", "application/x-helpfile"},
+ {"hgl", "application/vnd.hp-hpgl"},
+ {"hh", "text/plain"},
+ {"hlb", "text/x-script"},
+ {"hlp", "application/hlp"},
+ {"hpg", "application/vnd.hp-hpgl"},
+ {"hpgl", "application/vnd.hp-hpgl"},
+ {"hqx", "application/binhex"},
+ {"hta", "application/hta"},
+ {"htc", "text/x-component"},
+ {"htm", "text/html"},
+ {"html", "text/html"},
+ {"htmls", "text/html"},
+ {"htt", "text/webviewhtml"},
+ {"htx", "text/html"},
+ {"ice", "x-conference/x-cooltalk"},
+ {"ico", "image/x-icon"},
+ {"idc", "text/plain"},
+ {"ief", "image/ief"},
+ {"iefs", "image/ief"},
+ {"iges", "application/iges"},
+ {"igs", "application/iges"},
+ {"ima", "application/x-ima"},
+ {"imap", "application/x-httpd-imap"},
+ {"inf", "application/inf"},
+ {"ins", "application/x-internet-signup"},
+ {"ip", "application/x-ip2"},
+ {"isu", "video/x-isvideo"},
+ {"it", "audio/it"},
+ {"iv", "application/x-inventor"},
+ {"ivr", "i-world/i-vrml"},
+ {"ivy", "application/x-livescreen"},
+ {"jam", "audio/x-jam"},
+ {"jav", "text/x-java-source"},
+ {"java", "text/x-java-source"},
+ {"jcm", "application/x-java-commerce"},
+ {"jfif", "image/jpeg"},
+ {"jp2", "image/jp2"},
+ {"jfif-tbnl", "image/jpeg"},
+ {"jpe", "image/jpeg"},
+ {"jpeg", "image/jpeg"},
+ {"jpg", "image/jpeg"},
+ {"jps", "image/x-jps"},
+ {"js", "application/javascript"},
+ {"json", "application/json"},
+ {"jut", "image/jutvision"},
+ {"kar", "music/x-karaoke"},
+ {"kdc", "image/kdc"},
+ {"ksh", "text/x-script.ksh"},
+ {"la", "audio/nspaudio"},
+ {"lam", "audio/x-liveaudio"},
+ {"latex", "application/x-latex"},
+ {"lha", "application/lha"},
+ {"lhx", "application/octet-stream"},
+ {"list", "text/plain"},
+ {"lma", "audio/nspaudio"},
+ {"log", "text/plain"},
+ {"lsp", "application/x-lisp"},
+ {"lst", "text/plain"},
+ {"lsx", "text/x-la-asf"},
+ {"ltx", "application/x-latex"},
+ {"lzh", "application/x-lzh"},
+ {"lzx", "application/lzx"},
+ {"m", "text/x-m"},
+ {"m1v", "video/mpeg"},
+ {"m2a", "audio/mpeg"},
+ {"m2v", "video/mpeg"},
+ {"m3u", "audio/x-mpegurl"},
+ {"man", "application/x-troff-man"},
+ {"map", "application/x-navimap"},
+ {"mar", "text/plain"},
+ {"mbd", "application/mbedlet"},
+ {"mc$", "application/x-magic-cap-package-1.0"},
+ {"mcd", "application/x-mathcad"},
+ {"mcf", "text/mcf"},
+ {"mcp", "application/netmc"},
+ {"mdc", "image/mdc"},
+ {"me", "application/x-troff-me"},
+ {"mef", "image/mef"},
+ {"mht", "message/rfc822"},
+ {"mhtml", "message/rfc822"},
+ {"mid", "audio/midi"},
+ {"midi", "audio/midi"},
+ {"mif", "application/x-mif"},
+ {"mime", "message/rfc822"},
+ {"mjf", "audio/x-vnd.audioexplosion.mjuicemediafile"},
+ {"mjpg", "video/x-motion-jpeg"},
+ {"mka", "audio/x-matroska"},
+ {"mkv", "video/x-matroska"},
+ {"mk3d", "video/x-matroska-3d"},
+ {"mm", "application/x-meme"},
+ {"mme", "application/base64"},
+ {"mod", "audio/mod"},
+ {"moov", "video/quicktime"},
+ {"mov", "video/quicktime"},
+ {"movie", "video/x-sgi-movie"},
+ {"mos", "image/mos"},
+ {"mp2", "audio/mpeg"},
+ {"mp3", "audio/mpeg3"},
+ {"mp4", "video/mp4"},
+ {"mpa", "audio/mpeg"},
+ {"mpc", "application/x-project"},
+ {"mpe", "video/mpeg"},
+ {"mpeg", "video/mpeg"},
+ {"mpg", "video/mpeg"},
+ {"mpga", "audio/mpeg"},
+ {"mpp", "application/vnd.ms-project"},
+ {"mpt", "application/x-project"},
+ {"mpv", "application/x-project"},
+ {"mpx", "application/x-project"},
+ {"mrc", "application/marc"},
+ {"mrw", "image/mrw"},
+ {"ms", "application/x-troff-ms"},
+ {"mv", "video/x-sgi-movie"},
+ {"my", "audio/make"},
+ {"mzz", "application/x-vnd.audioexplosion.mzz"},
+ {"nap", "image/naplps"},
+ {"naplps", "image/naplps"},
+ {"nc", "application/x-netcdf"},
+ {"ncm", "application/vnd.nokia.configuration-message"},
+ {"nef", "image/nef"},
+ {"nfo", "text/xml"},
+ {"nif", "image/x-niff"},
+ {"niff", "image/x-niff"},
+ {"nix", "application/x-mix-transfer"},
+ {"nrw", "image/nrw"},
+ {"nsc", "application/x-conference"},
+ {"nvd", "application/x-navidoc"},
+ {"o", "application/octet-stream"},
+ {"oda", "application/oda"},
+ {"ogg", "audio/ogg"},
+ {"omc", "application/x-omc"},
+ {"omcd", "application/x-omcdatamaker"},
+ {"omcr", "application/x-omcregerator"},
+ {"orf", "image/orf"},
+ {"p", "text/x-pascal"},
+ {"p10", "application/pkcs10"},
+ {"p12", "application/pkcs-12"},
+ {"p7a", "application/x-pkcs7-signature"},
+ {"p7c", "application/pkcs7-mime"},
+ {"p7m", "application/pkcs7-mime"},
+ {"p7r", "application/x-pkcs7-certreqresp"},
+ {"p7s", "application/pkcs7-signature"},
+ {"part", "application/pro_eng"},
+ {"pas", "text/pascal"},
+ {"pbm", "image/x-portable-bitmap"},
+ {"pcl", "application/vnd.hp-pcl"},
+ {"pct", "image/x-pict"},
+ {"pcx", "image/x-pcx"},
+ {"pdb", "chemical/x-pdb"},
+ {"pdf", "application/pdf"},
+ {"pef", "image/pef"},
+ {"pfunk", "audio/make.my.funk"},
+ {"pgm", "image/x-portable-greymap"},
+ {"pic", "image/pict"},
+ {"pict", "image/pict"},
+ {"pkg", "application/x-newton-compatible-pkg"},
+ {"pko", "application/vnd.ms-pki.pko"},
+ {"pl", "text/x-script.perl"},
+ {"plx", "application/x-pixclscript"},
+ {"pm", "text/x-script.perl-module"},
+ {"pm4", "application/x-pagemaker"},
+ {"pm5", "application/x-pagemaker"},
+ {"png", "image/png"},
+ {"pnm", "application/x-portable-anymap"},
+ {"pot", "application/vnd.ms-powerpoint"},
+ {"pov", "model/x-pov"},
+ {"ppa", "application/vnd.ms-powerpoint"},
+ {"ppm", "image/x-portable-pixmap"},
+ {"pps", "application/mspowerpoint"},
+ {"ppt", "application/mspowerpoint"},
+ {"ppz", "application/mspowerpoint"},
+ {"pre", "application/x-freelance"},
+ {"prt", "application/pro_eng"},
+ {"ps", "application/postscript"},
+ {"psd", "application/octet-stream"},
+ {"pvu", "paleovu/x-pv"},
+ {"pwz", "application/vnd.ms-powerpoint"},
+ {"py", "text/x-script.python"},
+ {"pyc", "application/x-bytecode.python"},
+ {"qcp", "audio/vnd.qcelp"},
+ {"qd3", "x-world/x-3dmf"},
+ {"qd3d", "x-world/x-3dmf"},
+ {"qif", "image/x-quicktime"},
+ {"qt", "video/quicktime"},
+ {"qtc", "video/x-qtc"},
+ {"qti", "image/x-quicktime"},
+ {"qtif", "image/x-quicktime"},
+ {"ra", "audio/x-realaudio"},
+ {"raf", "image/raf"},
+ {"ram", "audio/x-pn-realaudio"},
+ {"ras", "image/cmu-raster"},
+ {"rast", "image/cmu-raster"},
+ {"raw", "image/raw"},
+ {"rexx", "text/x-script.rexx"},
+ {"rf", "image/vnd.rn-realflash"},
+ {"rgb", "image/x-rgb"},
+ {"rm", "audio/x-pn-realaudio"},
+ {"rmi", "audio/mid"},
+ {"rmm", "audio/x-pn-realaudio"},
+ {"rmp", "audio/x-pn-realaudio"},
+ {"rng", "application/ringing-tones"},
+ {"rnx", "application/vnd.rn-realplayer"},
+ {"roff", "application/x-troff"},
+ {"rp", "image/vnd.rn-realpix"},
+ {"rpm", "audio/x-pn-realaudio-plugin"},
+ {"rt", "text/richtext"},
+ {"rtf", "text/richtext"},
+ {"rtx", "text/richtext"},
+ {"rv", "video/vnd.rn-realvideo"},
+ {"rw2", "image/rw2"},
+ {"s", "text/x-asm"},
+ {"s3m", "audio/s3m"},
+ {"saveme", "application/octet-stream"},
+ {"sbk", "application/x-tbook"},
+ {"scm", "video/x-scm"},
+ {"sdml", "text/plain"},
+ {"sdp", "application/sdp"},
+ {"sdr", "application/sounder"},
+ {"sea", "application/sea"},
+ {"set", "application/set"},
+ {"sgm", "text/sgml"},
+ {"sgml", "text/sgml"},
+ {"sh", "text/x-script.sh"},
+ {"shar", "application/x-bsh"},
+ {"shtml", "text/x-server-parsed-html"},
+ {"sid", "audio/x-psid"},
+ {"sit", "application/x-stuffit"},
+ {"skd", "application/x-koan"},
+ {"skm", "application/x-koan"},
+ {"skp", "application/x-koan"},
+ {"skt", "application/x-koan"},
+ {"sl", "application/x-seelogo"},
+ {"smi", "application/smil"},
+ {"smil", "application/smil"},
+ {"snd", "audio/basic"},
+ {"sol", "application/solids"},
+ {"spc", "text/x-speech"},
+ {"spl", "application/futuresplash"},
+ {"spr", "application/x-sprite"},
+ {"sprite", "application/x-sprite"},
+ {"src", "application/x-wais-source"},
+ {"srw", "image/srw"},
+ {"ssi", "text/x-server-parsed-html"},
+ {"ssm", "application/streamingmedia"},
+ {"sst", "application/vnd.ms-pki.certstore"},
+ {"step", "application/step"},
+ {"stl", "application/sla"},
+ {"stp", "application/step"},
+ {"sup", "application/x-pgs"},
+ {"sv4cpio", "application/x-sv4cpio"},
+ {"sv4crc", "application/x-sv4crc"},
+ {"svf", "image/vnd.dwg"},
+ {"svg", "image/svg+xml"},
+ {"svr", "application/x-world"},
+ {"swf", "application/x-shockwave-flash"},
+ {"t", "application/x-troff"},
+ {"talk", "text/x-speech"},
+ {"tar", "application/x-tar"},
+ {"tbk", "application/toolbook"},
+ {"tcl", "text/x-script.tcl"},
+ {"tcsh", "text/x-script.tcsh"},
+ {"tex", "application/x-tex"},
+ {"texi", "application/x-texinfo"},
+ {"texinfo", "application/x-texinfo"},
+ {"text", "text/plain"},
+ {"tgz", "application/x-compressed"},
+ {"tif", "image/tiff"},
+ {"tiff", "image/tiff"},
+ {"tr", "application/x-troff"},
+ {"ts", "video/mp2t"},
+ {"tsi", "audio/tsp-audio"},
+ {"tsp", "audio/tsplayer"},
+ {"tsv", "text/tab-separated-values"},
+ {"turbot", "image/florian"},
+ {"txt", "text/plain"},
+ {"uil", "text/x-uil"},
+ {"uni", "text/uri-list"},
+ {"unis", "text/uri-list"},
+ {"unv", "application/i-deas"},
+ {"uri", "text/uri-list"},
+ {"uris", "text/uri-list"},
+ {"ustar", "application/x-ustar"},
+ {"uu", "text/x-uuencode"},
+ {"uue", "text/x-uuencode"},
+ {"vcd", "application/x-cdlink"},
+ {"vcs", "text/x-vcalendar"},
+ {"vda", "application/vda"},
+ {"vdo", "video/vdo"},
+ {"vew", "application/groupwise"},
+ {"viv", "video/vivo"},
+ {"vivo", "video/vivo"},
+ {"vmd", "application/vocaltec-media-desc"},
+ {"vmf", "application/vocaltec-media-file"},
+ {"voc", "audio/voc"},
+ {"vos", "video/vosaic"},
+ {"vox", "audio/voxware"},
+ {"vqe", "audio/x-twinvq-plugin"},
+ {"vqf", "audio/x-twinvq"},
+ {"vql", "audio/x-twinvq-plugin"},
+ {"vrml", "application/x-vrml"},
+ {"vrt", "x-world/x-vrt"},
+ {"vsd", "application/x-visio"},
+ {"vst", "application/x-visio"},
+ {"vsw", "application/x-visio"},
+ {"vtt", "text/vtt"},
+ {"w60", "application/wordperfect6.0"},
+ {"w61", "application/wordperfect6.1"},
+ {"w6w", "application/msword"},
+ {"wav", "audio/wav"},
+ {"wb1", "application/x-qpro"},
+ {"wbmp", "image/vnd.wap.wbmp"},
+ {"web", "application/vnd.xara"},
+ {"webp", "image/webp"},
+ {"wiz", "application/msword"},
+ {"wk1", "application/x-123"},
+ {"wma", "audio/x-ms-wma"},
+ {"wmf", "windows/metafile"},
+ {"wml", "text/vnd.wap.wml"},
+ {"wmlc", "application/vnd.wap.wmlc"},
+ {"wmls", "text/vnd.wap.wmlscript"},
+ {"wmlsc", "application/vnd.wap.wmlscriptc"},
+ {"wmv", "video/x-ms-wmv"},
+ {"word", "application/msword"},
+ {"wp", "application/wordperfect"},
+ {"wp5", "application/wordperfect"},
+ {"wp6", "application/wordperfect"},
+ {"wpd", "application/wordperfect"},
+ {"wq1", "application/x-lotus"},
+ {"wri", "application/mswrite"},
+ {"wrl", "model/vrml"},
+ {"wrz", "model/vrml"},
+ {"wsc", "text/scriplet"},
+ {"wsrc", "application/x-wais-source"},
+ {"wtk", "application/x-wintalk"},
+ {"x3f", "image/x3f"},
+ {"xbm", "image/xbm"},
+ {"xdr", "video/x-amt-demorun"},
+ {"xgz", "xgl/drawing"},
+ {"xif", "image/vnd.xiff"},
+ {"xl", "application/excel"},
+ {"xla", "application/excel"},
+ {"xlb", "application/excel"},
+ {"xlc", "application/excel"},
+ {"xld", "application/excel"},
+ {"xlk", "application/excel"},
+ {"xll", "application/excel"},
+ {"xlm", "application/excel"},
+ {"xls", "application/excel"},
+ {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
+ {"xlt", "application/excel"},
+ {"xlv", "application/excel"},
+ {"xlw", "application/excel"},
+ {"xm", "audio/xm"},
+ {"xml", "text/xml"},
+ {"xmz", "xgl/movie"},
+ {"xpix", "application/x-vnd.ls-xpix"},
+ {"xpm", "image/xpm"},
+ {"x-png", "image/png"},
+ {"xspf", "application/xspf+xml"},
+ {"xsr", "video/x-amt-showrun"},
+ {"xvid", "video/x-msvideo"},
+ {"xwd", "image/x-xwd"},
+ {"xyz", "chemical/x-pdb"},
+ {"z", "application/x-compressed"},
+ {"zip", "application/zip"},
+ {"zoo", "application/octet-stream"},
+ {"zsh", "text/x-script.zsh"}}};
+
+std::string CMime::GetMimeType(const std::string &extension)
+{
+ if (extension.empty())
+ return "";
+
+ std::string ext = extension;
+ size_t posNotPoint = ext.find_first_not_of('.');
+ if (posNotPoint != std::string::npos && posNotPoint > 0)
+ ext = extension.substr(posNotPoint);
+ transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
+
+ std::map<std::string, std::string>::const_iterator it = m_mimetypes.find(ext);
+ if (it != m_mimetypes.end())
+ return it->second;
+
+ return "";
+}
+
+std::string CMime::GetMimeType(const CFileItem &item)
+{
+ std::string path = item.GetDynPath();
+ if (item.HasVideoInfoTag() && !item.GetVideoInfoTag()->GetPath().empty())
+ path = item.GetVideoInfoTag()->GetPath();
+ else if (item.HasMusicInfoTag() && !item.GetMusicInfoTag()->GetURL().empty())
+ path = item.GetMusicInfoTag()->GetURL();
+
+ return GetMimeType(URIUtils::GetExtension(path));
+}
+
+std::string CMime::GetMimeType(const CURL &url, bool lookup)
+{
+
+ std::string strMimeType;
+
+ if( url.IsProtocol("shout") || url.IsProtocol("http") || url.IsProtocol("https"))
+ {
+ // If lookup is false, bail out early to leave mime type empty
+ if (!lookup)
+ return strMimeType;
+
+ std::string strmime;
+ XFILE::CCurlFile::GetMimeType(url, strmime);
+
+ // try to get mime-type again but with an NSPlayer User-Agent
+ // in order for server to provide correct mime-type. Allows us
+ // to properly detect an MMS stream
+ if (StringUtils::StartsWithNoCase(strmime, "video/x-ms-"))
+ XFILE::CCurlFile::GetMimeType(url, strmime, "NSPlayer/11.00.6001.7000");
+
+ // make sure there are no options set in mime-type
+ // mime-type can look like "video/x-ms-asf ; charset=utf8"
+ size_t i = strmime.find(';');
+ if(i != std::string::npos)
+ strmime.erase(i, strmime.length() - i);
+ StringUtils::Trim(strmime);
+ strMimeType = strmime;
+ }
+ else
+ strMimeType = GetMimeType(url.GetFileType());
+
+ // if it's still empty set to an unknown type
+ if (strMimeType.empty())
+ strMimeType = "application/octet-stream";
+
+ return strMimeType;
+}
+
+CMime::EFileType CMime::GetFileTypeFromMime(const std::string& mimeType)
+{
+ // based on http://mimesniff.spec.whatwg.org/
+
+ std::string type, subtype;
+ if (!parseMimeType(mimeType, type, subtype))
+ return FileTypeUnknown;
+
+ if (type == "application")
+ {
+ if (subtype == "zip")
+ return FileTypeZip;
+ if (subtype == "x-gzip")
+ return FileTypeGZip;
+ if (subtype == "x-rar-compressed")
+ return FileTypeRar;
+
+ if (subtype == "xml")
+ return FileTypeXml;
+ }
+ else if (type == "text")
+ {
+ if (subtype == "xml")
+ return FileTypeXml;
+ if (subtype == "html")
+ return FileTypeHtml;
+ if (subtype == "plain")
+ return FileTypePlainText;
+ }
+ else if (type == "image")
+ {
+ if (subtype == "bmp")
+ return FileTypeBmp;
+ if (subtype == "gif")
+ return FileTypeGif;
+ if (subtype == "png")
+ return FileTypePng;
+ if (subtype == "jpeg" || subtype == "pjpeg")
+ return FileTypeJpeg;
+ }
+
+ if (StringUtils::EndsWith(subtype, "+zip"))
+ return FileTypeZip;
+ if (StringUtils::EndsWith(subtype, "+xml"))
+ return FileTypeXml;
+
+ return FileTypeUnknown;
+}
+
+CMime::EFileType CMime::GetFileTypeFromContent(const std::string& fileContent)
+{
+ // based on http://mimesniff.spec.whatwg.org/#matching-a-mime-type-pattern
+
+ const size_t len = fileContent.length();
+ if (len < 2)
+ return FileTypeUnknown;
+
+ const unsigned char* const b = (const unsigned char*)fileContent.c_str();
+
+ //! @todo add detection for text types
+
+ // check image types
+ if (b[0] == 'B' && b[1] == 'M')
+ return FileTypeBmp;
+ if (len >= 6 && b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' && (b[4] == '7' || b[4] == '9') && b[5] == 'a')
+ return FileTypeGif;
+ if (len >= 8 && b[0] == 0x89 && b[1] == 'P' && b[2] == 'N' && b[3] == 'G' && b[4] == 0x0D && b[5] == 0x0A && b[6] == 0x1A && b[7] == 0x0A)
+ return FileTypePng;
+ if (len >= 3 && b[0] == 0xFF && b[1] == 0xD8 && b[2] == 0xFF)
+ return FileTypeJpeg;
+
+ // check archive types
+ if (len >= 3 && b[0] == 0x1F && b[1] == 0x8B && b[2] == 0x08)
+ return FileTypeGZip;
+ if (len >= 4 && b[0] == 'P' && b[1] == 'K' && b[2] == 0x03 && b[3] == 0x04)
+ return FileTypeZip;
+ if (len >= 7 && b[0] == 'R' && b[1] == 'a' && b[2] == 'r' && b[3] == ' ' && b[4] == 0x1A && b[5] == 0x07 && b[6] == 0x00)
+ return FileTypeRar;
+
+ //! @todo add detection for other types if required
+
+ return FileTypeUnknown;
+}
+
+bool CMime::parseMimeType(const std::string& mimeType, std::string& type, std::string& subtype)
+{
+ static const char* const whitespaceChars = "\x09\x0A\x0C\x0D\x20"; // tab, LF, FF, CR and space
+
+ type.clear();
+ subtype.clear();
+
+ const size_t slashPos = mimeType.find('/');
+ if (slashPos == std::string::npos)
+ return false;
+
+ type.assign(mimeType, 0, slashPos);
+ subtype.assign(mimeType, slashPos + 1, std::string::npos);
+
+ const size_t semicolonPos = subtype.find(';');
+ if (semicolonPos != std::string::npos)
+ subtype.erase(semicolonPos);
+
+ StringUtils::Trim(type, whitespaceChars);
+ StringUtils::Trim(subtype, whitespaceChars);
+
+ if (type.empty() || subtype.empty())
+ {
+ type.clear();
+ subtype.clear();
+ return false;
+ }
+
+ StringUtils::ToLower(type);
+ StringUtils::ToLower(subtype);
+
+ return true;
+}