summaryrefslogtreecommitdiffstats
path: root/khtml/misc/knsplugininstaller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/misc/knsplugininstaller.cpp')
-rw-r--r--khtml/misc/knsplugininstaller.cpp672
1 files changed, 672 insertions, 0 deletions
diff --git a/khtml/misc/knsplugininstaller.cpp b/khtml/misc/knsplugininstaller.cpp
new file mode 100644
index 000000000..4cfbf3339
--- /dev/null
+++ b/khtml/misc/knsplugininstaller.cpp
@@ -0,0 +1,672 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 2005 Benoit Canet <[email protected]>
+ * with some advices from Aurelien Gateau <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#include "knsplugininstaller.moc"
+
+#include <kdebug.h>
+#include <kdiroperator.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kstddirs.h>
+#include <ktempfile.h>
+#include <netaccess.h>
+
+#include <qbuttongroup.h>
+#include <qdir.h>
+#include <qiodevice.h>
+#include <qfile.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmap.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+#include <sys/utsname.h>
+
+// Use 6031 for debugging (render_frame)
+#define DEBUG_NUMBER 6031
+
+/*
+ * Utility class to associate a list item with a pluginInfo object
+ */
+class PluginListItem : public QListViewItem
+{
+
+public:
+ PluginListItem(KNSPluginInfo pluginInfo, QListView *parent)
+ : QListViewItem(parent, pluginInfo.pluginName())
+ , m_pluginInfo(pluginInfo) {}
+ KNSPluginInfo pluginInfo() const { return m_pluginInfo; }
+
+private:
+ KNSPluginInfo m_pluginInfo;
+
+};
+
+
+// public methods
+
+KNSPluginInstallEngine::KNSPluginInstallEngine(KMimeType::Ptr mime) : QObject()
+{
+ m_mime = mime;
+
+ // Fill the architecture map
+ m_archMap["i386"] = "ia32";
+ m_archMap["i486"] = "ia32";
+ m_archMap["i586"] = "ia32";
+ m_archMap["i686"] = "ia32";
+}
+
+KNSPluginInstallEngine::~KNSPluginInstallEngine()
+{
+}
+
+bool KNSPluginInstallEngine::pluginAvailable()
+{
+
+ if(m_pluginList.count())
+ return true;
+
+ // check if pluginsListFile is present in kde config
+ if(!loadConfig())
+ return false;
+
+ // load the xml configuration file
+ if(!loadXmlConfig())
+ return false;
+
+ return findPlugin();
+}
+
+bool KNSPluginInstallEngine::isActive()
+{
+ // check if we have a configuration key in the kde registry
+ QString pluginsListFile;
+ KConfig cfg("kcmnspluginrc", true);
+ cfg.setGroup("Misc");
+ pluginsListFile = cfg.readPathEntry("PluginsListFile");
+ return !pluginsListFile.isEmpty();
+}
+
+const QValueList<KNSPluginInfo>& KNSPluginInstallEngine::pluginList() const
+{
+ return m_pluginList;
+}
+
+// private methods
+bool KNSPluginInstallEngine::loadConfig()
+{
+ QString pluginsListFile;
+ KConfig cfg("kcmnspluginrc", true);
+ cfg.setGroup("Misc");
+ pluginsListFile = cfg.readPathEntry("PluginsListFile");
+ if(!pluginsListFile.isEmpty())
+ {
+ m_pluginsListFileURL = KURL(pluginsListFile);
+ kdDebug(DEBUG_NUMBER) << "config loaded "<<endl;
+ return true;
+ }
+ return false;
+}
+
+bool KNSPluginInstallEngine::loadXmlConfig()
+{
+
+ // load the Xml configuration file
+ if(m_pluginsXmlConfig.isEmpty())
+ {
+ QString tmpFile;
+ if(KIO::NetAccess::download(m_pluginsListFileURL, tmpFile, NULL)) {
+ QFile f(tmpFile);
+ if(!f.open(IO_ReadOnly))
+ return false;
+ QTextStream stream(&f);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ m_pluginsXmlConfig = stream.read();
+ f.close();
+ KIO::NetAccess::removeTempFile(tmpFile);
+ } else
+ return false;
+ }
+ kdDebug(DEBUG_NUMBER) << "xml config loaded :" << endl;
+ return true;
+}
+
+bool KNSPluginInstallEngine::findPlugin()
+{
+
+ // get system infos
+ // TODO/FIX : correct this to work with x86-64 machines
+ utsname sysinfo;
+ if(uname(&sysinfo))
+ return false;
+ QString sysname(sysinfo.sysname);
+ QString machine(sysinfo.machine);
+ QString arch = m_archMap[machine];
+
+ // Parse the document
+ QDomDocument doc("xmlConfig");
+ doc.setContent(m_pluginsXmlConfig);
+ QDomNodeList archList = doc.elementsByTagName(QString("arch"));
+ QDomNode archNode, osNode , pluginNode, node;
+ QDomElement e;
+
+ // look for the correct architecture
+ bool found = false;
+ unsigned int i;
+ for(i=0; i < archList.count() ; i++) {
+ archNode = archList.item(i);
+ e = archNode.toElement();
+ if( e.attribute("architecture") == arch) {
+ kdDebug(DEBUG_NUMBER) << "found correct architecture :" << arch << endl;
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ return false;
+
+ // look for the correct os
+ found = false;
+ osNode = archNode.firstChild();
+ while(!osNode.isNull()) {
+ e = osNode.toElement();
+ if( e.tagName() == "os" && e.attribute("name") == sysname) {
+ kdDebug(DEBUG_NUMBER) << "found correct os :" << sysname << endl;
+ found = true;
+ break;
+ }
+ osNode=osNode.nextSibling();
+ }
+
+ if(!found)
+ return false;
+
+ // Look for a plugin with the given mimetype
+ pluginNode = osNode.firstChild();
+ while(!pluginNode.isNull()) {
+ e = pluginNode.toElement();
+ if( e.tagName() == "plugin" && m_mime->is(e.attribute("mimetype")) ) {
+ kdDebug(DEBUG_NUMBER) << "found correct plugin :" << e.attribute("mimetype") << endl;
+ KNSPluginInfo pluginInfo(pluginNode);
+ if(pluginInfo.isValid())
+ m_pluginList.append(pluginInfo);
+ }
+ pluginNode=pluginNode.nextSibling();
+ }
+
+ if(m_pluginList.count())
+ return true;
+ else
+ return false;
+}
+
+
+void KNSPluginInstallEngine::startInstall(KNSPluginInfo info)
+{
+ m_toInstallPluginInfo = info;
+ // create a temporary dowload file
+ KTempFile tempFile(locateLocal("tmp", "plugin") , QString(".tar.gz"));
+ m_tmpPluginFileName = tempFile.name();
+ tempFile.unlink();
+ tempFile.close();
+ // start the download job
+ m_downloadJob = KIO::copy(info.pluginURL(), "file://"+m_tmpPluginFileName, false );
+ // connect signals
+ connect(m_downloadJob, SIGNAL(percent (KIO::Job *, unsigned long)), this , SLOT(slotDownLoadProgress(KIO::Job *, unsigned long)));
+ connect(m_downloadJob, SIGNAL(result(KIO::Job *)), this, SLOT(slotDownloadResult(KIO::Job *)) );
+ kdDebug(DEBUG_NUMBER) << "download plugin " << m_tmpPluginFileName << endl;
+}
+
+void KNSPluginInstallEngine::slotDownLoadProgress(KIO::Job *, unsigned long percent)
+{
+ // propagate the download progression
+ emit installProgress( ((int)percent)/3 );
+}
+
+void KNSPluginInstallEngine::slotDownloadResult(KIO::Job *job)
+{
+ // test if the download job suceed
+ if(job->error()) {
+ kdDebug(DEBUG_NUMBER) << "download error" << m_tmpPluginFileName << endl;
+ emit installFailed();
+ }
+ else {
+ kdDebug(DEBUG_NUMBER) << "download completed" << m_tmpPluginFileName << endl;
+ // the download succeed copy the plugins files
+
+ // test the existance of the homedir
+ QDir dir(QDir::homeDirPath());
+ if(!dir.exists()) {
+ emit installFailed();
+ return;
+ }
+
+ // test and create firefox plugins directory
+ if(!dir.exists(".mozilla"))
+ dir.mkdir(".mozilla");
+ if(!dir.exists(".mozilla/plugins"))
+ dir.mkdir(".mozilla/plugins");
+ // destination kurl
+ KURL destURL("file://"+QDir::homeDirPath()+"/.mozilla/plugins");
+
+ // construct the source kurlList
+ KURL::List urlList;
+ QStringList pluginFileList = m_toInstallPluginInfo.pluginFileList();
+
+ QStringList::iterator it;
+ for( it = pluginFileList.begin(); it != pluginFileList.end(); ++it ) {
+ urlList.append( KURL("tar://"+m_tmpPluginFileName+"/"+(*it)) );
+ }
+ m_installFileJob = KIO::copy(urlList , destURL, false );
+ connect(m_installFileJob, SIGNAL(percent (KIO::Job *, unsigned long)), this , SLOT(slotCopyProgress(KIO::Job *, unsigned long)));
+ connect(m_installFileJob, SIGNAL(result(KIO::Job *)), this, SLOT(slotCopyResult(KIO::Job *)) );
+ }
+ kdDebug(DEBUG_NUMBER) << "COPY FILE " << m_tmpPluginFileName << endl;
+
+ // zero the download job pointer
+ m_downloadJob = NULL;
+}
+
+void KNSPluginInstallEngine::slotCopyProgress(KIO::Job *, unsigned long percent)
+{
+ // propagate the download progression
+ emit installProgress( ((int)percent)/3 + 33 );
+}
+
+void KNSPluginInstallEngine::slotCopyResult(KIO::Job *job)
+{
+ // test if the download job suceed
+ if(job->error()) {
+ kdDebug(DEBUG_NUMBER) << "download error" << m_tmpPluginFileName << endl;
+ emit installFailed();
+ }
+ else {
+ // start the plugins scan
+ m_scanProc = new QProcess( this );
+ m_scanProc->addArgument( "nspluginscan" );
+ m_scanProc->addArgument( "--verbose" );
+
+ connect( m_scanProc, SIGNAL(readyReadStdout()),
+ this, SLOT(readScanProcFromStdout()) );
+ connect( m_scanProc, SIGNAL(processExited()),
+ this, SLOT(endScanProc()) );
+ if ( !m_scanProc->start() ) {
+ emit installFailed();
+ }
+ }
+}
+
+void KNSPluginInstallEngine::readScanProcFromStdout()
+{
+ // Monitor the scan progress
+ QString progress = m_scanProc->readLineStdout();
+ int percent;
+ bool ok;
+ percent = progress.toInt(&ok);
+ if(!ok)
+ emit installFailed();
+ emit installProgress( (percent)/3 + 66 );
+}
+
+
+void KNSPluginInstallEngine::endScanProc()
+{
+ // end of scan
+ if(m_scanProc->normalExit()) {
+ emit installProgress( 100 );
+ emit installCompleted();
+ } else
+ emit installFailed();
+}
+
+KNSPluginWizard::KNSPluginWizard(QWidget *parent, const char *name, KMimeType::Ptr mime)
+: KWizard(parent, name, true)
+, m_installEngine(mime)
+{
+ setCaption(i18n("KDE plugin wizard"));
+ setModal(true);
+
+ // read the plugin installer configuration
+ m_installEngine.pluginAvailable();
+
+ // init the wizzard Pages
+ initConfirmationPage();
+ initLicencePage();
+ initInstallationProgressPage();
+ initFinishPage();
+ initPagesButtonStates();
+
+ // connect signals and slots
+ connectSignals();
+
+ //set correct default installation status
+ m_installationComplete = false;
+
+};
+
+
+KNSPluginWizard::~KNSPluginWizard()
+{
+};
+
+void KNSPluginWizard::initConfirmationPage()
+{
+
+ m_confirmationVBox = new QVBox(this);
+ new QLabel(i18n("The following plugins are available."), m_confirmationVBox);
+ m_pluginListView = new KListView(m_confirmationVBox);
+ m_pluginListView->addColumn(i18n("Name"));
+ m_pluginListView->setSelectionMode(QListView::Single);
+ new QLabel(i18n("Click on next to install the selected plugin."), m_confirmationVBox);
+ addPage (m_confirmationVBox, i18n("Plugin installation confirmation"));
+
+ bool selected = false;
+
+ // Fill the plugin list
+ QValueList<KNSPluginInfo>::iterator it;
+ QValueList<KNSPluginInfo> pluginList = m_installEngine.pluginList();
+ for( it = pluginList.begin(); it != pluginList.end(); ++it ) {
+ PluginListItem *item = new PluginListItem((*it) , m_pluginListView);
+ if(!selected) {
+ selected = true;
+ m_pluginListView->setSelected(item, true);
+ }
+ kdDebug(DEBUG_NUMBER) << "New Plugin List item"<< endl;
+ setNextEnabled(m_confirmationVBox, true);
+ }
+}
+
+void KNSPluginWizard::initLicencePage()
+{
+ m_licenceVBox = new QVBox(this);
+ m_licencePageLabel = new QLabel(m_licenceVBox);
+ m_licencePageText = new KTextEdit(m_licenceVBox);
+ m_licencePageText->setReadOnly(true);
+
+ // invisible buttonGroup
+ QButtonGroup *buttonGroup = new QButtonGroup(this);
+ m_agreementButtonGroup = buttonGroup;
+ buttonGroup->hide();
+ buttonGroup->setExclusive(true);
+
+ m_licencePageAgree = new QRadioButton ( i18n("I agree."), m_licenceVBox);
+
+ m_licencePageDisagree = new QRadioButton ( i18n("I do not agree (plugin will not be installed)."), m_licenceVBox);
+
+ buttonGroup->insert(m_licencePageAgree);
+ buttonGroup->insert(m_licencePageDisagree);
+ m_licencePageDisagree->setChecked(true);
+
+ addPage (m_licenceVBox, i18n("Plugin licence"));
+
+
+ connect(buttonGroup, SIGNAL(clicked(int)), this, SLOT(slotAgreementClicked(int)));
+}
+
+void KNSPluginWizard::initInstallationProgressPage() {
+
+ m_installationProgressWidget = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(m_installationProgressWidget);
+ layout->addWidget(new QLabel(i18n("Installation in progress."), m_installationProgressWidget));
+ layout->addItem(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Expanding ));
+ m_installationProgressBar = new KProgress(m_installationProgressWidget);
+ m_installationProgressBar->setTotalSteps(100);
+ layout->addWidget(m_installationProgressBar);
+
+ addPage( m_installationProgressWidget, i18n("Plugin installation"));
+
+}
+
+void KNSPluginWizard::initFinishPage()
+{
+ m_finishWidget = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(m_finishWidget);
+ layout->addItem(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Expanding ));
+ m_finishLabel = new QLabel(m_finishWidget);
+ layout->addWidget(m_finishLabel);
+ layout->addItem(new QSpacerItem(40,20,QSizePolicy::Expanding,QSizePolicy::Expanding ));
+
+ addPage(m_finishWidget, i18n("Installation status"));
+
+}
+
+
+void KNSPluginWizard::initPagesButtonStates()
+{
+ // set buttons states for the confirmation page
+ setNextEnabled(m_confirmationVBox, true);
+ setFinishEnabled(m_confirmationVBox, false);
+ setHelpEnabled(m_confirmationVBox, false);
+
+ // set buttons states for the licence page
+ setNextEnabled(m_licenceVBox , false);
+ setBackEnabled(m_licenceVBox , false);
+ setFinishEnabled(m_licenceVBox , false);
+ setHelpEnabled(m_licenceVBox , false);
+
+ // for the installation page
+ setNextEnabled(m_installationProgressWidget , false);
+ setBackEnabled(m_installationProgressWidget , false);
+ setFinishEnabled(m_installationProgressWidget , false);
+ setHelpEnabled(m_installationProgressWidget , false);
+
+ // for the finish page
+ setNextEnabled(m_finishWidget , false);
+ setBackEnabled(m_finishWidget , false);
+ setFinishEnabled(m_finishWidget , true);
+ setHelpEnabled(m_finishWidget , false);
+}
+
+
+
+void KNSPluginWizard::connectSignals() {
+ connect(&m_installEngine, SIGNAL(installProgress(int)), m_installationProgressBar, SLOT(setProgress(int)) );
+ connect(&m_installEngine, SIGNAL(installCompleted()), this, SLOT(slotInstallationCompleted()) );
+ connect(&m_installEngine, SIGNAL(installFailed()), this, SLOT(slotInstallationFailed()) );
+
+
+}
+
+void KNSPluginWizard::showPage(QWidget *page)
+{
+
+ // if the licence page is shown set the label and the licence content
+ if(page == m_licenceVBox && m_licencePageLabel->text().isEmpty()) {
+ KNSPluginInfo info = static_cast<PluginListItem *>(m_pluginListView->selectedItem())->pluginInfo();
+ m_licencePageLabel->setText(i18n("To install ")+info.pluginName()+i18n(" you need to agree to the following"));
+ QString licence;
+ licence = info.licence();
+ QString tmpFile;
+ if(info.licenceURL().isValid())
+ // retrieve the licence if we have an url
+ if(KIO::NetAccess::download(info.licenceURL(), tmpFile, NULL)) {
+ QFile f(tmpFile);
+ if(f.open(IO_ReadOnly)) {
+ QTextStream stream(&f);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ licence = stream.read();
+ f.close();
+ KIO::NetAccess::removeTempFile(tmpFile);
+ }
+ }
+ // else display the licence found in the xml config
+ m_licencePageText->setText(licence);
+
+ }
+
+ // if the installation page is shown start the download
+ if(page == m_installationProgressWidget) {
+ KNSPluginInfo info = static_cast<PluginListItem *>(m_pluginListView->selectedItem())->pluginInfo();
+ m_installEngine.startInstall(info);
+
+ }
+
+ // If we must display the finish page
+ if(page == m_finishWidget) {
+ if(m_installationComplete) {
+ m_finishLabel->setText(i18n("Installation completed. Reload the page."));
+
+ } else
+ m_finishLabel->setText(i18n("Installation failed"));
+
+ }
+
+
+ KWizard::showPage(page);
+}
+
+int KNSPluginWizard::exec()
+{
+ if(!m_installEngine.pluginList().count())
+ return QDialog::Rejected;
+
+ return KWizard::exec();
+}
+
+
+bool KNSPluginWizard::pluginAvailable()
+{
+ return m_installEngine.pluginAvailable();
+}
+
+void KNSPluginWizard::slotAgreementClicked(int id)
+{
+ if( id == m_agreementButtonGroup->id(m_licencePageAgree) ) {
+ setNextEnabled(m_licenceVBox, true);
+
+ } else {
+ setNextEnabled(m_licenceVBox, false);
+ }
+
+}
+
+void KNSPluginWizard::slotInstallationCompleted()
+{
+ m_installationComplete = true;
+ // enable next button
+ setNextEnabled(m_installationProgressWidget, true);
+ next();
+}
+void KNSPluginWizard::slotInstallationFailed()
+{
+ m_installationComplete = false;
+ showPage(m_finishWidget);
+}
+
+
+// KNSPlugin info copy constructor
+
+KNSPluginInfo::KNSPluginInfo()
+{
+
+}
+
+// KNSPlugin info constructor par an xml dom fragment
+KNSPluginInfo::KNSPluginInfo(QDomNode pluginNode)
+{
+ QDomElement e;
+ QDomNode node;
+
+ // Read plugin informations
+ node = pluginNode.firstChild();
+ while(!node.isNull()) {
+ e = node.toElement();
+ if( e.tagName() == "pluginname") {
+ kdDebug(DEBUG_NUMBER) << "found name " << e.text() << endl;
+ m_pluginName = e.text();
+ }
+
+ if( e.tagName() == "pluginurl") {
+ kdDebug(DEBUG_NUMBER) << "found plugin url " << e.text() << endl;
+ m_pluginURL = KURL(e.text());
+ }
+
+ if( e.tagName() == "licence") {
+ kdDebug(DEBUG_NUMBER) << "found licence " << e.text() << endl;
+ m_licence = e.text();
+ }
+
+ if( e.tagName() == "licenceurl") {
+ kdDebug(DEBUG_NUMBER) << "found licenceurl " << e.text() << endl;
+ m_licenceURL = KURL(e.text());
+ }
+
+ if( e.tagName() == "pluginfile") {
+ kdDebug(DEBUG_NUMBER) << "found pluginfile " << e.text() << endl;
+ m_pluginFileList.append(e.text());
+ }
+ node = node.nextSibling();
+ }
+}
+
+
+KNSPluginInfo::~KNSPluginInfo()
+{
+
+}
+
+
+bool KNSPluginInfo::isValid() const
+{
+ // tell if the pluginInfo is a valid One
+ if( m_pluginName.isEmpty() || ( m_licence.isEmpty() && !m_licenceURL.isValid() ) || !m_pluginURL.isValid() || m_pluginFileList.empty() ) {
+ kdDebug(DEBUG_NUMBER) << "invalid plugin info" << endl;
+ return false;
+
+ }
+
+ else {
+
+ kdDebug(DEBUG_NUMBER) << "valid plugin info" << endl;
+ return true;
+ }
+}
+
+// Accesors
+QString KNSPluginInfo::pluginName() const
+{
+ return m_pluginName;
+}
+
+QString KNSPluginInfo::licence() const
+{
+ return m_licence;
+}
+
+KURL KNSPluginInfo::licenceURL() const
+{
+ return m_licenceURL;
+}
+
+KURL KNSPluginInfo::pluginURL() const
+{
+ return m_pluginURL;
+}
+
+const QStringList& KNSPluginInfo::pluginFileList() const
+{
+ return m_pluginFileList;
+}