From 56f5ea2e5054c4feb07a42a1973d64fc210a6c27 Mon Sep 17 00:00:00 2001
From: barracuda156 <vital.had@gmail.com>
Date: Tue, 29 Aug 2023 10:25:42 +0800
Subject: [PATCH] Revert "Remove Qt4 support and other changes"

This reverts commit be776bcad727ec55c543773f7b895eaa51905fb3.
---
 archiver/archiver.cpp                        |  407 +--
 debian/changelog                             |    7 -
 lib/Global.hpp                               |   20 +-
 lib/LibArchive.cpp                           | 3111 ++++++++++--------
 lib/LibBZip2.cpp                             |  157 +-
 lib/LibBZip2.hpp                             |   27 +-
 lib/LibGZip.cpp                              |  158 +-
 lib/LibGZip.hpp                              |   25 +-
 lib/LibLzma.cpp                              |  214 +-
 lib/LibLzma.hpp                              |   25 +-
 lib/LibLzma2.cpp                             |  226 +-
 lib/LibLzma2.hpp                             |   25 +-
 lib/MimeHandler/NBMimeDatabase.cpp           |  704 ++++
 lib/MimeHandler/NBMimeDatabase.hpp           |   91 +
 lib/MimeHandler/NBMimeDatabase_p.hpp         |   87 +
 lib/MimeHandler/NBMimeGlobPattern.cpp        |  290 ++
 lib/MimeHandler/NBMimeGlobPattern_p.hpp      |  145 +
 lib/MimeHandler/NBMimeMagicRule.cpp          |  479 +++
 lib/MimeHandler/NBMimeMagicRuleMatcher.cpp   |  114 +
 lib/MimeHandler/NBMimeMagicRuleMatcher_p.hpp |   76 +
 lib/MimeHandler/NBMimeMagicRule_p.hpp        |   87 +
 lib/MimeHandler/NBMimeProvider.cpp           | 1059 ++++++
 lib/MimeHandler/NBMimeProvider_p.hpp         |  163 +
 lib/MimeHandler/NBMimeType.cpp               |  537 +++
 lib/MimeHandler/NBMimeType.hpp               |  111 +
 lib/MimeHandler/NBMimeTypeParser.cpp         |  433 +++
 lib/MimeHandler/NBMimeTypeParser_p.hpp       |  116 +
 lib/MimeHandler/NBMimeType_p.hpp             |  111 +
 lib/StandardPaths/NBStandardPaths.cpp        |  306 ++
 lib/StandardPaths/NBStandardPaths.hpp        |  102 +
 lib/StandardPaths/NBStandardPaths_unix.cpp   |  322 ++
 lib/libarchiveqt.h                           |  221 +-
 lib/lz4dec.c                                 |  552 ++--
 lib/lz4dec.h                                 |   10 +-
 lib/meson.build                              |   52 +-
 meson.build                                  |   37 +-
 meson_options.txt                            |    2 +-
 37 files changed, 8153 insertions(+), 2456 deletions(-)
 create mode 100644 lib/MimeHandler/NBMimeDatabase.cpp
 create mode 100644 lib/MimeHandler/NBMimeDatabase.hpp
 create mode 100644 lib/MimeHandler/NBMimeDatabase_p.hpp
 create mode 100644 lib/MimeHandler/NBMimeGlobPattern.cpp
 create mode 100644 lib/MimeHandler/NBMimeGlobPattern_p.hpp
 create mode 100644 lib/MimeHandler/NBMimeMagicRule.cpp
 create mode 100644 lib/MimeHandler/NBMimeMagicRuleMatcher.cpp
 create mode 100644 lib/MimeHandler/NBMimeMagicRuleMatcher_p.hpp
 create mode 100644 lib/MimeHandler/NBMimeMagicRule_p.hpp
 create mode 100644 lib/MimeHandler/NBMimeProvider.cpp
 create mode 100644 lib/MimeHandler/NBMimeProvider_p.hpp
 create mode 100644 lib/MimeHandler/NBMimeType.cpp
 create mode 100644 lib/MimeHandler/NBMimeType.hpp
 create mode 100644 lib/MimeHandler/NBMimeTypeParser.cpp
 create mode 100644 lib/MimeHandler/NBMimeTypeParser_p.hpp
 create mode 100644 lib/MimeHandler/NBMimeType_p.hpp
 create mode 100644 lib/StandardPaths/NBStandardPaths.cpp
 create mode 100644 lib/StandardPaths/NBStandardPaths.hpp
 create mode 100644 lib/StandardPaths/NBStandardPaths_unix.cpp

diff --git archiver/archiver.cpp archiver/archiver.cpp
index 763aa39..b944d71 100644
--- archiver/archiver.cpp
+++ archiver/archiver.cpp
@@ -1,27 +1,27 @@
 /*
- *
- * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
- *
- *
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- *
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 // C++ Standard Library
 #include <QCoreApplication>
@@ -34,178 +34,205 @@
 #include "libarchiveqt.h"
 
 /* To pretty print file sizes */
-QString formatSize( qint64 num ) {
-    QString      total;
-    const qint64 kb = 1024;
-    const qint64 mb = 1024 * kb;
-    const qint64 gb = 1024 * mb;
-    const qint64 tb = 1024 * gb;
-
-    if ( num >= tb ) {
-        total = QString( "%1 TiB" ).arg( QString::number( qreal( num ) / tb, 'f', 3 ) );
-    }
-    else if ( num >= gb ) {
-        total = QString( "%1 GiB" ).arg( QString::number( qreal( num ) / gb, 'f', 2 ) );
-    }
-    else if ( num >= mb ) {
-        total = QString( "%1 MiB" ).arg( QString::number( qreal( num ) / mb, 'f', 1 ) );
-    }
-    else if ( num >= kb ) {
-        total = QString( "%1 KiB" ).arg( QString::number( qreal( num ) / kb, 'f', 1 ) );
-    }
-    else {
-        total = QString( "%1 byte%2" ).arg( num ).arg( num > 1 ? "s": "" );
-    }
-
-    return total;
+QString formatSize(qint64 num)
+{
+	QString      total;
+	const qint64 kb = 1024;
+	const qint64 mb = 1024 * kb;
+	const qint64 gb = 1024 * mb;
+	const qint64 tb = 1024 * gb;
+
+	if (num >= tb)
+	{
+		total = QString("%1 TiB").arg(QString::number(qreal(num) / tb, 'f', 3));
+	}
+	else if (num >= gb)
+	{
+		total = QString("%1 GiB").arg(QString::number(qreal(num) / gb, 'f', 2));
+	}
+	else if (num >= mb)
+	{
+		total = QString("%1 MiB").arg(QString::number(qreal(num) / mb, 'f', 1));
+	}
+	else if (num >= kb)
+	{
+		total = QString("%1 KiB").arg(QString::number(qreal(num) / kb, 'f', 1));
+	}
+	else
+	{
+		total = QString("%1 byte%2").arg(num).arg(num > 1 ? "s": "");
+	}
+
+	return total;
 }
 
 
 /* Pretty print the usage */
-void printUsage( const char *exec ) {
-    std::cout << "Archiver " ARCHIVEQT_VERSION_STR "\n" << std::endl;
-
-    std::cout << "Usage:\n\t" << exec << " -c archive.xxx file1 file2 file3 ..." << std::endl;
-    std::cout << "\t" << exec << " -d archive.xxx output_dir" << std::endl;
-    std::cout << "\t" << exec << " -m archive.xxx member_name output_dir" << std::endl;
-    std::cout << "\t" << exec << " -l archive.xxx" << std::endl;
+void printUsage(const char *exec)
+{
+	std::cout << "Archiver v" ARCHIVEQT_VERSION_STR "\n" << std::endl;
+
+	std::cout << "Usage:\n\t" << exec << " -c archive.xxx file1 file2 file3 ..." << std::endl;
+	std::cout << "\t" << exec << " -d archive.xxx output_dir" << std::endl;
+	std::cout << "\t" << exec << " -m archive.xxx member_name output_dir" << std::endl;
+	std::cout << "\t" << exec << " -l archive.xxx" << std::endl;
 }
 
 
-int main( int argc, char **argv ) {
-    /* Init the QApplication instance */
-    QCoreApplication app( argc, argv );
-
-    /*
-     *
-     * We need three arguments at minimum
-     *  1. The program name (argv[ 0 ]) => Always existing
-     *  2. The switch: one of c, d, m or l: Tells the program what to do
-     *  3. The archive name to operate on (list or decompress)
-     *	In case we are compressing or extracting a member, an additional argument is necessary
-     *
-     */
-    if ( argc < 3 ) {
-        printUsage( argv[ 0 ] );
-        return 1;
-    }
-
-    /* Print help text or usage */
-    else if ( (argc == 2) and (strcmp( argv[ 1 ], "-h" ) == 0) ) {
-        printUsage( argv[ 0 ] );
-        return 0;
-    }
-
-    /* Print help text or usage */
-    else if ( (argc == 2) and (strcmp( argv[ 1 ], "--help" ) == 0) ) {
-        printUsage( argv[ 0 ] );
-        return 0;
-    }
-
-    /* Switch c, but no input files mentioned */
-    else if ( (argc == 3) and (strcmp( argv[ 1 ], "-c" ) == 0) ) {
-        printUsage( argv[ 0 ] );
-
-        std::cout << "\nArchiver: ERROR: No input files specified." << std::endl;
-        return 1;
-    }
-
-    /* Switch m, but no member name mentioned */
-    else if ( (argc < 4) and (strcmp( argv[ 1 ], "-m" ) == 0) ) {
-        printUsage( argv[ 0 ] );
-
-        std::cout << "\nArchiver: ERROR: No member name specified." << std::endl;
-        return 1;
-    }
-
-    /* Excess arguments */
-    else if ( (argc > 3) and (strcmp( argv[ 1 ], "-l" ) == 0) ) {
-        printUsage( argv[ 0 ] );
-
-        std::cout << "\nArchiver: ERROR: Too many files specified" << std::endl;
-        return 1;
-    }
-
-    /* No switch mentioned */
-    else if ( (argc >= 3) and strcmp( argv[ 1 ], "-c" ) and strcmp( argv[ 1 ], "-d" ) and strcmp( argv[ 1 ], "-l" ) and strcmp( argv[ 1 ], "-m" ) ) {
-        printUsage( argv[ 0 ] );
-
-        std::cout << "\nArchiver: ERROR: You need to specify one of -c, -d, -m or -l" << std::endl;
-        return 1;
-    }
-
-    /* Compress the input files argv[3+] into archive argv[2] */
-    else if ( strcmp( argv[ 1 ], "-c" ) == 0 ) {
-        // Write archive code
-        LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
-
-        arc->updateInputFiles( app.arguments().mid( 3 ), LibArchiveQt::RelativeToCurrent );
-        arc->createArchive();
-        arc->waitForFinished();
-
-        return 0;
-    }
-
-    /* Decompress the archive argv[2] optionally to argv[3] */
-    else if ( strcmp( argv[ 1 ], "-d" ) == 0 ) {
-        // Read archive code
-        LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
-
-        if ( argc >= 4 ) {
-            arc->setDestination( argv[ 3 ] );
-        }
-
-        arc->extractArchive();
-        arc->waitForFinished();
-
-        return 0;
-    }
-
-    /* Decompress the member argv[3] optionally to argv[4] from archive argv[2] */
-    else if ( strcmp( argv[ 1 ], "-m" ) == 0 ) {
-        // Read archive code
-        LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
-
-        if ( argc == 5 ) {
-            arc->setDestination( argv[ 3 ] );
-            arc->extractMember( argv[ 4 ] );
-        }
-        else {
-            arc->extractMember( argv[ 3 ] );
-        }
-
-        arc->waitForFinished();
-        return 0;
-    }
-
-    /* List archive argv[2] */
-    else if ( strcmp( argv[ 1 ], "-l" ) == 0 ) {
-        // List archive code
-        LibArchiveQt *arc = new LibArchiveQt( argv[ 2 ] );
-
-        int length = 0;
-        Q_FOREACH (ArchiveEntry *ae, arc->listArchive() ) {
-            length = (ae->name.length() > length ? ae->name.length() : length);
-        }
-
-        Q_FOREACH (ArchiveEntry *ae, arc->listArchive() ) {
-            if ( ae->type == AE_IFREG ) {
-                qDebug() << ae->name.rightJustified( length + 10 ).toLocal8Bit().data() << "  " << formatSize( ae->size ).toLocal8Bit().data();
-            }
-
-            else {
-                qDebug() << ae->name.rightJustified( length + 10 ).toLocal8Bit().data();
-            }
-        }
-
-        arc->waitForFinished();
-
-        return 0;
-    }
-
-    /* Print help text */
-    else {
-        printUsage( argv[ 0 ] );
-        return 0;
-    }
+int main(int argc, char **argv)
+{
+	/* Init the QApplication instance */
+	QCoreApplication app(argc, argv);
+
+	/*
+	  *
+	  * We need three arguments at minimum
+	  * 	1. The program name (argv[ 0 ]) => Always existing
+	  * 	2. The switch: one of c, d, m or l: Tells the program what to do
+	  * 	3. The archive name to operate on (list or decompress)
+	  *	In case we are compressing or extracting a member, an additional argument is necessary
+	  *
+	  */
+	if (argc < 3)
+	{
+		printUsage(argv[0]);
+		return 1;
+	}
+
+	/* Print help text or usage */
+	else if ((argc == 2) and (strcmp(argv[1], "-h") == 0))
+	{
+		printUsage(argv[0]);
+		return 0;
+	}
+
+	/* Print help text or usage */
+	else if ((argc == 2) and (strcmp(argv[1], "--help") == 0))
+	{
+		printUsage(argv[0]);
+		return 0;
+	}
+
+	/* Switch c, but no input files mentioned */
+	else if ((argc == 3) and (strcmp(argv[1], "-c") == 0))
+	{
+		printUsage(argv[0]);
+
+		std::cout << "\nArchiver: ERROR: No input files specified." << std::endl;
+		return 1;
+	}
+
+	/* Switch m, but no member name mentioned */
+	else if ((argc < 4) and (strcmp(argv[1], "-m") == 0))
+	{
+		printUsage(argv[0]);
+
+		std::cout << "\nArchiver: ERROR: No member name specified." << std::endl;
+		return 1;
+	}
+
+	/* Excess arguments */
+	else if ((argc > 3) and (strcmp(argv[1], "-l") == 0))
+	{
+		printUsage(argv[0]);
+
+		std::cout << "\nArchiver: ERROR: Too many files specified" << std::endl;
+		return 1;
+	}
+
+	/* No switch mentioned */
+	else if ((argc >= 3) and strcmp(argv[1], "-c") and strcmp(argv[1], "-d") and strcmp(argv[1], "-l") and strcmp(argv[1], "-m"))
+	{
+		printUsage(argv[0]);
+
+		std::cout << "\nArchiver: ERROR: You need to specify one of -c, -d, -m or -l" << std::endl;
+		return 1;
+	}
+
+	/* Compress the input files argv[3+] into archive argv[2] */
+	else if (strcmp(argv[1], "-c") == 0)
+	{
+		// Write archive code
+		LibArchiveQt *arc = new LibArchiveQt(argv[2]);
+
+		arc->updateInputFiles(app.arguments().mid(3), LibArchiveQt::RelativeToCurrent);
+		arc->createArchive();
+		arc->waitForFinished();
+
+		return 0;
+	}
+
+	/* Decompress the archive argv[2] optionally to argv[3] */
+	else if (strcmp(argv[1], "-d") == 0)
+	{
+		// Read archive code
+		LibArchiveQt *arc = new LibArchiveQt(argv[2]);
+
+		if (argc >= 4)
+		{
+			arc->setDestination(argv[3]);
+		}
+
+		arc->extractArchive();
+		arc->waitForFinished();
+
+		return 0;
+	}
+
+	/* Decompress the member argv[3] optionally to argv[4] from archive argv[2] */
+	else if (strcmp(argv[1], "-m") == 0)
+	{
+		// Read archive code
+		LibArchiveQt *arc = new LibArchiveQt(argv[2]);
+
+		if (argc == 5)
+		{
+			arc->setDestination(argv[3]);
+			arc->extractMember(argv[4]);
+		}
+		else
+		{
+			arc->extractMember(argv[3]);
+		}
+
+		arc->waitForFinished();
+		return 0;
+	}
+
+	/* List archive argv[2] */
+	else if (strcmp(argv[1], "-l") == 0)
+	{
+		// List archive code
+		LibArchiveQt *arc = new LibArchiveQt(argv[2]);
+
+		int length = 0;
+		Q_FOREACH (ArchiveEntry *ae, arc->listArchive())
+		{
+			length = (ae->name.length() > length ? ae->name.length() : length);
+		}
+
+		Q_FOREACH (ArchiveEntry *ae, arc->listArchive())
+		{
+			if (ae->type == AE_IFREG)
+			{
+				qDebug() << ae->name.rightJustified(length + 10).toLocal8Bit().data() << "  " << formatSize(ae->size).toLocal8Bit().data();
+			}
+
+			else
+			{
+				qDebug() << ae->name.rightJustified(length + 10).toLocal8Bit().data();
+			}
+		}
+
+		arc->waitForFinished();
+
+		return 0;
+	}
+
+	/* Print help text */
+	else
+	{
+		printUsage(argv[0]);
+		return 0;
+	}
 }
diff --git debian/changelog debian/changelog
index fab2911..35844c3 100644
--- debian/changelog
+++ debian/changelog
@@ -1,10 +1,3 @@
-libarchiveqt (2.0.8) unstable; urgency=medium
-  * Remove Qt4 support
-  * Remove Qt5/Qt6 deprecation warnings
-  * Bump version number
-
- -- Marcus Britanicus <marcusbritanicus@gmail.com>  Thu, 04 Mar 2023 10:00:00 +0530
-
 libarchiveqt (2.0.7) unstable; urgency=medium
   * Fix meson-related bugs
   * Bump version number
diff --git lib/Global.hpp lib/Global.hpp
index f6027f6..ba6d28a 100644
--- lib/Global.hpp
+++ lib/Global.hpp
@@ -1,6 +1,8 @@
-/**
- * Global.hpp - Globally used header
- **/
+/*
+    *
+    * Global.hpp - Globally used header
+    *
+*/
 
 #pragma once
 
@@ -22,13 +24,13 @@
 #include <assert.h>
 
 #if QT_VERSION >= 0x050000
-#include <QMimeDatabase>
-#include <QMimeType>
-#include <QStandardPaths>
+	#include <QMimeDatabase>
+	#include <QMimeType>
+	#include <QStandardPaths>
 #else
-#include <NBMimeDatabase.hpp>
-#include <NBMimeType.hpp>
-#include <NBStandardPaths.hpp>
+	#include <NBMimeDatabase.hpp>
+	#include <NBMimeType.hpp>
+	#include <NBStandardPaths.hpp>
 #endif
 
 static QMimeDatabase mimeDb;
diff --git lib/LibArchive.cpp lib/LibArchive.cpp
index c58f242..abfe81b 100644
--- lib/LibArchive.cpp
+++ lib/LibArchive.cpp
@@ -1,19 +1,27 @@
-/**
- * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- **/
+/*
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 #include "Global.hpp"
 #include "libarchiveqt.h"
@@ -34,1588 +42,1793 @@ extern "C" {
 #include <assert.h>
 #include <libgen.h>
 
-inline static bool isDir( QString path ) {
-    struct stat statbuf;
-
-    if ( stat( path.toLocal8Bit().data(), &statbuf ) == 0 ) {
-        if ( S_ISDIR( statbuf.st_mode ) ) {
-            return true;
-        }
-
-        else {
-            return false;
-        }
-    }
-
-    else {
-        return false;
-    }
+inline static bool isDir(QString path)
+{
+	struct stat statbuf;
+
+	if (stat(path.toLocal8Bit().data(), &statbuf) == 0)
+	{
+		if (S_ISDIR(statbuf.st_mode))
+		{
+			return true;
+		}
+
+		else
+		{
+			return false;
+		}
+	}
+
+	else
+	{
+		return false;
+	}
 }
 
 
-inline static QStringList recDirWalk( QString path ) {
-    QStringList fileList;
+inline static QStringList recDirWalk(QString path)
+{
+	QStringList fileList;
 
-    if ( not isDir( path ) ) {
-        return fileList;
-    }
+	if (not isDir(path))
+	{
+		return fileList;
+	}
 
-    QDirIterator it( path, QDir::AllEntries | QDir::System | QDir::NoDotAndDotDot | QDir::Hidden, QDirIterator::Subdirectories );
+	QDirIterator it(path, QDir::AllEntries | QDir::System | QDir::NoDotAndDotDot | QDir::Hidden, QDirIterator::Subdirectories);
 
-    while ( it.hasNext() ) {
-        it.next();
+	while (it.hasNext())
+	{
+		it.next();
+		if (it.fileInfo().isFile())
+		{
+			fileList.append(it.fileInfo().filePath());
+		}
+	}
 
-        if ( it.fileInfo().isFile() ) {
-            fileList.append( it.fileInfo().filePath() );
-        }
-    }
-
-    return fileList;
+	return fileList;
 }
 
 
-inline static QString dirName( QString path ) {
-    while ( path.contains( "//" ) ) {
-        path = path.replace( "//", "/" );
-    }
+inline static QString dirName(QString path)
+{
+	while (path.contains("//"))
+	{
+		path = path.replace("//", "/");
+	}
 
-    if ( path.endsWith( "/" ) ) {
-        path.chop( 1 );
-    }
+	if (path.endsWith("/"))
+	{
+		path.chop(1);
+	}
 
-    char    *dupPath = strdup( path.toLocal8Bit().constData() );
-    QString dirPth   = QString( dirname( dupPath ) ) + "/";
+	char    *dupPath = strdup(path.toLocal8Bit().constData());
+	QString dirPth   = QString(dirname(dupPath)) + "/";
 
-    free( dupPath );
+	free(dupPath);
 
-    return (dirPth == "//" ? "/" : dirPth);
+	return(dirPth == "//" ? "/" : dirPth);
 }
 
 
-inline static QString baseName( QString path ) {
-    while ( path.contains( "//" ) ) {
-        path = path.replace( "//", "/" );
-    }
+inline static QString baseName(QString path)
+{
+	while (path.contains("//"))
+	{
+		path = path.replace("//", "/");
+	}
 
-    if ( path.endsWith( "/" ) ) {
-        path.chop( 1 );
-    }
+	if (path.endsWith("/"))
+	{
+		path.chop(1);
+	}
 
-    char    *dupPath = strdup( path.toLocal8Bit().constData() );
-    QString basePth  = QString( basename( dupPath ) );
+	char    *dupPath = strdup(path.toLocal8Bit().constData());
+	QString basePth  = QString(basename(dupPath));
 
-    free( dupPath );
+	free(dupPath);
 
-    return basePth;
+	return basePth;
 }
 
 
-inline static bool exists( QString path ) {
-    return not access( path.toLocal8Bit().constData(), F_OK );
+inline static bool exists(QString path)
+{
+	return not access(path.toLocal8Bit().constData(), F_OK);
 }
 
 
-inline static int mkpath( QString path, mode_t mode ) {
-    /* Root always exists */
-    if ( path == "/" ) {
-        return 0;
-    }
+inline static int mkpath(QString path, mode_t mode)
+{
+	/* Root always exists */
+	if (path == "/")
+	{
+		return 0;
+	}
 
-    /* If the directory exists, thats okay for us */
-    if ( exists( path ) ) {
-        return 0;
-    }
+	/* If the directory exists, thats okay for us */
+	if (exists(path))
+	{
+		return 0;
+	}
 
-    /* If the path is absolute, remove the leading '/' */
-    if ( path.startsWith( '/' ) ) {
-        path.remove( 0, 1 );
-    }
+	/* If the path is absolute, remove the leading '/' */
+	if (path.startsWith('/'))
+	{
+		path.remove(0, 1);
+	}
 
-    mkpath( dirName( path ), mode );
+	mkpath(dirName(path), mode);
 
-    return mkdir( path.toLocal8Bit().constData(), mode );
+	return mkdir(path.toLocal8Bit().constData(), mode);
 }
 
 
-inline static QString longestPath( QStringList& dirs ) {
-    QStringList paths;
+inline static QString longestPath(QStringList& dirs)
+{
+	QStringList paths;
 
-    Q_FOREACH (QString file, dirs) {
-        paths << QFileInfo( file ).absoluteFilePath();
-    }
+	Q_FOREACH (QString file, dirs)
+	{
+		paths << QFileInfo(file).absoluteFilePath();
+	}
 
-    /* Get shortest path: Shortest path is the one with least number of '/' */
-    QString shortest = paths.at( 0 );
-    int     count    = 10240;
+	/* Get shortest path: Shortest path is the one with least number of '/' */
+	QString shortest = paths.at(0);
+	int     count    = 10240;
 
-    Q_FOREACH (QString path, paths) {
-        if ( path.count( "/" ) < count ) {
-            count    = path.count( "/" );
-            shortest = path;
-        }
-    }
+	Q_FOREACH (QString path, paths)
+	{
+		if (path.count("/") < count)
+		{
+			count    = path.count("/");
+			shortest = path;
+		}
+	}
 
-    /* Remove the trailing '/' */
-    if ( shortest.endsWith( "/" ) ) {
-        shortest.chop( 1 );
-    }
+	/* Remove the trailing '/' */
+	if (shortest.endsWith("/"))
+	{
+		shortest.chop(1);
+	}
 
-    QFileInfo sDir( shortest );
+	QFileInfo sDir(shortest);
 
-    while ( paths.filter( sDir.absoluteFilePath() ).length() != paths.length() ) {
-        if ( sDir.absoluteFilePath() == "/" ) {
-            break;
-        }
+	while (paths.filter(sDir.absoluteFilePath()).count() != paths.count())
+	{
+		if (sDir.absoluteFilePath() == "/")
+		{
+			break;
+		}
 
-        sDir = QFileInfo( sDir.absolutePath() );
-    }
+		sDir = QFileInfo(sDir.absolutePath());
+	}
 
-    return sDir.absoluteFilePath();
+	return sDir.absoluteFilePath();
 }
 
 
-LibArchiveQt::LibArchiveQt( QString archive ) {
-    readDone        = false;
-    isRunning       = false;
-    mJob            = NoJob;
-    extractedMember = QString();
-    mExitStatus     = 0;            // 0 - Good, 1 - Bad
+LibArchiveQt::LibArchiveQt(QString archive)
+{
+	readDone        = false;
+	isRunning       = false;
+	mJob            = NoJob;
+	extractedMember = QString();
+	mExitStatus     = 0;            // 0 - Good, 1 - Bad
 
-    archiveName = QDir( archive ).absolutePath();
+	archiveName = QDir(archive).absolutePath();
 
-    setFilterFormat( mimeDb.mimeTypeForFile( archiveName ) );
+	setFilterFormat(mimeDb.mimeTypeForFile(archiveName));
 }
 
 
-QString LibArchiveQt::suffix( QString archiveName ) {
-    QMimeType mType = mimeDb.mimeTypeForFile( archiveName );
-
-    if ( mType == mimeDb.mimeTypeForFile( "file.cpio" ) ) {
-        return ".cpio";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.shar" ) ) {
-        return ".shar";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar" ) ) {
-        return ".tar";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.gz" ) ) {
-        return (archiveName.endsWith( ".tar.gz" ) ? ".tar.gz" : ".tgz");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.grz" ) ) {
-        return (archiveName.endsWith( ".tar.grz" ) ? ".tar.grz" : ".tgrz");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.xz" ) ) {
-        return (archiveName.endsWith( ".tar.xz" ) ? ".tar.xz" : ".txz");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lzo" ) ) {
-        return (archiveName.endsWith( ".tar.lzo" ) ? ".tar.lzo" : ".tlzo");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lzma" ) ) {
-        return (archiveName.endsWith( ".tar.lzma" ) ? ".tar.lzma" : ".tlzma");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lz" ) ) {
-        return (archiveName.endsWith( ".tar.lz" ) ? ".tar.lz" : ".tlz");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lrz" ) ) {
-        return (archiveName.endsWith( ".tar.lrz" ) ? ".tar.lrz" : ".tlrz");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lz4" ) ) {
-        return (archiveName.endsWith( ".tar.lz4" ) ? ".tar.lz4" : ".tlzo4");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.bz2" ) ) {
-        return (archiveName.endsWith( ".tar.bz2" ) ? ".tar.bz2" : ".tbz2");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.Z" ) ) {
-        return (archiveName.endsWith( ".tar.Z" ) ? ".tar.Z" : ".tZ");
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.iso" ) ) {
-        return ".iso";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.zip" ) ) {
-        return ".zip";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.ar" ) ) {
-        return ".ar";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.xar" ) ) {
-        return ".xar";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.7z" ) ) {
-        return ".7z";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lz" ) ) {
-        return ".lz";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lz4" ) ) {
-        return ".lz4";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.uu" ) ) {
-        return ".uu";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lzo" ) ) {
-        return ".lzo";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.gz" ) ) {
-        return ".gz";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.bz2" ) ) {
-        return ".bz2";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lzma" ) ) {
-        return ".lzma";
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.xz" ) ) {
-        return ".xz";
-    }
-
-    return "";
+QString LibArchiveQt::suffix(QString archiveName)
+{
+	QMimeType mType = mimeDb.mimeTypeForFile(archiveName);
+
+	if (mType == mimeDb.mimeTypeForFile("file.cpio"))
+	{
+		return ".cpio";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.shar"))
+	{
+		return ".shar";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar"))
+	{
+		return ".tar";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.gz"))
+	{
+		return(archiveName.endsWith(".tar.gz") ? ".tar.gz" : ".tgz");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.grz"))
+	{
+		return(archiveName.endsWith(".tar.grz") ? ".tar.grz" : ".tgrz");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.xz"))
+	{
+		return(archiveName.endsWith(".tar.xz") ? ".tar.xz" : ".txz");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lzo"))
+	{
+		return(archiveName.endsWith(".tar.lzo") ? ".tar.lzo" : ".tlzo");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lzma"))
+	{
+		return(archiveName.endsWith(".tar.lzma") ? ".tar.lzma" : ".tlzma");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lz"))
+	{
+		return(archiveName.endsWith(".tar.lz") ? ".tar.lz" : ".tlz");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lrz"))
+	{
+		return(archiveName.endsWith(".tar.lrz") ? ".tar.lrz" : ".tlrz");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lz4"))
+	{
+		return(archiveName.endsWith(".tar.lz4") ? ".tar.lz4" : ".tlzo4");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.bz2"))
+	{
+		return(archiveName.endsWith(".tar.bz2") ? ".tar.bz2" : ".tbz2");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.Z"))
+	{
+		return(archiveName.endsWith(".tar.Z") ? ".tar.Z" : ".tZ");
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.iso"))
+	{
+		return ".iso";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.zip"))
+	{
+		return ".zip";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.ar"))
+	{
+		return ".ar";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.xar"))
+	{
+		return ".xar";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.7z"))
+	{
+		return ".7z";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lz"))
+	{
+		return ".lz";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lz4"))
+	{
+		return ".lz4";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.uu"))
+	{
+		return ".uu";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lzo"))
+	{
+		return ".lzo";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.gz"))
+	{
+		return ".gz";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.bz2"))
+	{
+		return ".bz2";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lzma"))
+	{
+		return ".lzma";
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.xz"))
+	{
+		return ".xz";
+	}
+
+	return "";
 }
 
 
-QStringList LibArchiveQt::supportedFormats() {
-    QStringList supported;
-
-    supported << mimeDb.mimeTypeForFile( "file.cpio" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.shar" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.gz" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.grz" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.xz" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.lzma" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.lz4" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.bz2" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.tar.Z" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.iso" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.zip" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.ar" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.xar" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.7z" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.lz" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.lz4" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.uu" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.lzo" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.gz" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.bz2" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.lzma" ).name();
-    supported << mimeDb.mimeTypeForFile( "file.xz" ).name();
-
-    QString binary;
-
-#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
-    QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", Qt::SkipEmptyParts );
+QStringList LibArchiveQt::supportedFormats()
+{
+	QStringList supported;
+
+	supported << mimeDb.mimeTypeForFile("file.cpio").name();
+	supported << mimeDb.mimeTypeForFile("file.shar").name();
+	supported << mimeDb.mimeTypeForFile("file.tar").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.gz").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.grz").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.xz").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.lzma").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.lz4").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.bz2").name();
+	supported << mimeDb.mimeTypeForFile("file.tar.Z").name();
+	supported << mimeDb.mimeTypeForFile("file.iso").name();
+	supported << mimeDb.mimeTypeForFile("file.zip").name();
+	supported << mimeDb.mimeTypeForFile("file.ar").name();
+	supported << mimeDb.mimeTypeForFile("file.xar").name();
+	supported << mimeDb.mimeTypeForFile("file.7z").name();
+	supported << mimeDb.mimeTypeForFile("file.lz").name();
+	supported << mimeDb.mimeTypeForFile("file.lz4").name();
+	supported << mimeDb.mimeTypeForFile("file.uu").name();
+	supported << mimeDb.mimeTypeForFile("file.lzo").name();
+	supported << mimeDb.mimeTypeForFile("file.gz").name();
+	supported << mimeDb.mimeTypeForFile("file.bz2").name();
+	supported << mimeDb.mimeTypeForFile("file.lzma").name();
+	supported << mimeDb.mimeTypeForFile("file.xz").name();
+
+	QString binary;
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+	QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", Qt::SkipEmptyParts);
 #else
-    QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", QString::SkipEmptyParts );
+	QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", QString::SkipEmptyParts);
 #endif
 
-    QString lzop  = mimeDb.mimeTypeForFile( "file.lzo" ).name();
-    QString lzip  = mimeDb.mimeTypeForFile( "file.lz" ).name();
-    QString lrzip = mimeDb.mimeTypeForFile( "file.lrz" ).name();
-
-    Q_FOREACH (QString loc, exeLocs) {
-        if ( exists( loc + "/lzip" ) and not supported.contains( lzip ) ) {
-            supported << lzip;
-        }
-
-        if ( exists( loc + "/lzop" ) and not supported.contains( lzop ) ) {
-            supported << lzop;
-        }
-
-        if ( exists( loc + "/lrzip" ) and not supported.contains( lrzip ) ) {
-            supported << lrzip;
-        }
-    }
-
-    return supported;
+	QString lzop  = mimeDb.mimeTypeForFile("file.lzo").name();
+	QString lzip  = mimeDb.mimeTypeForFile("file.lz").name();
+	QString lrzip = mimeDb.mimeTypeForFile("file.lrz").name();
+
+	Q_FOREACH (QString loc, exeLocs)
+	{
+		if (exists(loc + "/lzip") and not supported.contains(lzip))
+		{
+			supported << lzip;
+		}
+
+		if (exists(loc + "/lzop") and not supported.contains(lzop))
+		{
+			supported << lzop;
+		}
+
+		if (exists(loc + "/lrzip") and not supported.contains(lrzip))
+		{
+			supported << lrzip;
+		}
+	}
+
+	return supported;
 }
 
 
-void LibArchiveQt::createArchive() {
-    mJob      = CreateArchive;
-    isRunning = true;
+void LibArchiveQt::createArchive()
+{
+	mJob      = CreateArchive;
+	isRunning = true;
 
-    start();
+	start();
 }
 
 
-void LibArchiveQt::extractArchive() {
-    mJob      = ExtractArchive;
-    isRunning = true;
+void LibArchiveQt::extractArchive()
+{
+	mJob      = ExtractArchive;
+	isRunning = true;
 
-    start();
+	start();
 }
 
 
-void LibArchiveQt::extractMember( QString memberName ) {
-    extractedMember = memberName;
-    mJob            = ExtractMember;
-    isRunning       = true;
+void LibArchiveQt::extractMember(QString memberName)
+{
+	extractedMember = memberName;
+	mJob            = ExtractMember;
+	isRunning       = true;
 
-    start();
+	start();
 }
 
 
-ArchiveEntries LibArchiveQt::listArchive() {
-    if ( readDone ) {
-        return memberList;
-    }
+ArchiveEntries LibArchiveQt::listArchive()
+{
+	if (readDone)
+	{
+		return memberList;
+	}
 
-    memberList.clear();
+	memberList.clear();
 
-    struct archive       *a;
-    struct archive_entry *entry;
-    int r;
+	struct archive       *a;
+	struct archive_entry *entry;
+	int r;
 
-    // Source Archive
-    a = archive_read_new();
-    archive_read_support_format_all( a );
-    archive_read_support_format_raw( a );
-    archive_read_support_filter_all( a );
+	// Source Archive
+	a = archive_read_new();
+	archive_read_support_format_all(a);
+	archive_read_support_format_raw(a);
+	archive_read_support_filter_all(a);
 
-    if ( (r = archive_read_open_filename( a, archiveName.toUtf8().data(), 10240 ) ) ) {
-        qDebug() << "[Error]" << archive_error_string( a );
-        readDone = true;
-        return ArchiveEntries();
-    }
+	if ((r = archive_read_open_filename(a, archiveName.toUtf8().data(), 10240)))
+	{
+		qDebug() << "[Error]" << archive_error_string(a);
+		readDone = true;
+		return ArchiveEntries();
+	}
 
-    while ( true ) {
-        r = archive_read_next_header( a, &entry );
+	while (true)
+	{
+		r = archive_read_next_header(a, &entry);
 
-        if ( r == ARCHIVE_EOF ) {
-            break;
-        }
+		if (r == ARCHIVE_EOF)
+		{
+			break;
+		}
 
-        if ( r < ARCHIVE_OK ) {
-            qDebug() << archive_error_string( a );
-        }
+		if (r < ARCHIVE_OK)
+		{
+			qDebug() << archive_error_string(a);
+		}
 
-        ArchiveEntry *ae = new ArchiveEntry;
-        ae->name = archive_entry_pathname( entry );
-        ae->size = archive_entry_size( entry );
-        ae->type = archive_entry_filetype( entry );
-        memcpy( &ae->info, archive_entry_stat( entry ), sizeof(struct stat) );
+		ArchiveEntry *ae = new ArchiveEntry;
+		ae->name = archive_entry_pathname(entry);
+		ae->size = archive_entry_size(entry);
+		ae->type = archive_entry_filetype(entry);
+		memcpy(&ae->info, archive_entry_stat(entry), sizeof(struct stat));
 
-        memberList << ae;
-    }
+		memberList << ae;
+	}
 
-    archive_read_close( a );
-    archive_read_free( a );
+	archive_read_close(a);
+	archive_read_free(a);
 
-    readDone = true;
+	readDone = true;
 
-    return memberList;
+	return memberList;
 }
 
 
-int LibArchiveQt::exitStatus() {
-    return mExitStatus;
+int LibArchiveQt::exitStatus()
+{
+	return mExitStatus;
 }
 
 
-void LibArchiveQt::updateInputFiles( QStringList inFiles, LibArchiveQt::InputFileMode inMode ) {
-    if ( not inFiles.length() ) {
-        return;
-    }
-
-    /* First get the absolute filenames */
-    Q_FOREACH (QString file, inFiles) {
-        if ( isDir( file ) ) {
-            updateInputFiles( recDirWalk( file ), inMode );
-        }
-
-        else {
-            QFileInfo info( file );
-            switch ( inMode ) {
-                case AbsolutePath: {
-                    inputList.insert( info.absoluteFilePath(), info.absoluteFilePath() );
-                    break;
-                }
-
-                case RelativeToRoot: {
-                    inputList.insert( info.absoluteFilePath(), QDir::root().relativeFilePath( info.absoluteFilePath() ) );
-                    break;
-                }
-
-                case RelativeToHome: {
-                    QString relPath = QDir::home().relativeFilePath( info.absoluteFilePath() );
-                    while ( relPath.startsWith( "../" ) ) {
-                        relPath.remove( 0, 3 );
-                    }
-
-                    inputList.insert( info.absoluteFilePath(), relPath );
-                    break;
-                }
-
-                case RelativeToCurrent: {
-                    QString relPath = QDir::current().relativeFilePath( info.absoluteFilePath() );
-                    while ( relPath.startsWith( "../" ) ) {
-                        relPath.remove( 0, 3 );
-                    }
-
-                    inputList.insert( info.absoluteFilePath(), relPath );
-                    break;
-                }
-
-                case RelativeToWorkDir: {
-                    /* If @src is empty, set it to root */
-                    src = (src.isEmpty() ? "/" : src);
-
-                    QString relPath = QDir( src ).relativeFilePath( info.absoluteFilePath() );
-                    while ( relPath.startsWith( "../" ) ) {
-                        relPath.remove( 0, 3 );
-                    }
-
-                    inputList.insert( info.absoluteFilePath(), relPath );
-                    break;
-                }
-
-                case CommonRelativePath: {
-                    QString common;
-
-                    if ( inFiles.length() == 1 ) {
-                        common = dirName( inFiles.at( 0 ) );
-                    }
-
-                    else {
-                        common = longestPath( inFiles );
-                    }
-
-                    QString relPath = QDir( common ).relativeFilePath( info.absoluteFilePath() );
-                    while ( relPath.startsWith( "../" ) ) {
-                        relPath.remove( 0, 3 );
-                    }
-
-                    inputList.insert( info.absoluteFilePath(), relPath );
-                    break;
-                }
-
-                default: {
-                    QString relPath = QDir::current().relativeFilePath( info.absoluteFilePath() );
-                    while ( relPath.startsWith( "../" ) ) {
-                        relPath.remove( 0, 3 );
-                    }
-
-                    inputList.insert( info.absoluteFilePath(), relPath );
-                    break;
-                }
-            }
-        }
-    }
+void LibArchiveQt::updateInputFiles(QStringList inFiles, LibArchiveQt::InputFileMode inMode)
+{
+	if (not inFiles.count())
+	{
+		return;
+	}
+
+	/* First get the absolute filenames */
+	Q_FOREACH (QString file, inFiles)
+	{
+		if (isDir(file))
+		{
+			updateInputFiles(recDirWalk(file), inMode);
+		}
+
+		else
+		{
+			QFileInfo info(file);
+			switch (inMode)
+			{
+			case AbsolutePath:
+				inputList.insert(info.absoluteFilePath(), info.absoluteFilePath());
+				break;
+
+			case RelativeToRoot:
+				inputList.insert(info.absoluteFilePath(), QDir::root().relativeFilePath(info.absoluteFilePath()));
+				break;
+
+			case RelativeToHome:
+			   {
+				   QString relPath = QDir::home().relativeFilePath(info.absoluteFilePath());
+				   while (relPath.startsWith("../"))
+				   {
+					   relPath.remove(0, 3);
+				   }
+
+				   inputList.insert(info.absoluteFilePath(), relPath);
+				   break;
+			   }
+
+			case RelativeToCurrent:
+			   {
+				   QString relPath = QDir::current().relativeFilePath(info.absoluteFilePath());
+				   while (relPath.startsWith("../"))
+				   {
+					   relPath.remove(0, 3);
+				   }
+
+				   inputList.insert(info.absoluteFilePath(), relPath);
+				   break;
+			   }
+
+			case RelativeToWorkDir:
+			   {
+				   /* If @src is empty, set it to root */
+				   src = (src.isEmpty() ? "/" : src);
+
+				   QString relPath = QDir(src).relativeFilePath(info.absoluteFilePath());
+				   while (relPath.startsWith("../"))
+				   {
+					   relPath.remove(0, 3);
+				   }
+
+				   inputList.insert(info.absoluteFilePath(), relPath);
+				   break;
+			   }
+
+			case CommonRelativePath:
+			   {
+				   QString common;
+				   if (inFiles.count() == 1)
+				   {
+					   common = dirName(inFiles.at(0));
+				   }
+
+				   else
+				   {
+					   common = longestPath(inFiles);
+				   }
+
+				   QString relPath = QDir(common).relativeFilePath(info.absoluteFilePath());
+				   while (relPath.startsWith("../"))
+				   {
+					   relPath.remove(0, 3);
+				   }
+
+				   inputList.insert(info.absoluteFilePath(), relPath);
+				   break;
+			   }
+
+			default:
+			   {
+				   QString relPath = QDir::current().relativeFilePath(info.absoluteFilePath());
+				   while (relPath.startsWith("../"))
+				   {
+					   relPath.remove(0, 3);
+				   }
+
+				   inputList.insert(info.absoluteFilePath(), relPath);
+				   break;
+			   }
+			}
+		}
+	}
 }
 
 
-void LibArchiveQt::setWorkingDir( QString wDir ) {
-    src = QString( wDir );
+void LibArchiveQt::setWorkingDir(QString wDir)
+{
+	src = QString(wDir);
 }
 
 
-void LibArchiveQt::setDestination( QString path ) {
-    /*
-     *
-     * @p path will be a absolute.
-     * So QDir we construct will be home path
-     *
-     */
-
-    dest = QString( path );
+void LibArchiveQt::setDestination(QString path)
+{
+	/*
+	  *
+	  * @p path will be a absolute.
+	  * So QDir we construct will be home path
+	  *
+	  */
 
-    if ( not QFileInfo( QDir( dest ).absolutePath() ).exists() ) {
-        mkpath( path, 0755 );
-    }
+	dest = QString(path);
+	if (not QFileInfo(QDir(dest).absolutePath()).exists())
+	{
+		mkpath(path, 0755);
+	}
 
-    qDebug() << "Extracting to:" << dest;
+	qDebug() << "Extracting to:" << dest;
 }
 
 
-void LibArchiveQt::waitForFinished() {
-    if ( not isRunning ) {
-        return;
-    }
+void LibArchiveQt::waitForFinished()
+{
+	if (not isRunning)
+	{
+		return;
+	}
 
-    QEventLoop eventLoop;
+	QEventLoop eventLoop;
 
 #if QT_VERSION >= 0x050000
-    connect( this, &LibArchiveQt::jobFailed,   &eventLoop, &QEventLoop::quit );
-    connect( this, &LibArchiveQt::jobComplete, &eventLoop, &QEventLoop::quit );
+	connect(this, &LibArchiveQt::jobFailed, &eventLoop, &QEventLoop::quit);
+	connect(this, &LibArchiveQt::jobComplete, &eventLoop, &QEventLoop::quit);
 #else
-    connect( this, SIGNAL(jobFailed()),        &eventLoop, SLOT( quit() ) );
-    connect( this, SIGNAL(jobComplete()),      &eventLoop, SLOT( quit() ) );
+	connect(this, SIGNAL(jobFailed()), &eventLoop, SLOT(quit()));
+	connect(this, SIGNAL(jobComplete()), &eventLoop, SLOT(quit()));
 #endif
 
-    eventLoop.exec();
+	eventLoop.exec();
 }
 
 
-void LibArchiveQt::run() {
-    switch ( mJob ) {
-        case CreateArchive: {
-            if ( doCreateArchive() ) {
-                mExitStatus = 0;
-                emit jobComplete();
-            }
-
-            else {
-                mExitStatus = 1;
-                emit jobFailed();
-            }
-
-            isRunning = false;
-            return;
-        }
-
-        case ExtractArchive: {
-            if ( doExtractArchive() ) {
-                mExitStatus = 0;
-                emit jobComplete();
-            }
-
-            else {
-                mExitStatus = 1;
-                emit jobFailed();
-            }
-
-            isRunning = false;
-            return;
-        }
-
-        case ExtractMember: {
-            if ( doExtractMember( extractedMember ) ) {
-                mExitStatus = 0;
-                emit jobComplete();
-            }
-
-            else {
-                mExitStatus = 1;
-                emit jobFailed();
-            }
-
-            isRunning = false;
-            return;
-        }
-
-        case ListArchive: {
-            /* Nothing to run in the thread */
-            return;
-        }
-    }
+void LibArchiveQt::run()
+{
+	switch (mJob)
+	{
+	case CreateArchive:
+		if (doCreateArchive())
+		{
+			mExitStatus = 0;
+			emit jobComplete();
+		}
+
+		else
+		{
+			mExitStatus = 1;
+			emit jobFailed();
+		}
+
+		isRunning = false;
+		return;
+
+	case ExtractArchive:
+		if (doExtractArchive())
+		{
+			mExitStatus = 0;
+			emit jobComplete();
+		}
+
+		else
+		{
+			mExitStatus = 1;
+			emit jobFailed();
+		}
+
+		isRunning = false;
+		return;
+
+	case ExtractMember:
+		if (doExtractMember(extractedMember))
+		{
+			mExitStatus = 0;
+			emit jobComplete();
+		}
+
+		else
+		{
+			mExitStatus = 1;
+			emit jobFailed();
+		}
+
+		isRunning = false;
+		return;
+
+	case ListArchive:
+		/* Nothing to run in the thread */
+		return;
+	}
 }
 
 
-bool LibArchiveQt::doCreateArchive() {
-    struct archive       *a;
-    struct archive_entry *entry;
-    struct stat          st;
-    char                 buff[ 8192 ];
-    int len;
-    int fd;
-    int r         = ARCHIVE_OK;
-    int errors    = 0;
-    int processed = 0;
-
-    /* Prepare the workingDir */
-    if ( src.isEmpty() ) {
-        src = "/";
-    }
-
-    a = archive_write_new();
-
-    // Depend on the format provided by the user
-    r |= archive_write_set_format( a, mArchiveFormat );
-    r |= archive_write_add_filter( a, mArchiveFilter );
-
-    if ( r < ARCHIVE_OK ) {
-        qDebug() << "Cannot use the input filter/format.";
-        return false;
-    }
-
-    r = archive_write_open_filename( a, archiveName.toUtf8().data() );
-
-    if ( r < ARCHIVE_OK ) {
-        qDebug() << "Unable to write file for writing.";
-        return false;
-    }
-
-    Q_FOREACH (QString file, inputList.keys() ) {
-        char *filename = new char[ file.length() + 1 ];
-        strcpy( filename, file.toUtf8().data() );
-
-        if ( stat( filename, &st ) != 0 ) {
-            errors++;
-            printf( "[Error %d]: %s: %s\n", errno, strerror( errno ), filename );
-            continue;
-        }
-
-        char *arcPath = new char[ file.length() + 1 ];
-        strcpy( arcPath, inputList.value( file ).toUtf8().data() );
-
-        entry = archive_entry_new();
-        archive_entry_set_pathname( entry, arcPath );
-        archive_entry_set_size( entry, st.st_size );
-        archive_entry_set_filetype( entry, st.st_mode );
-        archive_entry_set_perm( entry, st.st_mode );
-
-        archive_write_header( a, entry );
-
-        // Perform the write
-        fd  = open( filename, O_RDONLY );
-        len = read( fd, buff, sizeof(buff) );
-        while ( len > 0 ) {
-            archive_write_data( a, buff, len );
-            len = read( fd, buff, sizeof(buff) );
-        }
-        close( fd );
-        archive_entry_free( entry );
-
-        processed++;
-
-        emit progress( processed * 100 / inputList.count() );
-        qApp->processEvents();
-    }
-
-    archive_write_close( a );
-    archive_write_free( a );
-
-    return (errors ? false : true);
+bool LibArchiveQt::doCreateArchive()
+{
+	struct archive       *a;
+	struct archive_entry *entry;
+	struct stat          st;
+	char                 buff[8192];
+	int len;
+	int fd;
+	int r         = ARCHIVE_OK;
+	int errors    = 0;
+	int processed = 0;
+
+	/* Prepare the workingDir */
+	if (src.isEmpty())
+	{
+		src = "/";
+	}
+
+	a = archive_write_new();
+
+	// Depend on the format provided by the user
+	r |= archive_write_set_format(a, mArchiveFormat);
+	r |= archive_write_add_filter(a, mArchiveFilter);
+	if (r < ARCHIVE_OK)
+	{
+		qDebug() << "Cannot use the input filter/format.";
+		return false;
+	}
+
+	r = archive_write_open_filename(a, archiveName.toUtf8().data());
+	if (r < ARCHIVE_OK)
+	{
+		qDebug() << "Unable to write file for writing.";
+		return false;
+	}
+
+	Q_FOREACH (QString file, inputList.keys())
+	{
+		char *filename = new char[file.count() + 1];
+		strcpy(filename, file.toUtf8().data());
+
+		if (stat(filename, &st) != 0)
+		{
+			errors++;
+			printf("[Error %d]: %s: %s\n", errno, strerror(errno), filename);
+			continue;
+		}
+
+		char *arcPath = new char[file.count() + 1];
+		strcpy(arcPath, inputList.value(file).toUtf8().data());
+
+		entry = archive_entry_new();
+		archive_entry_set_pathname(entry, arcPath);
+		archive_entry_set_size(entry, st.st_size);
+		archive_entry_set_filetype(entry, st.st_mode);
+		archive_entry_set_perm(entry, st.st_mode);
+
+		archive_write_header(a, entry);
+
+		// Perform the write
+		fd  = open(filename, O_RDONLY);
+		len = read(fd, buff, sizeof(buff));
+		while (len > 0)
+		{
+			archive_write_data(a, buff, len);
+			len = read(fd, buff, sizeof(buff));
+		}
+		close(fd);
+		archive_entry_free(entry);
+
+		processed++;
+
+		emit progress(processed * 100 / inputList.count());
+		qApp->processEvents();
+	}
+
+	archive_write_close(a);
+	archive_write_free(a);
+
+	return(errors ? false : true);
 }
 
 
-bool LibArchiveQt::doExtractArchive() {
-    if ( archiveType == None ) {
-        return false;
-    }
-
-    // Change to the target directory
-    char srcDir[ 10240 ] = { 0 };
+bool LibArchiveQt::doExtractArchive()
+{
+	if (archiveType == None)
+	{
+		return false;
+	}
 
-    getcwd( srcDir, 10240 );
+	// Change to the target directory
+	char srcDir[10240] = { 0 };
 
-    if ( not dest.isEmpty() ) {
-        int ret = chdir( dest.toUtf8().data() );
+	getcwd(srcDir, 10240);
 
-        if ( ret ) {
-            qDebug() << "chdir() failed:" << errno;
-        }
-    }
+	if (not dest.isEmpty())
+	{
+		int ret = chdir(dest.toUtf8().data());
+		if (ret)
+		{
+			qDebug() << "chdir() failed:" << errno;
+		}
+	}
 
-    if ( archiveType == Single ) {
-        QMimeType mType = mimeDb.mimeTypeForFile( archiveName );
+	if (archiveType == Single)
+	{
+		QMimeType mType = mimeDb.mimeTypeForFile(archiveName);
 
-        if ( mType == mimeDb.mimeTypeForFile( "file.lz" ) ) {
-            /* LZip Extractor */
+		if (mType == mimeDb.mimeTypeForFile("file.lz"))
+		{
+			/* LZip Extractor */
 
-            QString lzip;
+			QString lzip;
 
-#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
-            QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", Qt::SkipEmptyParts );
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+			QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", Qt::SkipEmptyParts);
 #else
-            QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", QString::SkipEmptyParts );
+			QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", QString::SkipEmptyParts);
 #endif
 
-            Q_FOREACH (QString loc, exeLocs) {
-                if ( exists( loc + "/lzip" ) ) {
-                    lzip = loc + "/lzip";
-                    break;
-                }
-            }
-
-            if ( not lzip.length() ) {
-                qDebug() << "External program lzip not found.";
-                return false;
-            }
-
-            struct archive       *a;
-            struct archive       *ext;
-            struct archive_entry *entry;
-            int flags;
-
-            int r = ARCHIVE_OK;
-
-            /* Select which attributes we want to restore. */
-            flags  = ARCHIVE_EXTRACT_TIME;
-            flags |= ARCHIVE_EXTRACT_PERM;
-            flags |= ARCHIVE_EXTRACT_ACL;
-            flags |= ARCHIVE_EXTRACT_FFLAGS;
-
-            // Source Archive
-            a  = archive_read_new();
-            r |= archive_read_support_format_raw( a );
-            r |= archive_read_support_filter_program( a, QString( lzip + " -d" ).toLocal8Bit().data() );
-
-            if ( r < ARCHIVE_OK ) {
-                qDebug() << "Cannot use the input filter/format.";
-                return false;
-            }
-
-            // Structure to write files to disk
-            ext = archive_write_disk_new();
-            archive_write_disk_set_options( ext, flags );
-            archive_write_disk_set_standard_lookup( ext );
-
-            if ( (r = archive_read_open_filename( a, archiveName.toLocal8Bit().data(), 10240 ) ) ) {
-                qDebug() << "Unable to read archive:" << archive_error_string( a );
-                return false;
-            }
-
-            while ( true ) {
-                r = archive_read_next_header( a, &entry );
-
-                if ( r == ARCHIVE_EOF ) {
-                    qDebug() << "EOF";
-                    break;
-                }
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( a ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    fprintf( stderr, "%s\n", archive_error_string( a ) );
-                    return false;
-                }
-
-                r = archive_write_header( ext, entry );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                else if ( archive_entry_size( entry ) == 0 ) {
-                    r = copyData( a, ext );
-
-                    if ( r < ARCHIVE_OK ) {
-                        fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                    }
-
-                    if ( r < ARCHIVE_WARN ) {
-                        return false;
-                    }
-                }
-
-                r = archive_write_finish_entry( ext );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    return true;
-                }
-            }
-
-            archive_read_close( a );
-            archive_read_free( a );
-
-            archive_write_close( ext );
-            archive_write_free( ext );
-
-            return true;
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.uu" ) ) {
-            /* UUEncode Extractor */
-
-            return false;
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.lrz" ) ) {
-            /* lrzip Extractor */
-
-            QString lrzip;
-
-#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
-            QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", Qt::SkipEmptyParts );
+			Q_FOREACH (QString loc, exeLocs)
+			{
+				if (exists(loc + "/lzip"))
+				{
+					lzip = loc + "/lzip";
+					break;
+				}
+			}
+
+			if (not lzip.count())
+			{
+				qDebug() << "External program lzip not found.";
+				return false;
+			}
+
+			struct archive       *a;
+			struct archive       *ext;
+			struct archive_entry *entry;
+			int flags;
+
+			int r = ARCHIVE_OK;
+
+			/* Select which attributes we want to restore. */
+			flags  = ARCHIVE_EXTRACT_TIME;
+			flags |= ARCHIVE_EXTRACT_PERM;
+			flags |= ARCHIVE_EXTRACT_ACL;
+			flags |= ARCHIVE_EXTRACT_FFLAGS;
+
+			// Source Archive
+			a  = archive_read_new();
+			r |= archive_read_support_format_raw(a);
+			r |= archive_read_support_filter_program(a, QString(lzip + " -d").toLocal8Bit().data());
+
+			if (r < ARCHIVE_OK)
+			{
+				qDebug() << "Cannot use the input filter/format.";
+				return false;
+			}
+
+			// Structure to write files to disk
+			ext = archive_write_disk_new();
+			archive_write_disk_set_options(ext, flags);
+			archive_write_disk_set_standard_lookup(ext);
+
+			if ((r = archive_read_open_filename(a, archiveName.toLocal8Bit().data(), 10240)))
+			{
+				qDebug() << "Unable to read archive:" << archive_error_string(a);
+				return false;
+			}
+
+			while (true)
+			{
+				r = archive_read_next_header(a, &entry);
+				if (r == ARCHIVE_EOF)
+				{
+					qDebug() << "EOF";
+					break;
+				}
+
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(a));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(a));
+					return false;
+				}
+
+				r = archive_write_header(ext, entry);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				else if (archive_entry_size(entry) == 0)
+				{
+					r = copyData(a, ext);
+					if (r < ARCHIVE_OK)
+					{
+						fprintf(stderr, "%s\n", archive_error_string(ext));
+					}
+
+					if (r < ARCHIVE_WARN)
+					{
+						return false;
+					}
+				}
+
+				r = archive_write_finish_entry(ext);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					return true;
+				}
+			}
+
+			archive_read_close(a);
+			archive_read_free(a);
+
+			archive_write_close(ext);
+			archive_write_free(ext);
+
+			return true;
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.uu"))
+		{
+			/* UUEncode Extractor */
+
+			return false;
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.lrz"))
+		{
+			/* lrzip Extractor */
+
+			QString lrzip;
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+			QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", Qt::SkipEmptyParts);
 #else
-            QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", QString::SkipEmptyParts );
+			QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", QString::SkipEmptyParts);
 #endif
-            Q_FOREACH (QString loc, exeLocs) {
-                if ( exists( loc + "/lrzip" ) ) {
-                    lrzip = loc + "/lrzip";
-                    break;
-                }
-            }
-
-            if ( not lrzip.length() ) {
-                qDebug() << "External program lrzip not found.";
-                return false;
-            }
-
-            struct archive       *a;
-            struct archive       *ext;
-            struct archive_entry *entry;
-            int flags;
-
-            int r = ARCHIVE_OK;
-
-            /* Select which attributes we want to restore. */
-            flags  = ARCHIVE_EXTRACT_TIME;
-            flags |= ARCHIVE_EXTRACT_PERM;
-            flags |= ARCHIVE_EXTRACT_ACL;
-            flags |= ARCHIVE_EXTRACT_FFLAGS;
-
-            // Source Archive
-            a  = archive_read_new();
-            r |= archive_read_support_format_raw( a );
-            r |= archive_read_support_filter_program( a, QString( lrzip + " -d" ).toLocal8Bit().data() );
-
-            if ( r < ARCHIVE_OK ) {
-                qDebug() << "Cannot use the input filter/format.";
-            }
-
-            // Structure to write files to disk
-            ext = archive_write_disk_new();
-            archive_write_disk_set_options( ext, flags );
-            archive_write_disk_set_standard_lookup( ext );
-
-            if ( (r = archive_read_open_filename( a, archiveName.toLocal8Bit().data(), 10240 ) ) ) {
-                qDebug() << "Unable to read archive:" << archive_error_string( a );
-                return false;
-            }
-
-            while ( true ) {
-                r = archive_read_next_header( a, &entry );
-
-                if ( r == ARCHIVE_EOF ) {
-                    qDebug() << "EOF";
-                    break;
-                }
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( a ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    fprintf( stderr, "%s\n", archive_error_string( a ) );
-                    return false;
-                }
-
-                r = archive_write_header( ext, entry );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                else if ( archive_entry_size( entry ) == 0 ) {
-                    r = copyData( a, ext );
-
-                    if ( r < ARCHIVE_OK ) {
-                        fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                    }
-
-                    if ( r < ARCHIVE_WARN ) {
-                        return false;
-                    }
-                }
-
-                r = archive_write_finish_entry( ext );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    return true;
-                }
-            }
-
-            archive_read_close( a );
-            archive_read_free( a );
-
-            archive_write_close( ext );
-            archive_write_free( ext );
-
-            return true;
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.lzo" ) ) {
-            /* LZop Extractor */
-
-            QString lzop;
-
-#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0 )
-            QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", Qt::SkipEmptyParts );
+			Q_FOREACH (QString loc, exeLocs)
+			{
+				if (exists(loc + "/lrzip"))
+				{
+					lrzip = loc + "/lrzip";
+					break;
+				}
+			}
+
+			if (not lrzip.count())
+			{
+				qDebug() << "External program lrzip not found.";
+				return false;
+			}
+
+			struct archive       *a;
+			struct archive       *ext;
+			struct archive_entry *entry;
+			int flags;
+
+			int r = ARCHIVE_OK;
+
+			/* Select which attributes we want to restore. */
+			flags  = ARCHIVE_EXTRACT_TIME;
+			flags |= ARCHIVE_EXTRACT_PERM;
+			flags |= ARCHIVE_EXTRACT_ACL;
+			flags |= ARCHIVE_EXTRACT_FFLAGS;
+
+			// Source Archive
+			a  = archive_read_new();
+			r |= archive_read_support_format_raw(a);
+			r |= archive_read_support_filter_program(a, QString(lrzip + " -d").toLocal8Bit().data());
+
+			if (r < ARCHIVE_OK)
+			{
+				qDebug() << "Cannot use the input filter/format.";
+			}
+
+			// Structure to write files to disk
+			ext = archive_write_disk_new();
+			archive_write_disk_set_options(ext, flags);
+			archive_write_disk_set_standard_lookup(ext);
+
+			if ((r = archive_read_open_filename(a, archiveName.toLocal8Bit().data(), 10240)))
+			{
+				qDebug() << "Unable to read archive:" << archive_error_string(a);
+				return false;
+			}
+
+			while (true)
+			{
+				r = archive_read_next_header(a, &entry);
+				if (r == ARCHIVE_EOF)
+				{
+					qDebug() << "EOF";
+					break;
+				}
+
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(a));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(a));
+					return false;
+				}
+
+				r = archive_write_header(ext, entry);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				else if (archive_entry_size(entry) == 0)
+				{
+					r = copyData(a, ext);
+					if (r < ARCHIVE_OK)
+					{
+						fprintf(stderr, "%s\n", archive_error_string(ext));
+					}
+
+					if (r < ARCHIVE_WARN)
+					{
+						return false;
+					}
+				}
+
+				r = archive_write_finish_entry(ext);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					return true;
+				}
+			}
+
+			archive_read_close(a);
+			archive_read_free(a);
+
+			archive_write_close(ext);
+			archive_write_free(ext);
+
+			return true;
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.lzo"))
+		{
+			/* LZop Extractor */
+
+			QString lzop;
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+			QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", Qt::SkipEmptyParts);
 #else
-            QStringList exeLocs = QString::fromLocal8Bit( qgetenv( "PATH" ) ).split( ":", QString::SkipEmptyParts );
+			QStringList exeLocs = QString::fromLocal8Bit(qgetenv("PATH")).split(":", QString::SkipEmptyParts);
 #endif
-            Q_FOREACH (QString loc, exeLocs) {
-                if ( exists( loc + "/lzop" ) ) {
-                    lzop = loc + "/lzop";
-                    break;
-                }
-            }
-
-            if ( not lzop.length() ) {
-                qDebug() << "External program lzop not found.";
-                return false;
-            }
-
-            struct archive       *a;
-            struct archive       *ext;
-            struct archive_entry *entry;
-            int flags;
-
-            int r = ARCHIVE_OK;
-
-            /* Select which attributes we want to restore. */
-            flags  = ARCHIVE_EXTRACT_TIME;
-            flags |= ARCHIVE_EXTRACT_PERM;
-            flags |= ARCHIVE_EXTRACT_ACL;
-            flags |= ARCHIVE_EXTRACT_FFLAGS;
-
-            // Source Archive
-            a  = archive_read_new();
-            r |= archive_read_support_format_raw( a );
-            r |= archive_read_support_filter_program( a, QString( lzop + " -d" ).toLocal8Bit().data() );
-
-            if ( r < ARCHIVE_OK ) {
-                qDebug() << "Cannot use the input filter/format.";
-            }
-
-            // Structure to write files to disk
-            ext = archive_write_disk_new();
-            archive_write_disk_set_options( ext, flags );
-            archive_write_disk_set_standard_lookup( ext );
-
-            if ( (r = archive_read_open_filename( a, archiveName.toLocal8Bit().data(), 10240 ) ) ) {
-                qDebug() << "Unable to read archive:" << archive_error_string( a );
-                return false;
-            }
-
-            while ( true ) {
-                r = archive_read_next_header( a, &entry );
-
-                if ( r == ARCHIVE_EOF ) {
-                    qDebug() << "EOF";
-                    break;
-                }
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( a ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    fprintf( stderr, "%s\n", archive_error_string( a ) );
-                    return false;
-                }
-
-                r = archive_write_header( ext, entry );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                else if ( archive_entry_size( entry ) == 0 ) {
-                    r = copyData( a, ext );
-
-                    if ( r < ARCHIVE_OK ) {
-                        fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                    }
-
-                    if ( r < ARCHIVE_WARN ) {
-                        return false;
-                    }
-                }
-
-                r = archive_write_finish_entry( ext );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    return true;
-                }
-            }
-
-            archive_read_close( a );
-            archive_read_free( a );
-
-            archive_write_close( ext );
-            archive_write_free( ext );
-
-            return true;
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.lz4" ) ) {
-            /* LZ4 Extractor */
-
-            dest = archiveName;
-            dest.chop( 4 );
-
-            int i = 0;
-            while ( exists( dest ) ) {
-                i++;
-
-                dest = archiveName;
-                dest.chop( 3 );
-
-                dest = dirName( dest ) + QString( "(%1) - " ).arg( i ) + baseName( dest );
-            }
-
-            unlz4( archiveName.toLocal8Bit().constData(), dest.toLocal8Bit().constData(), NULL );
-            return true;
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.gz" ) ) {
-            /* GZip Extractor */
-
-            dest = archiveName;
-            dest.chop( 3 );
-
-            int i = 0;
-            while ( exists( dest ) ) {
-                i++;
-
-                dest = archiveName;
-                dest.chop( 3 );
-
-                dest = dirName( dest ) + QString( "(%1) - " ).arg( i ) + baseName( dest );
-            }
-
-            NBGZip *gzExt = new NBGZip( archiveName, dest );
-            return gzExt->extract();
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.bz2" ) ) {
-            /* BZip2 Extractor */
-
-            dest = archiveName;
-            dest.chop( 3 );
-
-            int i = 0;
-            while ( exists( dest ) ) {
-                i++;
-
-                dest = archiveName;
-                dest.chop( 3 );
-
-                dest = dirName( dest ) + QString( "(%1) - " ).arg( i ) + baseName( dest );
-            }
-
-            NBBZip2 *bz2Ext = new NBBZip2( archiveName, dest );
-            return bz2Ext->extract();
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.lzma" ) ) {
-            /* LZMA Extractor */
-
-            dest = archiveName;
-            dest.chop( 3 );
-
-            int i = 0;
-            while ( exists( dest ) ) {
-                i++;
-
-                dest = archiveName;
-                dest.chop( 3 );
-
-                dest = dirName( dest ) + QString( "(%1) - " ).arg( i ) + baseName( dest );
-            }
-
-            NBLzma *lzmaExt = new NBLzma( archiveName, dest );
-            return lzmaExt->extract();
-        }
-
-        else if ( mType == mimeDb.mimeTypeForFile( "file.xz" ) ) {
-            /* XZ Extractor */
-
-            dest = archiveName;
-            dest.chop( 3 );
-
-            int i = 0;
-            while ( exists( dest ) ) {
-                i++;
-
-                dest = archiveName;
-                dest.chop( 3 );
-
-                dest = dirName( dest ) + QString( "(%1) - " ).arg( i ) + baseName( dest );
-            }
-
-            NBXz *xzExt = new NBXz( archiveName, dest );
-            return xzExt->extract();
-        }
-
-        return false;
-    }
-
-    else {
-        /*
-         * To show progress we want the number of entries. So list the archive first.
-         * Then count the number of members. Then clear the memberList
-         */
-        listArchive();
-        int entryCount = memberList.length();
-        memberList.clear();
-        readDone = false;
-
-        struct archive       *a;
-        struct archive       *ext;
-        struct archive_entry *entry;
-        int flags;
-        int r = ARCHIVE_OK;
-
-        int processedEntries = 0;
-
-        /* Select which attributes we want to restore. */
-        flags  = ARCHIVE_EXTRACT_TIME;
-        flags |= ARCHIVE_EXTRACT_PERM;
-        flags |= ARCHIVE_EXTRACT_ACL;
-        flags |= ARCHIVE_EXTRACT_FFLAGS;
-
-        // Source Archive
-        a = archive_read_new();
-
-        r |= archive_read_support_format_all( a );
-        r |= archive_read_support_filter_all( a );
-
-        if ( (r |= archive_read_open_filename( a, archiveName.toUtf8().data(), 10240 ) ) < ARCHIVE_OK ) {
-            fprintf( stderr, "%s\n", archive_error_string( a ) );
-            return false;
-        }
-
-        r = ARCHIVE_OK;
-
-        // Structure to write files to disk
-        ext = archive_write_disk_new();
-        r  |= archive_write_disk_set_options( ext, flags );
-        r  |= archive_write_disk_set_standard_lookup( ext );
-
-        if ( r < ARCHIVE_WARN ) {
-            fprintf( stderr, "%s\n", archive_error_string( a ) );
-            return false;
-        }
-
-        while ( true ) {
-            r = archive_read_next_header( a, &entry );
-
-            if ( r == ARCHIVE_EOF ) {
-                break;
-            }
-
-            if ( r < ARCHIVE_OK ) {
-                fprintf( stderr, "%s\n", archive_error_string( a ) );
-            }
-
-            if ( r < ARCHIVE_WARN ) {
-                return 1;
-            }
-
-            r = archive_write_header( ext, entry );
-
-            if ( r < ARCHIVE_OK ) {
-                fprintf( stderr, "%s\n", archive_error_string( ext ) );
-            }
-
-            else if ( archive_entry_size( entry ) > 0 ) {
-                r = copyData( a, ext );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    return 1;
-                }
-            }
-
-            processedEntries++;
-            emit progress( processedEntries * 100 / entryCount );
-
-            qApp->processEvents();
-
-            r = archive_write_finish_entry( ext );
-
-            if ( r < ARCHIVE_OK ) {
-                fprintf( stderr, "%s\n", archive_error_string( ext ) );
-            }
-
-            if ( r < ARCHIVE_WARN ) {
-                return 1;
-            }
-        }
-
-        archive_read_close( a );
-        archive_read_free( a );
-
-        archive_write_close( ext );
-        archive_write_free( ext );
-
-        return true;
-    }
-
-    chdir( srcDir );
+			Q_FOREACH (QString loc, exeLocs)
+			{
+				if (exists(loc + "/lzop"))
+				{
+					lzop = loc + "/lzop";
+					break;
+				}
+			}
+
+			if (not lzop.count())
+			{
+				qDebug() << "External program lzop not found.";
+				return false;
+			}
+
+			struct archive       *a;
+			struct archive       *ext;
+			struct archive_entry *entry;
+			int flags;
+
+			int r = ARCHIVE_OK;
+
+			/* Select which attributes we want to restore. */
+			flags  = ARCHIVE_EXTRACT_TIME;
+			flags |= ARCHIVE_EXTRACT_PERM;
+			flags |= ARCHIVE_EXTRACT_ACL;
+			flags |= ARCHIVE_EXTRACT_FFLAGS;
+
+			// Source Archive
+			a  = archive_read_new();
+			r |= archive_read_support_format_raw(a);
+			r |= archive_read_support_filter_program(a, QString(lzop + " -d").toLocal8Bit().data());
+
+			if (r < ARCHIVE_OK)
+			{
+				qDebug() << "Cannot use the input filter/format.";
+			}
+
+			// Structure to write files to disk
+			ext = archive_write_disk_new();
+			archive_write_disk_set_options(ext, flags);
+			archive_write_disk_set_standard_lookup(ext);
+
+			if ((r = archive_read_open_filename(a, archiveName.toLocal8Bit().data(), 10240)))
+			{
+				qDebug() << "Unable to read archive:" << archive_error_string(a);
+				return false;
+			}
+
+			while (true)
+			{
+				r = archive_read_next_header(a, &entry);
+				if (r == ARCHIVE_EOF)
+				{
+					qDebug() << "EOF";
+					break;
+				}
+
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(a));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(a));
+					return false;
+				}
+
+				r = archive_write_header(ext, entry);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				else if (archive_entry_size(entry) == 0)
+				{
+					r = copyData(a, ext);
+					if (r < ARCHIVE_OK)
+					{
+						fprintf(stderr, "%s\n", archive_error_string(ext));
+					}
+
+					if (r < ARCHIVE_WARN)
+					{
+						return false;
+					}
+				}
+
+				r = archive_write_finish_entry(ext);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					return true;
+				}
+			}
+
+			archive_read_close(a);
+			archive_read_free(a);
+
+			archive_write_close(ext);
+			archive_write_free(ext);
+
+			return true;
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.lz4"))
+		{
+			/* LZ4 Extractor */
+
+			dest = archiveName;
+			dest.chop(4);
+
+			int i = 0;
+			while (exists(dest))
+			{
+				i++;
+
+				dest = archiveName;
+				dest.chop(3);
+
+				dest = dirName(dest) + QString("(%1) - ").arg(i) + baseName(dest);
+			}
+
+			unlz4(archiveName.toLocal8Bit().constData(), dest.toLocal8Bit().constData(), NULL);
+			return true;
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.gz"))
+		{
+			/* GZip Extractor */
+
+			dest = archiveName;
+			dest.chop(3);
+
+			int i = 0;
+			while (exists(dest))
+			{
+				i++;
+
+				dest = archiveName;
+				dest.chop(3);
+
+				dest = dirName(dest) + QString("(%1) - ").arg(i) + baseName(dest);
+			}
+
+			NBGZip *gzExt = new NBGZip(archiveName, dest);
+			return gzExt->extract();
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.bz2"))
+		{
+			/* BZip2 Extractor */
+
+			dest = archiveName;
+			dest.chop(3);
+
+			int i = 0;
+			while (exists(dest))
+			{
+				i++;
+
+				dest = archiveName;
+				dest.chop(3);
+
+				dest = dirName(dest) + QString("(%1) - ").arg(i) + baseName(dest);
+			}
+
+			NBBZip2 *bz2Ext = new NBBZip2(archiveName, dest);
+			return bz2Ext->extract();
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.lzma"))
+		{
+			/* LZMA Extractor */
+
+			dest = archiveName;
+			dest.chop(3);
+
+			int i = 0;
+			while (exists(dest))
+			{
+				i++;
+
+				dest = archiveName;
+				dest.chop(3);
+
+				dest = dirName(dest) + QString("(%1) - ").arg(i) + baseName(dest);
+			}
+
+			NBLzma *lzmaExt = new NBLzma(archiveName, dest);
+			return lzmaExt->extract();
+		}
+
+		else if (mType == mimeDb.mimeTypeForFile("file.xz"))
+		{
+			/* XZ Extractor */
+
+			dest = archiveName;
+			dest.chop(3);
+
+			int i = 0;
+			while (exists(dest))
+			{
+				i++;
+
+				dest = archiveName;
+				dest.chop(3);
+
+				dest = dirName(dest) + QString("(%1) - ").arg(i) + baseName(dest);
+			}
+
+			NBXz *xzExt = new NBXz(archiveName, dest);
+			return xzExt->extract();
+		}
+
+		return false;
+	}
+
+	else
+	{
+		/* To show progress we want the number of entries. So list the archive first. */
+		/* Then count the number of members. Then clear the memberList */
+		listArchive();
+		int entryCount = memberList.count();
+		memberList.clear();
+		readDone = false;
+
+		struct archive       *a;
+		struct archive       *ext;
+		struct archive_entry *entry;
+		int flags;
+		int r = ARCHIVE_OK;
+
+		int processedEntries = 0;
+
+		/* Select which attributes we want to restore. */
+		flags  = ARCHIVE_EXTRACT_TIME;
+		flags |= ARCHIVE_EXTRACT_PERM;
+		flags |= ARCHIVE_EXTRACT_ACL;
+		flags |= ARCHIVE_EXTRACT_FFLAGS;
+
+		// Source Archive
+		a = archive_read_new();
+
+		r |= archive_read_support_format_all(a);
+		r |= archive_read_support_filter_all(a);
+
+		if ((r |= archive_read_open_filename(a, archiveName.toUtf8().data(), 10240)) < ARCHIVE_OK)
+		{
+			fprintf(stderr, "%s\n", archive_error_string(a));
+			return false;
+		}
+
+		r = ARCHIVE_OK;
+
+		// Structure to write files to disk
+		ext = archive_write_disk_new();
+		r  |= archive_write_disk_set_options(ext, flags);
+		r  |= archive_write_disk_set_standard_lookup(ext);
+
+		if (r < ARCHIVE_WARN)
+		{
+			fprintf(stderr, "%s\n", archive_error_string(a));
+			return false;
+		}
+
+		while (true)
+		{
+			r = archive_read_next_header(a, &entry);
+			if (r == ARCHIVE_EOF)
+			{
+				break;
+			}
+
+			if (r < ARCHIVE_OK)
+			{
+				fprintf(stderr, "%s\n", archive_error_string(a));
+			}
+
+			if (r < ARCHIVE_WARN)
+			{
+				return 1;
+			}
+
+			r = archive_write_header(ext, entry);
+			if (r < ARCHIVE_OK)
+			{
+				fprintf(stderr, "%s\n", archive_error_string(ext));
+			}
+
+			else if (archive_entry_size(entry) > 0)
+			{
+				r = copyData(a, ext);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					return 1;
+				}
+			}
+
+			processedEntries++;
+			emit progress(processedEntries * 100 / entryCount);
+
+			qApp->processEvents();
+
+			r = archive_write_finish_entry(ext);
+			if (r < ARCHIVE_OK)
+			{
+				fprintf(stderr, "%s\n", archive_error_string(ext));
+			}
+
+			if (r < ARCHIVE_WARN)
+			{
+				return 1;
+			}
+		}
+
+		archive_read_close(a);
+		archive_read_free(a);
+
+		archive_write_close(ext);
+		archive_write_free(ext);
+
+		return true;
+	}
+
+	chdir(srcDir);
 }
 
 
-bool LibArchiveQt::doExtractMember( QString memberName ) {
-    listArchive();
-
-    if ( archiveType == Single ) {
-        return doExtractMember( memberName );
-    }
-
-    // Change to the target directory
-    char srcDir[ 10240 ] = { 0 };
-
-    getcwd( srcDir, 10240 );
-    chdir( dest.toUtf8().data() );
-
-    struct archive       *a;
-    struct archive       *ext;
-    struct archive_entry *entry;
-    int flags;
-    int r;
-
-    /* Select which attributes we want to restore. */
-    flags  = ARCHIVE_EXTRACT_TIME;
-    flags |= ARCHIVE_EXTRACT_PERM;
-    flags |= ARCHIVE_EXTRACT_ACL;
-    flags |= ARCHIVE_EXTRACT_FFLAGS;
-
-    // Source Archive
-    a = archive_read_new();
-    archive_read_support_format_all( a );
-    archive_read_support_filter_all( a );
-
-    // Structure to write files to disk
-    ext = archive_write_disk_new();
-    archive_write_disk_set_options( ext, flags );
-    archive_write_disk_set_standard_lookup( ext );
-
-    r = archive_read_open_filename( a, archiveName.toUtf8().data(), 10240 );
-
-    if ( r != ARCHIVE_OK ) {
-        qDebug() << "[ERROR]: Failed to open archive:" << archiveName;
-        return true;
-    }
-
-    bool dir = false, found = false;
-
-    /* Direct member */
-    Q_FOREACH (ArchiveEntry *ae, memberList) {
-        if ( ae->name == memberName ) {
-            dir   = (ae->type == AE_IFDIR);
-            found = true;
-            break;
-        }
-
-        if ( ae->name == memberName + "/" ) {
-            memberName += "/";
-            dir         = (ae->type == AE_IFDIR);
-            found       = true;
-            break;
-        }
-    }
-
-    if ( not found ) {
-        /* Always check for @memberName + "/" because, all indirect members will be directories */
-        memberName += "/";
-
-        /* Indirect member: ex. debug/ is a member if debug/path/to/file.ext exists */
-        Q_FOREACH (ArchiveEntry *ae, memberList) {
-            if ( ae->name.startsWith( memberName ) == 0 ) {
-                dir   = true;
-                found = true;
-                break;
-            }
-        }
-    }
-
-    if ( found ) {
-        while ( true ) {
-            r = archive_read_next_header( a, &entry );
-
-            if ( r == ARCHIVE_EOF ) {
-                break;
-            }
-
-            if ( r < ARCHIVE_OK ) {
-                fprintf( stderr, "%s\n", archive_error_string( a ) );
-            }
-
-            if ( r < ARCHIVE_WARN ) {
-                return true;
-            }
-
-            QString entryPath = archive_entry_pathname( entry );
-
-            /* Check if the current entry starts with @memberName */
-            if ( entryPath.startsWith( memberName ) ) {
-                if ( not dir ) {
-                    if ( entryPath != memberName ) {
-                        continue;
-                    }
-                }
-
-                r = archive_write_header( ext, entry );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                else if ( archive_entry_size( entry ) > 0 ) {
-                    r = copyData( a, ext );
-
-                    if ( r < ARCHIVE_OK ) {
-                        fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                    }
-
-                    if ( r < ARCHIVE_WARN ) {
-                        return false;
-                    }
-                }
-
-                r = archive_write_finish_entry( ext );
-
-                if ( r < ARCHIVE_OK ) {
-                    fprintf( stderr, "%s\n", archive_error_string( ext ) );
-                }
-
-                if ( r < ARCHIVE_WARN ) {
-                    return false;
-                }
-            }
-        }
-    }
-
-    else {
-        qDebug() << "[Error]" << "File not found in the archive:" << memberName;
-        return false;
-    }
-
-    archive_read_close( a );
-    archive_read_free( a );
-
-    archive_write_close( ext );
-    archive_write_free( ext );
-
-    chdir( srcDir );
-
-    return true;
+bool LibArchiveQt::doExtractMember(QString memberName)
+{
+	listArchive();
+
+	if (archiveType == Single)
+	{
+		return doExtractMember(memberName);
+	}
+
+	// Change to the target directory
+	char srcDir[10240] = { 0 };
+
+	getcwd(srcDir, 10240);
+	chdir(dest.toUtf8().data());
+
+	struct archive       *a;
+	struct archive       *ext;
+	struct archive_entry *entry;
+	int flags;
+	int r;
+
+	/* Select which attributes we want to restore. */
+	flags  = ARCHIVE_EXTRACT_TIME;
+	flags |= ARCHIVE_EXTRACT_PERM;
+	flags |= ARCHIVE_EXTRACT_ACL;
+	flags |= ARCHIVE_EXTRACT_FFLAGS;
+
+	// Source Archive
+	a = archive_read_new();
+	archive_read_support_format_all(a);
+	archive_read_support_filter_all(a);
+
+	// Structure to write files to disk
+	ext = archive_write_disk_new();
+	archive_write_disk_set_options(ext, flags);
+	archive_write_disk_set_standard_lookup(ext);
+
+	r = archive_read_open_filename(a, archiveName.toUtf8().data(), 10240);
+	if (r != ARCHIVE_OK)
+	{
+		qDebug() << "[ERROR]: Failed to open archive:" << archiveName;
+		return true;
+	}
+
+	bool dir = false, found = false;
+
+	/* Direct member */
+	Q_FOREACH (ArchiveEntry *ae, memberList)
+	{
+		if (ae->name == memberName)
+		{
+			dir   = (ae->type == AE_IFDIR);
+			found = true;
+			break;
+		}
+
+		if (ae->name == memberName + "/")
+		{
+			memberName += "/";
+			dir         = (ae->type == AE_IFDIR);
+			found       = true;
+			break;
+		}
+	}
+
+	if (not found)
+	{
+		/* Always check for @memberName + "/" because, all indirect members will be directories */
+		memberName += "/";
+
+		/* Indirect member: ex. debug/ is a member if debug/path/to/file.ext exists */
+		Q_FOREACH (ArchiveEntry *ae, memberList)
+		{
+			if (ae->name.startsWith(memberName) == 0)
+			{
+				dir   = true;
+				found = true;
+				break;
+			}
+		}
+	}
+
+	if (found)
+	{
+		while (true)
+		{
+			r = archive_read_next_header(a, &entry);
+			if (r == ARCHIVE_EOF)
+			{
+				break;
+			}
+
+			if (r < ARCHIVE_OK)
+			{
+				fprintf(stderr, "%s\n", archive_error_string(a));
+			}
+
+			if (r < ARCHIVE_WARN)
+			{
+				return true;
+			}
+
+			QString entryPath = archive_entry_pathname(entry);
+
+			/* Check if the current entry starts with @memberName */
+			if (entryPath.startsWith(memberName))
+			{
+				if (not dir)
+				{
+					if (entryPath != memberName)
+					{
+						continue;
+					}
+				}
+
+				r = archive_write_header(ext, entry);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				else if (archive_entry_size(entry) > 0)
+				{
+					r = copyData(a, ext);
+					if (r < ARCHIVE_OK)
+					{
+						fprintf(stderr, "%s\n", archive_error_string(ext));
+					}
+
+					if (r < ARCHIVE_WARN)
+					{
+						return false;
+					}
+				}
+
+				r = archive_write_finish_entry(ext);
+				if (r < ARCHIVE_OK)
+				{
+					fprintf(stderr, "%s\n", archive_error_string(ext));
+				}
+
+				if (r < ARCHIVE_WARN)
+				{
+					return false;
+				}
+			}
+		}
+	}
+
+	else
+	{
+		qDebug() << "[Error]" << "File not found in the archive:" << memberName;
+		return false;
+	}
+
+	archive_read_close(a);
+	archive_read_free(a);
+
+	archive_write_close(ext);
+	archive_write_free(ext);
+
+	chdir(srcDir);
+
+	return true;
 }
 
 
-int LibArchiveQt::copyData( struct archive *ar, struct archive *aw ) {
-    int        r;
-    const void *buff;
-    size_t     size;
+int LibArchiveQt::copyData(struct archive *ar, struct archive *aw)
+{
+	int        r;
+	const void *buff;
+	size_t     size;
 
 #ifdef __LP64__
-    off_t offset;
+	off_t offset;
 #else
-    la_int64_t offset;
+	la_int64_t offset;
 #endif
 
-    while ( true ) {
-        r = archive_read_data_block( ar, &buff, &size, &offset );
-
-        if ( r == ARCHIVE_EOF ) {
-            return (ARCHIVE_OK);
-        }
-
-        if ( r < ARCHIVE_OK ) {
-            return (r);
-        }
-
-        r = archive_write_data_block( aw, buff, size, offset );
-
-        if ( r < ARCHIVE_OK ) {
-            fprintf( stderr, "%s\n", archive_error_string( aw ) );
-            return (r);
-        }
-    }
+	while (true)
+	{
+		r = archive_read_data_block(ar, &buff, &size, &offset);
+		if (r == ARCHIVE_EOF)
+		{
+			return(ARCHIVE_OK);
+		}
+
+		if (r < ARCHIVE_OK)
+		{
+			return(r);
+		}
+
+		r = archive_write_data_block(aw, buff, size, offset);
+		if (r < ARCHIVE_OK)
+		{
+			fprintf(stderr, "%s\n", archive_error_string(aw));
+			return(r);
+		}
+	}
 }
 
 
-void LibArchiveQt::setFilterFormat( QMimeType mType ) {
-    if ( mType == mimeDb.mimeTypeForFile( "file.cpio" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_CPIO;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.shar" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_SHAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.gz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_GZIP;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.grz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_GRZIP;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.xz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_XZ;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lzo" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZOP;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lzma" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZMA;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZIP;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lrz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LRZIP;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
+void LibArchiveQt::setFilterFormat(QMimeType mType)
+{
+	if (mType == mimeDb.mimeTypeForFile("file.cpio"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_CPIO;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.shar"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_SHAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.gz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_GZIP;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.grz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_GRZIP;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.xz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_XZ;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lzo"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZOP;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lzma"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZMA;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZIP;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lrz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LRZIP;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
 
 #if ARCHIVE_VERSION_NUMBER > 3001002
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.lz4" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZ4;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.lz4"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZ4;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
 #endif
 
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.bz2" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_BZIP2;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.tar.Z" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_COMPRESS;
-        mArchiveFormat = ARCHIVE_FORMAT_TAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.iso" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_ISO9660;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.zip" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_ZIP;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.ar" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_AR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.xar" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_XAR;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.7z" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        mArchiveFormat = ARCHIVE_FORMAT_7ZIP;
-        archiveType    = Container;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZIP;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.bz2"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_BZIP2;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.tar.Z"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_COMPRESS;
+		mArchiveFormat = ARCHIVE_FORMAT_TAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.iso"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_ISO9660;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.zip"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_ZIP;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.ar"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_AR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.xar"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_XAR;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.7z"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		mArchiveFormat = ARCHIVE_FORMAT_7ZIP;
+		archiveType    = Container;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZIP;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
 
 #if ARCHIVE_VERSION_NUMBER > 3001002
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lz4" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZ4;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
+	else if (mType == mimeDb.mimeTypeForFile("file.lz4"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZ4;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
 #endif
 
-    else if ( mType == mimeDb.mimeTypeForFile( "file.uu" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_UU;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lzo" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZOP;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.gz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_GZIP;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.bz2" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_BZIP2;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.lzma" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_LZMA;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
-
-    else if ( mType == mimeDb.mimeTypeForFile( "file.xz" ) ) {
-        mArchiveFilter = ARCHIVE_FILTER_XZ;
-        mArchiveFormat = ARCHIVE_FORMAT_RAW;
-        archiveType    = Single;
-    }
-
-    else {
-        mArchiveFormat = ARCHIVE_FORMAT_EMPTY;
-        mArchiveFilter = ARCHIVE_FILTER_NONE;
-        archiveType    = None;
-    }
+	else if (mType == mimeDb.mimeTypeForFile("file.uu"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_UU;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lzo"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZOP;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.gz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_GZIP;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.bz2"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_BZIP2;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.lzma"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_LZMA;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
+
+	else if (mType == mimeDb.mimeTypeForFile("file.xz"))
+	{
+		mArchiveFilter = ARCHIVE_FILTER_XZ;
+		mArchiveFormat = ARCHIVE_FORMAT_RAW;
+		archiveType    = Single;
+	}
+
+	else
+	{
+		mArchiveFormat = ARCHIVE_FORMAT_EMPTY;
+		mArchiveFilter = ARCHIVE_FILTER_NONE;
+		archiveType    = None;
+	}
 }
diff --git lib/LibBZip2.cpp lib/LibBZip2.cpp
index 49e4b60..206cfa1 100644
--- lib/LibBZip2.cpp
+++ lib/LibBZip2.cpp
@@ -1,19 +1,27 @@
-/**
- * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- **/
+/*
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 // Local Headers
 #include <LibBZip2.hpp>
@@ -23,69 +31,80 @@ const int MAX_READ_SIZE = 40960;
 QString NBBZip2::bz2FileName = QString();
 QString NBBZip2::fileName    = QString();
 
-NBBZip2::NBBZip2( QString archive, QString file ) {
-    int error = 0;
-
-    bz2FileName = QString( archive );
-
-    if ( not file.isEmpty() ) {
-        if ( QFileInfo( file ).isDir() ) {
-            fileName = QDir( file ).filePath( QString( archive ) );
-            fileName.chop( 4 );
-        }
-
-        else if ( QFileInfo( file ).exists() ) {
-            QFile::rename( file, file + ".old" );
-            fileName = QString( file );
-        }
-
-        else {
-            fileName = QString( file );
-        }
-    }
-
-    else {
-        fileName = QString( archive );
-        fileName.chop( 4 );
-    }
-
-    bzFile = fopen( qPrintable( bz2FileName ), "r" );
-    bz2    = BZ2_bzReadOpen( &error, bzFile, 0, 0, NULL, 0 );
+NBBZip2::NBBZip2(QString archive, QString file)
+{
+	int error = 0;
+
+	bz2FileName = QString(archive);
+	if (not file.isEmpty())
+	{
+		if (QFileInfo(file).isDir())
+		{
+			fileName = QDir(file).filePath(QString(archive));
+			fileName.chop(4);
+		}
+
+		else if (QFileInfo(file).exists())
+		{
+			QFile::rename(file, file + ".old");
+			fileName = QString(file);
+		}
+
+		else
+		{
+			fileName = QString(file);
+		}
+	}
+
+	else
+	{
+		fileName = QString(archive);
+		fileName.chop(4);
+	}
+
+	bzFile = fopen(qPrintable(bz2FileName), "r");
+	bz2    = BZ2_bzReadOpen(&error, bzFile, 0, 0, NULL, 0);
 }
 
 
-bool NBBZip2::extract() {
-    int error;
+bool NBBZip2::extract()
+{
+	int error;
 
-    // Reading from the bz2 file opened
-    std::ofstream ofile( qPrintable( fileName ), std::ofstream::binary );
+	// Reading from the bz2 file opened
+	std::ofstream ofile(qPrintable(fileName), std::ofstream::binary);
 
-    while ( true ) {
-        char buffer[ MAX_READ_SIZE ] = { "\x00" };
-        int  charsRead = BZ2_bzRead( &error, bz2, buffer, MAX_READ_SIZE );
-        ofile.write( buffer, charsRead );
+	while (true)
+	{
+		char buffer[MAX_READ_SIZE] = { "\x00" };
+		int  charsRead             = BZ2_bzRead(&error, bz2, buffer, MAX_READ_SIZE);
+		ofile.write(buffer, charsRead);
 
-        if ( error == BZ_OK ) {
-            continue;
-        }
+		if (error == BZ_OK)
+		{
+			continue;
+		}
 
-        else {
-            break;
-        }
-    }
+		else
+		{
+			break;
+		}
+	}
 
-    if ( error != BZ_STREAM_END ) {
-        return false;
-    }
+	if (error != BZ_STREAM_END)
+	{
+		return false;
+	}
 
-    // Close the file
-    BZ2_bzReadClose( &error, bz2 );
+	// Close the file
+	BZ2_bzReadClose(&error, bz2);
 
-    if ( error != BZ_OK ) {
-        return false;
-    }
+	if (error != BZ_OK)
+	{
+		return false;
+	}
 
-    fclose( bzFile );
+	fclose(bzFile);
 
-    return true;
+	return true;
 }
diff --git lib/LibBZip2.hpp lib/LibBZip2.hpp
index 1403337..c3660a4 100644
--- lib/LibBZip2.hpp
+++ lib/LibBZip2.hpp
@@ -1,6 +1,8 @@
-/**
- * LibBZip2.hpp - LibBZip2.cpp header
- **/
+/*
+	*
+	* LibBZip2.hpp - LibBZip2.cpp header
+	*
+*/
 
 #pragma once
 
@@ -9,15 +11,16 @@
 #include <bzlib.h>
 
 class NBBZip2 {
-    public:
-        NBBZip2( QString, QString file = QString() );
-        bool extract();
 
-        static QString fileName;
-        static QString bz2FileName;
+	public:
+		NBBZip2( QString, QString file = QString() );
+		bool extract();
 
-    private:
-        BZFILE *bz2;
-        FILE *bzFile;
-        int NBBZip2Error;
+		static QString fileName;
+		static QString bz2FileName;
+
+	private:
+		BZFILE *bz2;
+		FILE *bzFile;
+		int NBBZip2Error;
 };
diff --git lib/LibGZip.cpp lib/LibGZip.cpp
index b2d5d82..b36f8b5 100644
--- lib/LibGZip.cpp
+++ lib/LibGZip.cpp
@@ -1,82 +1,100 @@
-/**
- * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- **/
+/*
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 // Local Headers
-#include "LibGZip.hpp"
+#include <LibGZip.hpp>
 
 const int MAX_READ_SIZE = 40960;
 
 QString NBGZip::gzFileName = QString();
 QString NBGZip::fileName   = QString();
 
-NBGZip::NBGZip( QString archive, QString file ) {
-    gzFileName = QString( archive );
-
-    if ( not file.isEmpty() ) {
-        if ( QFileInfo( file ).isDir() ) {
-            fileName = QDir( file ).filePath( QString( archive ) );
-            fileName.chop( 3 );
-        }
-
-        else if ( QFileInfo( file ).exists() ) {
-            QFile::rename( file, file + ".old" );
-            fileName = QString( file );
-        }
-
-        else {
-            fileName = QString( file );
-        }
-    }
-
-    gzip = gzopen( qPrintable( gzFileName ), "rb" );
+NBGZip::NBGZip(QString archive, QString file)
+{
+	gzFileName = QString(archive);
+	if (not file.isEmpty())
+	{
+		if (QFileInfo(file).isDir())
+		{
+			fileName = QDir(file).filePath(QString(archive));
+			fileName.chop(3);
+		}
+
+		else if (QFileInfo(file).exists())
+		{
+			QFile::rename(file, file + ".old");
+			fileName = QString(file);
+		}
+
+		else
+		{
+			fileName = QString(file);
+		}
+	}
+
+	gzip = gzopen(qPrintable(gzFileName), "rb");
 }
 
 
-bool NBGZip::extract() {
-    if ( gzip == NULL ) {
-        return true;
-    }
-
-    // Reading from the bz2 file opened
-    std::ofstream ofile( qPrintable( fileName ), std::ofstream::binary );
-
-    while ( true ) {
-        char buffer[ MAX_READ_SIZE ] = { "\x00" };
-        int  charsRead = gzread( gzip, buffer, sizeof(buffer) );
-
-        if ( charsRead > 0 ) {
-            ofile.write( buffer, charsRead );
-        }
-
-        else if ( charsRead == 0 ) {
-            break;
-        }
-
-        else {
-            return true;
-        }
-    }
-
-    // Close the file
-    ofile.close();
-
-    if ( gzclose( gzip ) != Z_OK ) {
-        return true;
-    }
-
-    return true;
+bool NBGZip::extract()
+{
+	if (gzip == NULL)
+	{
+		return true;
+	}
+
+	// Reading from the bz2 file opened
+	std::ofstream ofile(qPrintable(fileName), std::ofstream::binary);
+
+	while (true)
+	{
+		char buffer[MAX_READ_SIZE] = { "\x00" };
+		int  charsRead             = gzread(gzip, buffer, sizeof(buffer));
+
+		if (charsRead > 0)
+		{
+			ofile.write(buffer, charsRead);
+		}
+
+		else if (charsRead == 0)
+		{
+			break;
+		}
+
+		else
+		{
+			return true;
+		}
+	}
+
+	// Close the file
+	ofile.close();
+	if (gzclose(gzip) != Z_OK)
+	{
+		return true;
+	}
+
+	return true;
 }
diff --git lib/LibGZip.hpp lib/LibGZip.hpp
index 3914b3b..dd836d1 100644
--- lib/LibGZip.hpp
+++ lib/LibGZip.hpp
@@ -1,6 +1,8 @@
-/**
- * LibGZip.hpp - LibGZip.cpp header
- **/
+/*
+	*
+	* LibGZip.hpp - LibGZip.cpp header
+	*
+*/
 
 #pragma once
 
@@ -9,14 +11,15 @@
 #include <zlib.h>
 
 class NBGZip {
-    public:
-        NBGZip( QString, QString file = QString() );
-        bool extract();
 
-        static QString fileName;
-        static QString gzFileName;
+	public:
+		NBGZip( QString, QString file = QString() );
+		bool extract();
 
-    private:
-        gzFile gzip;
-        int NBGZipError;
+		static QString fileName;
+		static QString gzFileName;
+
+	private:
+		gzFile gzip;
+		int NBGZipError;
 };
diff --git lib/LibLzma.cpp lib/LibLzma.cpp
index 55222c0..b0fafd2 100644
--- lib/LibLzma.cpp
+++ lib/LibLzma.cpp
@@ -1,19 +1,27 @@
-/**
- * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- **/
+/*
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 // Local Headers
 #include <LibLzma.hpp>
@@ -23,87 +31,101 @@ const int MAX_READ_SIZE = 40960;
 QString NBLzma::lzmaFileName = QString();
 QString NBLzma::fileName     = QString();
 
-NBLzma::NBLzma( QString archive, QString file ) {
-    lzmaFileName = QString( archive );
-
-    if ( not file.isEmpty() ) {
-        if ( QFileInfo( file ).isDir() ) {
-            fileName = QDir( file ).filePath( QString( archive ) );
-            fileName.chop( 3 );
-        }
-
-        else if ( QFileInfo( file ).exists() ) {
-            QFile::rename( file, file + ".old" );
-            fileName = QString( file );
-        }
-
-        else {
-            fileName = QString( file );
-        }
-    }
-
-    fdin  = fopen( qPrintable( lzmaFileName ), "rb" );
-    fdout = fopen( qPrintable( fileName ), "wb" );
+NBLzma::NBLzma(QString archive, QString file)
+{
+	lzmaFileName = QString(archive);
+	if (not file.isEmpty())
+	{
+		if (QFileInfo(file).isDir())
+		{
+			fileName = QDir(file).filePath(QString(archive));
+			fileName.chop(3);
+		}
+
+		else if (QFileInfo(file).exists())
+		{
+			QFile::rename(file, file + ".old");
+			fileName = QString(file);
+		}
+
+		else
+		{
+			fileName = QString(file);
+		}
+	}
+
+	fdin  = fopen(qPrintable(lzmaFileName), "rb");
+	fdout = fopen(qPrintable(fileName), "wb");
 }
 
 
-bool NBLzma::extract() {
-    lzma_stream strm = LZMA_STREAM_INIT;
-    lzma_ret    ret;
-
-    // Initialize the decoder
-    ret = lzma_alone_decoder( &strm, UINT64_MAX );
-
-    if ( ret != LZMA_OK ) {
-        return false;
-    }
-
-    uint8_t in_buf[ MAX_READ_SIZE ];
-    uint8_t out_buf[ MAX_READ_SIZE ];
-
-    strm.avail_in  = 0;
-    strm.next_out  = out_buf;
-    strm.avail_out = MAX_READ_SIZE;
-
-    lzma_action action = LZMA_RUN;
-
-    while ( true ) {
-        if ( strm.avail_in == 0 ) {
-            strm.next_in  = in_buf;
-            strm.avail_in = fread( in_buf, 1, MAX_READ_SIZE, fdin );
-
-            if ( ferror( fdin ) ) {
-                return false;
-            }
-        }
-
-        if ( feof( fdin ) ) {
-            action = LZMA_FINISH;
-        }
-
-        ret = lzma_code( &strm, action );
-
-        if ( (strm.avail_out == 0) || (ret != LZMA_OK) ) {
-            const size_t write_size = MAX_READ_SIZE - strm.avail_out;
-
-            if ( fwrite( out_buf, 1, write_size, fdout ) != write_size ) {
-                return false;
-            }
-
-            strm.next_out  = out_buf;
-            strm.avail_out = MAX_READ_SIZE;
-        }
-
-        if ( ret != LZMA_OK ) {
-            if ( ret == LZMA_STREAM_END ) {
-                // lzma_stream_decoder() already guarantees that there's no trailing garbage.
-                assert( strm.avail_in == 0 );
-                assert( action == LZMA_FINISH );
-                assert( feof( fdin ) );
-                return false;
-            }
-        }
-    }
-
-    return false;
+bool NBLzma::extract()
+{
+	lzma_stream strm = LZMA_STREAM_INIT;
+	lzma_ret    ret;
+
+	// Initialize the decoder
+	ret = lzma_alone_decoder(&strm, UINT64_MAX);
+
+	if (ret != LZMA_OK)
+	{
+		return false;
+	}
+
+	uint8_t in_buf[MAX_READ_SIZE];
+	uint8_t out_buf[MAX_READ_SIZE];
+
+	strm.avail_in  = 0;
+	strm.next_out  = out_buf;
+	strm.avail_out = MAX_READ_SIZE;
+
+	lzma_action action = LZMA_RUN;
+
+	while (true)
+	{
+		if (strm.avail_in == 0)
+		{
+			strm.next_in  = in_buf;
+			strm.avail_in = fread(in_buf, 1, MAX_READ_SIZE, fdin);
+
+			if (ferror(fdin))
+			{
+				return false;
+			}
+		}
+
+		if (feof(fdin))
+		{
+			action = LZMA_FINISH;
+		}
+
+		ret = lzma_code(&strm, action);
+
+		if ((strm.avail_out == 0) || (ret != LZMA_OK))
+		{
+			const size_t write_size = MAX_READ_SIZE - strm.avail_out;
+
+			if (fwrite(out_buf, 1, write_size, fdout) != write_size)
+			{
+				return false;
+			}
+
+			strm.next_out  = out_buf;
+			strm.avail_out = MAX_READ_SIZE;
+		}
+
+		if (ret != LZMA_OK)
+		{
+			if (ret == LZMA_STREAM_END)
+			{
+				// lzma_stream_decoder() already guarantees that there's no trailing garbage.
+				assert(strm.avail_in == 0);
+				assert(action == LZMA_FINISH);
+				assert(feof(fdin));
+				return false;
+			}
+		}
+	}
+
+	return false;
 }
diff --git lib/LibLzma.hpp lib/LibLzma.hpp
index 3a4d347..02e4586 100644
--- lib/LibLzma.hpp
+++ lib/LibLzma.hpp
@@ -1,6 +1,8 @@
-/**
- * LibLzma.hpp - LibLzma.cpp header
- **/
+/*
+	*
+	* LibLzma.hpp - LibLzma.cpp header
+	*
+*/
 
 #pragma once
 
@@ -9,14 +11,15 @@
 #include <lzma.h>
 
 class NBLzma {
-    public:
-        NBLzma( QString, QString file = QString() );
-        bool extract();
 
-        static QString fileName;
-        static QString lzmaFileName;
+	public:
+		NBLzma( QString, QString file = QString() );
+		bool extract();
 
-    private:
-        FILE *fdin, *fdout;
-        int NBLzmaError;
+		static QString fileName;
+		static QString lzmaFileName;
+
+	private:
+		FILE *fdin, *fdout;
+		int NBLzmaError;
 };
diff --git lib/LibLzma2.cpp lib/LibLzma2.cpp
index 109d2bf..7fb7d5e 100644
--- lib/LibLzma2.cpp
+++ lib/LibLzma2.cpp
@@ -1,19 +1,27 @@
-/**
- * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- **/
+/*
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 // Local Headers
 #include <LibLzma2.hpp>
@@ -23,92 +31,108 @@ const int MAX_READ_SIZE = 40960;
 QString NBXz::xzFileName = QString();
 QString NBXz::fileName   = QString();
 
-NBXz::NBXz( QString archive, QString file ) {
-    xzFileName = QString( archive );
-
-    if ( not file.isEmpty() ) {
-        if ( QFileInfo( file ).isDir() ) {
-            fileName = QDir( file ).filePath( QString( archive ) );
-            fileName.chop( 3 );
-        }
-
-        else if ( QFileInfo( file ).exists() ) {
-            QFile::rename( file, file + ".old" );
-            fileName = QString( file );
-        }
-
-        else {
-            fileName = QString( file );
-        }
-    }
-
-    else {
-        fileName = file;
-        fileName.chop( 3 );
-    }
-
-    fdin  = fopen( qPrintable( xzFileName ), "rb" );
-    fdout = fopen( qPrintable( fileName ), "wb" );
+NBXz::NBXz(QString archive, QString file)
+{
+	xzFileName = QString(archive);
+
+	if (not file.isEmpty())
+	{
+		if (QFileInfo(file).isDir())
+		{
+			fileName = QDir(file).filePath(QString(archive));
+			fileName.chop(3);
+		}
+
+		else if (QFileInfo(file).exists())
+		{
+			QFile::rename(file, file + ".old");
+			fileName = QString(file);
+		}
+
+		else
+		{
+			fileName = QString(file);
+		}
+	}
+
+	else
+	{
+		fileName = file;
+		fileName.chop(3);
+	}
+
+	fdin  = fopen(qPrintable(xzFileName), "rb");
+	fdout = fopen(qPrintable(fileName), "wb");
 }
 
 
-bool NBXz::extract() {
-    lzma_stream strm = LZMA_STREAM_INIT;
-    lzma_ret    ret;
-
-    // Initialize the decoder
-    ret = lzma_stream_decoder( &strm, UINT64_MAX, LZMA_CONCATENATED );
-
-    if ( ret != LZMA_OK ) {
-        return false;
-    }
-
-    uint8_t in_buf[ MAX_READ_SIZE ];
-    uint8_t out_buf[ MAX_READ_SIZE ];
-
-    strm.avail_in  = 0;
-    strm.next_out  = out_buf;
-    strm.avail_out = MAX_READ_SIZE;
-
-    lzma_action action = LZMA_RUN;
-
-    while ( true ) {
-        if ( strm.avail_in == 0 ) {
-            strm.next_in  = in_buf;
-            strm.avail_in = fread( in_buf, 1, MAX_READ_SIZE, fdin );
-
-            if ( ferror( fdin ) ) {
-                return false;
-            }
-        }
-
-        if ( feof( fdin ) ) {
-            action = LZMA_FINISH;
-        }
-
-        ret = lzma_code( &strm, action );
-
-        if ( (strm.avail_out == 0) || (ret != LZMA_OK) ) {
-            const size_t write_size = MAX_READ_SIZE - strm.avail_out;
-
-            if ( fwrite( out_buf, 1, write_size, fdout ) != write_size ) {
-                return false;
-            }
-
-            strm.next_out  = out_buf;
-            strm.avail_out = MAX_READ_SIZE;
-        }
-
-        if ( ret != LZMA_OK ) {
-            if ( ret == LZMA_STREAM_END ) {
-                // lzma_stream_decoder() already guarantees that there's no trailing garbage.
-                assert( strm.avail_in == 0 );
-                assert( action == LZMA_FINISH );
-                assert( feof( fdin ) );
-                return false;
-            }
-        }
-    }
-
-    return true;
+bool NBXz::extract()
+{
+	lzma_stream strm = LZMA_STREAM_INIT;
+	lzma_ret    ret;
+
+	// Initialize the decoder
+	ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
+
+	if (ret != LZMA_OK)
+	{
+		return false;
+	}
+
+	uint8_t in_buf[MAX_READ_SIZE];
+	uint8_t out_buf[MAX_READ_SIZE];
+
+	strm.avail_in  = 0;
+	strm.next_out  = out_buf;
+	strm.avail_out = MAX_READ_SIZE;
+
+	lzma_action action = LZMA_RUN;
+
+	while (true)
+	{
+		if (strm.avail_in == 0)
+		{
+			strm.next_in  = in_buf;
+			strm.avail_in = fread(in_buf, 1, MAX_READ_SIZE, fdin);
+
+			if (ferror(fdin))
+			{
+				return false;
+			}
+		}
+
+		if (feof(fdin))
+		{
+			action = LZMA_FINISH;
+		}
+
+		ret = lzma_code(&strm, action);
+
+		if ((strm.avail_out == 0) || (ret != LZMA_OK))
+		{
+			const size_t write_size = MAX_READ_SIZE - strm.avail_out;
+
+			if (fwrite(out_buf, 1, write_size, fdout) != write_size)
+			{
+				return false;
+			}
+
+			strm.next_out  = out_buf;
+			strm.avail_out = MAX_READ_SIZE;
+		}
+
+		if (ret != LZMA_OK)
+		{
+			if (ret == LZMA_STREAM_END)
+			{
+				// lzma_stream_decoder() already guarantees that there's no trailing garbage.
+				assert(strm.avail_in == 0);
+				assert(action == LZMA_FINISH);
+				assert(feof(fdin));
+				return false;
+			}
+		}
+	}
+
+	return true;
 }
diff --git lib/LibLzma2.hpp lib/LibLzma2.hpp
index 440c182..b9efb42 100644
--- lib/LibLzma2.hpp
+++ lib/LibLzma2.hpp
@@ -1,6 +1,8 @@
-/**
- * LibLzma.hpp - LibLzma.cpp header
- **/
+/*
+	*
+	* LibLzma.hpp - LibLzma.cpp header
+	*
+*/
 
 #pragma once
 
@@ -9,14 +11,15 @@
 #include <lzma.h>
 
 class NBXz {
-    public:
-        NBXz( QString, QString file = QString() );
-        bool extract();
 
-        static QString fileName;
-        static QString xzFileName;
+	public:
+		NBXz( QString, QString file = QString() );
+		bool extract();
 
-    private:
-        FILE *fdin, *fdout;
-        int NBXzError;
+		static QString fileName;
+		static QString xzFileName;
+
+	private:
+		FILE *fdin, *fdout;
+		int NBXzError;
 };
diff --git lib/MimeHandler/NBMimeDatabase.cpp lib/MimeHandler/NBMimeDatabase.cpp
new file mode 100644
index 0000000..926c047
--- /dev/null
+++ lib/MimeHandler/NBMimeDatabase.cpp
@@ -0,0 +1,704 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <qplatformdefs.h> // always first
+
+#include <NBMimeDatabase.hpp>
+#include <NBMimeDatabase_p.hpp>
+#include <NBMimeProvider_p.hpp>
+#include <NBMimeType_p.hpp>
+
+#include <QFile>
+#include <QFileInfo>
+#include <QSet>
+#include <QBuffer>
+#include <QUrl>
+#include <QStack>
+#include <QDebug>
+
+#include <algorithm>
+#include <functional>
+
+bool qt_isQMimeDatabaseDebuggingActivated(false);
+
+#ifndef QT_NO_DEBUG_OUTPUT
+#define DBG()    if (qt_isQMimeDatabaseDebuggingActivated) qDebug() << static_cast<const void *>(this) << Q_FUNC_INFO
+#else
+#define DBG()    if (0) qDebug() << static_cast<const void *>(this) << Q_FUNC_INFO
+#endif
+
+Q_GLOBAL_STATIC(QMimeDatabasePrivate, staticQMimeDatabase)
+
+QMimeDatabasePrivate *QMimeDatabasePrivate::instance()
+{
+	return staticQMimeDatabase();
+}
+
+QMimeDatabasePrivate::QMimeDatabasePrivate()
+	: m_provider(0), m_defaultMimeType(QLatin1String("application/octet-stream"))
+{
+}
+
+
+QMimeDatabasePrivate::~QMimeDatabasePrivate()
+{
+	delete m_provider;
+	m_provider = 0;
+}
+
+
+QMimeProviderBase *QMimeDatabasePrivate::provider()
+{
+	if (!m_provider)
+	{
+		QMimeProviderBase *binaryProvider = new QMimeBinaryProvider(this);
+		if (binaryProvider->isValid())
+		{
+			m_provider = binaryProvider;
+		}
+		else
+		{
+			delete binaryProvider;
+			m_provider = new QMimeXMLProvider(this);
+		}
+	}
+	return m_provider;
+}
+
+
+void QMimeDatabasePrivate::setProvider(QMimeProviderBase *theProvider)
+{
+	delete m_provider;
+	m_provider = theProvider;
+}
+
+
+/*!
+  * \internal
+  * Returns a MIME type or an invalid one if none found
+  */
+QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString& nameOrAlias)
+{
+	return provider()->mimeTypeForName(provider()->resolveAlias(nameOrAlias));
+}
+
+
+QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString& fileName, QString *foundSuffix)
+{
+	if (fileName.endsWith(QLatin1Char('/')))
+	{
+		return QStringList() << QLatin1String("inode/directory");
+	}
+
+	const QStringList matchingMimeTypes = provider()->findByFileName(QFileInfo(fileName).fileName(), foundSuffix);
+
+	return matchingMimeTypes;
+}
+
+
+static inline bool isTextFile(const QByteArray& data)
+{
+	// UTF16 byte order marks
+	static const char bigEndianBOM[]    = "\xFE\xFF";
+	static const char littleEndianBOM[] = "\xFF\xFE";
+
+	if (data.startsWith(bigEndianBOM) || data.startsWith(littleEndianBOM))
+	{
+		return true;
+	}
+
+	// Check the first 32 bytes (see shared-mime spec)
+	const char *p = data.constData();
+	const char *e = p + qMin(32, data.size());
+
+	for ( ; p < e; ++p)
+	{
+		if (((unsigned char)(*p) < 32) && (*p != 9) && (*p != 10) && (*p != 13))
+		{
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+QMimeType QMimeDatabasePrivate::findByData(const QByteArray& data, int *accuracyPtr)
+{
+	if (data.isEmpty())
+	{
+		*accuracyPtr = 100;
+		return mimeTypeForName(QLatin1String("application/x-zerosize"));
+	}
+
+	*accuracyPtr = 0;
+	QMimeType candidate = provider()->findByMagic(data, accuracyPtr);
+
+	if (candidate.isValid())
+	{
+		return candidate;
+	}
+
+	if (isTextFile(data))
+	{
+		*accuracyPtr = 5;
+		return mimeTypeForName(QLatin1String("text/plain"));
+	}
+
+	return mimeTypeForName(defaultMimeType());
+}
+
+
+QMimeType QMimeDatabasePrivate::mimeTypeForNameAndData(const QString& fileName, QIODevice *device, int *accuracyPtr)
+{
+	// First, glob patterns are evaluated. If there is a match with max weight,
+	// this one is selected and we are done. Otherwise, the file contents are
+	// evaluated and the match with the highest value (either a magic priority or
+	// a glob pattern weight) is selected. Matching starts from max level (most
+	// specific) in both cases, even when there is already a suffix matching candidate.
+	*accuracyPtr = 0;
+
+	// Pass 1) Try to match on the file name
+	QStringList candidatesByName = mimeTypeForFileName(fileName);
+
+	if (candidatesByName.count() == 1)
+	{
+		*accuracyPtr = 100;
+		const QMimeType mime = mimeTypeForName(candidatesByName.at(0));
+		if (mime.isValid())
+		{
+			return mime;
+		}
+		candidatesByName.clear();
+	}
+
+	// Extension is unknown, or matches multiple mimetypes.
+	// Pass 2) Match on content, if we can read the data
+	if (device->isOpen())
+	{
+		// Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
+		// This is much faster than seeking back and forth into QIODevice.
+		const QByteArray data = device->peek(16384);
+
+		int       magicAccuracy = 0;
+		QMimeType candidateByData(findByData(data, &magicAccuracy));
+
+		// Disambiguate conflicting extensions (if magic matching found something)
+		if (candidateByData.isValid() && (magicAccuracy > 0))
+		{
+			// "for glob_match in glob_matches:"
+			// "if glob_match is subclass or equal to sniffed_type, use glob_match"
+			const QString sniffedMime = candidateByData.name();
+			foreach(const QString& m, candidatesByName)
+			{
+				if (inherits(m, sniffedMime))
+				{
+					// We have magic + pattern pointing to this, so it's a pretty good match
+					*accuracyPtr = 100;
+					return mimeTypeForName(m);
+				}
+			}
+			*accuracyPtr = magicAccuracy;
+			return candidateByData;
+		}
+	}
+
+	if (candidatesByName.count() > 1)
+	{
+		*accuracyPtr = 20;
+		candidatesByName.sort(); // to make it deterministic
+		const QMimeType mime = mimeTypeForName(candidatesByName.at(0));
+		if (mime.isValid())
+		{
+			return mime;
+		}
+	}
+
+	return mimeTypeForName(defaultMimeType());
+}
+
+
+QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
+{
+	return provider()->allMimeTypes();
+}
+
+
+bool QMimeDatabasePrivate::inherits(const QString& mime, const QString& parent)
+{
+	const QString resolvedParent = provider()->resolveAlias(parent);
+	//Q_ASSERT(provider()->resolveAlias(mime) == mime);
+	QStack<QString> toCheck;
+
+	toCheck.push(mime);
+	while (!toCheck.isEmpty())
+	{
+		const QString current = toCheck.pop();
+		if (current == resolvedParent)
+		{
+			return true;
+		}
+		foreach(const QString& par, provider()->parents(current))
+		toCheck.push(par);
+	}
+	return false;
+}
+
+
+/*!
+  * \class QMimeDatabase
+  * \brief The QMimeDatabase class maintains a database of MIME types.
+  *
+  * \since 5.0
+  *
+  * The MIME type database is provided by the freedesktop.org shared-mime-info
+  * project. If the MIME type database cannot be found on the system, as is the case
+  * on most Windows and Mac OS X systems, Qt will use its own copy of it.
+  *
+  * Applications which want to define custom MIME types need to install an
+  * XML file into the locations searched for MIME definitions.
+  * These locations can be queried with
+  * \code
+  * QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"),
+  *                           QStandardPaths::LocateDirectory);
+  * \endcode
+  * On a typical Unix system, this will be /usr/share/mime/packages/, but it is also
+  * possible to extend the list of directories by setting the environment variable
+  * XDG_DATA_DIRS. For instance adding /opt/myapp/share to XDG_DATA_DIRS will result
+  * in /opt/myapp/share/mime/packages/ being searched for MIME definitions.
+  *
+  * Here is an example of MIME XML:
+  * \code
+  * <?xml version="1.0" encoding="UTF-8"?>
+  * <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+  *   <mime-type type="application/vnd.nokia.qt.qmakeprofile">
+  *     <comment xml:lang="en">Qt qmake Profile</comment>
+  *     <glob pattern="*.pro" weight="50"/>
+  *   </mime-type>
+  * </mime-info>
+  * \endcode
+  *
+  * For more details about the syntax of XML MIME definitions, including defining
+  * "magic" in order to detect MIME types based on data as well, read the
+  * Shared Mime Info specification at
+  * http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
+  *
+  * On Unix systems, a binary cache is used for more performance. This cache is generated
+  * by the command "update-mime-database path", where path would be /opt/myapp/share/mime
+  * in the above example. Make sure to run this command when installing the MIME type
+  * definition file.
+  *
+  * \threadsafe
+  *
+  * \snippet doc/src/snippets/code/src_corelib_mimetype_qmimedatabase.cpp 0
+  *
+  * \sa QMimeType
+  */
+
+/*!
+  * \fn QMimeDatabase::QMimeDatabase();
+  * Constructs this QMimeDatabase object.
+  */
+QMimeDatabase::QMimeDatabase() :
+	d(staticQMimeDatabase())
+{
+	DBG();
+}
+
+
+/*!
+  * \fn QMimeDatabase::~QMimeDatabase();
+  * Destroys the QMimeDatabase object.
+  */
+QMimeDatabase::~QMimeDatabase()
+{
+	DBG();
+
+	d = 0;
+}
+
+
+/*!
+  * \fn QMimeType QMimeDatabase::mimeTypeForName(const QString &nameOrAlias) const;
+  * Returns a MIME type for \a nameOrAlias or an invalid one if none found.
+  */
+QMimeType QMimeDatabase::mimeTypeForName(const QString& nameOrAlias) const
+{
+	QMutexLocker locker(&d->mutex);
+
+	return d->mimeTypeForName(nameOrAlias);
+}
+
+
+/*!
+  * Returns a MIME type for \a fileInfo.
+  *
+  * A valid MIME type is always returned.
+  *
+  * The default matching algorithm looks at both the file name and the file
+  * contents, if necessary. The file extension has priority over the contents,
+  * but the contents will be used if the file extension is unknown, or
+  * matches multiple MIME types.
+  * If \a fileInfo is a Unix symbolic link, the file that it refers to
+  * will be used instead.
+  * If the file doesn't match any known pattern or data, the default MIME type
+  * (application/octet-stream) is returned.
+  *
+  * When \a mode is set to MatchExtension, only the file name is used, not
+  * the file contents. The file doesn't even have to exist. If the file name
+  * doesn't match any known pattern, the default MIME type (application/octet-stream)
+  * is returned.
+  * If multiple MIME types match this file, the first one (alphabetically) is returned.
+  *
+  * When \a mode is set to MatchContent, and the file is readable, only the
+  * file contents are used to determine the MIME type. This is equivalent to
+  * calling mimeTypeForData with a QFile as input device.
+  *
+  * In all cases, the \a fileName can also include an absolute or relative path.
+  *
+  * \sa isDefault, mimeTypeForData
+  */
+QMimeType QMimeDatabase::mimeTypeForFile(const QFileInfo& fileInfo, MatchMode mode) const
+{
+	DBG() << "fileInfo" << fileInfo.absoluteFilePath();
+
+	QMutexLocker locker(&d->mutex);
+
+	if (fileInfo.isDir())
+	{
+		return d->mimeTypeForName(QLatin1String("inode/directory"));
+	}
+
+	QFile file(fileInfo.absoluteFilePath());
+
+#ifdef Q_OS_UNIX
+	// Cannot access statBuf.st_mode from the filesystem engine, so we have to stat again.
+	const QByteArray nativeFilePath = QFile::encodeName(file.fileName());
+	QT_STATBUF       statBuffer;
+	if (QT_LSTAT(nativeFilePath.constData(), &statBuffer) == 0)
+	{
+		if (S_ISCHR(statBuffer.st_mode))
+		{
+			return d->mimeTypeForName(QLatin1String("inode/chardevice"));
+		}
+		if (S_ISBLK(statBuffer.st_mode))
+		{
+			return d->mimeTypeForName(QLatin1String("inode/blockdevice"));
+		}
+		if (S_ISFIFO(statBuffer.st_mode))
+		{
+			return d->mimeTypeForName(QLatin1String("inode/fifo"));
+		}
+		if (S_ISSOCK(statBuffer.st_mode))
+		{
+			return d->mimeTypeForName(QLatin1String("inode/socket"));
+		}
+	}
+#endif
+
+	int priority = 0;
+	switch (mode)
+	{
+	case MatchDefault:
+		file.open(QIODevice::ReadOnly); // isOpen() will be tested by method below
+		return d->mimeTypeForNameAndData(fileInfo.absoluteFilePath(), &file, &priority);
+
+	case MatchExtension:
+		locker.unlock();
+		return mimeTypeForFile(fileInfo.absoluteFilePath(), mode);
+
+	case MatchContent:
+		if (file.open(QIODevice::ReadOnly))
+		{
+			locker.unlock();
+			return mimeTypeForData(&file);
+		}
+		else
+		{
+			return d->mimeTypeForName(d->defaultMimeType());
+		}
+
+	default:
+		Q_ASSERT(false);
+	}
+	return d->mimeTypeForName(d->defaultMimeType());
+}
+
+
+/*!
+  * Returns a MIME type for the file named \a fileName using \a mode.
+  *
+  * \overload
+  */
+QMimeType QMimeDatabase::mimeTypeForFile(const QString& fileName, MatchMode mode) const
+{
+	if (mode == MatchExtension)
+	{
+		QMutexLocker locker(&d->mutex);
+		QStringList  matches    = d->mimeTypeForFileName(fileName);
+		const int    matchCount = matches.count();
+		if (matchCount == 0)
+		{
+			return d->mimeTypeForName(d->defaultMimeType());
+		}
+		else if (matchCount == 1)
+		{
+			return d->mimeTypeForName(matches.first());
+		}
+		else
+		{
+			// We have to pick one.
+			matches.sort(); // Make it deterministic
+			return d->mimeTypeForName(matches.first());
+		}
+	}
+	else
+	{
+		// Implemented as a wrapper around mimeTypeForFile(QFileInfo), so no mutex.
+		QFileInfo fileInfo(fileName);
+		return mimeTypeForFile(fileInfo);
+	}
+}
+
+
+/*!
+  * Returns the MIME types for the file name \a fileName.
+  *
+  * If the file name doesn't match any known pattern, an empty list is returned.
+  * If multiple MIME types match this file, they are all returned.
+  *
+  * This function does not try to open the file. To also use the content
+  * when determining the MIME type, use mimeTypeForFile() or
+  * mimeTypeForNameAndData() instead.
+  *
+  * \sa mimeTypeForFile
+  */
+QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString& fileName) const
+{
+	QMutexLocker locker(&d->mutex);
+
+	QStringList      matches = d->mimeTypeForFileName(fileName);
+	QList<QMimeType> mimes;
+
+	matches.sort(); // Make it deterministic
+	foreach(const QString& mime, matches)
+	mimes.append(d->mimeTypeForName(mime));
+	return mimes;
+}
+
+
+/*!
+  * Returns the suffix for the file \a fileName, as known by the MIME database.
+  *
+  * This allows to pre-select "tar.bz2" for foo.tar.bz2, but still only
+  * "txt" for my.file.with.dots.txt.
+  */
+QString QMimeDatabase::suffixForFileName(const QString& fileName) const
+{
+	QMutexLocker locker(&d->mutex);
+	QString      foundSuffix;
+
+	d->mimeTypeForFileName(fileName, &foundSuffix);
+	return foundSuffix;
+}
+
+
+/*!
+  * Returns a MIME type for \a data.
+  *
+  * A valid MIME type is always returned. If \a data doesn't match any
+  * known MIME type data, the default MIME type (application/octet-stream)
+  * is returned.
+  */
+QMimeType QMimeDatabase::mimeTypeForData(const QByteArray& data) const
+{
+	QMutexLocker locker(&d->mutex);
+
+	int accuracy = 0;
+
+	return d->findByData(data, &accuracy);
+}
+
+
+/*!
+  * Returns a MIME type for the data in \a device.
+  *
+  * A valid MIME type is always returned. If the data in \a device doesn't match any
+  * known MIME type data, the default MIME type (application/octet-stream)
+  * is returned.
+  */
+QMimeType QMimeDatabase::mimeTypeForData(QIODevice *device) const
+{
+	QMutexLocker locker(&d->mutex);
+
+	int        accuracy   = 0;
+	const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
+
+	if (device->isOpen())
+	{
+		// Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
+		// This is much faster than seeking back and forth into QIODevice.
+		const QByteArray data   = device->peek(16384);
+		const QMimeType  result = d->findByData(data, &accuracy);
+		if (openedByUs)
+		{
+			device->close();
+		}
+		return result;
+	}
+	return d->mimeTypeForName(d->defaultMimeType());
+}
+
+
+/*!
+  * Returns a MIME type for \a url.
+  *
+  * If the URL is a local file, this calls mimeTypeForFile.
+  *
+  * Otherwise the matching is done based on the file name only,
+  * except for schemes where file names don't mean much, like HTTP.
+  * This method always returns the default mimetype for HTTP URLs,
+  * use QNetworkAccessManager to handle HTTP URLs properly.
+  *
+  * A valid MIME type is always returned. If \a url doesn't match any
+  * known MIME type data, the default MIME type (application/octet-stream)
+  * is returned.
+  */
+QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl& url) const
+{
+	if (url.scheme().compare("file", Qt::CaseInsensitive) == 0)
+	{
+		return mimeTypeForFile(url.toLocalFile());
+	}
+
+	const QString scheme = url.scheme();
+
+	if (scheme.startsWith(QLatin1String("http")))
+	{
+		return mimeTypeForName(d->defaultMimeType());
+	}
+
+	return mimeTypeForFile(url.path());
+}
+
+
+/*!
+  * Returns a MIME type for the given \a fileName and \a device data.
+  *
+  * This overload can be useful when the file is remote, and we started to
+  * download some of its data in a device. This allows to do full MIME type
+  * matching for remote files as well.
+  *
+  * If the device is not open, it will be opened by this function, and closed
+  * after the MIME type detection is completed.
+  *
+  * A valid MIME type is always returned. If \a device data doesn't match any
+  * known MIME type data, the default MIME type (application/octet-stream)
+  * is returned.
+  *
+  * This method looks at both the file name and the file contents,
+  * if necessary. The file extension has priority over the contents,
+  * but the contents will be used if the file extension is unknown, or
+  * matches multiple MIME types.
+  */
+QMimeType QMimeDatabase::mimeTypeForNameAndData(const QString& fileName, QIODevice *device) const
+{
+	DBG() << "fileName" << fileName;
+
+	int             accuracy   = 0;
+	const bool      openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
+	const QMimeType result     = d->mimeTypeForNameAndData(fileName, device, &accuracy);
+
+	if (openedByUs)
+	{
+		device->close();
+	}
+	return result;
+}
+
+
+/*!
+  * Returns a MIME type for the given \a fileName and device \a data.
+  *
+  * This overload can be useful when the file is remote, and we started to
+  * download some of its data. This allows to do full MIME type matching for
+  * remote files as well.
+  *
+  * A valid MIME type is always returned. If \a data doesn't match any
+  * known MIME type data, the default MIME type (application/octet-stream)
+  * is returned.
+  *
+  * This method looks at both the file name and the file contents,
+  * if necessary. The file extension has priority over the contents,
+  * but the contents will be used if the file extension is unknown, or
+  * matches multiple MIME types.
+  */
+QMimeType QMimeDatabase::mimeTypeForNameAndData(const QString& fileName, const QByteArray& data) const
+{
+	DBG() << "fileName" << fileName;
+
+	QBuffer buffer(const_cast<QByteArray *>(&data));
+
+	buffer.open(QIODevice::ReadOnly);
+	int accuracy = 0;
+
+	return d->mimeTypeForNameAndData(fileName, &buffer, &accuracy);
+}
+
+
+/*!
+  * Returns the list of all available MIME types.
+  *
+  * This can be useful for showing all MIME types to the user, for instance
+  * in a MIME type editor. Do not use unless really necessary in other cases
+  * though, prefer using the mimeTypeFor* methods for performance reasons.
+  */
+QList<QMimeType> QMimeDatabase::allMimeTypes() const
+{
+	QMutexLocker locker(&d->mutex);
+
+	return d->allMimeTypes();
+}
+
+
+#undef DBG
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeDatabase.hpp lib/MimeHandler/NBMimeDatabase.hpp
new file mode 100644
index 0000000..4eee5cd
--- /dev/null
+++ lib/MimeHandler/NBMimeDatabase.hpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEDATABASE_H
+#define QMIMEDATABASE_H
+
+#include <NBMimeType.hpp>
+#include <QtCore/QStringList>
+
+class QByteArray;
+class QFileInfo;
+class QIODevice;
+class QUrl;
+
+class QMimeDatabasePrivate;
+class QMimeDatabase
+{
+    Q_DISABLE_COPY(QMimeDatabase)
+
+public:
+    QMimeDatabase();
+    ~QMimeDatabase();
+
+    QMimeType mimeTypeForName(const QString &nameOrAlias) const;
+
+    enum MatchMode {
+        MatchDefault = 0x0,
+        MatchExtension = 0x1,
+        MatchContent = 0x2
+    };
+
+    QMimeType mimeTypeForFile(const QString &fileName, MatchMode mode = MatchDefault) const;
+    QMimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode = MatchDefault) const;
+    QList<QMimeType> mimeTypesForFileName(const QString &fileName) const;
+
+    QMimeType mimeTypeForData(const QByteArray &data) const;
+    QMimeType mimeTypeForData(QIODevice *device) const;
+
+    QMimeType mimeTypeForUrl(const QUrl &url) const;
+    QMimeType mimeTypeForNameAndData(const QString &fileName, QIODevice *device) const;
+    QMimeType mimeTypeForNameAndData(const QString &fileName, const QByteArray &data) const;
+
+    QString suffixForFileName(const QString &fileName) const;
+
+    QList<QMimeType> allMimeTypes() const;
+
+private:
+    QMimeDatabasePrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif   // QMIMEDATABASE_H
diff --git lib/MimeHandler/NBMimeDatabase_p.hpp lib/MimeHandler/NBMimeDatabase_p.hpp
new file mode 100644
index 0000000..88d57ff
--- /dev/null
+++ lib/MimeHandler/NBMimeDatabase_p.hpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEDATABASE_P_H
+#define QMIMEDATABASE_P_H
+
+#include <QHash>
+#include <QMutex>
+
+#include <NBMimeType.hpp>
+#include <NBMimeType_p.hpp>
+#include <NBMimeGlobPattern_p.hpp>
+
+class QMimeDatabase;
+class QMimeProviderBase;
+
+class QMimeDatabasePrivate
+{
+public:
+    Q_DISABLE_COPY(QMimeDatabasePrivate)
+
+    QMimeDatabasePrivate();
+    ~QMimeDatabasePrivate();
+
+    static QMimeDatabasePrivate *instance();
+
+    QMimeProviderBase *provider();
+    void setProvider(QMimeProviderBase *theProvider);
+
+    inline QString defaultMimeType() const { return m_defaultMimeType; }
+
+    bool inherits(const QString &mime, const QString &parent);
+
+    QList<QMimeType> allMimeTypes();
+
+
+    QMimeType mimeTypeForName(const QString &nameOrAlias);
+    QMimeType mimeTypeForNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr);
+    QMimeType findByData(const QByteArray &data, int *priorityPtr);
+    QStringList mimeTypeForFileName(const QString &fileName, QString *foundSuffix = 0);
+
+    mutable QMimeProviderBase *m_provider;
+    const QString m_defaultMimeType;
+    QMutex mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif   // QMIMEDATABASE_P_H
diff --git lib/MimeHandler/NBMimeGlobPattern.cpp lib/MimeHandler/NBMimeGlobPattern.cpp
new file mode 100644
index 0000000..11f091c
--- /dev/null
+++ lib/MimeHandler/NBMimeGlobPattern.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <NBMimeGlobPattern_p.hpp>
+
+#include <QRegExp>
+#include <QStringList>
+#include <QDebug>
+
+/*!
+  * \internal
+  * \class QMimeGlobMatchResult
+  * \brief The QMimeGlobMatchResult class accumulates results from glob matching.
+  *
+  * Handles glob weights, and preferring longer matches over shorter matches.
+  */
+void QMimeGlobMatchResult::addMatch(const QString& mimeType, int weight, const QString& pattern)
+{
+	// Is this a lower-weight pattern than the last match? Skip this match then.
+	if (weight < m_weight)
+	{
+		return;
+	}
+	bool replace = weight > m_weight;
+
+	if (!replace)
+	{
+		// Compare the length of the match
+		if (pattern.length() < m_matchingPatternLength)
+		{
+			return; // too short, ignore
+		}
+		else if (pattern.length() > m_matchingPatternLength)
+		{
+			// longer: clear any previous match (like *.bz2, when pattern is *.tar.bz2)
+			replace = true;
+		}
+	}
+	if (replace)
+	{
+		m_matchingMimeTypes.clear();
+		// remember the new "longer" length
+		m_matchingPatternLength = pattern.length();
+		m_weight = weight;
+	}
+	m_matchingMimeTypes.append(mimeType);
+	if (pattern.startsWith(QLatin1String("*.")))
+	{
+		m_foundSuffix = pattern.mid(2);
+	}
+}
+
+
+/*!
+  * \internal
+  * \class QMimeGlobPattern
+  * \brief The QMimeGlobPattern class contains the glob pattern for file names for MIME type matching.
+  *
+  * \sa QMimeType, QMimeDatabase, QMimeMagicRuleMatcher, QMimeMagicRule
+  */
+bool QMimeGlobPattern::matchFileName(const QString& inputFilename) const
+{
+	// "Applications MUST match globs case-insensitively, except when the case-sensitive
+	// attribute is set to true."
+	// The constructor takes care of putting case-insensitive patterns in lowercase.
+	const QString filename = m_caseSensitivity == Qt::CaseInsensitive ? inputFilename.toLower() : inputFilename;
+
+	const int pattern_len = m_pattern.length();
+
+	if (!pattern_len)
+	{
+		return false;
+	}
+	const int len = filename.length();
+
+	const int starCount = m_pattern.count(QLatin1Char('*'));
+
+	// Patterns like "*~", "*.extension"
+	if ((m_pattern[0] == QLatin1Char('*')) && (m_pattern.indexOf(QLatin1Char('[')) == -1) && (starCount == 1))
+	{
+		if (len + 1 < pattern_len)
+		{
+			return false;
+		}
+
+		const QChar *c1 = m_pattern.unicode() + pattern_len - 1;
+		const QChar *c2 = filename.unicode() + len - 1;
+		int         cnt = 1;
+		while (cnt < pattern_len && *c1-- == *c2--)
+		{
+			++cnt;
+		}
+		return cnt == pattern_len;
+	}
+
+	// Patterns like "README*" (well this is currently the only one like that...)
+	if ((starCount == 1) && (m_pattern.at(pattern_len - 1) == QLatin1Char('*')))
+	{
+		if (len + 1 < pattern_len)
+		{
+			return false;
+		}
+		if (m_pattern.at(0) == QLatin1Char('*'))
+		{
+			return filename.indexOf(m_pattern.mid(1, pattern_len - 2)) != -1;
+		}
+
+		const QChar *c1 = m_pattern.unicode();
+		const QChar *c2 = filename.unicode();
+		int         cnt = 1;
+		while (cnt < pattern_len && *c1++ == *c2++)
+		{
+			++cnt;
+		}
+		return cnt == pattern_len;
+	}
+
+	// Names without any wildcards like "README"
+	if ((m_pattern.indexOf(QLatin1Char('[')) == -1) && (starCount == 0) && m_pattern.indexOf(QLatin1Char('?')))
+	{
+		return(m_pattern == filename);
+	}
+
+	// Other (quite rare) patterns, like "*.anim[1-9j]": use slow but correct method
+	const QRegExp rx(m_pattern, Qt::CaseSensitive, QRegExp::WildcardUnix);
+
+	return rx.exactMatch(filename);
+}
+
+
+static bool isFastPattern(const QString& pattern)
+{
+	// starts with "*.", has no other '*' and no other '.'
+	return pattern.lastIndexOf(QLatin1Char('*')) == 0 &&
+		   pattern.lastIndexOf(QLatin1Char('.')) == 1
+	       // and contains no other special character
+		   && !pattern.contains(QLatin1Char('?')) &&
+		   !pattern.contains(QLatin1Char('['))
+	;
+}
+
+
+void QMimeAllGlobPatterns::addGlob(const QMimeGlobPattern& glob)
+{
+	const QString& pattern = glob.pattern();
+
+	Q_ASSERT(!pattern.isEmpty());
+
+	// Store each patterns into either m_fastPatternDict (*.txt, *.html etc. with default weight 50)
+	// or for the rest, like core.*, *.tar.bz2, *~, into highWeightPatternOffset (>50)
+	// or lowWeightPatternOffset (<=50)
+
+	if ((glob.weight() == 50) && isFastPattern(pattern) && !glob.isCaseSensitive())
+	{
+		// The bulk of the patterns is *.foo with weight 50 --> those go into the fast patterns hash.
+		const QString extension = pattern.mid(2).toLower();
+		QStringList&  patterns  = m_fastPatterns[extension]; // find or create
+		// This would just slow things down: if (!patterns.contains(glob.mimeType()))
+		patterns.append(glob.mimeType());
+	}
+	else
+	{
+		if (glob.weight() > 50)
+		{
+			// This would just slow things down: if (!m_highWeightGlobs.hasPattern(glob.mimeType(), glob.pattern()))
+			m_highWeightGlobs.append(glob);
+		}
+		else
+		{
+			//This would just slow things down: if (!m_lowWeightGlobs.hasPattern(glob.mimeType(), glob.pattern()))
+			m_lowWeightGlobs.append(glob);
+		}
+	}
+}
+
+
+void QMimeAllGlobPatterns::removeMimeType(const QString& mimeType)
+{
+	QMutableHashIterator<QString, QStringList> it(m_fastPatterns);
+
+	while (it.hasNext())
+	{
+		it.next().value().removeAll(mimeType);
+	}
+	m_highWeightGlobs.removeMimeType(mimeType);
+	m_lowWeightGlobs.removeMimeType(mimeType);
+}
+
+
+void QMimeGlobPatternList::match(QMimeGlobMatchResult& result,
+								 const QString&        fileName) const
+{
+	QMimeGlobPatternList::const_iterator       it    = this->constBegin();
+	const QMimeGlobPatternList::const_iterator endIt = this->constEnd();
+
+	for ( ; it != endIt; ++it)
+	{
+		const QMimeGlobPattern& glob = *it;
+		if (glob.matchFileName(fileName))
+		{
+			result.addMatch(glob.mimeType(), glob.weight(), glob.pattern());
+		}
+	}
+}
+
+
+QStringList QMimeAllGlobPatterns::matchingGlobs(const QString& fileName, QString *foundSuffix) const
+{
+	// First try the high weight matches (>50), if any.
+	QMimeGlobMatchResult result;
+
+	m_highWeightGlobs.match(result, fileName);
+	if (result.m_matchingMimeTypes.isEmpty())
+	{
+		// Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
+		// (which is most of them, so this optimization is definitely worth it)
+		const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
+		if (lastDot != -1)   // if no '.', skip the extension lookup
+		{
+			const int     ext_len         = fileName.length() - lastDot - 1;
+			const QString simpleExtension = fileName.right(ext_len).toLower();
+			// (toLower because fast patterns are always case-insensitive and saved as lowercase)
+
+			const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
+			foreach(const QString& mime, matchingMimeTypes)
+			{
+				result.addMatch(mime, 50, QLatin1String("*.") + simpleExtension);
+			}
+			// Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
+			// at least those with weight 50.
+		}
+
+		// Finally, try the low weight matches (<=50)
+		m_lowWeightGlobs.match(result, fileName);
+	}
+	if (foundSuffix)
+	{
+		*foundSuffix = result.m_foundSuffix;
+	}
+	return result.m_matchingMimeTypes;
+}
+
+
+void QMimeAllGlobPatterns::clear()
+{
+	m_fastPatterns.clear();
+	m_highWeightGlobs.clear();
+	m_lowWeightGlobs.clear();
+}
+
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeGlobPattern_p.hpp lib/MimeHandler/NBMimeGlobPattern_p.hpp
new file mode 100644
index 0000000..c280b4f
--- /dev/null
+++ lib/MimeHandler/NBMimeGlobPattern_p.hpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEGLOBPATTERN_P_H
+#define QMIMEGLOBPATTERN_P_H
+
+#include <QStringList>
+#include <QHash>
+
+struct QMimeGlobMatchResult
+{
+    QMimeGlobMatchResult()
+    : m_weight(0), m_matchingPatternLength(0)
+    {}
+
+    void addMatch(const QString &mimeType, int weight, const QString &pattern);
+
+    QStringList m_matchingMimeTypes;
+    int m_weight;
+    int m_matchingPatternLength;
+    QString m_foundSuffix;
+};
+
+class QMimeGlobPattern
+{
+public:
+    static const unsigned MaxWeight = 100;
+    static const unsigned DefaultWeight = 50;
+    static const unsigned MinWeight = 1;
+
+    explicit QMimeGlobPattern(const QString &thePattern, const QString &theMimeType, unsigned theWeight = DefaultWeight, Qt::CaseSensitivity s = Qt::CaseInsensitive) :
+        m_pattern(thePattern), m_mimeType(theMimeType), m_weight(theWeight), m_caseSensitivity(s)
+    {
+        if (s == Qt::CaseInsensitive) {
+            m_pattern = m_pattern.toLower();
+        }
+    }
+    ~QMimeGlobPattern() {}
+
+    bool matchFileName(const QString &filename) const;
+
+    inline const QString &pattern() const { return m_pattern; }
+    inline unsigned weight() const { return m_weight; }
+    inline const QString &mimeType() const { return m_mimeType; }
+    inline bool isCaseSensitive() const { return m_caseSensitivity == Qt::CaseSensitive; }
+
+private:
+    QString m_pattern;
+    QString m_mimeType;
+    int m_weight;
+    Qt::CaseSensitivity m_caseSensitivity;
+};
+
+class QMimeGlobPatternList : public QList<QMimeGlobPattern>
+{
+public:
+    bool hasPattern(const QString &mimeType, const QString &pattern) const
+    {
+        const_iterator it = begin();
+        const const_iterator myend = end();
+        for (; it != myend; ++it)
+            if ((*it).pattern() == pattern && (*it).mimeType() == mimeType)
+                return true;
+        return false;
+    }
+
+    /*!
+        "noglobs" is very rare occurrence, so it's ok if it's slow
+     */
+    void removeMimeType(const QString &mimeType)
+    {
+        QMutableListIterator<QMimeGlobPattern> it(*this);
+        while (it.hasNext()) {
+            if (it.next().mimeType() == mimeType)
+                it.remove();
+        }
+    }
+
+    void match(QMimeGlobMatchResult &result, const QString &fileName) const;
+};
+
+/*!
+    \internal
+    Result of the globs parsing, as data structures ready for efficient MIME type matching.
+    This contains:
+    1) a map of fast regular patterns (e.g. *.txt is stored as "txt" in a qhash's key)
+    2) a linear list of high-weight globs
+    3) a linear list of low-weight globs
+ */
+class QMimeAllGlobPatterns
+{
+public:
+    typedef QHash<QString, QStringList> PatternsMap; // MIME type -> patterns
+
+    void addGlob(const QMimeGlobPattern &glob);
+    void removeMimeType(const QString &mimeType);
+    QStringList matchingGlobs(const QString &fileName, QString *foundSuffix) const;
+    void clear();
+
+    PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"
+    QMimeGlobPatternList m_highWeightGlobs;
+    QMimeGlobPatternList m_lowWeightGlobs; // <= 50, including the non-fast 50 patterns
+};
+
+QT_END_NAMESPACE
+
+#endif // QMIMEGLOBPATTERN_P_H
diff --git lib/MimeHandler/NBMimeMagicRule.cpp lib/MimeHandler/NBMimeMagicRule.cpp
new file mode 100644
index 0000000..0132b96
--- /dev/null
+++ lib/MimeHandler/NBMimeMagicRule.cpp
@@ -0,0 +1,479 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+
+#define QT_NO_CAST_FROM_ASCII
+
+#include <NBMimeMagicRule_p.hpp>
+
+#include <QList>
+#include <QDebug>
+#include <QtEndian>
+
+// in the same order as Type!
+static const char magicRuleTypes_string[] =
+	"invalid\0"
+	"string\0"
+	"host16\0"
+	"host32\0"
+	"big16\0"
+	"big32\0"
+	"little16\0"
+	"little32\0"
+	"byte\0"
+	"\0";
+
+static const int magicRuleTypes_indices[] = {
+	0, 8, 15, 22, 29, 35, 41, 50, 59, 65, 0
+};
+
+QMimeMagicRule::Type QMimeMagicRule::type(const QByteArray& theTypeName)
+{
+	for (int i = String; i <= Byte; ++i)
+	{
+		if (theTypeName == magicRuleTypes_string + magicRuleTypes_indices[i])
+		{
+			return Type(i);
+		}
+	}
+	return Invalid;
+}
+
+
+QByteArray QMimeMagicRule::typeName(QMimeMagicRule::Type theType)
+{
+	return magicRuleTypes_string + magicRuleTypes_indices[theType];
+}
+
+
+class QMimeMagicRulePrivate
+{
+public:
+	bool operator==(const QMimeMagicRulePrivate& other) const;
+
+	QMimeMagicRule::Type type;
+	QByteArray value;
+	int startPos;
+	int endPos;
+	QByteArray mask;
+
+	QByteArray pattern;
+	quint32 number;
+	quint32 numberMask;
+
+	typedef bool (*MatchFunction)(const QMimeMagicRulePrivate *d, const QByteArray& data);
+	MatchFunction matchFunction;
+};
+
+bool QMimeMagicRulePrivate::operator==(const QMimeMagicRulePrivate& other) const
+{
+	return type == other.type &&
+		   value == other.value &&
+		   startPos == other.startPos &&
+		   endPos == other.endPos &&
+		   mask == other.mask &&
+		   pattern == other.pattern &&
+		   number == other.number &&
+		   numberMask == other.numberMask &&
+		   matchFunction == other.matchFunction;
+}
+
+
+// Used by both providers
+bool QMimeMagicRule::matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength,
+									int valueLength, const char *valueData, const char *mask)
+{
+	// Size of searched data.
+	// Example: value="ABC", rangeLength=3 -> we need 3+3-1=5 bytes (ABCxx,xABCx,xxABC would match)
+	const int dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart);
+
+	if (!mask)
+	{
+		// callgrind says QByteArray::indexOf is much slower, since our strings are typically too
+		// short for be worth Boyer-Moore matching (1 to 71 bytes, 11 bytes on average).
+		bool found = false;
+		for (int i = rangeStart; i < rangeStart + rangeLength; ++i)
+		{
+			if (i + valueLength > dataSize)
+			{
+				break;
+			}
+
+			if (memcmp(valueData, dataPtr + i, valueLength) == 0)
+			{
+				found = true;
+				break;
+			}
+		}
+		if (!found)
+		{
+			return false;
+		}
+	}
+	else
+	{
+		bool       found         = false;
+		const char *readDataBase = dataPtr + rangeStart;
+		// Example (continued from above):
+		// deviceSize is 4, so dataNeeded was max'ed to 4.
+		// maxStartPos = 4 - 3 + 1 = 2, and indeed
+		// we need to check for a match a positions 0 and 1 (ABCx and xABC).
+		const int maxStartPos = dataNeeded - valueLength + 1;
+		for (int i = 0; i < maxStartPos; ++i)
+		{
+			const char *d    = readDataBase + i;
+			bool       valid = true;
+			for (int idx = 0; idx < valueLength; ++idx)
+			{
+				if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx]))
+				{
+					valid = false;
+					break;
+				}
+			}
+			if (valid)
+			{
+				found = true;
+			}
+		}
+		if (!found)
+		{
+			return false;
+		}
+	}
+	//qDebug() << "Found" << value << "in" << searchedData;
+	return true;
+}
+
+
+static bool matchString(const QMimeMagicRulePrivate *d, const QByteArray& data)
+{
+	const int rangeLength = d->endPos - d->startPos + 1;
+
+	return QMimeMagicRule::matchSubstring(data.constData(), data.size(), d->startPos, rangeLength, d->pattern.size(), d->pattern.constData(), d->mask.constData());
+}
+
+
+template<typename T>
+static bool matchNumber(const QMimeMagicRulePrivate *d, const QByteArray& data)
+{
+	const T value(d->number);
+	const T mask(d->numberMask);
+
+	//qDebug() << "matchNumber" << "0x" << QString::number(d->number, 16) << "size" << sizeof(T);
+	//qDebug() << "mask" << QString::number(d->numberMask, 16);
+
+	const char *p = data.constData() + d->startPos;
+	const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), d->endPos + 1);
+
+	for ( ; p <= e; ++p)
+	{
+		if ((*reinterpret_cast<const T *>(p) & mask) == (value & mask))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+
+static inline QByteArray makePattern(const QByteArray& value)
+{
+	QByteArray pattern(value.size(), Qt::Uninitialized);
+	char       *data = pattern.data();
+
+	const char *p = value.constData();
+	const char *e = p + value.size();
+
+	for ( ; p < e; ++p)
+	{
+		if ((*p == '\\') && (++p < e))
+		{
+			if (*p == 'x')   // hex (\\xff)
+			{
+				char c = 0;
+				for (int i = 0; i < 2 && p + 1 < e; ++i)
+				{
+					++p;
+					if ((*p >= '0') && (*p <= '9'))
+					{
+						c = (c << 4) + *p - '0';
+					}
+					else if ((*p >= 'a') && (*p <= 'f'))
+					{
+						c = (c << 4) + *p - 'a' + 10;
+					}
+					else if ((*p >= 'A') && (*p <= 'F'))
+					{
+						c = (c << 4) + *p - 'A' + 10;
+					}
+					else
+					{
+						continue;
+					}
+				}
+				*data++ = c;
+			}
+			else if ((*p >= '0') && (*p <= '7')) // oct (\\7, or \\77, or \\377)
+			{
+				char c = *p - '0';
+				if ((p + 1 < e) && (p[1] >= '0') && (p[1] <= '7'))
+				{
+					c = (c << 3) + *(++p) - '0';
+					if ((p + 1 < e) && (p[1] >= '0') && (p[1] <= '7') && (p[-1] <= '3'))
+					{
+						c = (c << 3) + *(++p) - '0';
+					}
+				}
+				*data++ = c;
+			}
+			else if (*p == 'n')
+			{
+				*data++ = '\n';
+			}
+			else if (*p == 'r')
+			{
+				*data++ = '\r';
+			}
+			else     // escaped
+			{
+				*data++ = *p;
+			}
+		}
+		else
+		{
+			*data++ = *p;
+		}
+	}
+	pattern.truncate(data - pattern.data());
+
+	return pattern;
+}
+
+
+QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType,
+							   const QByteArray&    theValue,
+							   int                  theStartPos,
+							   int                  theEndPos,
+							   const QByteArray&    theMask) :
+	d(new QMimeMagicRulePrivate)
+{
+	Q_ASSERT(!theValue.isEmpty());
+
+	d->type          = theType;
+	d->value         = theValue;
+	d->startPos      = theStartPos;
+	d->endPos        = theEndPos;
+	d->mask          = theMask;
+	d->matchFunction = 0;
+
+	if ((d->type >= Host16) && (d->type <= Byte))
+	{
+		bool ok;
+		d->number = d->value.toUInt(&ok, 0);                             // autodetect
+		Q_ASSERT(ok);
+		d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect
+	}
+
+	switch (d->type)
+	{
+	case String:
+		d->pattern = makePattern(d->value);
+		d->pattern.squeeze();
+		if (!d->mask.isEmpty())
+		{
+			Q_ASSERT(d->mask.size() >= 4 && d->mask.startsWith("0x"));
+			d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2));
+			Q_ASSERT(d->mask.size() == d->pattern.size());
+		}
+		else
+		{
+			d->mask.fill(char(-1), d->pattern.size());
+		}
+		d->mask.squeeze();
+		d->matchFunction = matchString;
+		break;
+
+	case Byte:
+		if (d->number <= quint8(-1))
+		{
+			if (d->numberMask == 0)
+			{
+				d->numberMask = quint8(-1);
+			}
+			d->matchFunction = matchNumber<quint8>;
+		}
+		break;
+
+	case Big16:
+	case Host16:
+	case Little16:
+		if (d->number <= quint16(-1))
+		{
+			d->number = d->type == Little16 ? qFromLittleEndian<quint16>(d->number) : qFromBigEndian<quint16>(d->number);
+			if (d->numberMask == 0)
+			{
+				d->numberMask = quint16(-1);
+			}
+			d->matchFunction = matchNumber<quint16>;
+		}
+		break;
+
+	case Big32:
+	case Host32:
+	case Little32:
+		if (d->number <= quint32(-1))
+		{
+			d->number = d->type == Little32 ? qFromLittleEndian<quint32>(d->number) : qFromBigEndian<quint32>(d->number);
+			if (d->numberMask == 0)
+			{
+				d->numberMask = quint32(-1);
+			}
+			d->matchFunction = matchNumber<quint32>;
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+QMimeMagicRule::QMimeMagicRule(const QMimeMagicRule& other) :
+	d(new QMimeMagicRulePrivate(*other.d))
+{
+}
+
+
+QMimeMagicRule::~QMimeMagicRule()
+{
+}
+
+
+QMimeMagicRule& QMimeMagicRule::operator=(const QMimeMagicRule& other)
+{
+	*d = *other.d;
+	return *this;
+}
+
+
+bool QMimeMagicRule::operator==(const QMimeMagicRule& other) const
+{
+	return d == other.d ||
+		   *d == *other.d;
+}
+
+
+QMimeMagicRule::Type QMimeMagicRule::type() const
+{
+	return d->type;
+}
+
+
+QByteArray QMimeMagicRule::value() const
+{
+	return d->value;
+}
+
+
+int QMimeMagicRule::startPos() const
+{
+	return d->startPos;
+}
+
+
+int QMimeMagicRule::endPos() const
+{
+	return d->endPos;
+}
+
+
+QByteArray QMimeMagicRule::mask() const
+{
+	QByteArray result = d->mask;
+
+	if (d->type == String)
+	{
+		// restore '0x'
+		result = "0x" + result.toHex();
+	}
+	return result;
+}
+
+
+bool QMimeMagicRule::isValid() const
+{
+	return d->matchFunction;
+}
+
+
+bool QMimeMagicRule::matches(const QByteArray& data) const
+{
+	const bool ok = d->matchFunction && d->matchFunction(d.data(), data);
+
+	if (!ok)
+	{
+		return false;
+	}
+
+	// No submatch? Then we are done.
+	if (m_subMatches.isEmpty())
+	{
+		return true;
+	}
+
+	//qDebug() << "Checking" << m_subMatches.count() << "sub-rules";
+	// Check that one of the submatches matches too
+	for (QList<QMimeMagicRule>::const_iterator it = m_subMatches.begin(), end = m_subMatches.end();
+		 it != end; ++it)
+	{
+		if ((*it).matches(data))
+		{
+			// One of the hierarchies matched -> mimetype recognized.
+			return true;
+		}
+	}
+	return false;
+}
+
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeMagicRuleMatcher.cpp lib/MimeHandler/NBMimeMagicRuleMatcher.cpp
new file mode 100644
index 0000000..431cda8
--- /dev/null
+++ lib/MimeHandler/NBMimeMagicRuleMatcher.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#define QT_NO_CAST_FROM_ASCII
+
+#include <NBMimeMagicRuleMatcher_p.hpp>
+#include <NBMimeType_p.hpp>
+
+/*!
+  * \internal
+  * \class QMimeMagicRuleMatcher
+  *
+  * \brief The QMimeMagicRuleMatcher class checks a number of rules based on operator "or".
+  *
+  * It is used for rules parsed from XML files.
+  *
+  * \sa QMimeType, QMimeDatabase, MagicRule, MagicStringRule, MagicByteRule, GlobPattern
+  * \sa QMimeTypeParserBase, MimeTypeParser
+  */
+
+QMimeMagicRuleMatcher::QMimeMagicRuleMatcher(const QString& mime, unsigned thePriority) :
+	m_list(),
+	m_priority(thePriority),
+	m_mimetype(mime)
+{
+}
+
+
+bool QMimeMagicRuleMatcher::operator==(const QMimeMagicRuleMatcher& other)
+{
+	return m_list == other.m_list &&
+		   m_priority == other.m_priority;
+}
+
+
+void QMimeMagicRuleMatcher::addRule(const QMimeMagicRule& rule)
+{
+	m_list.append(rule);
+}
+
+
+void QMimeMagicRuleMatcher::addRules(const QList<QMimeMagicRule>& rules)
+{
+	m_list.append(rules);
+}
+
+
+QList<QMimeMagicRule> QMimeMagicRuleMatcher::magicRules() const
+{
+	return m_list;
+}
+
+
+// Check for a match on contents of a file
+bool QMimeMagicRuleMatcher::matches(const QByteArray& data) const
+{
+	foreach(const QMimeMagicRule& magicRule, m_list)
+	{
+		if (magicRule.matches(data))
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+
+// Return a priority value from 1..100
+unsigned QMimeMagicRuleMatcher::priority() const
+{
+	return m_priority;
+}
+
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeMagicRuleMatcher_p.hpp lib/MimeHandler/NBMimeMagicRuleMatcher_p.hpp
new file mode 100644
index 0000000..6ba1834
--- /dev/null
+++ lib/MimeHandler/NBMimeMagicRuleMatcher_p.hpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEMAGICRULEMATCHER_P_H
+#define QMIMEMAGICRULEMATCHER_P_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+
+#include <NBMimeMagicRule_p.hpp>
+
+class QMimeMagicRuleMatcher
+{
+public:
+    explicit QMimeMagicRuleMatcher(const QString &mime, unsigned priority = 65535);
+
+    bool operator==(const QMimeMagicRuleMatcher &other);
+
+    void addRule(const QMimeMagicRule &rule);
+    void addRules(const QList<QMimeMagicRule> &rules);
+    QList<QMimeMagicRule> magicRules() const;
+
+    bool matches(const QByteArray &data) const;
+
+    unsigned priority() const;
+
+    QString mimetype() const { return m_mimetype; }
+
+private:
+    QList<QMimeMagicRule> m_list;
+    unsigned m_priority;
+    QString m_mimetype;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMIMEMAGICRULEMATCHER_P_H
diff --git lib/MimeHandler/NBMimeMagicRule_p.hpp lib/MimeHandler/NBMimeMagicRule_p.hpp
new file mode 100644
index 0000000..e074943
--- /dev/null
+++ lib/MimeHandler/NBMimeMagicRule_p.hpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEMAGICRULE_P_H
+#define QMIMEMAGICRULE_P_H
+
+#include <QByteArray>
+#include <QScopedPointer>
+#include <QList>
+
+class QMimeMagicRulePrivate;
+class QMimeMagicRule
+{
+public:
+    enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte };
+
+    QMimeMagicRule(Type type, const QByteArray &value, int startPos, int endPos, const QByteArray &mask = QByteArray());
+    QMimeMagicRule(const QMimeMagicRule &other);
+    ~QMimeMagicRule();
+
+    QMimeMagicRule &operator=(const QMimeMagicRule &other);
+
+    bool operator==(const QMimeMagicRule &other) const;
+
+    Type type() const;
+    QByteArray value() const;
+    int startPos() const;
+    int endPos() const;
+    QByteArray mask() const;
+
+    bool isValid() const;
+
+    bool matches(const QByteArray &data) const;
+
+    QList<QMimeMagicRule> m_subMatches;
+
+    static Type type(const QByteArray &type);
+    static QByteArray typeName(Type type);
+
+    static bool matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength, int valueLength, const char *valueData, const char *mask);
+
+private:
+    const QScopedPointer<QMimeMagicRulePrivate> d;
+};
+Q_DECLARE_TYPEINFO(QMimeMagicRule, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QMIMEMAGICRULE_H
diff --git lib/MimeHandler/NBMimeProvider.cpp lib/MimeHandler/NBMimeProvider.cpp
new file mode 100644
index 0000000..6a99853
--- /dev/null
+++ lib/MimeHandler/NBMimeProvider.cpp
@@ -0,0 +1,1059 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <NBMimeProvider_p.hpp>
+#include <NBMimeTypeParser_p.hpp>
+#include <NBMimeMagicRuleMatcher_p.hpp>
+#include <NBStandardPaths.hpp>
+
+#include <QXmlStreamReader>
+#include <QDir>
+#include <QFile>
+#include <QByteArrayMatcher>
+#include <QDebug>
+#include <QDateTime>
+#include <QtEndian>
+
+static QString fallbackParent(const QString& mimeTypeName)
+{
+	const QString myGroup = mimeTypeName.left(mimeTypeName.indexOf(QLatin1Char('/')));
+
+	// All text/* types are subclasses of text/plain.
+	if ((myGroup == QLatin1String("text")) && (mimeTypeName != QLatin1String("text/plain")))
+	{
+		return QLatin1String("text/plain");
+	}
+	// All real-file mimetypes implicitly derive from application/octet-stream
+	if ((myGroup != QLatin1String("inode")) &&
+	    // ignore non-file extensions
+		(myGroup != QLatin1String("all")) && (myGroup != QLatin1String("fonts")) && (myGroup != QLatin1String("print")) && (myGroup != QLatin1String("uri")) &&
+		(mimeTypeName != QLatin1String("application/octet-stream")))
+	{
+		return QLatin1String("application/octet-stream");
+	}
+	return QString();
+}
+
+
+QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db)
+	: m_db(db)
+{
+}
+
+
+int qmime_secondsBetweenChecks = 5;
+
+bool QMimeProviderBase::shouldCheck()
+{
+	const QDateTime now = QDateTime::currentDateTime();
+
+	if (m_lastCheck.isValid() && (m_lastCheck.secsTo(now) < qmime_secondsBetweenChecks))
+	{
+		return false;
+	}
+	m_lastCheck = now;
+	return true;
+}
+
+
+QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db)
+	: QMimeProviderBase(db), m_mimetypeListLoaded(false)
+{
+}
+
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
+#define QT_USE_MMAP
+#endif
+
+struct QMimeBinaryProvider::CacheFile
+{
+	CacheFile(const QString& fileName);
+	~CacheFile();
+
+	bool isValid() const { return m_valid; }
+	inline quint16 getUint16(int offset) const
+	{
+		return qFromBigEndian(*reinterpret_cast<quint16 *>(data + offset));
+	}
+
+	inline quint32 getUint32(int offset) const
+	{
+		return qFromBigEndian(*reinterpret_cast<quint32 *>(data + offset));
+	}
+
+	inline const char *getCharStar(int offset) const
+	{
+		return reinterpret_cast<const char *>(data + offset);
+	}
+
+	bool load();
+	bool reload();
+
+	QFile     file;
+	uchar     *data;
+	QDateTime m_mtime;
+	bool      m_valid;
+};
+
+QMimeBinaryProvider::CacheFile::CacheFile(const QString& fileName)
+	: file(fileName), m_valid(false)
+{
+	load();
+}
+
+
+QMimeBinaryProvider::CacheFile::~CacheFile()
+{
+}
+
+
+bool QMimeBinaryProvider::CacheFile::load()
+{
+	if (!file.open(QIODevice::ReadOnly))
+	{
+		return false;
+	}
+	data = file.map(0, file.size());
+	if (data)
+	{
+		const int major = getUint16(0);
+		const int minor = getUint16(2);
+		m_valid = (major == 1 && minor >= 1 && minor <= 2);
+	}
+	m_mtime = QFileInfo(file).lastModified();
+	return m_valid;
+}
+
+
+bool QMimeBinaryProvider::CacheFile::reload()
+{
+	//qDebug() << "reload!" << file->fileName();
+	m_valid = false;
+	if (file.isOpen())
+	{
+		file.close();
+	}
+	data = 0;
+	return load();
+}
+
+
+QMimeBinaryProvider::CacheFile *QMimeBinaryProvider::CacheFileList::findCacheFile(const QString& fileName) const
+{
+	for (const_iterator it = begin(); it != end(); ++it)
+	{
+		if ((*it)->file.fileName() == fileName)
+		{
+			return *it;
+		}
+	}
+	return 0;
+}
+
+
+QMimeBinaryProvider::~QMimeBinaryProvider()
+{
+	qDeleteAll(m_cacheFiles);
+}
+
+
+// Position of the "list offsets" values, at the beginning of the mime.cache file
+enum
+{
+	PosAliasListOffset         = 4,
+	PosParentListOffset        = 8,
+	PosLiteralListOffset       = 12,
+	PosReverseSuffixTreeOffset = 16,
+	PosGlobListOffset          = 20,
+	PosMagicListOffset         = 24,
+	// PosNamespaceListOffset = 28,
+	PosIconsListOffset         = 32,
+	PosGenericIconsListOffset  = 36
+};
+
+bool QMimeBinaryProvider::isValid()
+{
+#if defined(QT_USE_MMAP)
+	if (!qgetenv("QT_NO_MIME_CACHE").isEmpty())
+	{
+		return false;
+	}
+
+	Q_ASSERT(m_cacheFiles.isEmpty()); // this method is only ever called once
+	checkCache();
+
+	if (m_cacheFiles.count() > 1)
+	{
+		return true;
+	}
+	if (m_cacheFiles.isEmpty())
+	{
+		return false;
+	}
+
+	// We found exactly one file; is it the user-modified mimes, or a system file?
+	const QString foundFile      = m_cacheFiles.first()->file.fileName();
+	const QString localCacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/mime/mime.cache");
+
+	return foundFile != localCacheFile;
+#else
+	return false;
+#endif
+}
+
+
+bool QMimeBinaryProvider::CacheFileList::checkCacheChanged()
+{
+	bool somethingChanged = false;
+	QMutableListIterator<CacheFile *> it(*this);
+
+	while (it.hasNext())
+	{
+		CacheFile *cacheFile = it.next();
+		QFileInfo fileInfo(cacheFile->file);
+		if (!fileInfo.exists())   // This can't happen by just running update-mime-database. But the user could use rm -rf :-)
+		{
+			delete cacheFile;
+			it.remove();
+			somethingChanged = true;
+		}
+		else if (fileInfo.lastModified() > cacheFile->m_mtime)
+		{
+			if (!cacheFile->reload())
+			{
+				delete cacheFile;
+				it.remove();
+			}
+			somethingChanged = true;
+		}
+	}
+	return somethingChanged;
+}
+
+
+void QMimeBinaryProvider::checkCache()
+{
+	if (!shouldCheck())
+	{
+		return;
+	}
+
+	// First iterate over existing known cache files and check for uptodate
+	if (m_cacheFiles.checkCacheChanged())
+	{
+		m_mimetypeListLoaded = false;
+	}
+
+	// Then check if new cache files appeared
+	const QStringList cacheFileNames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/mime.cache"));
+
+	if (cacheFileNames != m_cacheFileNames)
+	{
+		foreach(const QString& cacheFileName, cacheFileNames)
+		{
+			CacheFile *cacheFile = m_cacheFiles.findCacheFile(cacheFileName);
+
+			if (!cacheFile)
+			{
+				//qDebug() << "new file:" << cacheFileName;
+				cacheFile = new CacheFile(cacheFileName);
+				if (cacheFile->isValid()) // verify version
+				{
+					m_cacheFiles.append(cacheFile);
+				}
+				else
+				{
+					delete cacheFile;
+				}
+			}
+		}
+		m_cacheFileNames     = cacheFileNames;
+		m_mimetypeListLoaded = false;
+	}
+}
+
+
+static QMimeType mimeTypeForNameUnchecked(const QString& name)
+{
+	QMimeTypePrivate data;
+
+	data.name = name;
+	// The rest is retrieved on demand.
+	// comment and globPatterns: in loadMimeTypePrivate
+	// iconName: in loadIcon
+	// genericIconName: in loadGenericIcon
+	return QMimeType(data);
+}
+
+
+QMimeType QMimeBinaryProvider::mimeTypeForName(const QString& name)
+{
+	checkCache();
+	if (!m_mimetypeListLoaded)
+	{
+		loadMimeTypeList();
+	}
+	if (!m_mimetypeNames.contains(name))
+	{
+		return QMimeType(); // unknown mimetype
+	}
+	return mimeTypeForNameUnchecked(name);
+}
+
+
+QStringList QMimeBinaryProvider::findByFileName(const QString& fileName, QString *foundSuffix)
+{
+	checkCache();
+	if (fileName.isEmpty())
+	{
+		return QStringList();
+	}
+	const QString        lowerFileName = fileName.toLower();
+	QMimeGlobMatchResult result;
+
+	// TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
+	foreach(CacheFile * cacheFile, m_cacheFiles)
+	{
+		matchGlobList(result, cacheFile, cacheFile->getUint32(PosLiteralListOffset), fileName);
+		matchGlobList(result, cacheFile, cacheFile->getUint32(PosGlobListOffset), fileName);
+		const int reverseSuffixTreeOffset = cacheFile->getUint32(PosReverseSuffixTreeOffset);
+		const int numRoots        = cacheFile->getUint32(reverseSuffixTreeOffset);
+		const int firstRootOffset = cacheFile->getUint32(reverseSuffixTreeOffset + 4);
+
+		matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, lowerFileName, fileName.length() - 1, false);
+		if (result.m_matchingMimeTypes.isEmpty())
+		{
+			matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
+		}
+	}
+	if (foundSuffix)
+	{
+		*foundSuffix = result.m_foundSuffix;
+	}
+	return result.m_matchingMimeTypes;
+}
+
+
+void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult& result, CacheFile *cacheFile, int off, const QString& fileName)
+{
+	const int numGlobs = cacheFile->getUint32(off);
+
+	//qDebug() << "Loading" << numGlobs << "globs from" << cacheFile->file.fileName() << "at offset" << cacheFile->globListOffset;
+	for (int i = 0; i < numGlobs; ++i)
+	{
+		const int                 globOffset      = cacheFile->getUint32(off + 4 + 12 * i);
+		const int                 mimeTypeOffset  = cacheFile->getUint32(off + 4 + 12 * i + 4);
+		const int                 flagsAndWeight  = cacheFile->getUint32(off + 4 + 12 * i + 8);
+		const int                 weight          = flagsAndWeight & 0xff;
+		const bool                caseSensitive   = flagsAndWeight & 0x100;
+		const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+		const QString             pattern         = QLatin1String(cacheFile->getCharStar(globOffset));
+
+		const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
+		//qDebug() << pattern << mimeType << weight << caseSensitive;
+		QMimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
+
+		// TODO: this could be done faster for literals where a simple == would do.
+		if (glob.matchFileName(fileName))
+		{
+			result.addMatch(QLatin1String(mimeType), weight, pattern);
+		}
+	}
+}
+
+
+bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult& result, QMimeBinaryProvider::CacheFile *cacheFile, int numEntries, int firstOffset, const QString& fileName, int charPos, bool caseSensitiveCheck)
+{
+	QChar fileChar = fileName[charPos];
+	int   min      = 0;
+	int   max      = numEntries - 1;
+
+	while (min <= max)
+	{
+		const int   mid = (min + max) / 2;
+		const int   off = firstOffset + 12 * mid;
+		const QChar ch  = cacheFile->getUint32(off);
+		if (ch < fileChar)
+		{
+			min = mid + 1;
+		}
+		else if (ch > fileChar)
+		{
+			max = mid - 1;
+		}
+		else
+		{
+			--charPos;
+			int  numChildren    = cacheFile->getUint32(off + 4);
+			int  childrenOffset = cacheFile->getUint32(off + 8);
+			bool success        = false;
+			if (charPos > 0)
+			{
+				success = matchSuffixTree(result, cacheFile, numChildren, childrenOffset, fileName, charPos, caseSensitiveCheck);
+			}
+			if (!success)
+			{
+				for (int i = 0; i < numChildren; ++i)
+				{
+					const int childOff = childrenOffset + 12 * i;
+					const int mch      = cacheFile->getUint32(childOff);
+					if (mch != 0)
+					{
+						break;
+					}
+					const int  mimeTypeOffset = cacheFile->getUint32(childOff + 4);
+					const char *mimeType      = cacheFile->getCharStar(mimeTypeOffset);
+					const int  flagsAndWeight = cacheFile->getUint32(childOff + 8);
+					const int  weight         = flagsAndWeight & 0xff;
+					const bool caseSensitive  = flagsAndWeight & 0x100;
+					if (caseSensitiveCheck || !caseSensitive)
+					{
+						result.addMatch(QLatin1String(mimeType), weight, QLatin1Char('*') + fileName.mid(charPos + 1));
+						success = true;
+					}
+				}
+			}
+			return success;
+		}
+	}
+	return false;
+}
+
+
+bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray& data)
+{
+	const char *dataPtr = data.constData();
+	const int  dataSize = data.size();
+
+	for (int matchlet = 0; matchlet < numMatchlets; ++matchlet)
+	{
+		const int off         = firstOffset + matchlet * 32;
+		const int rangeStart  = cacheFile->getUint32(off);
+		const int rangeLength = cacheFile->getUint32(off + 4);
+		//const int wordSize = cacheFile->getUint32(off + 8);
+		const int  valueLength = cacheFile->getUint32(off + 12);
+		const int  valueOffset = cacheFile->getUint32(off + 16);
+		const int  maskOffset  = cacheFile->getUint32(off + 20);
+		const char *mask       = maskOffset ? cacheFile->getCharStar(maskOffset) : NULL;
+
+		if (!QMimeMagicRule::matchSubstring(dataPtr, dataSize, rangeStart, rangeLength, valueLength, cacheFile->getCharStar(valueOffset), mask))
+		{
+			continue;
+		}
+
+		const int numChildren      = cacheFile->getUint32(off + 24);
+		const int firstChildOffset = cacheFile->getUint32(off + 28);
+		if (numChildren == 0) // No submatch? Then we are done.
+		{
+			return true;
+		}
+		// Check that one of the submatches matches too
+		if (matchMagicRule(cacheFile, numChildren, firstChildOffset, data))
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+
+QMimeType QMimeBinaryProvider::findByMagic(const QByteArray& data, int *accuracyPtr)
+{
+	checkCache();
+	foreach(CacheFile * cacheFile, m_cacheFiles)
+	{
+		const int magicListOffset = cacheFile->getUint32(PosMagicListOffset);
+		const int numMatches      = cacheFile->getUint32(magicListOffset);
+		//const int maxExtent = cacheFile->getUint32(magicListOffset + 4);
+		const int firstMatchOffset = cacheFile->getUint32(magicListOffset + 8);
+
+		for (int i = 0; i < numMatches; ++i)
+		{
+			const int off                 = firstMatchOffset + i * 16;
+			const int numMatchlets        = cacheFile->getUint32(off + 8);
+			const int firstMatchletOffset = cacheFile->getUint32(off + 12);
+			if (matchMagicRule(cacheFile, numMatchlets, firstMatchletOffset, data))
+			{
+				const int  mimeTypeOffset = cacheFile->getUint32(off + 4);
+				const char *mimeType      = cacheFile->getCharStar(mimeTypeOffset);
+				*accuracyPtr = cacheFile->getUint32(off);
+				// Return the first match. We have no rules for conflicting magic data...
+				// (mime.cache itself is sorted, but what about local overrides with a lower prio?)
+				return mimeTypeForNameUnchecked(QLatin1String(mimeType));
+			}
+		}
+	}
+	return QMimeType();
+}
+
+
+QStringList QMimeBinaryProvider::parents(const QString& mime)
+{
+	checkCache();
+	const QByteArray mimeStr = mime.toLatin1();
+	QStringList      result;
+
+	foreach(CacheFile * cacheFile, m_cacheFiles)
+	{
+		const int parentListOffset = cacheFile->getUint32(PosParentListOffset);
+		const int numEntries       = cacheFile->getUint32(parentListOffset);
+
+		int begin = 0;
+		int end   = numEntries - 1;
+
+		while (begin <= end)
+		{
+			const int  medium     = (begin + end) / 2;
+			const int  off        = parentListOffset + 4 + 8 * medium;
+			const int  mimeOffset = cacheFile->getUint32(off);
+			const char *aMime     = cacheFile->getCharStar(mimeOffset);
+			const int  cmp        = qstrcmp(aMime, mimeStr);
+			if (cmp < 0)
+			{
+				begin = medium + 1;
+			}
+			else if (cmp > 0)
+			{
+				end = medium - 1;
+			}
+			else
+			{
+				const int parentsOffset = cacheFile->getUint32(off + 4);
+				const int numParents    = cacheFile->getUint32(parentsOffset);
+				for (int i = 0; i < numParents; ++i)
+				{
+					const int  parentOffset = cacheFile->getUint32(parentsOffset + 4 + 4 * i);
+					const char *aParent     = cacheFile->getCharStar(parentOffset);
+					result.append(QString::fromLatin1(aParent));
+				}
+				break;
+			}
+		}
+	}
+	if (result.isEmpty())
+	{
+		const QString parent = fallbackParent(mime);
+		if (!parent.isEmpty())
+		{
+			result.append(parent);
+		}
+	}
+	return result;
+}
+
+
+QString QMimeBinaryProvider::resolveAlias(const QString& name)
+{
+	checkCache();
+	const QByteArray input = name.toLatin1();
+
+	foreach(CacheFile * cacheFile, m_cacheFiles)
+	{
+		const int aliasListOffset = cacheFile->getUint32(PosAliasListOffset);
+		const int numEntries      = cacheFile->getUint32(aliasListOffset);
+		int       begin           = 0;
+		int       end             = numEntries - 1;
+
+		while (begin <= end)
+		{
+			const int  medium      = (begin + end) / 2;
+			const int  off         = aliasListOffset + 4 + 8 * medium;
+			const int  aliasOffset = cacheFile->getUint32(off);
+			const char *alias      = cacheFile->getCharStar(aliasOffset);
+			const int  cmp         = qstrcmp(alias, input);
+			if (cmp < 0)
+			{
+				begin = medium + 1;
+			}
+			else if (cmp > 0)
+			{
+				end = medium - 1;
+			}
+			else
+			{
+				const int  mimeOffset = cacheFile->getUint32(off + 4);
+				const char *mimeType  = cacheFile->getCharStar(mimeOffset);
+				return QLatin1String(mimeType);
+			}
+		}
+	}
+
+	return name;
+}
+
+
+void QMimeBinaryProvider::loadMimeTypeList()
+{
+	if (!m_mimetypeListLoaded)
+	{
+		m_mimetypeListLoaded = true;
+		m_mimetypeNames.clear();
+		// Unfortunately mime.cache doesn't have a full list of all mimetypes.
+		// So we have to parse the plain-text files called "types".
+		const QStringList typesFilenames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/types"));
+		foreach(const QString& typeFilename, typesFilenames)
+		{
+			QFile file(typeFilename);
+
+			if (file.open(QIODevice::ReadOnly))
+			{
+				while (!file.atEnd())
+				{
+					QByteArray line = file.readLine();
+					line.chop(1);
+					m_mimetypeNames.insert(QString::fromLatin1(line.constData(), line.size()));
+				}
+			}
+		}
+	}
+}
+
+
+QList<QMimeType> QMimeBinaryProvider::allMimeTypes()
+{
+	QList<QMimeType> result;
+
+	loadMimeTypeList();
+
+	for (QSet<QString>::const_iterator it = m_mimetypeNames.constBegin();
+		 it != m_mimetypeNames.constEnd(); ++it)
+	{
+		result.append(mimeTypeForNameUnchecked(*it));
+	}
+
+	return result;
+}
+
+
+void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate& data)
+{
+	// load comment and globPatterns
+
+	const QString     file      = data.name + QLatin1String(".xml");
+	const QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file);
+
+	if (mimeFiles.isEmpty())
+	{
+		// TODO: ask Thiago about this
+		qWarning() << "No file found for" << file << ", even though the file appeared in a directory listing.";
+		qWarning() << "Either it was just removed, or the directory doesn't have executable permission...";
+		qWarning() << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
+		return;
+	}
+
+	QString       comment;
+	QString       mainPattern;
+	const QString preferredLanguage = QLocale::system().name();
+
+	QListIterator<QString> mimeFilesIter(mimeFiles);
+
+	mimeFilesIter.toBack();
+	while (mimeFilesIter.hasPrevious())   // global first, then local.
+	{
+		const QString fullPath = mimeFilesIter.previous();
+		QFile         qfile(fullPath);
+		if (!qfile.open(QFile::ReadOnly))
+		{
+			continue;
+		}
+
+		QXmlStreamReader xml(&qfile);
+		if (xml.readNextStartElement())
+		{
+			if (xml.name() != QLatin1String("mime-type"))
+			{
+				continue;
+			}
+			const QString name = xml.attributes().value(QLatin1String("type")).toString();
+			if (name.isEmpty())
+			{
+				continue;
+			}
+			if (name != data.name)
+			{
+				qWarning() << "Got name" << name << "in file" << file << "expected" << data.name;
+			}
+
+			while (xml.readNextStartElement())
+			{
+				const QStringRef tag = xml.name();
+				if (tag == QLatin1String("comment"))
+				{
+					QString       lang = xml.attributes().value(QLatin1String("xml:lang")).toString();
+					const QString text = xml.readElementText();
+					if (lang.isEmpty())
+					{
+						lang = QLatin1String("en_US");
+					}
+					data.localeComments.insert(lang, text);
+					continue;                          // we called readElementText, so we're at the EndElement already.
+				}
+				else if (tag == QLatin1String("icon")) // as written out by shared-mime-info >= 0.40
+				{
+					data.iconName = xml.attributes().value(QLatin1String("name")).toString();
+				}
+				else if (tag == QLatin1String("glob-deleteall"))     // as written out by shared-mime-info >= 0.70
+				{
+					data.globPatterns.clear();
+				}
+				else if (tag == QLatin1String("glob"))     // as written out by shared-mime-info >= 0.70
+				{
+					const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString();
+					if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*')))
+					{
+						mainPattern = pattern;
+					}
+					if (!data.globPatterns.contains(pattern))
+					{
+						data.globPatterns.append(pattern);
+					}
+				}
+				xml.skipCurrentElement();
+			}
+			Q_ASSERT(xml.name() == QLatin1String("mime-type"));
+		}
+	}
+
+	// Let's assume that shared-mime-info is at least version 0.70
+	// Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file.
+#if 1
+	if (!mainPattern.isEmpty() && (data.globPatterns.first() != mainPattern))
+	{
+		// ensure it's first in the list of patterns
+		data.globPatterns.removeAll(mainPattern);
+		data.globPatterns.prepend(mainPattern);
+	}
+#else
+	const bool globsInXml = sharedMimeInfoVersion() >= QT_VERSION_CHECK(0, 70, 0);
+	if (globsInXml)
+	{
+		if (!mainPattern.isEmpty() && (data.globPatterns.first() != mainPattern))
+		{
+			// ensure it's first in the list of patterns
+			data.globPatterns.removeAll(mainPattern);
+			data.globPatterns.prepend(mainPattern);
+		}
+	}
+	else
+	{
+		// Fallback: get the patterns from the globs file
+		// TODO: This would be the only way to support shared-mime-info < 0.70
+		// But is this really worth the effort?
+	}
+#endif
+}
+
+
+// Binary search in the icons or generic-icons list
+QString QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray& inputMime)
+{
+	const int iconsListOffset = cacheFile->getUint32(posListOffset);
+	const int numIcons        = cacheFile->getUint32(iconsListOffset);
+	int       begin           = 0;
+	int       end             = numIcons - 1;
+
+	while (begin <= end)
+	{
+		const int  medium     = (begin + end) / 2;
+		const int  off        = iconsListOffset + 4 + 8 * medium;
+		const int  mimeOffset = cacheFile->getUint32(off);
+		const char *mime      = cacheFile->getCharStar(mimeOffset);
+		const int  cmp        = qstrcmp(mime, inputMime);
+		if (cmp < 0)
+		{
+			begin = medium + 1;
+		}
+		else if (cmp > 0)
+		{
+			end = medium - 1;
+		}
+		else
+		{
+			const int iconOffset = cacheFile->getUint32(off + 4);
+			return QLatin1String(cacheFile->getCharStar(iconOffset));
+		}
+	}
+	return QString();
+}
+
+
+void QMimeBinaryProvider::loadIcon(QMimeTypePrivate& data)
+{
+	checkCache();
+	const QByteArray inputMime = data.name.toLatin1();
+
+	foreach(CacheFile * cacheFile, m_cacheFiles)
+	{
+		const QString icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
+
+		if (!icon.isEmpty())
+		{
+			data.iconName = icon;
+			return;
+		}
+	}
+}
+
+
+void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate& data)
+{
+	checkCache();
+	const QByteArray inputMime = data.name.toLatin1();
+
+	foreach(CacheFile * cacheFile, m_cacheFiles)
+	{
+		const QString icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
+
+		if (!icon.isEmpty())
+		{
+			data.genericIconName = icon;
+			return;
+		}
+	}
+}
+
+
+////
+
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db)
+	: QMimeProviderBase(db), m_loaded(false)
+{
+}
+
+
+bool QMimeXMLProvider::isValid()
+{
+	return true;
+}
+
+
+QMimeType QMimeXMLProvider::mimeTypeForName(const QString& name)
+{
+	ensureLoaded();
+
+	return m_nameMimeTypeMap.value(name);
+}
+
+
+QStringList QMimeXMLProvider::findByFileName(const QString& fileName, QString *foundSuffix)
+{
+	ensureLoaded();
+
+	const QStringList matchingMimeTypes = m_mimeTypeGlobs.matchingGlobs(fileName, foundSuffix);
+
+	return matchingMimeTypes;
+}
+
+
+QMimeType QMimeXMLProvider::findByMagic(const QByteArray& data, int *accuracyPtr)
+{
+	ensureLoaded();
+
+	QString candidate;
+
+	foreach(const QMimeMagicRuleMatcher& matcher, m_magicMatchers)
+	{
+		if (matcher.matches(data))
+		{
+			const int priority = matcher.priority();
+			if (priority > *accuracyPtr)
+			{
+				*accuracyPtr = priority;
+				candidate    = matcher.mimetype();
+			}
+		}
+	}
+	return mimeTypeForName(candidate);
+}
+
+
+void QMimeXMLProvider::ensureLoaded()
+{
+	if (!m_loaded || shouldCheck())
+	{
+		bool        fdoXmlFound = false;
+		QStringList allFiles;
+
+		const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory);
+		//qDebug() << "packageDirs=" << packageDirs;
+		foreach(const QString& packageDir, packageDirs)
+		{
+			QDir              dir(packageDir);
+			const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
+
+			//qDebug() << static_cast<const void *>(this) << Q_FUNC_INFO << packageDir << files;
+			if (!fdoXmlFound)
+			{
+				fdoXmlFound = files.contains(QLatin1String("freedesktop.org.xml"));
+			}
+			QStringList::const_iterator endIt(files.constEnd());
+
+			for (QStringList::const_iterator it(files.constBegin()); it != endIt; ++it)
+			{
+				allFiles.append(packageDir + QLatin1Char('/') + *it);
+			}
+		}
+
+		// if (!fdoXmlFound) {
+		// We could instead install the file as part of installing Qt?
+		// allFiles.prepend( QLatin1String( DATA_DIR ) + QLatin1String( "/freedesktop.org.xml" ) );
+		// }
+
+		if (m_allFiles == allFiles)
+		{
+			return;
+		}
+		m_allFiles = allFiles;
+
+		m_nameMimeTypeMap.clear();
+		m_aliases.clear();
+		m_parents.clear();
+		m_mimeTypeGlobs.clear();
+		m_magicMatchers.clear();
+
+		//qDebug() << "Loading" << m_allFiles;
+
+		foreach(const QString& file, allFiles)
+		load(file);
+	}
+}
+
+
+void QMimeXMLProvider::load(const QString& fileName)
+{
+	QString errorMessage;
+
+	if (!load(fileName, &errorMessage))
+	{
+		qWarning("QMimeDatabase: Error loading %s\n%s", qPrintable(fileName), qPrintable(errorMessage));
+	}
+}
+
+
+bool QMimeXMLProvider::load(const QString& fileName, QString *errorMessage)
+{
+	m_loaded = true;
+
+	QFile file(fileName);
+
+	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+	{
+		if (errorMessage)
+		{
+			*errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(fileName, file.errorString());
+		}
+		return false;
+	}
+
+	if (errorMessage)
+	{
+		errorMessage->clear();
+	}
+
+	QMimeTypeParser parser(*this);
+
+	return parser.parse(&file, fileName, errorMessage);
+}
+
+
+void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern& glob)
+{
+	m_mimeTypeGlobs.addGlob(glob);
+}
+
+
+void QMimeXMLProvider::addMimeType(const QMimeType& mt)
+{
+	m_nameMimeTypeMap.insert(mt.name(), mt);
+}
+
+
+QStringList QMimeXMLProvider::parents(const QString& mime)
+{
+	ensureLoaded();
+	QStringList result = m_parents.value(mime);
+
+	if (result.isEmpty())
+	{
+		const QString parent = fallbackParent(mime);
+		if (!parent.isEmpty())
+		{
+			result.append(parent);
+		}
+	}
+	return result;
+}
+
+
+void QMimeXMLProvider::addParent(const QString& child, const QString& parent)
+{
+	m_parents[child].append(parent);
+}
+
+
+QString QMimeXMLProvider::resolveAlias(const QString& name)
+{
+	ensureLoaded();
+	return m_aliases.value(name, name);
+}
+
+
+void QMimeXMLProvider::addAlias(const QString& alias, const QString& name)
+{
+	m_aliases.insert(alias, name);
+}
+
+
+QList<QMimeType> QMimeXMLProvider::allMimeTypes()
+{
+	ensureLoaded();
+	return m_nameMimeTypeMap.values();
+}
+
+
+void QMimeXMLProvider::addMagicMatcher(const QMimeMagicRuleMatcher& matcher)
+{
+	m_magicMatchers.append(matcher);
+}
+
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeProvider_p.hpp lib/MimeHandler/NBMimeProvider_p.hpp
new file mode 100644
index 0000000..23bfe13
--- /dev/null
+++ lib/MimeHandler/NBMimeProvider_p.hpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMEPROVIDER_P_H
+#define QMIMEPROVIDER_P_H
+
+#include <QDateTime>
+#include <NBMimeDatabase_p.hpp>
+#include <QSet>
+
+class QMimeMagicRuleMatcher;
+
+class QMimeProviderBase
+{
+public:
+    QMimeProviderBase(QMimeDatabasePrivate *db);
+    virtual ~QMimeProviderBase() {}
+
+    virtual bool isValid() = 0;
+    virtual QMimeType mimeTypeForName(const QString &name) = 0;
+    virtual QStringList findByFileName(const QString &fileName, QString *foundSuffix) = 0;
+    virtual QStringList parents(const QString &mime) = 0;
+    virtual QString resolveAlias(const QString &name) = 0;
+    virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) = 0;
+    virtual QList<QMimeType> allMimeTypes() = 0;
+    virtual void loadMimeTypePrivate(QMimeTypePrivate &) {}
+    virtual void loadIcon(QMimeTypePrivate &) {}
+    virtual void loadGenericIcon(QMimeTypePrivate &) {}
+
+    QMimeDatabasePrivate *m_db;
+protected:
+    bool shouldCheck();
+    QDateTime m_lastCheck;
+};
+
+/*
+   Parses the files 'mime.cache' and 'types' on demand
+ */
+class QMimeBinaryProvider : public QMimeProviderBase
+{
+public:
+    QMimeBinaryProvider(QMimeDatabasePrivate *db);
+    virtual ~QMimeBinaryProvider();
+
+    virtual bool isValid();
+    virtual QMimeType mimeTypeForName(const QString &name);
+    virtual QStringList findByFileName(const QString &fileName, QString *foundSuffix);
+    virtual QStringList parents(const QString &mime);
+    virtual QString resolveAlias(const QString &name);
+    virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr);
+    virtual QList<QMimeType> allMimeTypes();
+    virtual void loadMimeTypePrivate(QMimeTypePrivate &);
+    virtual void loadIcon(QMimeTypePrivate &);
+    virtual void loadGenericIcon(QMimeTypePrivate &);
+
+private:
+    struct CacheFile;
+
+    void matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, const QString &fileName);
+    bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck);
+    bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
+    QString iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
+    void loadMimeTypeList();
+    void checkCache();
+
+    class CacheFileList : public QList<CacheFile *>
+    {
+    public:
+        CacheFile *findCacheFile(const QString &fileName) const;
+        bool checkCacheChanged();
+    };
+    CacheFileList m_cacheFiles;
+    QStringList m_cacheFileNames;
+    QSet<QString> m_mimetypeNames;
+    bool m_mimetypeListLoaded;
+};
+
+/*
+   Parses the raw XML files (slower)
+ */
+class QMimeXMLProvider : public QMimeProviderBase
+{
+public:
+    QMimeXMLProvider(QMimeDatabasePrivate *db);
+
+    virtual bool isValid();
+    virtual QMimeType mimeTypeForName(const QString &name);
+    virtual QStringList findByFileName(const QString &fileName, QString *foundSuffix);
+    virtual QStringList parents(const QString &mime);
+    virtual QString resolveAlias(const QString &name);
+    virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr);
+    virtual QList<QMimeType> allMimeTypes();
+
+    bool load(const QString &fileName, QString *errorMessage);
+
+    // Called by the mimetype xml parser
+    void addMimeType(const QMimeType &mt);
+    void addGlobPattern(const QMimeGlobPattern &glob);
+    void addParent(const QString &child, const QString &parent);
+    void addAlias(const QString &alias, const QString &name);
+    void addMagicMatcher(const QMimeMagicRuleMatcher &matcher);
+
+private:
+    void ensureLoaded();
+    void load(const QString &fileName);
+
+    bool m_loaded;
+
+    typedef QHash<QString, QMimeType> NameMimeTypeMap;
+    NameMimeTypeMap m_nameMimeTypeMap;
+
+    typedef QHash<QString, QString> AliasHash;
+    AliasHash m_aliases;
+
+    typedef QHash<QString, QStringList> ParentsHash;
+    ParentsHash m_parents;
+    QMimeAllGlobPatterns m_mimeTypeGlobs;
+
+    QList<QMimeMagicRuleMatcher> m_magicMatchers;
+    QStringList m_allFiles;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMIMEPROVIDER_P_H
diff --git lib/MimeHandler/NBMimeType.cpp lib/MimeHandler/NBMimeType.cpp
new file mode 100644
index 0000000..0b83d17
--- /dev/null
+++ lib/MimeHandler/NBMimeType.cpp
@@ -0,0 +1,537 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <NBMimeType.hpp>
+#include <NBMimeType_p.hpp>
+#include <NBMimeDatabase_p.hpp>
+#include <NBMimeProvider_p.hpp>
+#include <NBMimeGlobPattern_p.hpp>
+
+#include <QDebug>
+#include <QLocale>
+
+#include <memory>
+
+bool qt_isQMimeTypeDebuggingActivated(false);
+
+#ifndef QT_NO_DEBUG_OUTPUT
+#define DBG()    if (qt_isQMimeTypeDebuggingActivated) qDebug() << static_cast<const void *>(this) << Q_FUNC_INFO
+#else
+#define DBG()    if (0) qDebug() << static_cast<const void *>(this) << Q_FUNC_INFO
+#endif
+
+QMimeTypePrivate::QMimeTypePrivate()
+{
+}
+
+
+QMimeTypePrivate::QMimeTypePrivate(const QMimeType& other)
+	: name(other.d->name),
+	localeComments(other.d->localeComments),
+	genericIconName(other.d->genericIconName),
+	iconName(other.d->iconName),
+	globPatterns(other.d->globPatterns)
+{
+}
+
+
+void QMimeTypePrivate::clear()
+{
+	name.clear();
+	localeComments.clear();
+	genericIconName.clear();
+	iconName.clear();
+	globPatterns.clear();
+}
+
+
+/*!
+  * \fn bool QMimeTypePrivate::operator==(const QMimeTypePrivate &other) const;
+  * Returns true if \a other equals this QMimeTypePrivate object, otherwise returns false.
+  */
+bool QMimeTypePrivate::operator==(const QMimeTypePrivate& other) const
+{
+	DBG();
+	if ((name == other.name) &&
+		(localeComments == other.localeComments) &&
+		(genericIconName == other.genericIconName) &&
+		(iconName == other.iconName) &&
+		(globPatterns == other.globPatterns))
+	{
+		return true;
+	}
+
+	DBG() << name << other.name << (name == other.name);
+	//DBG() << comment << other.comment << (comment == other.comment);
+	DBG() << localeComments << other.localeComments << (localeComments == other.localeComments);
+	DBG() << genericIconName << other.genericIconName << (genericIconName == other.genericIconName);
+	DBG() << iconName << other.iconName << (iconName == other.iconName);
+	DBG() << globPatterns << other.globPatterns << (globPatterns == other.globPatterns);
+	return false;
+}
+
+
+void QMimeTypePrivate::addGlobPattern(const QString& pattern)
+{
+	globPatterns.append(pattern);
+}
+
+
+/*!
+  * \class QMimeType
+  * \brief The QMimeType class describes types of file or data, represented by a MIME type string.
+  *
+  * \since 5.0
+  *
+  * For instance a file named "readme.txt" has the MIME type "text/plain".
+  * The MIME type can be determined from the file name, or from the file
+  * contents, or from both. MIME type determination can also be done on
+  * buffers of data not coming from files.
+  *
+  * Determining the MIME type of a file can be useful to make sure your
+  * application supports it. It is also useful in file-manager-like applications
+  * or widgets, in order to display an appropriate icon() for the file, or even
+  * the descriptive comment() in detailed views.
+  *
+  * To check if a file has the expected MIME type, you should use inherits()
+  * rather than a simple string comparison based on the name(). This is because
+  * MIME types can inherit from each other: for instance a C source file is
+  * a specific type of plain text file, so text/x-csrc inherits text/plain.
+  *
+  * \sa QMimeDatabase
+  */
+
+/*!
+  * \fn QMimeType::QMimeType();
+  * Constructs this QMimeType object initialized with default property values that indicate an invalid MIME type.
+  */
+QMimeType::QMimeType() :
+	d(new QMimeTypePrivate())
+{
+	DBG() << "name():" << name();
+	//DBG() << "aliases():" << aliases();
+	//DBG() << "comment():" << comment();
+	DBG() << "genericIconName():" << genericIconName();
+	DBG() << "iconName():" << iconName();
+	DBG() << "globPatterns():" << globPatterns();
+	DBG() << "suffixes():" << suffixes();
+	DBG() << "preferredSuffix():" << preferredSuffix();
+}
+
+
+/*!
+  * \fn QMimeType::QMimeType(const QMimeType &other);
+  * Constructs this QMimeType object as a copy of \a other.
+  */
+QMimeType::QMimeType(const QMimeType& other) :
+	d(other.d)
+{
+	DBG() << "name():" << name();
+	//DBG() << "aliases():" << aliases();
+	//DBG() << "comment():" << comment();
+	DBG() << "genericIconName():" << genericIconName();
+	DBG() << "iconName():" << iconName();
+	DBG() << "globPatterns():" << globPatterns();
+	DBG() << "suffixes():" << suffixes();
+	DBG() << "preferredSuffix():" << preferredSuffix();
+}
+
+
+/*!
+  * \fn QMimeType &QMimeType::operator=(const QMimeType &other);
+  * Assigns the data of \a other to this QMimeType object, and returns a reference to this object.
+  */
+QMimeType& QMimeType::operator=(const QMimeType& other)
+{
+	if (d != other.d)
+	{
+		d = other.d;
+	}
+	return *this;
+}
+
+
+/*!
+  * \fn QMimeType::QMimeType(const QMimeTypePrivate &dd);
+  * Assigns the data of the QMimeTypePrivate \a dd to this QMimeType object, and returns a reference to this object.
+  */
+QMimeType::QMimeType(const QMimeTypePrivate& dd) :
+	d(new QMimeTypePrivate(dd))
+{
+	DBG() << "name():" << name();
+	//DBG() << "aliases():" << aliases();
+	//DBG() << "comment():" << comment();
+	DBG() << "genericIconName():" << genericIconName();
+	DBG() << "iconName():" << iconName();
+	DBG() << "globPatterns():" << globPatterns();
+	DBG() << "suffixes():" << suffixes();
+	DBG() << "preferredSuffix():" << preferredSuffix();
+}
+
+
+/*!
+  * \fn void QMimeType::swap(QMimeType &other);
+  * Swaps QMimeType \a other with this QMimeType object.
+  *
+  * This operation is very fast and never fails.
+  *
+  * The swap() method helps with the implementation of assignment
+  * operators in an exception-safe way. For more information consult
+  * \l {http://en.wikibooks.org/wiki/More_C++_Idioms/Copy-and-swap}
+  * {More C++ Idioms - Copy-and-swap}.
+  */
+
+/*!
+  * \fn QMimeType::~QMimeType();
+  * Destroys the QMimeType object, and releases the d pointer.
+  */
+QMimeType::~QMimeType()
+{
+	DBG() << "name():" << name();
+	//DBG() << "aliases():" << aliases();
+	//DBG() << "comment():" << comment();
+	DBG() << "genericIconName():" << genericIconName();
+	DBG() << "iconName():" << iconName();
+	DBG() << "globPatterns():" << globPatterns();
+	DBG() << "suffixes():" << suffixes();
+	DBG() << "preferredSuffix():" << preferredSuffix();
+}
+
+
+/*!
+  * \fn bool QMimeType::operator==(const QMimeType &other) const;
+  * Returns true if \a other equals this QMimeType object, otherwise returns false.
+  */
+bool QMimeType::operator==(const QMimeType& other) const
+{
+	return d == other.d || *d == *other.d;
+}
+
+
+/*!
+  * \fn bool QMimeType::operator!=(const QMimeType &other) const;
+  * Returns true if \a other does not equal this QMimeType object, otherwise returns false.
+  */
+
+/*!
+  * \fn bool QMimeType::isValid() const;
+  * Returns true if the QMimeType object contains valid data, otherwise returns false.
+  * A valid MIME type has a non-empty name().
+  * The invalid MIME type is the default-constructed QMimeType.
+  */
+bool QMimeType::isValid() const
+{
+	return !d->name.isEmpty();
+}
+
+
+/*!
+  * \fn bool QMimeType::isDefault() const;
+  * Returns true if this MIME type is the default MIME type which
+  * applies to all files: application/octet-stream.
+  */
+bool QMimeType::isDefault() const
+{
+	return d->name == QMimeDatabasePrivate::instance()->defaultMimeType();
+}
+
+
+/*!
+  * \fn QString QMimeType::name() const;
+  * Returns the name of the MIME type.
+  */
+QString QMimeType::name() const
+{
+	return d->name;
+}
+
+
+/*!
+  * Returns the description of the MIME type to be displayed on user interfaces.
+  *
+  * The system language (QLocale::system().name()) is used to select the appropriate translation.
+  */
+QString QMimeType::comment() const
+{
+	QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
+
+	QStringList languageList;
+
+	languageList << QLocale::system().name();
+	/*temporally workaround until i learn the code behind the qt 4.8 api for locales */
+#if QT_VERSION >= 0x040800
+	languageList << QLocale::system().uiLanguages();
+#endif
+	Q_FOREACH (const QString& language, languageList)
+	{
+		const QString lang = language == QLatin1String("C") ? QLatin1String("en_US") : language;
+		const QString comm = d->localeComments.value(lang);
+		if (!comm.isEmpty())
+		{
+			return comm;
+		}
+		const int pos = lang.indexOf(QLatin1Char('_'));
+		if (pos != -1)
+		{
+			// "pt_BR" not found? try just "pt"
+			const QString shortLang = lang.left(pos);
+			const QString commShort = d->localeComments.value(shortLang);
+			if (!commShort.isEmpty())
+			{
+				return commShort;
+			}
+		}
+	}
+
+	// Use the mimetype name as fallback
+	return d->name;
+}
+
+
+/*!
+  * \fn QString QMimeType::genericIconName() const;
+  * Returns the file name of a generic icon that represents the MIME type.
+  *
+  * This should be used if the icon returned by iconName() cannot be found on
+  * the system. It is used for categories of similar types (like spreadsheets
+  * or archives) that can use a common icon.
+  * The freedesktop.org Icon Naming Specification lists a set of such icon names.
+  *
+  * The icon name can be given to QIcon::fromTheme() in order to load the icon.
+  */
+QString QMimeType::genericIconName() const
+{
+	QMimeDatabasePrivate::instance()->provider()->loadGenericIcon(*d);
+	if (d->genericIconName.isEmpty())
+	{
+		// From the spec:
+		// If the generic icon name is empty (not specified by the mimetype definition)
+		// then the mimetype is used to generate the generic icon by using the top-level
+		// media type (e.g.  "video" in "video/ogg") and appending "-x-generic"
+		// (i.e. "video-x-generic" in the previous example).
+		QString   group      = name();
+		const int slashindex = group.indexOf(QLatin1Char('/'));
+		if (slashindex != -1)
+		{
+			group = group.left(slashindex);
+		}
+		return group + QLatin1String("-x-generic");
+	}
+	return d->genericIconName;
+}
+
+
+/*!
+  * \fn QString QMimeType::iconName() const;
+  * Returns the file name of an icon image that represents the MIME type.
+  *
+  * The icon name can be given to QIcon::fromTheme() in order to load the icon.
+  */
+QString QMimeType::iconName() const
+{
+	QMimeDatabasePrivate::instance()->provider()->loadIcon(*d);
+	if (d->iconName.isEmpty())
+	{
+		// Make default icon name from the mimetype name
+		d->iconName = name();
+		const int slashindex = d->iconName.indexOf(QLatin1Char('/'));
+		if (slashindex != -1)
+		{
+			d->iconName[slashindex] = QLatin1Char('-');
+		}
+	}
+	return d->iconName;
+}
+
+
+/*!
+  * \fn QStringList QMimeType::globPatterns() const;
+  * Returns the list of glob matching patterns.
+  */
+QStringList QMimeType::globPatterns() const
+{
+	QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
+	return d->globPatterns;
+}
+
+
+/*!
+  * A type is a subclass of another type if any instance of the first type is
+  * also an instance of the second. For example, all image/svg+xml files are also
+  * text/xml, text/plain and application/octet-stream files. Subclassing is about
+  * the format, rather than the category of the data (for example, there is no
+  * 'generic spreadsheet' class that all spreadsheets inherit from).
+  * Conversely, the parent mimetype of image/svg+xml is text/xml.
+  *
+  * A mimetype can have multiple parents. For instance application/x-perl
+  * has two parents: application/x-executable and text/plain. This makes
+  * it possible to both execute perl scripts, and to open them in text editors.
+  */
+QStringList QMimeType::parentMimeTypes() const
+{
+	return QMimeDatabasePrivate::instance()->provider()->parents(d->name);
+}
+
+
+static void collectParentMimeTypes(const QString& mime, QStringList& allParents)
+{
+	QStringList parents = QMimeDatabasePrivate::instance()->provider()->parents(mime);
+
+	foreach(const QString& parent, parents)
+	{
+		// I would use QSet, but since order matters I better not
+		if (!allParents.contains(parent))
+		{
+			allParents.append(parent);
+		}
+	}
+	// We want a breadth-first search, so that the least-specific parent (octet-stream) is last
+	// This means iterating twice, unfortunately.
+	foreach(const QString& parent, parents)
+	{
+		collectParentMimeTypes(parent, allParents);
+	}
+}
+
+
+/*!
+  * Return all the parent mimetypes of this mimetype, direct and indirect.
+  * This includes the parent(s) of its parent(s), etc.
+  *
+  * For instance, for image/svg+xml the list would be:
+  * application/xml, text/plain, application/octet-stream.
+  *
+  * Note that application/octet-stream is the ultimate parent for all types
+  * of files (but not directories).
+  */
+QStringList QMimeType::allAncestors() const
+{
+	QStringList allParents;
+
+	collectParentMimeTypes(d->name, allParents);
+	return allParents;
+}
+
+
+/*!
+  * \fn QStringList QMimeType::suffixes() const;
+  * Returns the known suffixes for the MIME type.
+  */
+QStringList QMimeType::suffixes() const
+{
+	QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
+
+	QStringList result;
+
+	foreach(const QString& pattern, d->globPatterns)
+	{
+		// Not a simple suffix if if looks like: README or *. or *.* or *.JP*G or *.JP?
+		if (pattern.startsWith(QLatin1String("*.")) &&
+			(pattern.length() > 2) &&
+			(pattern.indexOf(QLatin1Char('*'), 2) < 0) && (pattern.indexOf(QLatin1Char('?'), 2) < 0))
+		{
+			const QString suffix = pattern.mid(2);
+			result.append(suffix);
+		}
+	}
+
+	return result;
+}
+
+
+/*!
+  * \fn QString QMimeType::preferredSuffix() const;
+  * Returns the preferred suffix for the MIME type.
+  */
+QString QMimeType::preferredSuffix() const
+{
+	const QStringList suffixList = suffixes();
+
+	return suffixList.isEmpty() ? QString() : suffixList.at(0);
+}
+
+
+/*!
+  * \fn QString QMimeType::filterString() const;
+  * Returns a filter string usable for a file dialog.
+  */
+QString QMimeType::filterString() const
+{
+	QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
+	QString filter;
+
+	if (!d->globPatterns.empty())
+	{
+		filter += comment() + QLatin1String(" (");
+		for (int i = 0; i < d->globPatterns.size(); ++i)
+		{
+			if (i != 0)
+			{
+				filter += QLatin1Char(' ');
+			}
+			filter += d->globPatterns.at(i);
+		}
+		filter += QLatin1Char(')');
+	}
+
+	return filter;
+}
+
+
+/*!
+  * \fn bool QMimeType::inherits(const QString &mimeTypeName) const;
+  * Returns true if this mimetype is \a mimeTypeName,
+  * or inherits \a mimeTypeName (see parentMimeTypes()),
+  * or \a mimeTypeName is an alias for this mimetype.
+  */
+bool QMimeType::inherits(const QString& mimeTypeName) const
+{
+	if (d->name == mimeTypeName)
+	{
+		return true;
+	}
+	return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName);
+}
+
+
+#undef DBG
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeType.hpp lib/MimeHandler/NBMimeType.hpp
new file mode 100644
index 0000000..11f655a
--- /dev/null
+++ lib/MimeHandler/NBMimeType.hpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+#ifndef NBMIMETYPE_HPP
+#define NBMIMETYPE_HPP
+
+#include <QSharedData>
+#include <QString>
+
+class QMimeTypePrivate;
+class QFileinfo;
+class QStringList;
+
+class QMimeType
+{
+public:
+    QMimeType();
+    QMimeType(const QMimeType &other);
+    QMimeType &operator=(const QMimeType &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+    QMimeType &operator=(QMimeType &&other)
+    {
+        qSwap(d, other.d);
+        return *this;
+    }
+#endif
+    void swap(QMimeType &other)
+    {
+        qSwap(d, other.d);
+    }
+    explicit QMimeType(const QMimeTypePrivate &dd);
+    ~QMimeType();
+
+    bool operator==(const QMimeType &other) const;
+
+    inline bool operator!=(const QMimeType &other) const
+    {
+        return !operator==(other);
+    }
+
+    bool isValid() const;
+
+    bool isDefault() const;
+
+    QString name() const;
+    QString comment() const;
+    QString genericIconName() const;
+    QString iconName() const;
+    QStringList globPatterns() const;
+    QStringList parentMimeTypes() const;
+    QStringList allAncestors() const;
+    QStringList suffixes() const;
+    QString preferredSuffix() const;
+
+    bool inherits(const QString &mimeTypeName) const;
+
+    QString filterString() const;
+
+protected:
+    friend class QMimeTypeParserBase;
+    friend class MimeTypeMapEntry;
+    friend class QMimeDatabasePrivate;
+    friend class QMimeXMLProvider;
+    friend class QMimeBinaryProvider;
+    friend class QMimeTypePrivate;
+
+    QExplicitlySharedDataPointer<QMimeTypePrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif   // QMIMETYPE_H
diff --git lib/MimeHandler/NBMimeTypeParser.cpp lib/MimeHandler/NBMimeTypeParser.cpp
new file mode 100644
index 0000000..18ef32f
--- /dev/null
+++ lib/MimeHandler/NBMimeTypeParser.cpp
@@ -0,0 +1,433 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the QtCore module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#define QT_NO_CAST_FROM_ASCII
+
+#include <NBMimeTypeParser_p.hpp>
+#include <NBMimeType_p.hpp>
+#include <NBMimeMagicRuleMatcher_p.hpp>
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QDir>
+#include <QPair>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+#include <QStack>
+
+// XML tags in MIME files
+static const char mimeInfoTagC[]            = "mime-info";
+static const char mimeTypeTagC[]            = "mime-type";
+static const char mimeTypeAttributeC[]      = "type";
+static const char subClassTagC[]            = "sub-class-of";
+static const char commentTagC[]             = "comment";
+static const char genericIconTagC[]         = "generic-icon";
+static const char iconTagC[]                = "icon";
+static const char nameAttributeC[]          = "name";
+static const char globTagC[]                = "glob";
+static const char aliasTagC[]               = "alias";
+static const char patternAttributeC[]       = "pattern";
+static const char weightAttributeC[]        = "weight";
+static const char caseSensitiveAttributeC[] = "case-sensitive";
+static const char localeAttributeC[]        = "xml:lang";
+
+static const char magicTagC[]          = "magic";
+static const char priorityAttributeC[] = "priority";
+
+static const char matchTagC[]             = "match";
+static const char matchValueAttributeC[]  = "value";
+static const char matchTypeAttributeC[]   = "type";
+static const char matchOffsetAttributeC[] = "offset";
+static const char matchMaskAttributeC[]   = "mask";
+
+/*!
+  * \class QMimeTypeParser
+  * \internal
+  * \brief The QMimeTypeParser class parses MIME types, and builds a MIME database hierarchy by adding to QMimeDatabasePrivate.
+  *
+  * Populates QMimeDataBase
+  *
+  * \sa QMimeDatabase, QMimeMagicRuleMatcher, MagicRule, MagicStringRule, MagicByteRule, GlobPattern
+  * \sa QMimeTypeParser
+  */
+
+/*!
+  * \class QMimeTypeParserBase
+  * \internal
+  * \brief The QMimeTypeParserBase class parses for a sequence of <mime-type> in a generic way.
+  *
+  * Calls abstract handler function process for QMimeType it finds.
+  *
+  * \sa QMimeDatabase, QMimeMagicRuleMatcher, MagicRule, MagicStringRule, MagicByteRule, GlobPattern
+  * \sa QMimeTypeParser
+  */
+
+/*!
+  * \fn virtual bool QMimeTypeParserBase::process(const QMimeType &t, QString *errorMessage) = 0;
+  * Overwrite to process the sequence of parsed data
+  */
+QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState currentState, const QStringRef& startElement)
+{
+	switch (currentState)
+	{
+	case ParseBeginning:
+		if (startElement == QLatin1String(mimeInfoTagC))
+		{
+			return ParseMimeInfo;
+		}
+		if (startElement == QLatin1String(mimeTypeTagC))
+		{
+			return ParseMimeType;
+		}
+		return ParseError;
+
+	case ParseMimeInfo:
+		return startElement == QLatin1String(mimeTypeTagC) ? ParseMimeType : ParseError;
+
+	case ParseMimeType:
+	case ParseComment:
+	case ParseGenericIcon:
+	case ParseIcon:
+	case ParseGlobPattern:
+	case ParseSubClass:
+	case ParseAlias:
+	case ParseOtherMimeTypeSubTag:
+	case ParseMagicMatchRule:
+		if (startElement == QLatin1String(mimeTypeTagC)) // Sequence of <mime-type>
+		{
+			return ParseMimeType;
+		}
+		if (startElement == QLatin1String(commentTagC))
+		{
+			return ParseComment;
+		}
+		if (startElement == QLatin1String(genericIconTagC))
+		{
+			return ParseGenericIcon;
+		}
+		if (startElement == QLatin1String(iconTagC))
+		{
+			return ParseIcon;
+		}
+		if (startElement == QLatin1String(globTagC))
+		{
+			return ParseGlobPattern;
+		}
+		if (startElement == QLatin1String(subClassTagC))
+		{
+			return ParseSubClass;
+		}
+		if (startElement == QLatin1String(aliasTagC))
+		{
+			return ParseAlias;
+		}
+		if (startElement == QLatin1String(magicTagC))
+		{
+			return ParseMagic;
+		}
+		if (startElement == QLatin1String(matchTagC))
+		{
+			return ParseMagicMatchRule;
+		}
+		return ParseOtherMimeTypeSubTag;
+
+	case ParseMagic:
+		if (startElement == QLatin1String(matchTagC))
+		{
+			return ParseMagicMatchRule;
+		}
+		break;
+
+	case ParseError:
+		break;
+	}
+	return ParseError;
+}
+
+
+// Parse int number from an (attribute) string)
+static bool parseNumber(const QString& n, int *target, QString *errorMessage)
+{
+	bool ok;
+
+	*target = n.toInt(&ok);
+	if (!ok)
+	{
+		*errorMessage = QString::fromLatin1("Not a number '%1'.").arg(n);
+		return false;
+	}
+	return true;
+}
+
+
+// Evaluate a magic match rule like
+//  <match value="must be converted with BinHex" type="string" offset="11"/>
+//  <match value="0x9501" type="big16" offset="0:64"/>
+static bool createMagicMatchRule(const QXmlStreamAttributes& atts,
+								 QString *errorMessage, QMimeMagicRule *& rule)
+{
+	const QString        type      = atts.value(QLatin1String(matchTypeAttributeC)).toString();
+	QMimeMagicRule::Type magicType = QMimeMagicRule::type(type.toLatin1());
+
+	if (magicType == QMimeMagicRule::Invalid)
+	{
+		qWarning("%s: match type %s is not supported.", Q_FUNC_INFO, type.toUtf8().constData());
+		return true;
+	}
+	const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString();
+
+	if (value.isEmpty())
+	{
+		*errorMessage = QString::fromLatin1("Empty match value detected.");
+		return false;
+	}
+	// Parse for offset as "1" or "1:10"
+	int           startPos, endPos;
+	const QString offsetS    = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
+	const int     colonIndex = offsetS.indexOf(QLatin1Char(':'));
+	const QString startPosS  = colonIndex == -1 ? offsetS : offsetS.mid(0, colonIndex);
+	const QString endPosS    = colonIndex == -1 ? offsetS : offsetS.mid(colonIndex + 1);
+
+	if (!parseNumber(startPosS, &startPos, errorMessage) || !parseNumber(endPosS, &endPos, errorMessage))
+	{
+		return false;
+	}
+	const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString();
+
+	rule = new QMimeMagicRule(magicType, value.toUtf8(), startPos, endPos, mask.toLatin1());
+
+	return true;
+}
+
+
+bool QMimeTypeParserBase::parse(QIODevice *dev, const QString& fileName, QString *errorMessage)
+{
+	QMimeTypePrivate         data;
+	int                      priority = 50;
+	QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules
+	QList<QMimeMagicRule>    rules;        // toplevel rules
+	QXmlStreamReader         reader(dev);
+	ParseState               ps = ParseBeginning;
+	QXmlStreamAttributes     atts;
+
+	while (!reader.atEnd())
+	{
+		switch (reader.readNext())
+		{
+		case QXmlStreamReader::StartElement:
+			ps   = nextState(ps, reader.name());
+			atts = reader.attributes();
+			switch (ps)
+			{
+			case ParseMimeType:
+			   {                  // start parsing a MIME type name
+				   const QString name = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+				   if (name.isEmpty())
+				   {
+					   reader.raiseError(QString::fromLatin1("Missing '%1'-attribute").arg(QString::fromLatin1(mimeTypeAttributeC)));
+				   }
+				   else
+				   {
+					   data.name = name;
+				   }
+			   }
+			   break;
+
+			case ParseGenericIcon:
+				data.genericIconName = atts.value(QLatin1String(nameAttributeC)).toString();
+				break;
+
+			case ParseIcon:
+				data.iconName = atts.value(QLatin1String(nameAttributeC)).toString();
+				break;
+
+			case ParseGlobPattern:
+			   {
+				   const QString pattern       = atts.value(QLatin1String(patternAttributeC)).toString();
+				   unsigned      weight        = atts.value(QLatin1String(weightAttributeC)).toString().toInt();
+				   const bool    caseSensitive = atts.value(QLatin1String(caseSensitiveAttributeC)).toString() == QLatin1String("true");
+
+				   if (weight == 0)
+				   {
+					   weight = QMimeGlobPattern::DefaultWeight;
+				   }
+
+				   Q_ASSERT(!data.name.isEmpty());
+				   const QMimeGlobPattern glob(pattern, data.name, weight, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
+				   if (!process(glob, errorMessage)) // for actual glob matching
+				   {
+					   return false;
+				   }
+				   data.addGlobPattern(pattern); // just for QMimeType::globPatterns()
+			   }
+			   break;
+
+			case ParseSubClass:
+			   {
+				   const QString inheritsFrom = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+				   if (!inheritsFrom.isEmpty())
+				   {
+					   processParent(data.name, inheritsFrom);
+				   }
+			   }
+			   break;
+
+			case ParseComment:
+			   {
+				   // comments have locale attributes. We want the default, English one
+				   QString       locale  = atts.value(QLatin1String(localeAttributeC)).toString();
+				   const QString comment = reader.readElementText();
+				   if (locale.isEmpty())
+				   {
+					   locale = QString::fromLatin1("en_US");
+				   }
+				   data.localeComments.insert(locale, comment);
+			   }
+			   break;
+
+			case ParseAlias:
+			   {
+				   const QString alias = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
+				   if (!alias.isEmpty())
+				   {
+					   processAlias(alias, data.name);
+				   }
+			   }
+			   break;
+
+			case ParseMagic:
+			   {
+				   priority = 50;
+				   const QString priorityS = atts.value(QLatin1String(priorityAttributeC)).toString();
+				   if (!priorityS.isEmpty())
+				   {
+					   if (!parseNumber(priorityS, &priority, errorMessage))
+					   {
+						   return false;
+					   }
+				   }
+				   currentRules.clear();
+				   //qDebug() << "MAGIC start for mimetype" << data.name;
+			   }
+			   break;
+
+			case ParseMagicMatchRule:
+			   {
+				   QMimeMagicRule *rule = 0;
+				   if (!createMagicMatchRule(atts, errorMessage, rule))
+				   {
+					   return false;
+				   }
+				   QList<QMimeMagicRule> *ruleList;
+				   if (currentRules.isEmpty())
+				   {
+					   ruleList = &rules;
+				   }
+				   else // nest this rule into the proper parent
+				   {
+					   ruleList = &currentRules.top()->m_subMatches;
+				   }
+				   ruleList->append(*rule);
+				   //qDebug() << " MATCH added. Stack size was" << currentRules.size();
+				   currentRules.push(&ruleList->last());
+				   delete rule;
+				   break;
+			   }
+
+			case ParseError:
+				reader.raiseError(QString::fromLatin1("Unexpected element <%1>").
+									 arg(reader.name().toString()));
+				break;
+
+			default:
+				break;
+			}
+			break;
+
+		// continue switch QXmlStreamReader::Token...
+		case QXmlStreamReader::EndElement: // Finished element
+		   {
+			   const QStringRef elementName = reader.name();
+			   if (elementName == QLatin1String(mimeTypeTagC))
+			   {
+				   if (!process(QMimeType(data), errorMessage))
+				   {
+					   return false;
+				   }
+				   data.clear();
+			   }
+			   else if (elementName == QLatin1String(matchTagC))
+			   {
+				   // Closing a <match> tag, pop stack
+				   currentRules.pop();
+				   //qDebug() << " MATCH closed. Stack size is now" << currentRules.size();
+			   }
+			   else if (elementName == QLatin1String(magicTagC))
+			   {
+				   //qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority;
+				   // Finished a <magic> sequence
+				   QMimeMagicRuleMatcher ruleMatcher(data.name, priority);
+				   ruleMatcher.addRules(rules);
+				   processMagicMatcher(ruleMatcher);
+				   rules.clear();
+			   }
+			   break;
+		   }
+
+		default:
+			break;
+		}
+	}
+
+	if (reader.hasError())
+	{
+		if (errorMessage)
+		{
+			*errorMessage = QString::fromLatin1("An error has been encountered at line %1 of %2: %3:").arg(reader.lineNumber()).arg(fileName, reader.errorString());
+		}
+		return false;
+	}
+
+	return true;
+}
+
+
+QT_END_NAMESPACE
diff --git lib/MimeHandler/NBMimeTypeParser_p.hpp lib/MimeHandler/NBMimeTypeParser_p.hpp
new file mode 100644
index 0000000..e4ad366
--- /dev/null
+++ lib/MimeHandler/NBMimeTypeParser_p.hpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef MIMETYPEPARSER_P_H
+#define MIMETYPEPARSER_P_H
+
+#include <NBMimeDatabase_p.hpp>
+#include <NBMimeProvider_p.hpp>
+
+class QIODevice;
+
+class QMimeTypeParserBase
+{
+    Q_DISABLE_COPY(QMimeTypeParserBase)
+
+public:
+    QMimeTypeParserBase() {}
+    virtual ~QMimeTypeParserBase() {}
+
+    bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage);
+
+protected:
+    virtual bool process(const QMimeType &t, QString *errorMessage) = 0;
+    virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;
+    virtual void processParent(const QString &child, const QString &parent) = 0;
+    virtual void processAlias(const QString &alias, const QString &name) = 0;
+    virtual void processMagicMatcher(const QMimeMagicRuleMatcher &matcher) = 0;
+
+private:
+    enum ParseState {
+        ParseBeginning,
+        ParseMimeInfo,
+        ParseMimeType,
+        ParseComment,
+        ParseGenericIcon,
+        ParseIcon,
+        ParseGlobPattern,
+        ParseSubClass,
+        ParseAlias,
+        ParseMagic,
+        ParseMagicMatchRule,
+        ParseOtherMimeTypeSubTag,
+        ParseError
+    };
+
+    static ParseState nextState(ParseState currentState, const QStringRef &startElement);
+};
+
+
+class QMimeTypeParser : public QMimeTypeParserBase
+{
+public:
+    explicit QMimeTypeParser(QMimeXMLProvider &provider) : m_provider(provider) {}
+
+protected:
+    inline bool process(const QMimeType &t, QString *)
+    { m_provider.addMimeType(t); return true; }
+
+    inline bool process(const QMimeGlobPattern &glob, QString *)
+    { m_provider.addGlobPattern(glob); return true; }
+
+    inline void processParent(const QString &child, const QString &parent)
+    { m_provider.addParent(child, parent); }
+
+    inline void processAlias(const QString &alias, const QString &name)
+    { m_provider.addAlias(alias, name); }
+
+    inline void processMagicMatcher(const QMimeMagicRuleMatcher &matcher)
+    { m_provider.addMagicMatcher(matcher); }
+
+private:
+    QMimeXMLProvider &m_provider;
+};
+
+QT_END_NAMESPACE
+
+#endif // MIMETYPEPARSER_P_H
diff --git lib/MimeHandler/NBMimeType_p.hpp lib/MimeHandler/NBMimeType_p.hpp
new file mode 100644
index 0000000..6f45530
--- /dev/null
+++ lib/MimeHandler/NBMimeType_p.hpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMIMETYPE_P_H
+#define QMIMETYPE_P_H
+
+#include <NBMimeType.hpp>
+
+#include <QHash>
+#include <QStringList>
+
+class Q_AUTOTEST_EXPORT QMimeTypePrivate : public QSharedData
+{
+public:
+    typedef QHash<QString, QString> LocaleHash;
+
+    QMimeTypePrivate();
+    explicit QMimeTypePrivate(const QMimeType &other);
+
+    void clear();
+
+    bool operator==(const QMimeTypePrivate &other) const;
+
+    void addGlobPattern(const QString &pattern);
+
+    QString name;
+    LocaleHash localeComments;
+    QString genericIconName;
+    QString iconName;
+    QStringList globPatterns;
+};
+
+QT_END_NAMESPACE
+
+#define QMIMETYPE_BUILDER \
+    QT_BEGIN_NAMESPACE \
+    static QMimeType buildQMimeType ( \
+                         const QString &name, \
+                         const QString &genericIconName, \
+                         const QString &iconName, \
+                         const QStringList &globPatterns \
+                     ) \
+    { \
+        QMimeTypePrivate qMimeTypeData; \
+        qMimeTypeData.name = name; \
+        qMimeTypeData.genericIconName = genericIconName; \
+        qMimeTypeData.iconName = iconName; \
+        qMimeTypeData.globPatterns = globPatterns; \
+        return QMimeType(qMimeTypeData); \
+    } \
+    QT_END_NAMESPACE
+
+#ifdef Q_COMPILER_RVALUE_REFS
+#define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \
+    QT_BEGIN_NAMESPACE \
+    static QMimeType buildQMimeType ( \
+                         QString &&name, \
+                         QString &&genericIconName, \
+                         QString &&iconName, \
+                         QStringList &&globPatterns \
+                     ) \
+    { \
+        QMimeTypePrivate qMimeTypeData; \
+        qMimeTypeData.name = std::move(name); \
+        qMimeTypeData.genericIconName = std::move(genericIconName); \
+        qMimeTypeData.iconName = std::move(iconName); \
+        qMimeTypeData.globPatterns = std::move(globPatterns); \
+        return QMimeType(qMimeTypeData); \
+    } \
+    QT_END_NAMESPACE
+#endif
+
+#endif   // QMIMETYPE_P_H
diff --git lib/StandardPaths/NBStandardPaths.cpp lib/StandardPaths/NBStandardPaths.cpp
new file mode 100644
index 0000000..c26cd3b
--- /dev/null
+++ lib/StandardPaths/NBStandardPaths.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <NBStandardPaths.hpp>
+
+#include <QDir>
+#include <QFileInfo>
+#include <QHash>
+#include <QObject>
+#include <QCoreApplication>
+
+#ifndef QT_NO_STANDARDPATHS
+
+/*!
+  * \class QStandardPaths
+  * \brief The QStandardPaths class provides methods for accessing standard paths.
+  * \since 5.0
+  *
+  * This class contains functions to query standard locations on the local
+  * filesystem, for common tasks such as user-specific directories or system-wide
+  * configuration directories.
+  */
+
+/*!
+  * \enum QStandardPaths::StandardLocation
+  *
+  * This enum describes the different locations that can be queried using
+  * methods such as QStandardPaths::writableLocation, QStandardPaths::standardLocations,
+  * and QStandardPaths::displayName.
+  *
+  * \value DesktopLocation Returns the user's desktop directory.
+  * \value DocumentsLocation Returns the user's document.
+  * \value FontsLocation Returns the user's fonts.
+  * \value ApplicationsLocation Returns the user's applications.
+  * \value MusicLocation Returns the users music.
+  * \value MoviesLocation Returns the user's movies.
+  * \value PicturesLocation Returns the user's pictures.
+  * \value TempLocation Returns the system's temporary directory.
+  * \value HomeLocation Returns the user's home directory.
+  * \value DataLocation Returns a directory location where persistent
+  *        application data can be stored. QCoreApplication::organizationName
+  *        and QCoreApplication::applicationName are appended to the directory location
+  *        returned for GenericDataLocation.
+  * \value CacheLocation Returns a directory location where user-specific
+  *        non-essential (cached) data should be written.
+  * \value GenericDataLocation Returns a directory location where persistent
+  *        data shared across applications can be stored.
+  * \value RuntimeLocation Returns a directory location where runtime communication
+  *        files should be written. For instance unix local sockets.
+  * \value ConfigLocation Returns a directory location where user-specific
+  *        configuration files should be written.
+  *
+  *
+  * \sa writableLocation(), standardLocations(), displayName(), locate(), locateAll()
+  */
+
+/*!
+  * \fn QString QStandardPaths::writableLocation(StandardLocation type)
+  *
+  * Returns the directory where files of \a type should be written to, or an empty string
+  * if the location cannot be determined.
+  *
+  * \note The storage location returned can be a directory that does not exist; i.e., it
+  * may need to be created by the system or the user.
+  *
+  * \note On Symbian OS, ApplicationsLocation always point /sys/bin folder on the same drive
+  * with executable. FontsLocation always points to folder on ROM drive. Symbian OS does not
+  * have desktop concept, DesktopLocation returns same path as DocumentsLocation.
+  * Rest of the standard locations point to folder on same drive with executable, except
+  * that if executable is in ROM the folder from C drive is returned.
+  */
+
+
+/*!
+  * \fn QStringList QStandardPaths::standardLocations(StandardLocation type)
+  *
+  * Returns all the directories where files of \a type belong.
+  *
+  * Much like the PATH variable, it returns the directories in order of priority,
+  * starting with the user-specific writableLocation() for the \a type.
+  */
+
+/*!
+  * \enum QStandardPaths::LocateOption
+  *
+  * This enum describes the different flags that can be used for
+  * controlling the behavior of QStandardPaths::locate and
+  * QStandardPaths::locateAll.
+  *
+  * \value LocateFile return only files
+  * \value LocateDirectory return only directories
+  */
+static bool existsAsSpecified(const QString& path, QStandardPaths::LocateOptions options)
+{
+	if (options & QStandardPaths::LocateDirectory)
+	{
+		return QDir(path).exists();
+	}
+	return QFileInfo(path).isFile();
+}
+
+
+/*!
+  * Tries to find a file or directory called \a fileName in the standard locations
+  * for \a type.
+  *
+  * The full path to the first file or directory (depending on \a options) found is returned.
+  * If no such file or directory can be found, an empty string is returned.
+  */
+QString QStandardPaths::locate(StandardLocation type, const QString& fileName, LocateOptions options)
+{
+	const QStringList dirs = standardLocations(type);
+
+	for (QStringList::const_iterator dir = dirs.constBegin(); dir != dirs.constEnd(); ++dir)
+	{
+		const QString path = *dir + QLatin1Char('/') + fileName;
+		if (existsAsSpecified(path, options))
+		{
+			return path;
+		}
+	}
+	return QString();
+}
+
+
+/*!
+  * Tries to find all files or directories called \a fileName in the standard locations
+  * for \a type.
+  *
+  * The \a options flag allows to specify whether to look for files or directories.
+  *
+  * Returns the list of all the files that were found.
+  */
+QStringList QStandardPaths::locateAll(StandardLocation type, const QString& fileName, LocateOptions options)
+{
+	const QStringList dirs = standardLocations(type);
+	QStringList       result;
+
+	for (QStringList::const_iterator dir = dirs.constBegin(); dir != dirs.constEnd(); ++dir)
+	{
+		const QString path = *dir + QLatin1Char('/') + fileName;
+		if (existsAsSpecified(path, options))
+		{
+			result.append(path);
+		}
+	}
+	return result;
+}
+
+
+#ifdef Q_OS_WIN
+static QStringList executableExtensions()
+{
+	QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
+
+	if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive))
+	{
+		// If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
+		ret.clear();
+		ret << QLatin1String(".exe")
+			<< QLatin1String(".com")
+			<< QLatin1String(".bat")
+			<< QLatin1String(".cmd");
+	}
+	return ret;
+}
+
+
+#endif
+
+static QString checkExecutable(const QString& path)
+{
+	const QFileInfo info(path);
+
+	if (info.isBundle())
+	{
+		return info.bundleName();
+	}
+	if (info.isFile() && info.isExecutable())
+	{
+		return QDir::cleanPath(path);
+	}
+	return QString();
+}
+
+
+/*!
+  * Finds the executable named \a executableName in the paths specified by \a paths,
+  * or the system paths if \a paths is empty.
+  *
+  * On most operating systems the system path is determined by the PATH environment variable.
+  *
+  * The directories where to search for the executable can be set in the \a paths argument.
+  * To search in both your own paths and the system paths, call findExecutable twice, once with
+  * \a paths set and once with \a paths empty.
+  *
+  * Symlinks are not resolved, in order to preserve behavior for the case of executables
+  * whose behavior depends on the name they are invoked with.
+  *
+  * \note On Windows, the usual executable extensions (from the PATHEXT environment variable)
+  * are automatically appended, so that for instance findExecutable("foo") will find foo.exe
+  * or foo.bat if present.
+  *
+  * Returns the absolute file path to the executable, or an empty string if not found.
+  */
+QString QStandardPaths::findExecutable(const QString& executableName, const QStringList& paths)
+{
+	QStringList searchPaths = paths;
+
+	if (paths.isEmpty())
+	{
+		QByteArray pEnv = qgetenv("PATH");
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+		const QLatin1Char pathSep(';');
+#else
+		const QLatin1Char pathSep(':');
+#endif
+		searchPaths = QString::fromLocal8Bit(pEnv.constData()).split(pathSep, QString::SkipEmptyParts);
+	}
+
+	if (QFileInfo(executableName).isAbsolute())
+	{
+		return checkExecutable(executableName);
+	}
+
+	QDir    currentDir = QDir::current();
+	QString absPath;
+#ifdef Q_OS_WIN
+	static QStringList executable_extensions = executableExtensions();
+#endif
+
+	for (QStringList::const_iterator p = searchPaths.constBegin(); p != searchPaths.constEnd(); ++p)
+	{
+		const QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + executableName);
+#ifdef Q_OS_WIN
+		const QString extension = QLatin1Char('.') + QFileInfo(executableName).suffix();
+		if (!executable_extensions.contains(extension, Qt::CaseInsensitive))
+		{
+			foreach(const QString& extension, executable_extensions)
+			{
+				absPath = checkExecutable(candidate + extension.toLower());
+				if (!absPath.isEmpty())
+				{
+					break;
+				}
+			}
+		}
+#endif
+		absPath = checkExecutable(candidate);
+		if (!absPath.isEmpty())
+		{
+			break;
+		}
+	}
+	return absPath;
+}
+
+
+/*!
+  * \fn QString QStandardPaths::displayName(StandardLocation type)
+  *
+  * Returns a localized display name for the given location \a type or
+  * an empty QString if no relevant location can be found.
+  */
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STANDARDPATHS
diff --git lib/StandardPaths/NBStandardPaths.hpp lib/StandardPaths/NBStandardPaths.hpp
new file mode 100644
index 0000000..efff304
--- /dev/null
+++ lib/StandardPaths/NBStandardPaths.hpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTANDARDPATHS_H
+#define QSTANDARDPATHS_H
+
+#include <QStringList>
+QT_BEGIN_HEADER
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STANDARDPATHS
+
+class QStringList;
+
+class QStandardPaths
+{
+public:
+    // Do not re-order, must match QDesktopServices
+    enum StandardLocation {
+        DesktopLocation,
+        DocumentsLocation,
+        FontsLocation,
+        ApplicationsLocation,
+        MusicLocation,
+        MoviesLocation,
+        PicturesLocation,
+        TempLocation,
+        HomeLocation,
+        DataLocation,
+        CacheLocation,
+        GenericDataLocation,
+        RuntimeLocation,
+        ConfigLocation
+    };
+
+    static QString writableLocation(StandardLocation type);
+    static QStringList standardLocations(StandardLocation type);
+
+    enum LocateOption {
+        LocateFile = 0x0,
+        LocateDirectory = 0x1
+    };
+    Q_DECLARE_FLAGS(LocateOptions, LocateOption)
+
+    static QString locate(StandardLocation type, const QString &fileName, LocateOptions options = LocateFile);
+    static QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options = LocateFile);
+    static QString displayName(StandardLocation type);
+
+    static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList());
+
+private:
+    // prevent construction
+    QStandardPaths();
+    ~QStandardPaths();
+};
+
+#endif // QT_NO_STANDARDPATHS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTANDARDPATHS_H
diff --git lib/StandardPaths/NBStandardPaths_unix.cpp lib/StandardPaths/NBStandardPaths_unix.cpp
new file mode 100644
index 0000000..2a7c1cf
--- /dev/null
+++ lib/StandardPaths/NBStandardPaths_unix.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the QtGui module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include <NBStandardPaths.hpp>
+#include <QProcess>
+#include <QUrl>
+#include <QDir>
+#include <QFile>
+#include <QTextStream>
+#include <QCoreApplication>
+#if QT_VERSION <= QT_VERSION_CHECK(4, 7, 0)  // i do not sure but for qt 4.7 and 4.6 we need this include
+#include <QHash>
+#endif
+// LOCAL HACK #include <private/qfilesystemengine_p.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifndef QT_NO_STANDARDPATHS
+
+QString QStandardPaths::writableLocation(StandardLocation type)
+{
+	switch (type)
+	{
+	case HomeLocation:
+		return QDir::homePath();
+
+	case TempLocation:
+		return QDir::tempPath();
+
+	case CacheLocation:
+	   {
+		   // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
+		   QString xdgCacheHome = QLatin1String(qgetenv("XDG_CACHE_HOME"));
+		   if (xdgCacheHome.isEmpty())
+		   {
+			   xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
+		   }
+		   if (!QCoreApplication::organizationName().isEmpty())
+		   {
+			   xdgCacheHome += QLatin1Char('/') + QCoreApplication::organizationName();
+		   }
+		   if (!QCoreApplication::applicationName().isEmpty())
+		   {
+			   xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
+		   }
+		   return xdgCacheHome;
+	   }
+
+	case DataLocation:
+	case GenericDataLocation:
+	   {
+		   QString xdgDataHome = QLatin1String(qgetenv("XDG_DATA_HOME"));
+		   if (xdgDataHome.isEmpty())
+		   {
+			   xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
+		   }
+		   if (type == QStandardPaths::DataLocation)
+		   {
+			   if (!QCoreApplication::organizationName().isEmpty())
+			   {
+				   xdgDataHome += QLatin1Char('/') + QCoreApplication::organizationName();
+			   }
+			   if (!QCoreApplication::applicationName().isEmpty())
+			   {
+				   xdgDataHome += QLatin1Char('/') + QCoreApplication::applicationName();
+			   }
+		   }
+		   return xdgDataHome;
+	   }
+
+	case ConfigLocation:
+	   {
+		   // http://standards.freedesktop.org/basedir-spec/latest/
+		   QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
+		   if (xdgConfigHome.isEmpty())
+		   {
+			   xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
+		   }
+		   return xdgConfigHome;
+	   }
+
+	case RuntimeLocation:
+	   {
+		   const uid_t myUid = geteuid();
+		   // http://standards.freedesktop.org/basedir-spec/latest/
+		   QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
+		   if (xdgRuntimeDir.isEmpty())
+		   {
+			   const QString userName = QString(); // LOCAL HACK QFileSystemEngine::resolveUserName(myUid);
+			   xdgRuntimeDir = QDir::tempPath() + QLatin1String("/runtime-") + userName;
+			   QDir dir(xdgRuntimeDir);
+			   if (!dir.exists())
+			   {
+				   if (!QDir().mkdir(xdgRuntimeDir))
+				   {
+					   qWarning("QStandardPaths: error creating runtime directory %s: %s", qPrintable(xdgRuntimeDir), qPrintable(qt_error_string(errno)));
+					   return QString();
+				   }
+			   }
+		   }
+		   // "The directory MUST be owned by the user"
+		   QFileInfo fileInfo(xdgRuntimeDir);
+		   if (fileInfo.ownerId() != myUid)
+		   {
+			   qWarning("QStandardPaths: wrong ownership on runtime directory %s, %d instead of %d", qPrintable(xdgRuntimeDir),
+						fileInfo.ownerId(), myUid);
+			   return QString();
+		   }
+		   // "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700."
+		   QFile file(xdgRuntimeDir);
+		   const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser;
+		   if ((file.permissions() != wantedPerms) && !file.setPermissions(wantedPerms))
+		   {
+			   qWarning("QStandardPaths: wrong permissions on runtime directory %s", qPrintable(xdgRuntimeDir));
+			   return QString();
+		   }
+		   return xdgRuntimeDir;
+	   }
+
+	default:
+		break;
+	}
+
+	// http://www.freedesktop.org/wiki/Software/xdg-user-dirs
+	QString xdgConfigHome = QLatin1String(qgetenv("XDG_CONFIG_HOME"));
+
+	if (xdgConfigHome.isEmpty())
+	{
+		xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
+	}
+	QFile file(xdgConfigHome + QLatin1String("/user-dirs.dirs"));
+
+	if (file.exists() && file.open(QIODevice::ReadOnly))
+	{
+		QHash<QString, QString> lines;
+		QTextStream             stream(&file);
+		// Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop"
+		QRegExp exp(QLatin1String("^XDG_(.*)_DIR=(.*)$"));
+		while (!stream.atEnd())
+		{
+			const QString line = stream.readLine();
+			if (exp.indexIn(line) != -1)
+			{
+				QStringList lst   = exp.capturedTexts();
+				QString     key   = lst.at(1);
+				QString     value = lst.at(2);
+				if ((value.length() > 2) &&
+					value.startsWith(QLatin1Char('\"')) &&
+					value.endsWith(QLatin1Char('\"')))
+				{
+					value = value.mid(1, value.length() - 2);
+				}
+				// Store the key and value: "DESKTOP", "$HOME/Desktop"
+				lines[key] = value;
+			}
+		}
+
+		QString key;
+		switch (type)
+		{
+		case DesktopLocation:
+			key = QLatin1String("DESKTOP");
+			break;
+
+		case DocumentsLocation:
+			key = QLatin1String("DOCUMENTS");
+			break;
+
+		case PicturesLocation:
+			key = QLatin1String("PICTURES");
+			break;
+
+		case MusicLocation:
+			key = QLatin1String("MUSIC");
+			break;
+
+		case MoviesLocation:
+			key = QLatin1String("VIDEOS");
+			break;
+
+		default:
+			break;
+		}
+		if (!key.isEmpty() && lines.contains(key))
+		{
+			QString value = lines[key];
+			// value can start with $HOME
+			if (value.startsWith(QLatin1String("$HOME")))
+			{
+				value = QDir::homePath() + value.mid(5);
+			}
+			return value;
+		}
+	}
+
+	QString path;
+
+	switch (type)
+	{
+	case DesktopLocation:
+		path = QDir::homePath() + QLatin1String("/Desktop");
+		break;
+
+	case DocumentsLocation:
+		path = QDir::homePath() + QLatin1String("/Documents");
+		break;
+
+	case PicturesLocation:
+		path = QDir::homePath() + QLatin1String("/Pictures");
+		break;
+
+	case FontsLocation:
+		path = QDir::homePath() + QLatin1String("/.fonts");
+		break;
+
+	case MusicLocation:
+		path = QDir::homePath() + QLatin1String("/Music");
+		break;
+
+	case MoviesLocation:
+		path = QDir::homePath() + QLatin1String("/Videos");
+		break;
+
+	case ApplicationsLocation:
+		path = writableLocation(GenericDataLocation) + QLatin1String("/applications");
+		break;
+
+	default:
+		break;
+	}
+
+	return path;
+}
+
+
+QStringList QStandardPaths::standardLocations(StandardLocation type)
+{
+	QStringList dirs;
+
+	if (type == ConfigLocation)
+	{
+		// http://standards.freedesktop.org/basedir-spec/latest/
+		QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS"));
+		if (xdgConfigDirs.isEmpty())
+		{
+			dirs.append(QString::fromLatin1("/etc/xdg"));
+		}
+		else
+		{
+			dirs = xdgConfigDirs.split(QLatin1Char(':'));
+		}
+	}
+	else if (type == GenericDataLocation)
+	{
+		// http://standards.freedesktop.org/basedir-spec/latest/
+		QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
+		if (xdgConfigDirs.isEmpty())
+		{
+			dirs.append(QString::fromLatin1("/usr/local/share"));
+			dirs.append(QString::fromLatin1("/usr/share"));
+		}
+		else
+		{
+			dirs = xdgConfigDirs.split(QLatin1Char(':'));
+		}
+	}
+	const QString localDir = writableLocation(type);
+
+	dirs.prepend(localDir);
+	return dirs;
+}
+
+
+QString QStandardPaths::displayName(StandardLocation type)
+{
+	Q_UNUSED(type);
+	return QString();
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STANDARDPATHS
diff --git lib/libarchiveqt.h lib/libarchiveqt.h
index d5188af..f374e73 100644
--- lib/libarchiveqt.h
+++ lib/libarchiveqt.h
@@ -1,19 +1,27 @@
-/**
- * Copyright 2018-2023 Britanicus <marcusbritanicus@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- **/
+/*
+  *
+  * Copyright 2018 Britanicus <marcusbritanicus@gmail.com>
+  *
+  *
+  *
+  * This program is free software: you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as published by
+  * the Free Software Foundation, either version 3 of the License, or
+  * (at your option) any later version.
+  *
+  *
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU Lesser General Public License for more details.
+  *
+  *
+  *
+  * You should have received a copy of the GNU Lesser General Public License
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
 
 #pragma once
 
@@ -26,130 +34,129 @@
 
 class QMimeType;
 
-typedef struct {
-    /* Name of the entry */
-    QString     name;
+typedef struct
+{
+	/* Name of the entry */
+	QString     name;
 
-    /* Size of the entry */
-    quint64     size;
+	/* Size of the entry */
+	quint64     size;
 
-    /* Type of the entry */
-    int         type;
+	/* Type of the entry */
+	int         type;
 
-    /* Stat equivalent */
-    struct stat info;
+	/* Stat equivalent */
+	struct stat info;
 } ArchiveEntry;
 
 typedef QList<ArchiveEntry *> ArchiveEntries;
 
 class LibArchiveQt : public QThread {
-    Q_OBJECT
+	Q_OBJECT
 
-    public:
-        /* Used with updateInputFiles, this helps libarchive to choose how to handle paths */
-        enum InputFileMode {
-            AbsolutePath = 0x703857,    // Use absolute file paths - Discouraged
-            RelativeToRoot,             // All paths will be relative to '/' - Useful for packaging of
-                                        // installed files
-            RelativeToHome,             // Files will have paths relative to home folder - good for saving
-                                        // config files
-            RelativeToCurrent,          // The paths will be relative to the current path - Useful for
-                                        // archiving files in current dir [Default]
-            RelativeToWorkDir,          // Set archive paths of the file relative to @src - @src should be
-                                        // set before calling updateInputFiles
-            CommonRelativePath,         // Added files will have paths relative to path common to all files
-                                        // - Costly for large number of files
-        };
+public:
+	/* Used with updateInputFiles, this helps libarchive to choose how to handle paths */
+	enum InputFileMode
+	{
+		AbsolutePath = 0x703857,        // Use absolute file paths - Discouraged
+		RelativeToRoot,                 // All paths will be relative to '/' - Useful for packaging of installed files
+		RelativeToHome,                 // Files will have paths relative to home folder - good for saving config files
+		RelativeToCurrent,              // The paths will be relative to the current path - Useful for archiving files in current dir [Default]
+		RelativeToWorkDir,              // Set archive paths of the file relative to @src - @src should be set before calling updateInputFiles
+		CommonRelativePath,             // Added files will have paths relative to path common to all files - Costly for large number of files
+	};
 
-        LibArchiveQt( QString );
+	LibArchiveQt(QString);
 
-        // Convenience Functions
-        void updateInputFiles( QStringList, LibArchiveQt::InputFileMode inMode = LibArchiveQt::RelativeToCurrent );
-        void setWorkingDir( QString );
-        void setDestination( QString );
-        void waitForFinished();
+	// Convenience Functions
+	void updateInputFiles(QStringList, LibArchiveQt::InputFileMode inMode = LibArchiveQt::RelativeToCurrent);
+	void setWorkingDir(QString);
+	void setDestination(QString);
+	void waitForFinished();
 
-        /* Create an archive */
-        void createArchive();
+	/* Create an archive */
+	void createArchive();
 
-        /* Extract the archive */
-        void extractArchive();
+	/* Extract the archive */
+	void extractArchive();
 
-        /* Extract a named member of the archive */
-        void extractMember( QString );
+	/* Extract a named member of the archive */
+	void extractMember(QString);
 
-        /* List the contetns of the archive */
-        ArchiveEntries listArchive();
+	/* List the contetns of the archive */
+	ArchiveEntries listArchive();
 
-        /* Exit status */
-        int exitStatus();
+	/* Exit status */
+	int exitStatus();
 
-        /* Convenience functions */
-        static QString suffix( QString name );
-        static QStringList supportedFormats();
+	/* Convenience functions */
+	static QString suffix(QString name);
+	static QStringList supportedFormats();
 
-    private:
-        enum Mode {
-            None = 0xF650E7,
-            Single,
-            Container
-        };
+private:
+	enum Mode
+	{
+		None = 0xF650E7,
+		Single,
+		Container
+	};
 
-        enum Job {
-            NoJob = 0x25CEE9,
-            CreateArchive,
-            ExtractArchive,
-            ExtractMember,
-            ListArchive
-        };
+	enum Job
+	{
+		NoJob = 0x25CEE9,
+		CreateArchive,
+		ExtractArchive,
+		ExtractMember,
+		ListArchive
+	};
 
-        /* Internal worker for copying data */
-        int copyData( struct archive *ar, struct archive *aw );
+	/* Internal worker for copying data */
+	int copyData(struct archive *ar, struct archive *aw);
 
-        /* Set the archive filter format based on extensions */
-        void setFilterFormat( QMimeType mType );
+	/* Set the archive filter format based on extensions */
+	void setFilterFormat(QMimeType mType);
 
-        /* Create an archive - Internal Worker */
-        bool doCreateArchive();
+	/* Create an archive - Internal Worker */
+	bool doCreateArchive();
 
-        /* Extract the archive - Internal Worker */
-        bool doExtractArchive();
+	/* Extract the archive - Internal Worker */
+	bool doExtractArchive();
 
-        /* Extract a named member of the archive - Internal Worker */
-        bool doExtractMember( QString );
+	/* Extract a named member of the archive - Internal Worker */
+	bool doExtractMember(QString);
 
-        int mArchiveFilter;
-        int mArchiveFormat;
+	int mArchiveFilter;
+	int mArchiveFormat;
 
-        QString archiveName;
+	QString archiveName;
 
-        QHash<QString, QString> inputList;
-        QString dest;
-        QString src;
+	QHash<QString, QString> inputList;
+	QString dest;
+	QString src;
 
-        ArchiveEntries memberList;
-        bool readDone;
-        int archiveType;
+	ArchiveEntries memberList;
+	bool readDone;
+	int archiveType;
 
-        /* What job are we doing? */
-        int mJob;
+	/* What job are we doing? */
+	int mJob;
 
-        /* Is the job running? */
-        bool isRunning;
+	/* Is the job running? */
+	bool isRunning;
 
-        /* Exit status */
-        int mExitStatus;
+	/* Exit status */
+	int mExitStatus;
 
-        /* Member to be extracted */
-        QString extractedMember;
+	/* Member to be extracted */
+	QString extractedMember;
 
-    protected:
-        void run();
+protected:
+	void run();
 
-    Q_SIGNALS:
-        void jobComplete();
-        void jobFailed();
+Q_SIGNALS:
+	void jobComplete();
+	void jobFailed();
 
-        /* Progress is always in percentage */
-        void progress( int );
+	/* Progress is always in percentage */
+	void progress(int);
 };
diff --git lib/lz4dec.c lib/lz4dec.c
index b11d6ba..6685ba8 100644
--- lib/lz4dec.c
+++ lib/lz4dec.c
@@ -21,8 +21,7 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-// This program is a shorter, more readable, albeit slower re-implementation of lz4cat (
-// https://github.com/Cyan4973/xxHash )
+// This program is a shorter, more readable, albeit slower re-implementation of lz4cat ( https://github.com/Cyan4973/xxHash )
 
 // compile: gcc smallz4cat.c -O3 -o smallz4cat -Wall -pedantic -std=c99 -s
 // The static 8k binary was compiled using Clang and dietlibc (see https://www.fefe.de/dietlibc/ )
@@ -34,7 +33,7 @@
 // Replace getByteFromIn() and sendToOut() by your own code if you need in-memory LZ4 decompression.
 // Corrupted data causes a call to error().
 
-#define READ_BUFFER_SIZE    4 * 1024
+#define READ_BUFFER_SIZE 4*1024
 
 #include <stdint.h> // uint32_t
 #include <stdio.h>  // stdin/stdout/stderr, fopen, ...
@@ -44,296 +43,273 @@
 #include "lz4dec.h"
 
 // error handler
-void error( const char *msg ) {
-    // smaller static binary than fprintf(stderr, "ERROR: %s\n", msg);
-    fputs( "ERROR: ", stderr );
-    fputs( msg,       stderr );
-    fputs( "\n",      stderr );
-    exit( 1 );
+void error(const char* msg) {
+	// smaller static binary than fprintf(stderr, "ERROR: %s\n", msg);
+	fputs("ERROR: ", stderr);
+	fputs(msg,       stderr);
+	fputs("\n",      stderr);
+	exit(  1);
 }
 
-
 static unsigned char getByte( FILE *in ) {
-    // modify buffer size as you like ... for most use cases, bigger buffer aren't faster anymore - and even
-    // reducing to 1 byte works !
-    static unsigned char readBuffer[ READ_BUFFER_SIZE ];
-    static size_t        pos       = 0;
-    static size_t        available = 0;
-
-    // refill buffer
-    if ( pos == available ) {
-        pos       = 0;
-        available = fread( readBuffer, 1, READ_BUFFER_SIZE, in );
-
-        if ( available == 0 ) {
-            error( "out of data" );
-        }
-    }
-
-    // return a byte
-    return readBuffer[ pos++ ];
+	// modify buffer size as you like ... for most use cases, bigger buffer aren't faster anymore - and even reducing to 1 byte works !
+	static unsigned char readBuffer[READ_BUFFER_SIZE];
+	static size_t        pos       = 0;
+	static size_t        available = 0;
+
+	// refill buffer
+	if (pos == available)
+	{
+		pos = 0;
+		available = fread(readBuffer, 1, READ_BUFFER_SIZE, in);
+		if (available == 0)
+			error("out of data");
+	}
+
+	// return a byte
+	return readBuffer[pos++];
 }
 
-
-static void sendBytes( const unsigned char *data, unsigned int numBytes, FILE *out ) {
-    if ( (data != NULL) && (numBytes > 0) ) {
-        fwrite( data, 1, numBytes, out );
-    }
+static void sendBytes(const unsigned char* data, unsigned int numBytes, FILE *out) {
+	if (data != NULL && numBytes > 0)
+		fwrite(data, 1, numBytes, out);
 }
 
-
-void unlz4( const char *ifn, const char *ofn, const char *dictionary ) {
-    FILE *inpFp = fopen( ifn, "rb" );
-    FILE *outFp = fopen( ofn, "wb" );
-
-    // signature
-    unsigned char signature1 = getByte( inpFp );
-    unsigned char signature2 = getByte( inpFp );
-    unsigned char signature3 = getByte( inpFp );
-    unsigned char signature4 = getByte( inpFp );
-    uint32_t      signature  = (signature4 << 24) | (signature3 << 16) | (signature2 << 8) | signature1;
-    int           isModern   = (signature == 0x184D2204);
-    int           isLegacy   = (signature == 0x184C2102);
-
-    if ( !isModern && !isLegacy ) {
-        error( "invalid signature" );
-    }
-
-    unsigned char hasBlockChecksum   = 0;
-    unsigned char hasContentSize     = 0;
-    unsigned char hasContentChecksum = 0;
-    unsigned char hasDictionaryID    = 0;
-
-    if ( isModern ) {
-        // flags
-        unsigned char flags = getByte( inpFp );
-        hasBlockChecksum   = flags & 16;
-        hasContentSize     = flags & 8;
-        hasContentChecksum = flags & 4;
-        hasDictionaryID    = flags & 1;
-
-        // only version 1 file format
-        unsigned char version = flags >> 6;
-
-        if ( version != 1 ) {
-            error( "only LZ4 file format version 1 supported" );
-        }
-
-        // ignore blocksize
-        getByte( inpFp );
-
-        if ( hasContentSize ) {
-            // ignore, skip 8 bytes
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-        }
-
-        if ( hasDictionaryID ) {
-            // ignore, skip 4 bytes
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-        }
-
-        // ignore header checksum (xxhash32 of everything up this point & 0xFF)
-        getByte( inpFp );
-    }
-
-    // don't lower this value, backreferences can be 64kb far away
-#define HISTORY_SIZE    64 * 1024
-    // contains the latest decoded data
-    unsigned char history[ HISTORY_SIZE ];
-    // next free position in history[]
-    unsigned int pos = 0;
-
-    // dictionary compression is a recently introduced feature, just move its contents to the buffer
-    if ( dictionary != NULL ) {
-        // open dictionary
-        FILE *dict = fopen( dictionary, "rb" );
-
-        if ( !dict ) {
-            error( "cannot open dictionary" );
-        }
-
-        // get dictionary's filesize
-        fseek( dict, 0, SEEK_END );
-        size_t dictSize = ftell( dict );
-        // only the last 64k are relevant
-        size_t relevant = dictSize < 65536 ? 0 : dictSize - 65536;
-        fseek( dict, (long)relevant, SEEK_SET );
-
-        if ( dictSize > 65536 ) {
-            dictSize = 65536;
-        }
-
-        // read it and store it at the end of the buffer
-        fread( history + HISTORY_SIZE - dictSize, 1, dictSize, dict );
-        fclose( dict );
-    }
-
-    // parse all blocks until blockSize == 0
-    while ( 1 ) {
-        // block size
-        uint32_t blockSize = getByte( inpFp );
-        blockSize |= (uint32_t)getByte( inpFp ) << 8;
-        blockSize |= (uint32_t)getByte( inpFp ) << 16;
-        blockSize |= (uint32_t)getByte( inpFp ) << 24;
-
-        // highest bit set ?
-        unsigned char isCompressed = isLegacy || (blockSize & 0x80000000) == 0;
-
-        if ( isModern ) {
-            blockSize &= 0x7FFFFFFF;
-        }
-
-        // stop after last block
-        if ( blockSize == 0 ) {
-            break;
-        }
-
-        if ( isCompressed ) {
-            // decompress block
-            uint32_t blockOffset = 0;
-            while ( blockOffset < blockSize ) {
-                // get a token
-                unsigned char token = getByte( inpFp );
-
-                blockOffset++;
-
-                // determine number of literals
-                uint32_t numLiterals = (token >> 4) & 0x0F;
-
-                if ( numLiterals == 15 ) {
-                    // number of literals length encoded in more than 1 byte
-                    unsigned char current;
-                    do{
-                        current      = getByte( inpFp );
-                        numLiterals += current;
-                        blockOffset++;
-                    } while ( current == 255 );
-                }
-
-                blockOffset += numLiterals;
-                // copy all those literals
-                while ( numLiterals-- > 0 ) {
-                    history[ pos++ ] = getByte( inpFp );
-
-                    // flush output buffer
-                    if ( pos == HISTORY_SIZE ) {
-                        sendBytes( history, HISTORY_SIZE, outFp );
-                        pos = 0;
-                    }
-                }
-
-                // last token has only literals
-                if ( blockOffset == blockSize ) {
-                    break;
-                }
-
-                // match distance is encoded by two bytes (little endian)
-                blockOffset += 2;
-                uint32_t delta = getByte( inpFp );
-                delta |= (uint32_t)getByte( inpFp ) << 8;
-
-                // zero isn't allowed
-                if ( delta == 0 ) {
-                    error( "invalid offset" );
-                }
-
-                // match length (must be >= 4, therefore length is stored minus 4)
-                uint32_t matchLength = 4 + (token & 0x0F);
-
-                if ( matchLength == 4 + 0x0F ) {
-                    unsigned char current;
-                    do{ // match length encoded in more than 1 byte
-                        current      = getByte( inpFp );
-                        matchLength += current;
-                        blockOffset++;
-                    } while ( current == 255 );
-                }
-
-                // copy match
-                uint32_t reference = (pos >= delta) ? pos - delta : HISTORY_SIZE + pos - delta;
-
-                if ( (pos + matchLength < HISTORY_SIZE) && (reference + matchLength < HISTORY_SIZE) ) {
-                    // fast copy
-                    if ( (pos >= reference + matchLength) || (reference >= pos + matchLength) ) {
-                        // non-overlapping
-                        memcpy( history + pos, history + reference, matchLength );
-                        pos += matchLength;
-                    }
-                    else {
-                        // overlapping
-                        while ( matchLength-- > 0 ) {
-                            history[ pos++ ] = history[ reference++ ];
-                        }
-                    }
-                }
-                else {
-                    // slower copy, have to take care of buffer limits
-                    while ( matchLength-- > 0 ) {
-                        // copy single byte
-                        history[ pos++ ] = history[ reference++ ];
-
-                        // cannot write anymore ? => wrap around
-                        if ( pos == HISTORY_SIZE ) {
-                            // flush output buffer
-                            sendBytes( history, HISTORY_SIZE, outFp );
-                            pos = 0;
-                        }
-
-                        // cannot read anymore ? => wrap around
-                        if ( reference == HISTORY_SIZE ) {
-                            reference = 0;
-                        }
-                    }
-                }
-            }
-
-            // all legacy blocks must be completely filled - except for the last one
-            if ( isLegacy && (blockSize < 8 * 1024 * 1024) ) {
-                break;
-            }
-        }
-        else {
-            // copy uncompressed data and add to history, too (if next block is compressed and some matches
-            // refer to this block)
-            while ( blockSize-- > 0 ) {
-                // copy a byte ...
-                history[ pos++ ] = getByte( inpFp );
-
-                // ... until buffer is full => send to output
-                if ( pos == HISTORY_SIZE ) {
-                    sendBytes( history, HISTORY_SIZE, outFp );
-                    pos = 0;
-                }
-            }
-        }
-
-        if ( hasBlockChecksum ) {
-            // ignore checksum, skip 4 bytes
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-            getByte( inpFp );
-        }
-    }
-
-    if ( hasContentChecksum ) {
-        // ignore checksum, skip 4 bytes
-        getByte( inpFp );
-        getByte( inpFp );
-        getByte( inpFp );
-        getByte( inpFp );
-    }
-
-    // flush output buffer
-    sendBytes( history, pos, outFp );
+void unlz4( const char *ifn, const char *ofn, const char* dictionary) {
+
+	FILE *inpFp = fopen( ifn, "rb" );
+	FILE *outFp = fopen( ofn, "wb" );
+
+	// signature
+	unsigned char signature1 = getByte( inpFp );
+	unsigned char signature2 = getByte( inpFp );
+	unsigned char signature3 = getByte( inpFp );
+	unsigned char signature4 = getByte( inpFp );
+	uint32_t signature = (signature4 << 24) | (signature3 << 16) | (signature2 << 8) | signature1;
+	int isModern = (signature == 0x184D2204);
+	int isLegacy = (signature == 0x184C2102);
+	if (!isModern && !isLegacy)
+		error("invalid signature");
+
+	unsigned char hasBlockChecksum   = 0;
+	unsigned char hasContentSize     = 0;
+	unsigned char hasContentChecksum = 0;
+	unsigned char hasDictionaryID    = 0;
+	if (isModern) {
+		// flags
+		unsigned char flags = getByte( inpFp );
+		hasBlockChecksum   = flags & 16;
+		hasContentSize     = flags &  8;
+		hasContentChecksum = flags &  4;
+		hasDictionaryID    = flags &  1;
+
+		// only version 1 file format
+		unsigned char version = flags >> 6;
+		if (version != 1)
+			error("only LZ4 file format version 1 supported");
+
+		// ignore blocksize
+		getByte( inpFp );
+
+		if (hasContentSize)
+		{
+			// ignore, skip 8 bytes
+			getByte( inpFp ); getByte( inpFp ); getByte( inpFp ); getByte( inpFp );
+			getByte( inpFp ); getByte( inpFp ); getByte( inpFp ); getByte( inpFp );
+		}
+		if (hasDictionaryID)
+		{
+			// ignore, skip 4 bytes
+			getByte( inpFp ); getByte( inpFp ); getByte( inpFp ); getByte( inpFp );
+		}
+
+		// ignore header checksum (xxhash32 of everything up this point & 0xFF)
+		getByte( inpFp );
+	}
+
+	// don't lower this value, backreferences can be 64kb far away
+#define HISTORY_SIZE 64*1024
+	// contains the latest decoded data
+	unsigned char history[HISTORY_SIZE];
+	// next free position in history[]
+	unsigned int  pos = 0;
+
+	// dictionary compression is a recently introduced feature, just move its contents to the buffer
+	if (dictionary != NULL)
+	{
+		// open dictionary
+		FILE* dict = fopen(dictionary, "rb");
+		if (!dict)
+			error("cannot open dictionary");
+
+		// get dictionary's filesize
+		fseek(dict, 0, SEEK_END);
+		size_t dictSize = ftell(dict);
+		// only the last 64k are relevant
+		size_t relevant = dictSize < 65536 ? 0 : dictSize - 65536;
+		fseek(dict, (long)relevant, SEEK_SET);
+		if (dictSize > 65536)
+			dictSize = 65536;
+		// read it and store it at the end of the buffer
+		fread(history + HISTORY_SIZE - dictSize, 1, dictSize, dict);
+		fclose(dict);
+	}
+
+	// parse all blocks until blockSize == 0
+	while (1)
+	{
+		// block size
+		uint32_t blockSize = getByte( inpFp );
+		blockSize |= (uint32_t)getByte( inpFp ) <<  8;
+		blockSize |= (uint32_t)getByte( inpFp ) << 16;
+		blockSize |= (uint32_t)getByte( inpFp ) << 24;
+
+		// highest bit set ?
+		unsigned char isCompressed = isLegacy || (blockSize & 0x80000000) == 0;
+		if (isModern)
+			blockSize &= 0x7FFFFFFF;
+
+		// stop after last block
+		if (blockSize == 0)
+			break;
+
+		if (isCompressed)
+		{
+			// decompress block
+			uint32_t blockOffset = 0;
+			while (blockOffset < blockSize)
+			{
+				// get a token
+				unsigned char token = getByte( inpFp );
+
+				blockOffset++;
+
+				// determine number of literals
+				uint32_t numLiterals = (token >> 4) & 0x0F;
+				if (numLiterals == 15)
+				{
+					// number of literals length encoded in more than 1 byte
+					unsigned char current;
+					do
+					{
+						current = getByte( inpFp );
+						numLiterals += current;
+						blockOffset++;
+					} while (current == 255);
+				}
+
+				blockOffset += numLiterals;
+				// copy all those literals
+				while (numLiterals-- > 0)
+				{
+					history[pos++] = getByte( inpFp );
+
+					// flush output buffer
+					if (pos == HISTORY_SIZE)
+					{
+						sendBytes(history, HISTORY_SIZE, outFp);
+						pos = 0;
+					}
+				}
+
+				// last token has only literals
+				if (blockOffset == blockSize)
+					break;
+
+				// match distance is encoded by two bytes (little endian)
+				blockOffset += 2;
+				uint32_t delta = getByte( inpFp );
+				delta |= (uint32_t)getByte( inpFp ) << 8;
+				// zero isn't allowed
+				if (delta == 0)
+					error("invalid offset");
+
+				// match length (must be >= 4, therefore length is stored minus 4)
+				uint32_t matchLength = 4 + (token & 0x0F);
+				if (matchLength == 4 + 0x0F)
+				{
+					unsigned char current;
+					do // match length encoded in more than 1 byte
+					{
+						current = getByte( inpFp );
+						matchLength += current;
+						blockOffset++;
+					} while (current == 255);
+				}
+
+				// copy match
+				uint32_t reference = (pos >= delta) ? pos - delta : HISTORY_SIZE + pos - delta;
+				if (pos + matchLength < HISTORY_SIZE && reference + matchLength < HISTORY_SIZE)
+				{
+					// fast copy
+					if (pos >= reference + matchLength || reference >= pos + matchLength)
+					{
+						// non-overlapping
+						memcpy(history + pos, history + reference, matchLength);
+						pos += matchLength;
+					}
+					else
+					{
+						// overlapping
+						while (matchLength-- > 0)
+							history[pos++] = history[reference++];
+					}
+				}
+				else
+				{
+					// slower copy, have to take care of buffer limits
+					while (matchLength-- > 0)
+					{
+						// copy single byte
+						history[pos++] = history[reference++];
+
+						// cannot write anymore ? => wrap around
+						if (pos == HISTORY_SIZE)
+						{
+							// flush output buffer
+							sendBytes(history, HISTORY_SIZE, outFp);
+							pos = 0;
+						}
+						// cannot read anymore ? => wrap around
+						if (reference == HISTORY_SIZE)
+							reference = 0;
+					}
+				}
+			}
+
+			// all legacy blocks must be completely filled - except for the last one
+			if (isLegacy && blockSize < 8*1024*1024)
+				break;
+		}
+		else
+		{
+			// copy uncompressed data and add to history, too (if next block is compressed and some matches refer to this block)
+			while (blockSize-- > 0)
+			{
+				// copy a byte ...
+				history[pos++] = getByte( inpFp );
+				// ... until buffer is full => send to output
+				if (pos == HISTORY_SIZE)
+				{
+					sendBytes(history, HISTORY_SIZE, outFp);
+					pos = 0;
+				}
+			}
+		}
+
+		if (hasBlockChecksum)
+		{
+			// ignore checksum, skip 4 bytes
+			getByte( inpFp ); getByte( inpFp ); getByte( inpFp ); getByte( inpFp );
+		}
+	}
+
+	if (hasContentChecksum)
+	{
+		// ignore checksum, skip 4 bytes
+		getByte( inpFp ); getByte( inpFp ); getByte( inpFp ); getByte( inpFp );
+	}
+
+	// flush output buffer
+	sendBytes(history, pos, outFp);
 }
diff --git lib/lz4dec.h lib/lz4dec.h
index daf72d2..e1d1a96 100644
--- lib/lz4dec.h
+++ lib/lz4dec.h
@@ -1,7 +1,9 @@
-/**
- * lz4dec.h - Lz4 decompression header
- **/
+/*
+  *
+  * lz4dec.h - Lz4 decompression header
+  *
+  */
 
 #pragma once
 
-void unlz4( const char *, const char *, const char * );
+void unlz4(const char *, const char *, const char *);
diff --git lib/meson.build lib/meson.build
index ff87c69..a95b987 100644
--- lib/meson.build
+++ lib/meson.build
@@ -16,6 +16,36 @@ Sources = [
   	'lz4dec.c'
 ]
 
+if ( QtCore.version().startswith( '4.' ) )
+    warning( 'We strongly advice against using Qt4.' )
+
+    Headers += [
+        'MimeHandler/NBMimeDatabase.hpp',
+        'MimeHandler/NBMimeDatabase_p.hpp',
+        'MimeHandler/NBMimeGlobPattern_p.hpp',
+        'MimeHandler/NBMimeMagicRule_p.hpp',
+        'MimeHandler/NBMimeMagicRuleMatcher_p.hpp',
+        'MimeHandler/NBMimeProvider_p.hpp',
+        'MimeHandler/NBMimeType.hpp',
+        'MimeHandler/NBMimeType_p.hpp',
+        'MimeHandler/NBMimeTypeParser_p.hpp',
+        'StandardPaths/NBStandardPaths.hpp'
+    ]
+
+    Sources += [
+    		'MimeHandler/NBMimeDatabase.cpp',
+    		'MimeHandler/NBMimeDatabase.cpp',
+    		'MimeHandler/NBMimeGlobPattern.cpp',
+    		'MimeHandler/NBMimeMagicRule.cpp',
+    		'MimeHandler/NBMimeMagicRuleMatcher.cpp',
+    		'MimeHandler/NBMimeProvider.cpp',
+    		'MimeHandler/NBMimeType.cpp',
+    		'MimeHandler/NBMimeTypeParser.cpp',
+    		'StandardPaths/NBStandardPaths_unix.cpp',
+    		'StandardPaths/NBStandardPaths.cpp'
+    ]
+endif
+
 Mocs = Qt.compile_moc(
     headers : Headers,
     dependencies: Deps
@@ -23,8 +53,8 @@ Mocs = Qt.compile_moc(
 
 shared = shared_library(
     TgtName, [ Sources, Mocs ],
-	version: meson.project_version(),
-	include_directories: Includes,
+		version: meson.project_version(),
+		include_directories: Includes,
     dependencies: Deps,
     install: true,
     link_args: ['-rdynamic','-fPIC'],
@@ -33,7 +63,7 @@ shared = shared_library(
 
 static = static_library(
     TgtName, [ Sources, Mocs ],
-    include_directories: Includes,
+		include_directories: Includes,
     dependencies: Deps,
     install: get_option( 'install_static' ),
     install_dir: join_paths( get_option( 'libdir' ) )
@@ -44,21 +74,21 @@ install_headers(
 )
 
 ArchiveQtShared = declare_dependency(
-    link_with: shared,
+		link_with: shared,
 )
 
 ArchiveQtStatic = declare_dependency(
-    link_with: static,
+		link_with: static,
 )
 
 ## PkgConfig Section
 pkgconfig = import( 'pkgconfig' )
 pkgconfig.generate(
-    shared,
-    name: TgtName,
-    version: meson.project_version(),
-    filebase: TgtName,
-    description: 'A Qt based archiving solution with libarchive backend',
-    requires: [ QtCore.name(), Zlib.name(), Lzma.name(), Archive.name() ],
+		shared,
+		name: TgtName,
+		version: meson.project_version(),
+		filebase: TgtName,
+		description: 'A Qt based archiving solution with libarchive backend',
+		requires: [ QtCore.name(), Zlib.name(), Lzma.name(), Archive.name() ],
     libraries: [ '-lbz2' ]
 )
diff --git meson.build meson.build
index 1cd1cca..7ad65d8 100644
--- meson.build
+++ meson.build
@@ -2,7 +2,7 @@ project(
 	'Archive Qt',
     'c',
 	'cpp',
-	version: '2.0.8',
+	version: '2.0.7',
 	license: 'GPLv3',
 	meson_version: '>=0.59.0',
 	default_options: [
@@ -21,24 +21,43 @@ Lzma = dependency( 'liblzma' )
 BZip = meson.get_compiler( 'cpp' ).find_library( 'bz2' )
 Archive = dependency( 'libarchive' )
 
-if get_option('use_qt_version') == 'qt5'
-	Qt = import( 'qt5' )
-	QtCore = dependency( 'Qt5Core' )
-	TgtName = 'archiveqt5'
+if get_option('use_qt_version') == 'qt4'
+		Qt = import( 'qt4' )
+		QtCore = dependency( 'QtCore' )
+		TgtName = 'archiveqt4'
+
+elif get_option('use_qt_version') == 'qt5'
+		Qt = import( 'qt5' )
+		QtCore = dependency( 'Qt5Core' )
+		TgtName = 'archiveqt5'
 
 elif get_option('use_qt_version') == 'qt6'
-	Qt = import( 'qt6' )
-	QtCore = dependency( 'Qt6Core' )
-	TgtName = 'archiveqt6'
+		Qt = import( 'qt6' )
+		QtCore = dependency( 'Qt6Core' )
+		TgtName = 'archiveqt6'
 
 endif
 
 Deps = [ QtCore, Zlib, Lzma, BZip, Archive ]
 
-Includes = include_directories( 'lib' )
+Includes = include_directories(
+    'lib',
+    'lib/MimeHandler',
+    'lib/StandardPaths',
+)
 
 # Contains the main library
 subdir( 'lib' )
 
 # Contains the archvier cli app
 subdir( 'archiver' )
+
+
+summary = [
+	'',
+	'----------------',
+	'Archive Qt @0@'.format(meson.project_version()),
+	'----------------',
+	''
+]
+message('\n'.join(summary))
diff --git meson_options.txt meson_options.txt
index 157d261..62c66b9 100644
--- meson_options.txt
+++ meson_options.txt
@@ -1,7 +1,7 @@
 option(
     'use_qt_version',
     type: 'combo',
-    choices: ['qt5', 'qt6'],
+    choices: ['qt4', 'qt5', 'qt6'],
     value: 'qt5',
     description: 'Select the Qt version to use'
 )
