• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

kmimetypefactory.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
00003  *  Copyright (C) 2006-2009 David Faure <faure@kde.org>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation;
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 "kmimetypefactory.h"
00021 #include "kmimetype.h"
00022 #include "kfoldermimetype.h"
00023 #include <ksycoca.h>
00024 #include <ksycocadict.h>
00025 #include <kshell.h>
00026 #include <kdebug.h>
00027 
00028 K_GLOBAL_STATIC(KSycocaFactorySingleton<KMimeTypeFactory>, kMimeTypeFactoryInstance)
00029 
00030 KMimeTypeFactory::KMimeTypeFactory()
00031     : KSycocaFactory( KST_KMimeTypeFactory ),
00032       m_highWeightPatternsLoaded(false),
00033       m_lowWeightPatternsLoaded(false),
00034       m_parentsMapLoaded(false),
00035       m_magicFilesParsed(false)
00036 {
00037     kMimeTypeFactoryInstance->instanceCreated(this);
00038     m_fastPatternOffset = 0;
00039     m_highWeightPatternOffset = 0;
00040     m_lowWeightPatternOffset = 0;
00041     if (!KSycoca::self()->isBuilding()) {
00042         QDataStream* str = stream();
00043         Q_ASSERT(str);
00044         // Read Header
00045         qint32 i;
00046         (*str) >> i;
00047         m_fastPatternOffset = i;
00048         (*str) >> i;
00049         // that's the old m_otherPatternOffset, kept for compat but unused
00050 
00051         // alias map
00052         // TODO: to save time in apps that don't need this, we could
00053         // do like the parents hash (move it, store offset, and load it delayed).
00054         qint32 n;
00055         (*str) >> n;
00056         QString str1, str2;
00057         for(;n;n--) {
00058             KSycocaEntry::read(*str, str1);
00059             KSycocaEntry::read(*str, str2);
00060             m_aliases.insert(str1, str2);
00061         }
00062 
00063         (*str) >> i;
00064         m_highWeightPatternOffset = i;
00065         (*str) >> i;
00066         m_lowWeightPatternOffset = i;
00067         (*str) >> i;
00068         m_parentsMapOffset = i;
00069 
00070         const int saveOffset = str->device()->pos();
00071         // Init index tables
00072         m_fastPatternDict = new KSycocaDict(str, m_fastPatternOffset);
00073         str->device()->seek(saveOffset);
00074     } else {
00075         m_parentsMapLoaded = true;
00076     }
00077 }
00078 
00079 KMimeTypeFactory::~KMimeTypeFactory()
00080 {
00081     if (kMimeTypeFactoryInstance.exists())
00082         kMimeTypeFactoryInstance->instanceDestroyed(this);
00083     delete m_fastPatternDict;
00084 }
00085 
00086 KMimeTypeFactory * KMimeTypeFactory::self()
00087 {
00088     return kMimeTypeFactoryInstance->self();
00089 }
00090 
00091 KMimeType::Ptr KMimeTypeFactory::findMimeTypeByName(const QString &_name, KMimeType::FindByNameOption options)
00092 {
00093     if (!sycocaDict()) return KMimeType::Ptr(); // Error!
00094     assert (!KSycoca::self()->isBuilding());
00095 
00096     QString name = _name;
00097     if (options & KMimeType::ResolveAliases) {
00098         AliasesMap::const_iterator it = m_aliases.constFind(_name);
00099         if (it != m_aliases.constEnd())
00100             name = *it;
00101     }
00102 
00103     int offset = sycocaDict()->find_string( name );
00104     if (!offset) return KMimeType::Ptr(); // Not found
00105     KMimeType::Ptr newMimeType(createEntry(offset));
00106 
00107     // Check whether the dictionary was right.
00108     if (newMimeType && (newMimeType->name() != name))
00109     {
00110         // No it wasn't...
00111         newMimeType = 0; // Not found
00112     }
00113     return newMimeType;
00114 }
00115 
00116 bool KMimeTypeFactory::checkMimeTypes()
00117 {
00118    QDataStream *str = KSycoca::self()->findFactory( factoryId() );
00119    if (!str) return false;
00120 
00121    // check if there are mimetypes
00122    return !isEmpty();
00123 }
00124 
00125 KMimeType * KMimeTypeFactory::createEntry(int offset) const
00126 {
00127    KMimeType *newEntry = 0;
00128    KSycocaType type;
00129    QDataStream *str = KSycoca::self()->findEntry(offset, type);
00130    if (!str) return 0;
00131 
00132    switch(type)
00133    {
00134      case KST_KMimeType:
00135      case KST_KDEDesktopMimeType: // old, compat only
00136         newEntry = new KMimeType(*str, offset);
00137         break;
00138      case KST_KFolderMimeType:
00139         newEntry = new KFolderMimeType(*str, offset);
00140         break;
00141 
00142      default:
00143         kError(7011) << QString("KMimeTypeFactory: unexpected object entry in KSycoca database (type = %1)").arg((int)type) << endl;
00144         break;
00145    }
00146    if (newEntry && !newEntry->isValid())
00147    {
00148       kError(7011) << "KMimeTypeFactory: corrupt object in KSycoca database!\n" << endl;
00149       delete newEntry;
00150       newEntry = 0;
00151    }
00152    return newEntry;
00153 }
00154 
00155 
00156 QString KMimeTypeFactory::resolveAlias(const QString& mime) const
00157 {
00158     return m_aliases.value(mime);
00159 }
00160 
00161 QList<KMimeType::Ptr> KMimeTypeFactory::findFromFileName( const QString &filename, QString *matchingExtension )
00162 {
00163     // Assume we're NOT building a database
00164     if (!stream()) return QList<KMimeType::Ptr>();
00165 
00166     // "Applications MUST first try a case-sensitive match, then try again with
00167     // the filename converted to lower-case if that fails. This is so that
00168     // main.C will be seen as a C++ file, but IMAGE.GIF will still use the
00169     // *.gif pattern."
00170     QList<KMimeType::Ptr> mimeList = findFromFileNameHelper(filename, matchingExtension);
00171     if (mimeList.isEmpty()) {
00172         const QString lowerCase = filename.toLower();
00173         if (lowerCase != filename)
00174             mimeList = findFromFileNameHelper(lowerCase, matchingExtension);
00175     }
00176     return mimeList;
00177 }
00178 
00179 QList<KMimeType::Ptr> KMimeTypeFactory::findFromFastPatternDict(const QString &extension)
00180 {
00181     QList<KMimeType::Ptr> mimeList;
00182     if (!m_fastPatternDict) return mimeList; // Error!
00183 
00184     // Warning : this assumes we're NOT building a database
00185     const QList<int> offsetList = m_fastPatternDict->findMultiString(extension);
00186     if (offsetList.isEmpty()) return mimeList;
00187     const QString expectedPattern = "*."+extension;
00188     foreach(int offset, offsetList) {
00189         KMimeType::Ptr newMimeType(createEntry(offset));
00190         // Check whether the dictionary was right.
00191         if (newMimeType && newMimeType->patterns().contains(expectedPattern)) {
00192             mimeList.append(newMimeType);
00193         }
00194     }
00195     return mimeList;
00196 }
00197 
00198 bool KMimeTypeFactory::matchFileName( const QString &filename, const QString &pattern )
00199 {
00200     const int pattern_len = pattern.length();
00201     if (!pattern_len)
00202         return false;
00203     const int len = filename.length();
00204 
00205     const int starCount = pattern.count('*');
00206 
00207     // Patterns like "*~", "*.extension"
00208     if (pattern[0] == '*'  && pattern.indexOf('[') == -1 && starCount == 1)
00209     {
00210         if ( len + 1 < pattern_len ) return false;
00211 
00212         const QChar *c1 = pattern.unicode() + pattern_len - 1;
00213         const QChar *c2 = filename.unicode() + len - 1;
00214         int cnt = 1;
00215         while (cnt < pattern_len && *c1-- == *c2--)
00216             ++cnt;
00217         return cnt == pattern_len;
00218     }
00219 
00220     // Patterns like "README*" (well this is currently the only one like that...)
00221     if (starCount == 1 && pattern[pattern_len - 1] == '*') {
00222         if ( len + 1 < pattern_len ) return false;
00223         if (pattern[0] == '*')
00224             return filename.indexOf(pattern.mid(1, pattern_len - 2)) != -1;
00225 
00226         const QChar *c1 = pattern.unicode();
00227         const QChar *c2 = filename.unicode();
00228         int cnt = 1;
00229         while (cnt < pattern_len && *c1++ == *c2++)
00230            ++cnt;
00231         return cnt == pattern_len;
00232     }
00233 
00234     // Names without any wildcards like "README"
00235     if (pattern.indexOf('[') == -1 && starCount == 0 && pattern.indexOf('?'))
00236         return (pattern == filename);
00237 
00238     // Other (quite rare) patterns, like "*.anim[1-9j]": use slow but correct method
00239     QRegExp rx(pattern);
00240     rx.setPatternSyntax(QRegExp::Wildcard);
00241     return rx.exactMatch(filename);
00242 }
00243 
00244 void KMimeTypeFactory::findFromOtherPatternList(QList<KMimeType::Ptr>& matchingMimeTypes,
00245                                                 const QString &fileName,
00246                                                 QString& foundExt,
00247                                                 bool highWeight)
00248 {
00249     OtherPatternList& patternList = highWeight ? m_highWeightPatterns : m_lowWeightPatterns;
00250     bool& loaded = highWeight ? m_highWeightPatternsLoaded : m_lowWeightPatternsLoaded;
00251     if ( !loaded ) {
00252         loaded = true;
00253         // Load it only once
00254         QDataStream* str = stream();
00255         str->device()->seek( highWeight ? m_highWeightPatternOffset : m_lowWeightPatternOffset );
00256 
00257         QString pattern;
00258         qint32 mimetypeOffset;
00259         qint32 weight;
00260         Q_FOREVER {
00261             KSycocaEntry::read(*str, pattern);
00262             if (pattern.isEmpty()) // end of list
00263                 break;
00264             (*str) >> mimetypeOffset;
00265             (*str) >> weight;
00266             patternList.push_back(OtherPattern(pattern, mimetypeOffset, weight));
00267         }
00268     }
00269 
00270     int matchingPatternLength = 0;
00271     qint32 lastMatchedWeight = 0;
00272     if (!highWeight && !matchingMimeTypes.isEmpty()) {
00273         // We found matches in the fast pattern dict already:
00274         matchingPatternLength = foundExt.length() + 2; // *.foo -> length=5
00275         lastMatchedWeight = 50;
00276     }
00277     OtherPatternList::const_iterator it = patternList.constBegin();
00278     const OtherPatternList::const_iterator end = patternList.constEnd();
00279     for ( ; it != end; ++it ) {
00280         const OtherPattern op = *it;
00281         if ( matchFileName( fileName, op.pattern ) ) {
00282             // Is this a lower-weight pattern than the last match? Stop here then.
00283             if (op.weight < lastMatchedWeight)
00284                 break;
00285             if (lastMatchedWeight > 0 && op.weight > lastMatchedWeight) // can't happen
00286                 kWarning(7009) << "Assumption failed; globs2 weights not sorted correctly"
00287                                << op.weight << ">" << lastMatchedWeight;
00288             // Is this a shorter or a longer match than an existing one, or same length?
00289             if (op.pattern.length() < matchingPatternLength) {
00290                 continue; // too short, ignore
00291             } else if (op.pattern.length() > matchingPatternLength) {
00292                 // longer: clear any previous match (like *.bz2, when pattern is *.tar.bz2)
00293                 matchingMimeTypes.clear();
00294                 // remember the new "longer" length
00295                 matchingPatternLength = op.pattern.length();
00296             }
00297             KMimeType *newMimeType = createEntry( op.offset );
00298             assert (newMimeType && newMimeType->isType( KST_KMimeType ));
00299             matchingMimeTypes.push_back( KMimeType::Ptr( newMimeType ) );
00300             if (op.pattern.startsWith("*."))
00301                 foundExt = op.pattern.mid(2);
00302         }
00303     }
00304 }
00305 
00306 QList<KMimeType::Ptr> KMimeTypeFactory::findFromFileNameHelper(const QString &fileName, QString *pMatchingExtension)
00307 {
00308     // First try the high weight matches (>50), if any.
00309     QList<KMimeType::Ptr> matchingMimeTypes;
00310     QString foundExt;
00311     findFromOtherPatternList(matchingMimeTypes, fileName, foundExt, true);
00312     if (matchingMimeTypes.isEmpty()) {
00313 
00314         // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
00315         // (which is most of them, so this optimization is definitely worth it)
00316         const int lastDot = fileName.lastIndexOf('.');
00317         if (lastDot != -1) { // if no '.', skip the extension lookup
00318             const int ext_len = fileName.length() - lastDot - 1;
00319             const QString simpleExtension = fileName.right( ext_len );
00320 
00321             matchingMimeTypes = findFromFastPatternDict(simpleExtension);
00322             if (!matchingMimeTypes.isEmpty()) {
00323                 foundExt = simpleExtension;
00324                 // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
00325                 // at least those with weight 50.
00326             }
00327         }
00328 
00329         // Finally, try the low weight matches (<=50)
00330         findFromOtherPatternList(matchingMimeTypes, fileName, foundExt, false);
00331     }
00332     if (pMatchingExtension)
00333         *pMatchingExtension = foundExt;
00334     return matchingMimeTypes;
00335 }
00336 
00337 // TODO: remove unused whichPriority argument
00338 KMimeType::Ptr KMimeTypeFactory::findFromContent(QIODevice* device, WhichPriority whichPriority, int* accuracy, QByteArray& beginning)
00339 {
00340     Q_ASSERT(device->isOpen());
00341     if (device->size() == 0) {
00342         if (accuracy)
00343             *accuracy = 100;
00344         return findMimeTypeByName("application/x-zerosize");
00345     }
00346 
00347     if (!m_magicFilesParsed) {
00348         parseMagic();
00349         m_magicFilesParsed = true;
00350     }
00351 
00352     Q_FOREACH ( const KMimeMagicRule& rule, m_magicRules ) {
00353         // HighPriorityRules: select rules with priority >= 80
00354         // LowPriorityRules: select rules with priority < 80
00355         if ( ( whichPriority == AllRules ) ||
00356              ( (rule.priority() >= 80) == (whichPriority == HighPriorityRules) ) ) {
00357             if (rule.match(device, beginning)) {
00358                 if (accuracy)
00359                     *accuracy = rule.priority();
00360                 return findMimeTypeByName(rule.mimetype());
00361             }
00362         }
00363         // Rules are sorted by decreasing priority, so we can abort when we're past high-prio rules
00364         if (whichPriority == HighPriorityRules && rule.priority() < 80)
00365             break;
00366     }
00367 
00368     // Do fallback code so that we never return 0 - unless we were only looking for HighPriorityRules
00369     if (whichPriority != HighPriorityRules) {
00370         // Nothing worked, check if the file contents looks like binary or text
00371         if (!KMimeType::isBufferBinaryData(beginning)) {
00372             if (accuracy)
00373                 *accuracy = 5;
00374             return findMimeTypeByName("text/plain");
00375         }
00376         if (accuracy)
00377             *accuracy = 0;
00378         return KMimeType::defaultMimeTypePtr();
00379     }
00380 
00381     return KMimeType::Ptr();
00382 }
00383 
00384 KMimeType::List KMimeTypeFactory::allMimeTypes()
00385 {
00386     KMimeType::List result;
00387     const KSycocaEntry::List list = allEntries();
00388     for( KSycocaEntry::List::ConstIterator it = list.begin();
00389          it != list.end();
00390          ++it)
00391     {
00392         Q_ASSERT( (*it)->isType( KST_KMimeType ) );
00393         result.append( KMimeType::Ptr::staticCast( *it ) );
00394     }
00395     return result;
00396 }
00397 
00398 QStringList KMimeTypeFactory::parents(const QString& mime)
00399 {
00400     if (!m_parentsMapLoaded) {
00401         m_parentsMapLoaded = true;
00402         Q_ASSERT(m_parents.isEmpty());
00403         QDataStream* str = stream();
00404         str->device()->seek(m_parentsMapOffset);
00405         qint32 n;
00406         (*str) >> n;
00407         QString str1, str2;
00408         for(;n;n--) {
00409             KSycocaEntry::read(*str, str1);
00410             KSycocaEntry::read(*str, str2);
00411             m_parents.insert(str1, str2.split('|'));
00412         }
00413 
00414     }
00415     return m_parents.value(mime);
00416 }
00417 
00418 #include <arpa/inet.h> // for ntohs
00419 #include <kstandarddirs.h>
00420 #include <QFile>
00421 
00422 // Sort them in descending order of priority
00423 static bool mimeMagicRuleCompare(const KMimeMagicRule& lhs, const KMimeMagicRule& rhs) {
00424     return lhs.priority() > rhs.priority();
00425 }
00426 
00427 
00428 void KMimeTypeFactory::parseMagic()
00429 {
00430     const QStringList magicFiles = KGlobal::dirs()->findAllResources("xdgdata-mime", "magic");
00431     //kDebug() << magicFiles;
00432     QListIterator<QString> magicIter( magicFiles );
00433     magicIter.toBack();
00434     while (magicIter.hasPrevious()) { // global first, then local. Turns out it doesn't matter though.
00435         const QString fileName = magicIter.previous();
00436         QFile magicFile(fileName);
00437         kDebug(7009) << "Now parsing " << fileName;
00438         if (magicFile.open(QIODevice::ReadOnly))
00439             m_magicRules += parseMagicFile(&magicFile, fileName);
00440     }
00441     qSort(m_magicRules.begin(), m_magicRules.end(), mimeMagicRuleCompare);
00442 }
00443 
00444 static char readNumber(qint64& value, QIODevice* file)
00445 {
00446     char ch;
00447     while (file->getChar(&ch)) {
00448         if (ch < '0' || ch > '9')
00449             return ch;
00450         value = 10 * value + ch - '0';
00451     }
00452     // eof
00453     return '\0';
00454 }
00455 
00456 
00457 #define MAKE_LITTLE_ENDIAN16(val) val = (quint16)(((quint16)(val) << 8)|((quint16)(val) >> 8))
00458 
00459 #define MAKE_LITTLE_ENDIAN32(val) \
00460    val = (((quint32)(val) & 0xFF000000U) >> 24) | \
00461          (((quint32)(val) & 0x00FF0000U) >> 8) | \
00462          (((quint32)(val) & 0x0000FF00U) << 8) | \
00463          (((quint32)(val) & 0x000000FFU) << 24)
00464 
00465 QList<KMimeMagicRule> KMimeTypeFactory::parseMagicFile(QIODevice* file, const QString& fileName) const
00466 {
00467     QList<KMimeMagicRule> rules;
00468     QByteArray header = file->read(12);
00469     if (header != QByteArray::fromRawData("MIME-Magic\0\n", 12)) {
00470         kWarning(7009) << "Invalid magic file " << fileName << " starts with " << header;
00471         return rules;
00472     }
00473     QList<KMimeMagicMatch> matches; // toplevel matches (indent==0)
00474     int priority = 0; // to avoid warning
00475     QString mimeTypeName;
00476 
00477     Q_FOREVER {
00478         char ch = '\0';
00479         bool chOk = file->getChar(&ch);
00480 
00481         if (!chOk || ch == '[') {
00482             // Finish previous section
00483             if (!mimeTypeName.isEmpty()) {
00484                 rules.append(KMimeMagicRule(mimeTypeName, priority, matches));
00485                 matches.clear();
00486                 mimeTypeName.clear();
00487             }
00488             if (file->atEnd())
00489                 break; // done
00490 
00491             // Parse new section
00492             const QString line = file->readLine();
00493             const int pos = line.indexOf(':');
00494             if (pos == -1) { // syntax error
00495                 kWarning(7009) << "Syntax error in " << mimeTypeName
00496                                << " ':' not present in section name" << endl;
00497                 break;
00498             }
00499             priority = line.left(pos).toInt();
00500             mimeTypeName = line.mid(pos+1);
00501             mimeTypeName = mimeTypeName.left(mimeTypeName.length()-2); // remove ']\n'
00502             //kDebug(7009) << "New rule for " << mimeTypeName
00503             //             << " with priority " << priority << endl;
00504         } else {
00505             // Parse line in the section
00506             // [ indent ] ">" start-offset "=" value
00507             //   [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n"
00508             qint64 indent = 0;
00509             if (ch != '>') {
00510                 indent = ch - '0';
00511                 ch = readNumber(indent, file);
00512                 if (ch != '>') {
00513                     kWarning(7009) << "Invalid magic file " << fileName << " '>' not found, got " << ch << " at pos " << file->pos();
00514                     break;
00515                 }
00516             }
00517 
00518             KMimeMagicMatch match;
00519             match.m_rangeStart = 0;
00520             ch = readNumber(match.m_rangeStart, file);
00521             if (ch != '=') {
00522                 kWarning(7009) << "Invalid magic file " << fileName << " '=' not found";
00523                 break;
00524             }
00525 
00526             char lengthBuffer[2];
00527             if (file->read(lengthBuffer, 2) != 2)
00528                 break;
00529             const short valueLength = ntohs(*(short*)lengthBuffer);
00530             //kDebug() << "indent=" << indent << " rangeStart=" << match.m_rangeStart
00531             //         << " valueLength=" << valueLength << endl;
00532 
00533             match.m_data.resize(valueLength);
00534             if (file->read(match.m_data.data(), valueLength) != valueLength)
00535                 break;
00536 
00537             match.m_rangeLength = 1;
00538             bool invalidLine = false;
00539 
00540             if (!file->getChar(&ch))
00541                 break;
00542             qint64 wordSize = 1;
00543 
00544             Q_FOREVER {
00545                 // We get 'ch' before coming here, or as part of the parsing in each case below.
00546                 switch (ch) {
00547                 case '\n':
00548                     break;
00549                 case '&':
00550                     match.m_mask.resize(valueLength);
00551                     if (file->read(match.m_mask.data(), valueLength) != valueLength)
00552                         invalidLine = true;
00553                     if (!file->getChar(&ch))
00554                         invalidLine = true;
00555                     break;
00556                 case '~': {
00557                     wordSize = 0;
00558                     ch = readNumber(wordSize, file);
00559                     //kDebug() << "wordSize=" << wordSize;
00560                     break;
00561                 }
00562                 case '+':
00563                     // Parse range length
00564                     match.m_rangeLength = 0;
00565                     ch = readNumber(match.m_rangeLength, file);
00566                     if (ch == '\n')
00567                         break;
00568                     // fall-through intended
00569                 default:
00570                     // "If an unknown character is found where a newline is expected
00571                     // then the whole line should be ignored (there will be no binary
00572                     // data after the new character, so the next line starts after the
00573                     // next "\n" character). This is for future extensions.", says spec
00574                     while (ch != '\n' && !file->atEnd()) {
00575                         file->getChar(&ch);
00576                     }
00577                     invalidLine = true;
00578                     kDebug(7009) << "invalid line - garbage found - ch=" << ch;
00579                     break;
00580                 }
00581                 if (ch == '\n' || invalidLine)
00582                     break;
00583             }
00584             if (!invalidLine) {
00585                 // Finish match, doing byte-swapping on little endian hosts
00586 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
00587                 if (wordSize > 1) {
00588                     //kDebug() << "data before swapping: " << match.m_data;;
00589                     if ((wordSize != 2 && wordSize != 4) || (valueLength % wordSize != 0))
00590                         continue; // invalid word size
00591                     char* data = match.m_data.data();
00592                     char* mask = match.m_mask.data();
00593                     for (int i = 0; i < valueLength; i += wordSize) {
00594                         if (wordSize == 2)
00595                             MAKE_LITTLE_ENDIAN16( *((quint16 *) data + i) );
00596                         else if (wordSize == 4)
00597                             MAKE_LITTLE_ENDIAN32( *((quint32 *) data + i) );
00598                         if (!match.m_mask.isEmpty()) {
00599                             if (wordSize == 2)
00600                                 MAKE_LITTLE_ENDIAN16( *((quint16 *) mask + i) );
00601                             else if (wordSize == 4)
00602                                 MAKE_LITTLE_ENDIAN32( *((quint32 *) mask + i) );
00603                         }
00604                     }
00605                     //kDebug() << "data after swapping: " << match.m_data;
00606                 }
00607 #endif
00608                 // Append match at the right place depending on indent:
00609                 if (indent == 0) {
00610                     matches.append(match);
00611                 } else {
00612                     KMimeMagicMatch* m = &matches.last();
00613                     Q_ASSERT(m);
00614                     for (int i = 1 /* nothing to do for indent==1 */; i < indent; ++i) {
00615                         m = &m->m_subMatches.last();
00616                         Q_ASSERT(m);
00617                     }
00618                     m->m_subMatches.append(match);
00619                 }
00620             }
00621         }
00622     }
00623     return rules;
00624 }

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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