File indexing completed on 2024-05-05 04:52:23

0001 /*
0002  * updatemimetypes.cpp
0003  *
0004  * Copyright (C) 2010-2011 Christoph Pfister <christophpfister@gmail.com>
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License along
0017  * with this program; if not, write to the Free Software Foundation, Inc.,
0018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0019  */
0020 
0021 #include <QDebug>
0022 #if QT_VERSION < 0x050500
0023 # define qInfo qDebug
0024 #endif
0025 
0026 #include <QCoreApplication>
0027 #include <QFile>
0028 #include <QMimeDatabase>
0029 #include <QMimeType>
0030 
0031 int main(int argc, char *argv[])
0032 {
0033     bool dontUpdate = false;
0034 
0035     // QCoreApplication is needed for proper file name handling
0036     QCoreApplication application(argc, argv);
0037 
0038     if (argc != 3) {
0039         qCritical() << "syntax:" << argv[0] << "<desktop file> <path to mediawidget.cpp>";
0040         return 1;
0041     }
0042 
0043     QFile file(argv[1]);
0044     QStringList lines;
0045 
0046     {
0047         if (!file.open(QFile::ReadOnly)) {
0048             qCritical() << "cannot open file" << file.fileName();
0049             return 1;
0050         }
0051 
0052         QTextStream stream(&file);
0053         stream.setCodec("UTF-8");
0054 
0055         while (!stream.atEnd()) {
0056             lines.append(stream.readLine());
0057         }
0058 
0059         file.close();
0060     }
0061 
0062     int mimeTypeIndex = -1;
0063     QStringList mimeTypes;
0064 
0065     for (int i = 0; i < lines.size(); ++i) {
0066         if (lines.at(i).startsWith(QLatin1String("MimeType="))) {
0067             if (mimeTypeIndex >= 0) {
0068                 qCritical() << "more than one MimeType entry found in file" <<
0069                     file.fileName();
0070                 dontUpdate = true;
0071             }
0072 
0073             mimeTypeIndex = i;
0074             mimeTypes = lines.at(i).mid(9).split(';', Qt::SkipEmptyParts);
0075         }
0076     }
0077 
0078     if (mimeTypeIndex < 0) {
0079         qCritical() << "cannot find a MimeType entry in file" << file.fileName();
0080         return 1;
0081     }
0082 
0083     mimeTypes.removeDuplicates();
0084     mimeTypes.sort();
0085 
0086     QStringList mimeTypesExt;
0087 
0088     for (int i = 0; i < mimeTypes.size(); ++i) {
0089         QMimeDatabase db;
0090         QString curMime, newMime;
0091 
0092         curMime = mimeTypes.at(i);
0093 
0094         if (!curMime.compare("application/x-extension-mp4")) {
0095             newMime = db.mimeTypeForFile("*.mp4").name();
0096         } else if (!curMime.compare("application/x-flac")) {
0097             newMime = db.mimeTypeForFile("*.flac").name();
0098         } else if (!curMime.compare("audio/x-ms-asf")) {
0099             newMime = db.mimeTypeForFile("*.wma").name();
0100         } else if (!curMime.compare("audio/x-ms-wax")) {
0101             newMime = db.mimeTypeForFile("*.wax").name();
0102         } else if (!curMime.compare("audio/x-pn-aiff")) {
0103             newMime = db.mimeTypeForFile("*.aif").name();
0104         } else if (!curMime.compare("audio/x-pn-au")) {
0105             newMime = db.mimeTypeForFile("*.au").name();
0106         } else if (!curMime.compare("audio/x-real-audio")) {
0107             newMime = db.mimeTypeForFile("*.rmvb").name();
0108         } else if (!curMime.compare("audio/x-pn-wav") || !curMime.compare("audio/x-pn-acm") || !curMime.compare("audio/x-pn-windows-acm")) {
0109             newMime = db.mimeTypeForFile("*.wav").name();
0110         } else if (!curMime.compare("video/x-flc")) {
0111             newMime = db.mimeTypeForFile("*.flc").name();
0112         } else if (!curMime.compare("misc/ultravox")) {
0113             // Mime Type is not associated with extensions
0114             continue;
0115         } else if (curMime.contains("x-scheme-handler/")) {
0116             // Mime Type is not associated with extensions
0117             continue;
0118         }
0119         if (!newMime.isEmpty()) {
0120             // Use the mime type name known by QMimeDatabase
0121             mimeTypes.replace(i, newMime);
0122 
0123             mimeTypesExt << newMime;
0124             qInfo() << "replacing" << curMime << "by" << newMime;
0125         } else {
0126             mimeTypesExt << curMime;
0127         }
0128     }
0129 
0130     mimeTypes.removeDuplicates();
0131     mimeTypes.sort();
0132 
0133     mimeTypesExt.removeDuplicates();
0134     mimeTypesExt.sort();
0135 
0136     QStringList realExtensions;
0137 
0138     for (int skipMimeType = -1; skipMimeType < mimeTypesExt.size(); ++skipMimeType) {
0139         QStringList extensions;
0140 
0141         for (int i = 0; i < mimeTypesExt.size(); ++i) {
0142             if (i != skipMimeType) {
0143                 QMimeDatabase db;
0144                 QString mime = mimeTypesExt.at(i);
0145                 QMimeType mimetype = db.mimeTypeForName(mime);
0146 
0147                 if (!mime.compare("skip")) {
0148                     continue;
0149                 }
0150                 if (!mime.compare("application/octet-stream")) {
0151                     qInfo() << "Warning: application/octet-stream detected!";
0152                     continue;
0153                 }
0154                 if (!mime.compare("application/text")) {
0155                     qInfo() << "Warning: application/text detected!";
0156                     continue;
0157                 }
0158 
0159                 if (!mimetype.isValid()) {
0160                     qCritical() << "unknown mime type" << mime;
0161                     dontUpdate = true;
0162                     continue;
0163                 }
0164 
0165                 extensions.append(mimetype.globPatterns());
0166             }
0167         }
0168 
0169         QRegExp regExp("\\*\\.[a-z0-9+]+");
0170 
0171         for (int i = 0; i < extensions.size(); ++i) {
0172             if (extensions.at(i) == "*.anim[1-9j]") {
0173                 extensions.removeAt(i);
0174                 extensions.insert(i, "*.anim1");
0175                 extensions.insert(i, "*.anim2");
0176                 extensions.insert(i, "*.anim3");
0177                 extensions.insert(i, "*.anim4");
0178                 extensions.insert(i, "*.anim5");
0179                 extensions.insert(i, "*.anim6");
0180                 extensions.insert(i, "*.anim7");
0181                 extensions.insert(i, "*.anim8");
0182                 extensions.insert(i, "*.anim9");
0183                 extensions.insert(i, "*.animj");
0184             }
0185             if (extensions.at(i) == "[0-9][0-9][0-9].vdr") {
0186                 extensions.removeAt(i);
0187                 extensions.insert(i, "*.vdr");
0188             }
0189 
0190             if (!regExp.exactMatch(extensions.at(i))) {
0191                 qCritical() << "unknown extension syntax" << extensions.at(i);
0192                 dontUpdate = true;
0193             }
0194         }
0195 
0196         extensions.removeDuplicates();
0197         extensions.sort();
0198 
0199         if (realExtensions.isEmpty()) {
0200             realExtensions = extensions;
0201         } else if (extensions.size() == realExtensions.size()) {
0202             qWarning() << "possibly unneeded mime type found" <<
0203                 mimeTypes.at(skipMimeType);
0204         }
0205     }
0206 
0207     qInfo() << "Supported mime types:" << mimeTypes;
0208     qInfo() << "Supported file extensions:" << realExtensions;
0209 
0210     if (dontUpdate) {
0211         qInfo() << "Error parsing mime types. Aborting.";
0212         return 1;
0213     }
0214 
0215     {
0216         qInfo() << "Updating" << file.fileName();
0217         if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
0218             qCritical() << "cannot open file" << file.fileName();
0219             return 1;
0220         }
0221 
0222         QTextStream stream(&file);
0223         stream.setCodec("UTF-8");
0224 
0225         lines[mimeTypeIndex] = "MimeType=" + mimeTypes.join(";") + ';';
0226 
0227         foreach (const QString &line, lines) {
0228             stream << line << '\n';
0229         }
0230 
0231         file.close();
0232     }
0233 
0234     file.setFileName(argv[2]);
0235     lines.clear();
0236 
0237     {
0238         if (!file.open(QFile::ReadOnly)) {
0239             qCritical() << "cannot open file" << file.fileName();
0240             return 1;
0241         }
0242 
0243         QTextStream stream(&file);
0244         stream.setCodec("UTF-8");
0245 
0246         while (!stream.atEnd()) {
0247             lines.append(stream.readLine());
0248         }
0249 
0250         file.close();
0251     }
0252 
0253     {
0254         qInfo() << "Updating" << file.fileName();
0255         if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
0256             qCritical() << "cannot open file" << file.fileName();
0257             return 1;
0258         }
0259 
0260         QTextStream stream(&file);
0261         stream.setCodec("UTF-8");
0262 
0263         for (int i = 0; i < lines.size(); ++i) {
0264             stream << lines.at(i) << '\n';
0265 
0266             if (lines.at(i) == "\t\t// generated from kaffeine.desktop's mime types") {
0267                 QString line = "\t\t\"";
0268 
0269                 foreach (const QString &extension, realExtensions) {
0270                     if ((line.size() + extension.size()) > 83) {
0271                         stream << line << "\"\n";
0272                         line = "\t\t\"";
0273                     }
0274 
0275                     line += extension;
0276                     line += ' ';
0277                 }
0278 
0279                 stream << line << "\"\n";
0280 
0281                 while ((i < lines.size()) &&
0282                        (lines.at(i) != "\t\t// manual entries")) {
0283                     ++i;
0284                 }
0285 
0286                 stream << lines.at(i) << '\n';
0287             }
0288         }
0289 
0290         file.close();
0291     }
0292 
0293     qInfo() << "file extensions updated successfully.";
0294     return 0;
0295 }