/* * This file is part of the KDE project. * * Copyright (C) 2005 Benoit Canet * with some advices from Aurelien Gateau * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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& 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 "<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::iterator it; QValueList 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(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(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; }