• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

kmimeglobsfileparser.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries
00002  *  Copyright 2007, 2010 David Faure <faure@kde.org>
00003  *
00004  *  This library is free software; you can redistribute it and/or
00005  *  modify it under the terms of the GNU Library General Public
00006  *  License as published by the Free Software Foundation; either
00007  *  version 2 of the License, or (at your option) any later version.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include "kmimeglobsfileparser_p.h"
00021 #include <kglobal.h>
00022 #include <kdeversion.h>
00023 #include <kmimetype.h>
00024 #include <kstandarddirs.h>
00025 #include "kmimetyperepository_p.h"
00026 #include <kdebug.h>
00027 #include <QtCore/QTextStream>
00028 #include <QtCore/QFile>
00029 
00030 KMimeGlobsFileParser::KMimeGlobsFileParser()
00031 {
00032 }
00033 
00034 KMimeGlobsFileParser::AllGlobs KMimeGlobsFileParser::parseGlobs()
00035 {
00036     const QStringList globFiles = KGlobal::dirs()->findAllResources("xdgdata-mime", QString::fromLatin1("globs"));
00037     //kDebug() << globFiles;
00038     return parseGlobs(globFiles);
00039 }
00040 
00041 KMimeGlobsFileParser::AllGlobs KMimeGlobsFileParser::parseGlobs(const QStringList& globFiles)
00042 {
00043     QStringList parsedFiles;
00044     return parseGlobFiles(globFiles, parsedFiles);
00045 }
00046 
00047 KMimeGlobsFileParser::AllGlobs KMimeGlobsFileParser::parseGlobFiles(const QStringList& globFiles, QStringList& parsedFiles)
00048 {
00049     KMimeGlobsFileParser::AllGlobs allGlobs;
00050     QListIterator<QString> globIter(globFiles);
00051     globIter.toBack();
00052     // At each level, we must be able to override (not just add to) the information that we read at higher levels
00053     // (if glob-deleteall is used).
00054     while (globIter.hasPrevious()) { // global first, then local
00055         Format format = OldGlobs;
00056         QString fileName = globIter.previous();
00057         QString fileNamev2 = fileName + QLatin1Char('2'); // NOTE: this relies on u-m-d always generating the old globs file
00058         if (QFile::exists(fileNamev2)) {
00059             fileName = fileNamev2;
00060             format = Globs2WithWeight;
00061         }
00062         parsedFiles << fileName;
00063         QFile globFile(fileName);
00064         //kDebug() << "Now parsing" << fileName;
00065         parseGlobFile(&globFile, format, allGlobs);
00066     }
00067     return allGlobs;
00068 }
00069 
00070 // uses a QIODevice to make unit tests possible
00071 bool KMimeGlobsFileParser::parseGlobFile(QIODevice* file, Format format, AllGlobs& globs)
00072 {
00073     if (!file->open(QIODevice::ReadOnly))
00074         return false;
00075 
00076     // If we're not going to get the "cs" flag because smi is too old, then we need to emulate it for *.C at least.
00077     const bool caseSensitiveHackNeeded = (KMimeType::sharedMimeInfoVersion() <= KDE_MAKE_VERSION(0, 60, 0));
00078 
00079     QTextStream stream(file);
00080     //stream.setCodec("UTF-8"); // should be all latin1
00081     QString lastMime, lastPattern;
00082     QString line;
00083     while (!stream.atEnd()) {
00084         line = stream.readLine();
00085         if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
00086             continue;
00087 
00088         const QStringList fields = line.split(QLatin1Char(':'), QString::KeepEmptyParts);
00089         if (fields.count() < 2) // syntax error
00090             continue;
00091 
00092         //kDebug() << "line=" << line;
00093 
00094         QString mimeTypeName, pattern;
00095         QStringList flagList;
00096         int weight = 50;
00097         if (format == Globs2WithWeight) {
00098             if (fields.count() < 3) // syntax error
00099                 continue;
00100             weight = fields[0].toInt();
00101             mimeTypeName = fields[1];
00102             pattern = fields[2];
00103             const QString flagsStr = fields.value(3); // could be empty
00104             flagList = flagsStr.split(QLatin1Char(','), QString::SkipEmptyParts);
00105         } else {
00106             mimeTypeName = fields[0];
00107             pattern = fields[1];
00108         }
00109         Q_ASSERT(!pattern.isEmpty());
00110         Q_ASSERT(!pattern.contains(QLatin1Char(':')));
00111 
00112         //kDebug() << " got:" << mimeTypeName << pattern;
00113 
00114         if (lastMime == mimeTypeName && lastPattern == pattern) {
00115             // Ignore duplicates, especially important for those with no flags after a line with flags:
00116             // 50:text/x-csrc:*.c:cs
00117             // 50:text/x-csrc:*.c
00118             continue;
00119         }
00120 
00121         bool caseSensitive = flagList.contains(QLatin1String("cs"));
00122 
00123         if (caseSensitiveHackNeeded && (pattern == QLatin1String("*.C") || pattern == QLatin1String("*.c") || pattern == QLatin1String("core")))
00124             caseSensitive = true;
00125 
00126         if (pattern == QLatin1String("__NOGLOBS__")) {
00127             //kDebug() << "removing" << mimeTypeName;
00128             globs.removeMime(mimeTypeName);
00129             lastMime.clear();
00130         } else {
00131             int flags = 0;
00132             if (caseSensitive)
00133                 flags = KMimeTypeRepository::CaseSensitive;
00134 
00135             //if (mimeTypeName == "text/plain")
00136             //    kDebug() << "Adding pattern" << pattern << "to mimetype" << mimeTypeName << "from globs file, with weight" << weight;
00137             //if (pattern.toLower() == "*.c")
00138             //    kDebug() << " Adding pattern" << pattern << "to mimetype" << mimeTypeName << "from globs file, with weight" << weight << "flags" << flags;
00139             globs.addGlob(Glob(mimeTypeName, weight, pattern, flags));
00140             lastMime = mimeTypeName;
00141             lastPattern = pattern;
00142         }
00143     }
00144     return true;
00145 }
00146 
00147 static bool isFastPattern(const QString& pattern)
00148 {
00149    // starts with "*.", has no other '*' and no other '.'
00150    return pattern.lastIndexOf(QLatin1Char('*')) == 0
00151       && pattern.lastIndexOf(QLatin1Char('.')) == 1
00152       // and contains no other special character
00153       && !pattern.contains(QLatin1Char('?'))
00154       && !pattern.contains(QLatin1Char('['))
00155       ;
00156 }
00157 
00158 void KMimeGlobsFileParser::AllGlobs::addGlob(const Glob& glob)
00159 {
00160     // Note that in each case, we check for duplicates to avoid inserting duplicated patterns.
00161     // This can happen when installing kde.xml and freedesktop.org.xml
00162     // in the same prefix, and they both have text/plain:*.txt
00163     // TODO: skipping for now; evaluate if performance problem
00164 
00165     const QString &pattern = glob.pattern;
00166     Q_ASSERT(!pattern.isEmpty());
00167 
00168     //kDebug() << "pattern" << pattern << "glob.weight=" << glob.weight << "isFast=" << isFastPattern(pattern) << glob.flags;
00169 
00170     // Store each patterns into either m_fastPatternDict (*.txt, *.html etc. with default weight 50)
00171     // or for the rest, like core.*, *.tar.bz2, *~, into highWeightPatternOffset (>50)
00172     // or lowWeightPatternOffset (<=50)
00173 
00174     if (glob.weight == 50 && isFastPattern(pattern) && ((glob.flags & KMimeTypeRepository::CaseSensitive) == 0)) {
00175         // The bulk of the patterns is *.foo with weight 50 --> those go into the fast patterns hash.
00176         const QString extension = pattern.mid(2).toLower();
00177         QStringList& patterns = m_fastPatterns[extension]; // find or create
00178         //if (!patterns.contains(glob.mimeType))
00179             patterns.append(glob.mimeType);
00180     } else {
00181         Glob adjustedGlob(glob);
00182         if ((adjustedGlob.flags & KMimeTypeRepository::CaseSensitive) == 0)
00183             adjustedGlob.pattern = adjustedGlob.pattern.toLower();
00184         if (adjustedGlob.weight > 50) {
00185             //if (!m_highWeightGlobs.hasPattern(adjustedGlob.mimeType, adjustedGlob.pattern))
00186                 m_highWeightGlobs.append(adjustedGlob);
00187         } else {
00188             //if (!m_lowWeightGlobs.hasPattern(adjustedGlob.mimeType, adjustedGlob.pattern))
00189                 m_lowWeightGlobs.append(adjustedGlob);
00190         }
00191     }
00192 }
00193 
00194 KMimeGlobsFileParser::PatternsMap KMimeGlobsFileParser::AllGlobs::patternsMap() const
00195 {
00196     PatternsMap patMap;
00197 
00198     // This is just to fill in KMimeType::patterns. This has no real effect
00199     // on the actual mimetype matching.
00200 
00201     QHash<QString, QStringList>::const_iterator it = m_fastPatterns.begin();
00202     const QHash<QString, QStringList>::const_iterator end = m_fastPatterns.end();
00203     for (; it != end; ++it) {
00204         Q_FOREACH(const QString& mime, it.value())
00205             patMap[mime].append(QString::fromLatin1("*.") + it.key());
00206     }
00207 
00208     Q_FOREACH(const Glob& glob, m_highWeightGlobs)
00209         patMap[glob.mimeType].append(glob.pattern);
00210 
00211     Q_FOREACH(const Glob& glob, m_lowWeightGlobs)
00212         patMap[glob.mimeType].append(glob.pattern);
00213 
00214     return patMap;
00215 }
00216 
00217 void KMimeGlobsFileParser::AllGlobs::removeMime(const QString& mime)
00218 {
00219     QMutableHashIterator<QString, QStringList> it(m_fastPatterns);
00220     while (it.hasNext()) {
00221         it.next().value().removeAll(mime);
00222     }
00223     m_highWeightGlobs.removeMime(mime);
00224     m_lowWeightGlobs.removeMime(mime);
00225 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal