mirror of
https://invent.kde.org/system/dolphin
synced 2024-11-05 18:47:12 +00:00
686 lines
22 KiB
C++
686 lines
22 KiB
C++
/*
|
|
|
|
This application scans for Netscape plugins and create a cache and
|
|
the necessary mime and service files.
|
|
|
|
|
|
Copyright (c) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
|
|
Stefan Schimanski <1Stein@gmx.de>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
#include <mimetypewriter.h>
|
|
#include <config-apps.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QRegExp>
|
|
#include <QBuffer>
|
|
|
|
#include <QtDBus/QtDBus>
|
|
|
|
#include <kapplication.h>
|
|
#include <kdebug.h>
|
|
#include <kglobal.h>
|
|
#include <kstandarddirs.h>
|
|
#include <klibrary.h>
|
|
#include <kconfig.h>
|
|
#include <kconfiggroup.h>
|
|
#include <kcrash.h>
|
|
#include <kdesktopfile.h>
|
|
#include <kservicetype.h>
|
|
#include <kmimetype.h>
|
|
#include <kcmdlineargs.h>
|
|
#include <kaboutdata.h>
|
|
#include <klocale.h>
|
|
#include <kprocess.h>
|
|
#include <ksycoca.h>
|
|
|
|
#include "sdk/npfunctions.h"
|
|
|
|
#include "plugin_paths.h"
|
|
|
|
static int showProgress=0;
|
|
|
|
// provide these symbols when compiling with gcc 3.x
|
|
|
|
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
|
#define KDE_GNUC_PREREQ(maj,min) \
|
|
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
|
#else
|
|
#define KDE_GNUC_PREREQ(maj,min) 0
|
|
#endif
|
|
|
|
#if defined(__GNUC__) && KDE_GNUC_PREREQ(3,0)
|
|
extern "C" void* __builtin_new(size_t s)
|
|
{
|
|
return operator new(s);
|
|
}
|
|
|
|
extern "C" void __builtin_delete(void* p)
|
|
{
|
|
operator delete(p);
|
|
}
|
|
|
|
extern "C" void* __builtin_vec_new(size_t s)
|
|
{
|
|
return operator new[](s);
|
|
}
|
|
|
|
extern "C" void __builtin_vec_delete(void* p)
|
|
{
|
|
operator delete[](p);
|
|
}
|
|
|
|
extern "C" void __pure_virtual()
|
|
{
|
|
abort();
|
|
}
|
|
#endif
|
|
|
|
KConfig *infoConfig = 0;
|
|
|
|
static const char s_mimeTypeMarker[] = "MimeType generated by nspluginscan";
|
|
|
|
|
|
static bool isPluginMimeType( const QString &fname )
|
|
{
|
|
QFile file(fname);
|
|
if (file.open(QIODevice::ReadOnly)) {
|
|
const QByteArray firstLine = file.readLine();
|
|
if (!firstLine.startsWith("<?xml")) {
|
|
kWarning() << "Malformed XML file:" << fname;
|
|
return false;
|
|
}
|
|
const QByteArray secondLine = file.readLine();
|
|
// In Qt-4.3.3 the newlines are missing around the comment
|
|
// so the comment marker is part of the first line instead of the second one
|
|
// So we grep both.
|
|
return secondLine.startsWith(s_mimeTypeMarker) || firstLine.contains(s_mimeTypeMarker);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
static QStringList deletePluginMimeTypes()
|
|
{
|
|
QStringList removedMimes;
|
|
|
|
// get local mime type directory
|
|
const QString dirPath = KGlobal::dirs()->saveLocation( "xdgdata-mime", "packages" );
|
|
kDebug(1433) << "Removing nsplugin MIME types in " << dirPath;
|
|
QDir dir( dirPath, QString(), QDir::Name|QDir::IgnoreCase, QDir::Files );
|
|
if ( !dir.exists() ) {
|
|
kDebug(1433) << "Local mime directory not found, nothing to remove";
|
|
return removedMimes;
|
|
}
|
|
|
|
// check all user mime types for our own marker
|
|
kDebug(1433) << " - Looking in " << dirPath;
|
|
for (unsigned int i=0; i<dir.count(); i++) {
|
|
|
|
// check mimetype file
|
|
const QString file = dir[i];
|
|
kDebug(1433) << " - Checking" << file;
|
|
if ( isPluginMimeType(dir.absoluteFilePath(file)) ) {
|
|
kDebug(1433) << " - Removing" << file;
|
|
dir.remove( file );
|
|
QString mimeType = file;
|
|
mimeType.replace('-', '/');
|
|
Q_ASSERT(mimeType.endsWith(".xml"));
|
|
mimeType.truncate(mimeType.length()-4);
|
|
removedMimes.append(mimeType);
|
|
kDebug(1433) << " - Removing" << file << '(' << mimeType << ')';
|
|
}
|
|
}
|
|
return removedMimes;
|
|
}
|
|
|
|
|
|
static void generateMimeType( const QString &mime, const QString &extensions, const QString &pluginName, const QString &description )
|
|
{
|
|
kDebug(1433) << "-> generateMimeType mime=" << mime << " ext="<< extensions;
|
|
|
|
// get directory from mime string
|
|
int pos = mime.lastIndexOf('/');
|
|
if ( pos<0 ) {
|
|
kDebug(1433) << "Invalid MIME type " << mime;
|
|
kDebug(1433) << "<- generateMimeType";
|
|
return;
|
|
}
|
|
|
|
// create mime type definition file
|
|
MimeTypeWriter mimeTypeWriter(mime);
|
|
mimeTypeWriter.setMarker(QString::fromLatin1(s_mimeTypeMarker));
|
|
if (!description.isEmpty()) {
|
|
mimeTypeWriter.setComment(description);
|
|
} else {
|
|
mimeTypeWriter.setComment(i18nc("Name of the netscape-plugin which generated this mimetype", "Netscape plugin %1", pluginName));
|
|
}
|
|
|
|
// Maybe we should do it only if the icon named after the mimetype doesn't exist on the system...
|
|
// but this is quite unlikely, why would have the icon and not the mimetype.
|
|
mimeTypeWriter.setIconName("x-kde-nsplugin-generated");
|
|
|
|
if (!extensions.isEmpty()) {
|
|
const QStringList exts = extensions.split(',');
|
|
QStringList patterns;
|
|
for (QStringList::const_iterator it=exts.constBegin(); it != exts.constEnd(); ++it)
|
|
patterns.append( "*." + (*it).trimmed() );
|
|
mimeTypeWriter.setPatterns(patterns);
|
|
}
|
|
|
|
mimeTypeWriter.write();
|
|
|
|
// In KDE 3 we wrote X-KDE-AutoEmbed=true into the mimetype desktop file.
|
|
// In KDE 4 this has moved to a filetypesrc config file.
|
|
KSharedConfig::Ptr fileTypesConfig = KSharedConfig::openConfig("filetypesrc", KConfig::NoGlobals);
|
|
fileTypesConfig->group("EmbedSettings").writeEntry("embed-" + mime, true);
|
|
|
|
kDebug(1433) << "<- generateMimeType";
|
|
}
|
|
|
|
|
|
void registerPlugin( const QString &name, const QString &description,
|
|
const QString &file, const QString &mimeInfo )
|
|
{
|
|
// global stuff
|
|
KConfigGroup cg( infoConfig, QString() );
|
|
int num = cg.readEntry( "number", 0 );
|
|
cg.writeEntry( "number", num+1 );
|
|
|
|
cg = KConfigGroup(infoConfig,QString::number(num));
|
|
// create plugin info
|
|
cg.writeEntry( "name", name );
|
|
cg.writeEntry( "description", description );
|
|
cg.writeEntry( "file", file );
|
|
cg.writeEntry( "mime", mimeInfo );
|
|
}
|
|
|
|
static void segv_handler(int)
|
|
{
|
|
_exit(255);
|
|
}
|
|
|
|
static int tryCheck(int write_fd, const QString &absFile)
|
|
{
|
|
KLibrary _handle(absFile);
|
|
if (!_handle.load()) {
|
|
kDebug(1433) << " - open failed with message " <<
|
|
_handle.errorString() << ", skipping " << endl;
|
|
return 1;
|
|
}
|
|
|
|
// ask for name and description
|
|
QString name = i18n("Unnamed plugin");
|
|
QString description;
|
|
|
|
NPError (*func_GetValue)(void *, NPPVariable, void *) =
|
|
(NPError(*)(void *, NPPVariable, void *))
|
|
_handle.resolveFunction("NP_GetValue");
|
|
if ( func_GetValue ) {
|
|
|
|
// get name
|
|
char *buf = 0;
|
|
NPError err = func_GetValue( 0, NPPVpluginNameString,
|
|
(void*)&buf );
|
|
if ( err==NPERR_NO_ERROR )
|
|
name = QString::fromLatin1( buf );
|
|
kDebug() << "name = " << name;
|
|
|
|
// get name
|
|
NPError nperr = func_GetValue( 0, NPPVpluginDescriptionString,
|
|
(void*)&buf );
|
|
if ( nperr==NPERR_NO_ERROR )
|
|
description = QString::fromLatin1( buf );
|
|
kDebug() << "description = " << description;
|
|
}
|
|
else
|
|
kWarning() << "Plugin doesn't implement NP_GetValue" ;
|
|
|
|
// get mime description function pointer
|
|
char* (*func_GetMIMEDescription)() =
|
|
(char *(*)())_handle.resolveFunction("NP_GetMIMEDescription");
|
|
if ( !func_GetMIMEDescription ) {
|
|
kDebug(1433) << " - no GetMIMEDescription, skipping";
|
|
_handle.unload();
|
|
return 1;
|
|
}
|
|
|
|
// ask for mime information
|
|
QString mimeInfo = func_GetMIMEDescription();
|
|
if ( mimeInfo.isEmpty() ) {
|
|
kDebug(1433) << " - no mime info returned, skipping";
|
|
_handle.unload();
|
|
return 1;
|
|
}
|
|
|
|
// remove version info, as it is not used at the moment
|
|
QRegExp versionRegExp(";version=[^:]*:");
|
|
mimeInfo.replace( versionRegExp, ":");
|
|
if (!mimeInfo.isEmpty() && !mimeInfo.endsWith(';')) {
|
|
mimeInfo += ';'; // XDG compliance
|
|
}
|
|
|
|
// unload plugin lib
|
|
kDebug(1433) << " - unloading plugin";
|
|
_handle.unload();
|
|
|
|
// create a QDataStream for our IPC pipe (to send plugin info back to the parent)
|
|
QFile stream_file;
|
|
stream_file.open(write_fd, QIODevice::WriteOnly);
|
|
QDataStream stream(&stream_file);
|
|
|
|
// return the gathered info to the parent
|
|
stream << name;
|
|
stream << description;
|
|
stream << mimeInfo;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void scanDirectory( const QString &dir, QStringList &mimeInfoList,
|
|
QTextStream &cache )
|
|
{
|
|
kDebug(1433) << "-> scanDirectory dir=" << dir;
|
|
|
|
// iterate over all files
|
|
QDir files( dir, QString(), QDir::Name|QDir::IgnoreCase, QDir::Files );
|
|
if ( !files.exists( dir ) ) {
|
|
kDebug(1433) << "No files found";
|
|
kDebug(1433) << "<- scanDirectory dir=" << dir;
|
|
return;
|
|
}
|
|
|
|
for (unsigned int i=0; i<files.count(); i++) {
|
|
QString extension;
|
|
int j = files[i].lastIndexOf('.');
|
|
if (j > 0)
|
|
extension = files[i].mid(j+1);
|
|
|
|
// ignore crashing libs
|
|
if ( files[i]=="librvplayer.so" || // RealPlayer 5
|
|
files[i]=="libnullplugin.so" || // Netscape Default Plugin
|
|
files[i]=="cult3dplugin.so" || // Cult 3d plugin
|
|
extension == "jar" || // Java archive
|
|
extension == "zip" || // Zip file (for classes)
|
|
extension == "class" || // Java class
|
|
extension == "png" || // PNG Image
|
|
extension == "jpg" || // JPEG image
|
|
extension == "gif" || // GIF image
|
|
extension == "bak" || // .so.bak-up files
|
|
extension == "tmp" || // tmp files
|
|
extension == "xpt" || // XPConnect
|
|
extension.startsWith("htm") // HTML
|
|
)
|
|
continue;
|
|
|
|
// get absolute file path
|
|
QString absFile = files.absoluteFilePath( files[i] );
|
|
kDebug(1433) << "Checking library " << absFile;
|
|
|
|
// open the library and ask for the mimetype
|
|
kDebug(1433) << " - opening " << absFile;
|
|
|
|
cache.flush();
|
|
// fork, so that a crash in the plugin won't stop the scanning of other plugins
|
|
int pipes[2];
|
|
if (pipe(pipes) != 0) continue;
|
|
|
|
int loader_pid = fork();
|
|
|
|
if (loader_pid == -1) {
|
|
// unable to fork
|
|
continue;
|
|
} else if (loader_pid == 0) {
|
|
// inside the child
|
|
close(pipes[0]);
|
|
KCrash::setCrashHandler(segv_handler);
|
|
_exit(tryCheck(pipes[1], absFile));
|
|
} else {
|
|
close(pipes[1]);
|
|
|
|
QBuffer m_buffer;
|
|
m_buffer.open(QIODevice::WriteOnly);
|
|
|
|
QFile q_read_pipe;
|
|
q_read_pipe.open(pipes[0], QIODevice::ReadOnly);
|
|
|
|
char *data = (char *)malloc(4096);
|
|
if (!data) continue;
|
|
int size;
|
|
|
|
// when the child closes, we'll get an EOF (size == 0)
|
|
while ((size = q_read_pipe.read(data, 4096)) > 0)
|
|
m_buffer.write(data, size);
|
|
free(data);
|
|
|
|
q_read_pipe.close();
|
|
close(pipes[0]); // we no longer need the pipe's reading end
|
|
|
|
// close the buffer and open for reading (from the start)
|
|
m_buffer.close();
|
|
m_buffer.open(QIODevice::ReadOnly);
|
|
|
|
// create a QDataStream for our buffer
|
|
QDataStream stream(&m_buffer);
|
|
|
|
if (stream.atEnd()) continue;
|
|
|
|
QString name, description, mimeInfo;
|
|
stream >> name;
|
|
stream >> description;
|
|
stream >> mimeInfo;
|
|
|
|
bool actuallyUsing = false;
|
|
|
|
// get mime types from string
|
|
QStringList types = mimeInfo.split( ';' );
|
|
QStringList::const_iterator type;
|
|
for ( type=types.constBegin(); type!=types.constEnd(); ++type ) {
|
|
|
|
kDebug(1433) << " - type=" << *type;
|
|
name = name.replace( ':', "%3A" );
|
|
|
|
QString entry = name + ':' + (*type).trimmed();
|
|
if ( !mimeInfoList.contains( entry ) ) {
|
|
if (!actuallyUsing) {
|
|
// note the plugin name
|
|
cache << "[" << absFile << "]" << endl;
|
|
actuallyUsing = true;
|
|
}
|
|
|
|
// write into type cache
|
|
QStringList tokens = (*type).split(':', QString::KeepEmptyParts);
|
|
QStringList::const_iterator token;
|
|
token = tokens.constBegin();
|
|
cache << (*token).toLower();
|
|
++token;
|
|
for ( ; token!=tokens.constEnd(); ++token )
|
|
cache << ":" << *token;
|
|
cache << endl;
|
|
|
|
// append type to MIME type list
|
|
mimeInfoList.append( entry );
|
|
}
|
|
}
|
|
|
|
// register plugin for javascript
|
|
registerPlugin( name, description, files[i], mimeInfo );
|
|
}
|
|
}
|
|
|
|
// iterate over all sub directories
|
|
// NOTE: Mozilla doesn't iterate over subdirectories of the plugin dir.
|
|
// We still do (as Netscape 4 did).
|
|
QDir dirs( dir, QString(), QDir::Name|QDir::IgnoreCase, QDir::Dirs );
|
|
if ( !dirs.exists() )
|
|
return;
|
|
|
|
static int depth = 0; // avoid recursion because of symlink circles
|
|
depth++;
|
|
for ( unsigned int i=0; i<dirs.count(); i++ ) {
|
|
if ( depth<8 && !dirs[i].contains(".") )
|
|
scanDirectory( dirs.absoluteFilePath(dirs[i]), mimeInfoList, cache );
|
|
}
|
|
depth--;
|
|
|
|
kDebug() << "<- scanDirectory dir=" << dir;
|
|
}
|
|
|
|
|
|
void writeServicesFile( const QStringList &mimeTypes )
|
|
{
|
|
QString fname = KGlobal::dirs()->saveLocation("services", "")
|
|
+ "/nsplugin.desktop";
|
|
kDebug(1433) << "Creating services file " << fname;
|
|
|
|
QFile f(fname);
|
|
if ( f.open(QIODevice::WriteOnly) ) {
|
|
|
|
QTextStream ts(&f);
|
|
|
|
ts << "[Desktop Entry]" << endl;
|
|
ts << "Name=" << i18n("Netscape plugin viewer") << endl;
|
|
ts << "Type=Service" << endl;
|
|
ts << "Icon=netscape" << endl;
|
|
ts << "Comment=" << i18n("Netscape plugin viewer") << endl;
|
|
ts << "X-KDE-Library=libnsplugin" << endl;
|
|
ts << "InitialPreference=0" << endl;
|
|
ts << "ServiceTypes=KParts/ReadOnlyPart,Browser/View" << endl;
|
|
ts << "X-KDE-BrowserView-PluginsInfo=nsplugins/pluginsinfo" << endl;
|
|
|
|
if (mimeTypes.count() > 0)
|
|
ts << "MimeType=" << mimeTypes.join(";") << ";" << endl;
|
|
|
|
f.close();
|
|
} else
|
|
kDebug(1433) << "Failed to open file " << fname;
|
|
}
|
|
|
|
|
|
void removeExistingExtensions( QString &extension )
|
|
{
|
|
QStringList filtered;
|
|
const QStringList exts = extension.split( ',' );
|
|
for ( QStringList::const_iterator it=exts.constBegin(); it!=exts.constEnd(); ++it ) {
|
|
QString ext = (*it).trimmed();
|
|
if ( ext == "*" ) // some plugins have that, but we don't want to associate a mimetype with *.*!
|
|
continue;
|
|
|
|
KMimeType::Ptr mime = KMimeType::findByUrl( KUrl("file:///foo."+ext ),
|
|
0, true, true );
|
|
if( mime->isDefault() ||
|
|
mime->comment().startsWith("Netscape") ) {
|
|
kDebug() << "accepted";
|
|
filtered.append( ext );
|
|
}
|
|
}
|
|
|
|
extension = filtered.join( "," );
|
|
}
|
|
|
|
void sigChildHandler(int)
|
|
{
|
|
// since waitpid and write change errno, we have to save it and restore it
|
|
// (Richard Stevens, Advanced programming in the Unix Environment)
|
|
int saved_errno = errno;
|
|
|
|
while (waitpid(-1, 0, WNOHANG) == 0)
|
|
;
|
|
|
|
errno = saved_errno;
|
|
}
|
|
|
|
|
|
int main( int argc, char **argv )
|
|
{
|
|
KAboutData aboutData( "nspluginscan", "nsplugin", ki18n("nspluginscan"),
|
|
"0.3", ki18n("nspluginscan"), KAboutData::License_GPL,
|
|
ki18n("(c) 2000,2001 by Stefan Schimanski") );
|
|
|
|
KCmdLineArgs::init( argc, argv, &aboutData );
|
|
|
|
KCmdLineOptions options;
|
|
options.add("verbose", ki18n("Show progress output for GUI"));
|
|
KCmdLineArgs::addCmdLineOptions( options );
|
|
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
|
|
|
showProgress = args->isSet("verbose");
|
|
if (showProgress) {
|
|
printf("10\n"); fflush(stdout);
|
|
}
|
|
|
|
KApplication app(false);
|
|
|
|
// Set up SIGCHLD handler
|
|
struct sigaction act;
|
|
act.sa_handler=sigChildHandler;
|
|
sigemptyset(&(act.sa_mask));
|
|
sigaddset(&(act.sa_mask), SIGCHLD);
|
|
// Make sure we don't block this signal. gdb tends to do that :-(
|
|
sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0);
|
|
|
|
act.sa_flags = SA_NOCLDSTOP;
|
|
|
|
// CC: take care of SunOS which automatically restarts interrupted system
|
|
// calls (and thus does not have SA_RESTART)
|
|
|
|
#ifdef SA_RESTART
|
|
act.sa_flags |= SA_RESTART;
|
|
#endif
|
|
|
|
struct sigaction oldact;
|
|
sigaction( SIGCHLD, &act, &oldact );
|
|
|
|
|
|
// set up the paths used to look for plugins
|
|
QStringList searchPaths = getSearchPaths();
|
|
QStringList mimeInfoList;
|
|
|
|
infoConfig = new KConfig( KGlobal::dirs()->saveLocation("data", "nsplugins") +
|
|
"/pluginsinfo" );
|
|
infoConfig->group("<default>").writeEntry( "number", 0 );
|
|
|
|
// open the cache file for the mime information
|
|
QString cacheName = KGlobal::dirs()->saveLocation("data", "nsplugins")+"/cache";
|
|
kDebug(1433) << "Creating MIME cache file " << cacheName;
|
|
QFile cachef(cacheName);
|
|
if (!cachef.open(QIODevice::WriteOnly))
|
|
return -1;
|
|
QTextStream cache(&cachef);
|
|
if (showProgress) {
|
|
printf("20\n"); fflush(stdout);
|
|
}
|
|
|
|
// read in the plugins mime information
|
|
kDebug(1433) << "Scanning directories" << searchPaths;
|
|
int count = searchPaths.count();
|
|
int i = 0;
|
|
for ( QStringList::const_iterator it = searchPaths.constBegin();
|
|
it != searchPaths.constEnd(); ++it, ++i)
|
|
{
|
|
if ((*it).isEmpty())
|
|
continue;
|
|
scanDirectory( *it, mimeInfoList, cache );
|
|
if (showProgress) {
|
|
printf("%d\n", 25 + (50*i) / count ); fflush(stdout);
|
|
}
|
|
}
|
|
|
|
if (showProgress) {
|
|
printf("75\n"); fflush(stdout);
|
|
}
|
|
|
|
// We're done with forking,
|
|
// KProcess needs SIGCHLD to be reset to what it was initially
|
|
sigaction( SIGCHLD, &oldact, 0 );
|
|
|
|
// delete old mime types
|
|
kDebug(1433) << "Removing old mimetypes";
|
|
const QStringList oldMimes = deletePluginMimeTypes();
|
|
bool mimeTypesChanged = !oldMimes.isEmpty();
|
|
|
|
if (showProgress) {
|
|
printf("80\n"); fflush(stdout);
|
|
}
|
|
|
|
// write mimetype files
|
|
kDebug(1433) << "Creating MIME type descriptions";
|
|
QStringList mimeTypes;
|
|
for ( QStringList::const_iterator it=mimeInfoList.constBegin();
|
|
it!=mimeInfoList.constEnd(); ++it) {
|
|
|
|
kDebug(1433) << "Handling MIME type " << *it;
|
|
|
|
QStringList info = (*it).split(':', QString::KeepEmptyParts);
|
|
if ( info.count()==4 ) {
|
|
QString pluginName = info[0];
|
|
QString type = info[1].toLower();
|
|
QString extension = info[2];
|
|
QString desc = info[3];
|
|
|
|
// append to global mime type list
|
|
if ( !mimeTypes.contains(type) ) {
|
|
kDebug(1433) << " - mimeType=" << type;
|
|
mimeTypes.append( type );
|
|
|
|
// write or update mime type file, if
|
|
// 1) it doesn't exist in ksycoca (meaning we never heard of it)
|
|
// 2) or we just deleted it [it's still in ksycoca though]
|
|
// This prevents noticing that a shared-mime-info upgrade brought
|
|
// us a mimetype we needed; but doing this right requires launching
|
|
// kbuildsycoca4 after removing mimetypes above, and that's really slow
|
|
bool mustWriteMimeType = KMimeType::mimeType(type).isNull();
|
|
if (!mustWriteMimeType)
|
|
mustWriteMimeType = oldMimes.contains(type);
|
|
if ( mustWriteMimeType ) {
|
|
kDebug(1433) << " - creating MIME type description";
|
|
removeExistingExtensions( extension );
|
|
generateMimeType( type, extension, pluginName, desc );
|
|
mimeTypesChanged = true;
|
|
} else {
|
|
kDebug(1433) << " - already exists";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// done with new mimetypes, run update-mime-database
|
|
if (mimeTypesChanged) {
|
|
MimeTypeWriter::runUpdateMimeDatabase();
|
|
// note that we'll run kbuildsycoca below anyway
|
|
}
|
|
|
|
if (showProgress) {
|
|
printf("85\n"); fflush(stdout);
|
|
}
|
|
|
|
// close files
|
|
kDebug(1433) << "Closing cache file";
|
|
cachef.close();
|
|
|
|
infoConfig->sync();
|
|
delete infoConfig;
|
|
|
|
// write plugin lib service file
|
|
writeServicesFile( mimeTypes );
|
|
if (showProgress) {
|
|
printf("90\n"); fflush(stdout);
|
|
}
|
|
|
|
if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kded")) {
|
|
// Tell kded to update sycoca database.
|
|
QDBusInterface kbuildsycoca("org.kde.kded", "/kbuildsycoca",
|
|
"org.kde.kded");
|
|
kbuildsycoca.call("recreate");
|
|
} else {
|
|
// kded not running? fallback to calling kbuildsycoca directly:
|
|
KProcess proc;
|
|
proc << KStandardDirs::findExe(KBUILDSYCOCA_EXENAME);
|
|
proc.setOutputChannelMode(KProcess::MergedChannels); // silence kbuildsycoca output
|
|
proc.execute();
|
|
}
|
|
}
|