|
|
|
/*
|
|
|
|
|
|
|
|
This application scans for Netscape plugins and create a cache and
|
|
|
|
the necessary mimelnk 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 <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqbuffer.h>
|
|
|
|
|
|
|
|
#include <dcopclient.h>
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <klibloader.h>
|
|
|
|
#include <tdeconfig.h>
|
|
|
|
#include <kcrash.h>
|
|
|
|
#include <kdesktopfile.h>
|
|
|
|
#include <kservicetype.h>
|
|
|
|
#include <kmimetype.h>
|
|
|
|
#include <kcmdlineargs.h>
|
|
|
|
#include <kaboutdata.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include "sdk/npupp.h"
|
|
|
|
#include <X11/Intrinsic.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
|
|
|
|
|
|
|
|
// The only purpose of this function is just to pull in libXt.
|
|
|
|
// Using --enable-new-ldflags makes the linker use --as-needed and since
|
|
|
|
// otherwise nspluginscan wouldn't actually use libXt it wouldn't be really
|
|
|
|
// linked against it. However some plugins are not linked against libXt
|
|
|
|
// yet expect to have it available in the hosting application.
|
|
|
|
void pullInXt()
|
|
|
|
{
|
|
|
|
XtFree( NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEConfig *infoConfig = 0;
|
|
|
|
|
|
|
|
|
|
|
|
bool isPluginMimeType( TQString fname )
|
|
|
|
{
|
|
|
|
KDesktopFile cfg( fname, true );
|
|
|
|
cfg.setDesktopGroup();
|
|
|
|
return cfg.hasKey( "X-TDE-nsplugin" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void deletePluginMimeTypes()
|
|
|
|
{
|
|
|
|
// iterate through local mime type directories
|
|
|
|
TQString dir = TDEGlobal::dirs()->saveLocation( "mime" );
|
|
|
|
kdDebug(1433) << "Removing nsplugin MIME types in " << dir << endl;
|
|
|
|
TQDir dirs( dir, TQString::null, TQDir::Name|TQDir::IgnoreCase, TQDir::Dirs );
|
|
|
|
if ( !dirs.exists() ) {
|
|
|
|
kdDebug(1433) << "Directory not found" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( unsigned int i=0; i<dirs.count(); i++ ) {
|
|
|
|
if ( !dirs[i].contains(".") ) {
|
|
|
|
|
|
|
|
// check all mime types for X-TDE-nsplugin flag
|
|
|
|
kdDebug(1433) << " - Looking in " << dirs[i] << endl;
|
|
|
|
TQDir files( dirs.absFilePath(dirs[i]), TQString::null,
|
|
|
|
TQDir::Name|TQDir::IgnoreCase, TQDir::Files );
|
|
|
|
if ( files.exists( dir ) ) {
|
|
|
|
|
|
|
|
for (unsigned int i=0; i<files.count(); i++) {
|
|
|
|
|
|
|
|
// check .desktop file
|
|
|
|
kdDebug(1433) << " - Checking " << files[i] << endl;
|
|
|
|
if ( isPluginMimeType(files.absFilePath(files[i])) ) {
|
|
|
|
kdDebug(1433) << " - Removing " << files[i] << endl;
|
|
|
|
files.remove( files[i] );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void generateMimeType( TQString mime, TQString extensions, TQString pluginName, TQString description )
|
|
|
|
{
|
|
|
|
kdDebug(1433) << "-> generateMimeType mime=" << mime << " ext="<< extensions << endl;
|
|
|
|
|
|
|
|
// get directory from mime string
|
|
|
|
TQString dir;
|
|
|
|
TQString name;
|
|
|
|
int pos = mime.findRev('/');
|
|
|
|
if ( pos<0 ) {
|
|
|
|
kdDebug(1433) << "Invalid MIME type " << mime << endl;
|
|
|
|
kdDebug(1433) << "<- generateMimeType" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
dir = TDEGlobal::dirs()->saveLocation( "mime", mime.left(pos) );
|
|
|
|
name = mime.mid(pos);
|
|
|
|
|
|
|
|
// create mimelnk file
|
|
|
|
TQFile f( dir + name + ".desktop" );
|
|
|
|
if ( f.open(IO_WriteOnly) ) {
|
|
|
|
|
|
|
|
// write .desktop file
|
|
|
|
TQTextStream ts(&f);
|
|
|
|
|
|
|
|
ts << "[Desktop Entry]" << endl;
|
|
|
|
ts << "Type=MimeType" << endl;
|
|
|
|
ts << "MimeType=" << mime << endl;
|
|
|
|
ts << "Icon=netscape_doc" << endl;
|
|
|
|
ts << "Comment=Netscape " << pluginName << endl;
|
|
|
|
ts << "X-TDE-AutoEmbed=true" << endl;
|
|
|
|
ts << "X-TDE-nsplugin=true" << endl;
|
|
|
|
|
|
|
|
if (!extensions.isEmpty()) {
|
|
|
|
TQStringList exts = TQStringList::split(",", extensions);
|
|
|
|
TQStringList patterns;
|
|
|
|
for (TQStringList::Iterator it=exts.begin(); it != exts.end(); ++it)
|
|
|
|
patterns.append( "*." + (*it).stripWhiteSpace() );
|
|
|
|
|
|
|
|
ts << "Patterns=" << patterns.join( ";" ) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!description.isEmpty())
|
|
|
|
ts << "Name=" << description << endl;
|
|
|
|
else
|
|
|
|
ts << "Name=" << i18n("Netscape plugin mimeinfo") << endl;
|
|
|
|
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebug(1433) << "<- generateMimeType" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void registerPlugin( const TQString &name, const TQString &description,
|
|
|
|
const TQString &file, const TQString &mimeInfo )
|
|
|
|
{
|
|
|
|
// global stuff
|
|
|
|
infoConfig->setGroup( TQString::null );
|
|
|
|
int num = infoConfig->readNumEntry( "number", 0 );
|
|
|
|
infoConfig->writeEntry( "number", num+1 );
|
|
|
|
|
|
|
|
// create plugin info
|
|
|
|
infoConfig->setGroup( TQString::number(num) );
|
|
|
|
infoConfig->writeEntry( "name", name );
|
|
|
|
infoConfig->writeEntry( "description", description );
|
|
|
|
infoConfig->writeEntry( "file", file );
|
|
|
|
infoConfig->writeEntry( "mime", mimeInfo );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void segv_handler(int)
|
|
|
|
{
|
|
|
|
_exit(255);
|
|
|
|
}
|
|
|
|
|
|
|
|
int tryCheck(int write_fd, const TQString &absFile)
|
|
|
|
{
|
|
|
|
KLibrary *_handle = KLibLoader::self()->library( TQFile::encodeName(absFile) );
|
|
|
|
if (!_handle) {
|
|
|
|
kdDebug(1433) << " - open failed with message " <<
|
|
|
|
KLibLoader::self()->lastErrorMessage() << ", skipping " << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ask for name and description
|
|
|
|
TQString name = i18n("Unnamed plugin");
|
|
|
|
TQString description;
|
|
|
|
|
|
|
|
NPError (*func_GetValue)(void *, NPPVariable, void *) =
|
|
|
|
(NPError(*)(void *, NPPVariable, void *))
|
|
|
|
_handle->symbol("NP_GetValue");
|
|
|
|
if ( func_GetValue ) {
|
|
|
|
|
|
|
|
// get name
|
|
|
|
char *buf = 0;
|
|
|
|
NPError err = func_GetValue( 0, NPPVpluginNameString,
|
|
|
|
(void*)&buf );
|
|
|
|
if ( err==NPERR_NO_ERROR )
|
|
|
|
name = TQString::fromLatin1( buf );
|
|
|
|
kdDebug() << "name = " << name << endl;
|
|
|
|
|
|
|
|
// get name
|
|
|
|
NPError nperr = func_GetValue( 0, NPPVpluginDescriptionString,
|
|
|
|
(void*)&buf );
|
|
|
|
if ( nperr==NPERR_NO_ERROR )
|
|
|
|
description = TQString::fromLatin1( buf );
|
|
|
|
kdDebug() << "description = " << description << endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdWarning() << "Plugin doesn't implement NP_GetValue" << endl;
|
|
|
|
|
|
|
|
// get mime description function pointer
|
|
|
|
char* (*func_GetMIMEDescription)() =
|
|
|
|
(char *(*)())_handle->symbol("NP_GetMIMEDescription");
|
|
|
|
if ( !func_GetMIMEDescription ) {
|
|
|
|
kdDebug(1433) << " - no GetMIMEDescription, skipping" << endl;
|
|
|
|
KLibLoader::self()->unloadLibrary( TQFile::encodeName(absFile) );
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ask for mime information
|
|
|
|
TQString mimeInfo = func_GetMIMEDescription();
|
|
|
|
if ( mimeInfo.isEmpty() ) {
|
|
|
|
kdDebug(1433) << " - no mime info returned, skipping" << endl;
|
|
|
|
KLibLoader::self()->unloadLibrary( TQFile::encodeName(absFile) );
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove version info, as it is not used at the moment
|
|
|
|
TQRegExp versionRegExp(";version=[^:]*:");
|
|
|
|
mimeInfo.replace( versionRegExp, ":");
|
|
|
|
|
|
|
|
// unload plugin lib
|
|
|
|
kdDebug(1433) << " - unloading plugin" << endl;
|
|
|
|
KLibLoader::self()->unloadLibrary( TQFile::encodeName(absFile) );
|
|
|
|
|
|
|
|
// create a TQDataStream for our IPC pipe (to send plugin info back to the parent)
|
|
|
|
FILE *write_pipe = fdopen(write_fd, "w");
|
|
|
|
TQFile stream_file;
|
|
|
|
stream_file.open(IO_WriteOnly, write_pipe);
|
|
|
|
TQDataStream stream(&stream_file);
|
|
|
|
|
|
|
|
// return the gathered info to the parent
|
|
|
|
stream << name;
|
|
|
|
stream << description;
|
|
|
|
stream << mimeInfo;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void scanDirectory( TQString dir, TQStringList &mimeInfoList,
|
|
|
|
TQTextStream &cache )
|
|
|
|
{
|
|
|
|
kdDebug(1433) << "-> scanDirectory dir=" << dir << endl;
|
|
|
|
|
|
|
|
// iterate over all files
|
|
|
|
TQDir files( dir, TQString::null, TQDir::Name|TQDir::IgnoreCase, TQDir::Files );
|
|
|
|
if ( !files.exists( dir ) ) {
|
|
|
|
kdDebug(1433) << "No files found" << endl;
|
|
|
|
kdDebug(1433) << "<- scanDirectory dir=" << dir << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int i=0; i<files.count(); i++) {
|
|
|
|
TQString extension;
|
|
|
|
int j = files[i].findRev('.');
|
|
|
|
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
|
|
|
|
TQString absFile = files.absFilePath( files[i] );
|
|
|
|
kdDebug(1433) << "Checking library " << absFile << endl;
|
|
|
|
|
|
|
|
// open the library and ask for the mimetype
|
|
|
|
kdDebug(1433) << " - opening " << absFile << endl;
|
|
|
|
|
|
|
|
cache.device()->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]);
|
|
|
|
|
|
|
|
TQBuffer m_buffer;
|
|
|
|
m_buffer.open(IO_WriteOnly);
|
|
|
|
|
|
|
|
FILE *read_pipe = fdopen(pipes[0], "r");
|
|
|
|
TQFile q_read_pipe;
|
|
|
|
q_read_pipe.open(IO_ReadOnly, read_pipe);
|
|
|
|
|
|
|
|
char *data = (char *)malloc(4096);
|
|
|
|
if (!data) continue;
|
|
|
|
|
|
|
|
// when the child closes, we'll get an EOF (size == 0)
|
|
|
|
while (int size = q_read_pipe.readBlock(data, 4096)) {
|
|
|
|
if (size > 0)
|
|
|
|
m_buffer.writeBlock(data, size);
|
|
|
|
}
|
|
|
|
free(data);
|
|
|
|
|
|
|
|
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(IO_ReadOnly);
|
|
|
|
|
|
|
|
// create a TQDataStream for our buffer
|
|
|
|
TQDataStream stream(&m_buffer);
|
|
|
|
|
|
|
|
if (stream.atEnd()) continue;
|
|
|
|
|
|
|
|
TQString name, description, mimeInfo;
|
|
|
|
stream >> name;
|
|
|
|
stream >> description;
|
|
|
|
stream >> mimeInfo;
|
|
|
|
|
|
|
|
bool actuallyUsing = false;
|
|
|
|
|
|
|
|
// get mime types from string
|
|
|
|
TQStringList types = TQStringList::split( ';', mimeInfo );
|
|
|
|
TQStringList::Iterator type;
|
|
|
|
for ( type=types.begin(); type!=types.end(); ++type ) {
|
|
|
|
|
|
|
|
kdDebug(1433) << " - type=" << *type << endl;
|
|
|
|
name = name.replace( ':', "%3A" );
|
|
|
|
|
|
|
|
TQString entry = name + ":" + *type;
|
|
|
|
if ( !mimeInfoList.contains( entry ) ) {
|
|
|
|
if (!actuallyUsing) {
|
|
|
|
// note the plugin name
|
|
|
|
cache << "[" << absFile << "]" << endl;
|
|
|
|
actuallyUsing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write into type cache
|
|
|
|
TQStringList tokens = TQStringList::split(':', *type, TRUE);
|
|
|
|
TQStringList::Iterator token;
|
|
|
|
token = tokens.begin();
|
|
|
|
cache << (*token).lower();
|
|
|
|
++token;
|
|
|
|
for ( ; token!=tokens.end(); ++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).
|
|
|
|
TQDir dirs( dir, TQString::null, TQDir::Name|TQDir::IgnoreCase, TQDir::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.absFilePath(dirs[i]), mimeInfoList, cache );
|
|
|
|
}
|
|
|
|
depth--;
|
|
|
|
|
|
|
|
kdDebug() << "<- scanDirectory dir=" << dir << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void writeServicesFile( TQStringList mimeTypes )
|
|
|
|
{
|
|
|
|
TQString fname = TDEGlobal::dirs()->saveLocation("services", "")
|
|
|
|
+ "/nsplugin.desktop";
|
|
|
|
kdDebug(1433) << "Creating services file " << fname << endl;
|
|
|
|
|
|
|
|
TQFile f(fname);
|
|
|
|
if ( f.open(IO_WriteOnly) ) {
|
|
|
|
|
|
|
|
TQTextStream 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-TDE-Library=libnsplugin" << endl;
|
|
|
|
ts << "InitialPreference=7" << endl;
|
|
|
|
ts << "ServiceTypes=KParts/ReadOnlyPart,Browser/View" << endl;
|
|
|
|
ts << "X-TDE-BrowserView-PluginsInfo=nsplugins/pluginsinfo" << endl;
|
|
|
|
|
|
|
|
if (mimeTypes.count() > 0)
|
|
|
|
ts << "MimeType=" << mimeTypes.join(";") << endl;
|
|
|
|
|
|
|
|
f.close();
|
|
|
|
} else
|
|
|
|
kdDebug(1433) << "Failed to open file " << fname << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void removeExistingExtensions( TQString &extension )
|
|
|
|
{
|
|
|
|
TQStringList filtered;
|
|
|
|
TQStringList exts = TQStringList::split( ",", extension );
|
|
|
|
for ( TQStringList::Iterator it=exts.begin(); it!=exts.end(); ++it ) {
|
|
|
|
TQString ext = (*it).stripWhiteSpace();
|
|
|
|
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->name()=="application/octet-stream" ||
|
|
|
|
mime->comment().left(8)=="Netscape" ) {
|
|
|
|
kdDebug() << "accepted" << endl;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static KCmdLineOptions options[] =
|
|
|
|
{
|
|
|
|
{ "verbose", I18N_NOOP("Show progress output for GUI"), 0 },
|
|
|
|
KCmdLineLastOption
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main( int argc, char **argv )
|
|
|
|
{
|
|
|
|
TDEAboutData aboutData( "nspluginscan", I18N_NOOP("nspluginscan"),
|
|
|
|
"0.3", "nspluginscan", TDEAboutData::License_GPL,
|
|
|
|
"(c) 2000,2001 by Stefan Schimanski" );
|
|
|
|
|
|
|
|
TDELocale::setMainCatalogue("nsplugin");
|
|
|
|
TDECmdLineArgs::init( argc, argv, &aboutData );
|
|
|
|
TDECmdLineArgs::addCmdLineOptions( options );
|
|
|
|
TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
|
|
|
|
|
|
|
|
showProgress = args->isSet("verbose");
|
|
|
|
if (showProgress) {
|
|
|
|
printf("10\n"); fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEApplication app(false, 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
|
|
|
|
|
|
|
|
sigaction( SIGCHLD, &act, 0 );
|
|
|
|
|
|
|
|
pullInXt();
|
|
|
|
|
|
|
|
// set up the paths used to look for plugins
|
|
|
|
TQStringList searchPaths = getSearchPaths();
|
|
|
|
TQStringList mimeInfoList;
|
|
|
|
|
|
|
|
infoConfig = new TDEConfig( TDEGlobal::dirs()->saveLocation("data", "nsplugins") +
|
|
|
|
"/pluginsinfo" );
|
|
|
|
infoConfig->writeEntry( "number", 0 );
|
|
|
|
|
|
|
|
// open the cache file for the mime information
|
|
|
|
TQString cacheName = TDEGlobal::dirs()->saveLocation("data", "nsplugins")+"/cache";
|
|
|
|
kdDebug(1433) << "Creating MIME cache file " << cacheName << endl;
|
|
|
|
TQFile cachef(cacheName);
|
|
|
|
if (!cachef.open(IO_WriteOnly))
|
|
|
|
return -1;
|
|
|
|
TQTextStream cache(&cachef);
|
|
|
|
if (showProgress) {
|
|
|
|
printf("20\n"); fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
// read in the plugins mime information
|
|
|
|
kdDebug(1433) << "Scanning directories" << endl;
|
|
|
|
int count = searchPaths.count();
|
|
|
|
int i = 0;
|
|
|
|
for ( TQStringList::Iterator it = searchPaths.begin();
|
|
|
|
it != searchPaths.end(); ++it, ++i)
|
|
|
|
{
|
|
|
|
scanDirectory( *it, mimeInfoList, cache );
|
|
|
|
if (showProgress) {
|
|
|
|
printf("%d\n", 25 + (50*i) / count ); fflush(stdout);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (showProgress) {
|
|
|
|
printf("75\n"); fflush(stdout);
|
|
|
|
}
|
|
|
|
// delete old mime types
|
|
|
|
kdDebug(1433) << "Removing old mimetypes" << endl;
|
|
|
|
deletePluginMimeTypes();
|
|
|
|
if (showProgress) {
|
|
|
|
printf("80\n"); fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
// write mimetype files
|
|
|
|
kdDebug(1433) << "Creating MIME type descriptions" << endl;
|
|
|
|
TQStringList mimeTypes;
|
|
|
|
for ( TQStringList::Iterator it=mimeInfoList.begin();
|
|
|
|
it!=mimeInfoList.end(); ++it) {
|
|
|
|
|
|
|
|
kdDebug(1433) << "Handling MIME type " << *it << endl;
|
|
|
|
|
|
|
|
TQStringList info = TQStringList::split(":", *it, true);
|
|
|
|
if ( info.count()==4 ) {
|
|
|
|
TQString pluginName = info[0];
|
|
|
|
TQString type = info[1].lower();
|
|
|
|
TQString extension = info[2];
|
|
|
|
TQString desc = info[3];
|
|
|
|
|
|
|
|
// append to global mime type list
|
|
|
|
if ( !mimeTypes.contains(type) ) {
|
|
|
|
kdDebug(1433) << " - mimeType=" << type << endl;
|
|
|
|
mimeTypes.append( type );
|
|
|
|
|
|
|
|
// check mimelnk file
|
|
|
|
TQString fname = TDEGlobal::dirs()->findResource("mime", type+".desktop");
|
|
|
|
if ( fname.isEmpty() || isPluginMimeType(fname) ) {
|
|
|
|
kdDebug(1433) << " - creating MIME type description" << endl;
|
|
|
|
removeExistingExtensions( extension );
|
|
|
|
generateMimeType( type, extension, pluginName, desc );
|
|
|
|
} else {
|
|
|
|
kdDebug(1433) << " - already existant" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (showProgress) {
|
|
|
|
printf("85\n"); fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
// close files
|
|
|
|
kdDebug(1433) << "Closing cache file" << endl;
|
|
|
|
cachef.close();
|
|
|
|
|
|
|
|
infoConfig->sync();
|
|
|
|
delete infoConfig;
|
|
|
|
|
|
|
|
// write plugin lib service file
|
|
|
|
writeServicesFile( mimeTypes );
|
|
|
|
if (showProgress) {
|
|
|
|
printf("90\n"); fflush(stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
DCOPClient *dcc = kapp->dcopClient();
|
|
|
|
if ( !dcc->isAttached() )
|
|
|
|
dcc->attach();
|
|
|
|
// Tel kded to update sycoca database.
|
|
|
|
dcc->send("kded", "tdebuildsycoca", "recreate()", TQByteArray());
|
|
|
|
}
|