├── README.md ├── xmime.cmake ├── xmime.pri ├── LICENSE ├── xmime.h └── xmime.cpp /README.md: -------------------------------------------------------------------------------- 1 | # XMIME 2 | 3 | Detect MIME 4 | -------------------------------------------------------------------------------- /xmime.cmake: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_CURRENT_LIST_DIR}) 2 | 3 | include(${CMAKE_CURRENT_LIST_DIR}/../SpecAbstract/specabstract.cmake) 4 | 5 | set(XMIME_SOURCES 6 | ${SPECABSTRACT_SOURCES} 7 | ${CMAKE_CURRENT_LIST_DIR}/xmime.cpp 8 | ) 9 | -------------------------------------------------------------------------------- /xmime.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | 4 | HEADERS += \ 5 | $$PWD/xmime.h 6 | 7 | SOURCES += \ 8 | $$PWD/xmime.cpp 9 | 10 | !contains(XCONFIG, specabstract) { 11 | XCONFIG += specabstract 12 | include($$PWD/../SpecAbstract/specabstract.pri) 13 | } 14 | 15 | DISTFILES += \ 16 | $$PWD/LICENSE \ 17 | $$PWD/README.md \ 18 | $$PWD/xmime.cmake 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2025 hors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /xmime.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all 11 | * copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef XMIME_H 22 | #define XMIME_H 23 | 24 | #include "specabstract.h" 25 | 26 | class XMIME : public QObject { 27 | Q_OBJECT 28 | 29 | public: 30 | explicit XMIME(QObject *pParent = nullptr); 31 | static QList getTypes(QIODevice *pDevice, bool bIsAll = false); 32 | static QList getTypes(const QString &sFileName, bool bIsAll = false); 33 | }; 34 | 35 | #endif // XMIME_H 36 | -------------------------------------------------------------------------------- /xmime.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2020-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all 11 | * copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "xmime.h" 22 | 23 | XMIME::XMIME(QObject *pParent) : QObject(pParent) 24 | { 25 | } 26 | 27 | QList XMIME::getTypes(QIODevice *pDevice, bool bIsAll) 28 | { 29 | QList listResult; 30 | 31 | XScanEngine::SCAN_OPTIONS scanOptions = {}; 32 | scanOptions.bShowType = true; 33 | scanOptions.bShowVersion = true; 34 | scanOptions.bShowInfo = true; 35 | 36 | XScanEngine::SCAN_RESULT scanResult = SpecAbstract().scanDevice(pDevice, &scanOptions); 37 | 38 | bool bBinary = false; 39 | // Executables 40 | { 41 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_PE32) || 42 | SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_PE64)) { 43 | listResult.append("application/vnd.microsoft.portable-executable"); 44 | bBinary = true; 45 | } else if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_ELF32) || 46 | SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_ELF64)) { 47 | listResult.append("application/x-executable"); 48 | bBinary = true; 49 | // TODO 50 | } else if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_MACHO32) || 51 | SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_MACHO64)) { 52 | listResult.append("application/x-mach-binary"); 53 | bBinary = true; 54 | // TODO 55 | } 56 | 57 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_MSDOS)) { 58 | listResult.append("application/x-dosexec"); 59 | bBinary = true; 60 | } 61 | } 62 | 63 | // Documents 64 | if (!bBinary) { 65 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_PYTHON)) { 66 | listResult.append("text/x-python"); 67 | } 68 | 69 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_PERL)) { 70 | listResult.append("text/x-perl"); 71 | } 72 | 73 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_RUBY)) { 74 | listResult.append("text/x-ruby"); 75 | } 76 | 77 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_HTML)) { 78 | listResult.append("text/html"); 79 | } 80 | 81 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_XML)) { 82 | listResult.append("text/xml"); 83 | } 84 | 85 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_PDF)) { 86 | listResult.append("application/pdf"); 87 | } 88 | 89 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_SHELL)) { 90 | listResult.append("text/x-shellscript"); 91 | } 92 | 93 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_C) || 94 | SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_CCPP)) { 95 | listResult.append("text/x-c"); 96 | } 97 | } 98 | 99 | // Media 100 | { 101 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_MP3)) { 102 | listResult.append("audio/mpeg"); 103 | } 104 | 105 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_PNG)) { 106 | listResult.append("image/png"); 107 | } 108 | 109 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_WEBP)) { 110 | listResult.append("image/webp"); 111 | } 112 | 113 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_JPEG)) { 114 | listResult.append("image/jpg"); 115 | listResult.append("image/jpeg"); 116 | } 117 | 118 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNKNOWN, SpecAbstract::RECORD_TYPE_UNKNOWN, SpecAbstract::RECORD_NAME_GIF)) { 119 | listResult.append("image/gif"); 120 | } 121 | } 122 | 123 | if (SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_TEXT) || 124 | SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_PLAINTEXT) || 125 | SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UTF8) || SpecAbstract::isScanStructPresent(&scanResult.listRecords, XBinary::FT_UNICODE)) { 126 | if ((listResult.count() == 0) || (bIsAll)) { 127 | listResult.append("text/plain"); 128 | } 129 | } else { 130 | if ((listResult.count() == 0) || (bIsAll)) { 131 | listResult.append("application/octet-stream"); 132 | } 133 | } 134 | 135 | // TODO 136 | // application/vnd.android.package-archive 137 | // application/x-gzip 138 | // application/x-bzip2 139 | // application/x-bzip 140 | // application/x-lzip 141 | // application/x-7z-compressed 142 | // application/x-lzma 143 | // application/x-xz 144 | // application/x-lrzip 145 | // application/x-lz4 146 | // application/x-zstd 147 | // application/zlib 148 | // application/javascript 149 | // application/x-archive 150 | // TODO wmv/wma 151 | 152 | return listResult; 153 | } 154 | 155 | QList XMIME::getTypes(const QString &sFileName, bool bIsAll) 156 | { 157 | QList listResult; 158 | 159 | QFile file; 160 | 161 | file.setFileName(sFileName); 162 | 163 | if (file.open(QIODevice::ReadOnly)) { 164 | listResult = getTypes(&file, bIsAll); 165 | 166 | file.close(); 167 | } 168 | 169 | return listResult; 170 | } 171 | --------------------------------------------------------------------------------