You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
adept/adept/kubuntu_upgrader/upgradewizard.cpp

544 lines
19 KiB

/***************************************************************************
* Copyright (C) 2006 by Vladimir Stefan *
* vstefan85@gmail.com *
* *
* 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 <kurl.h>
#include <tdeio/netaccess.h>
#include <tdeio/job.h>
#include <kprocess.h>
#include <tdelocale.h>
#include <tdeglobal.h>
#include <tdeconfig.h>
#include <ktar.h>
#include <kdebug.h>
#include <tqwizard.h>
#include <tqwidget.h>
#include <tqpushbutton.h>
#include <tqtextstream.h>
#include <tqfile.h>
#include <tqtextbrowser.h>
#include <tqmime.h>
#include <tqstring.h>
#include <tqdialog.h>
#include <tqlabel.h>
#include <tqdatetime.h>
#include <tqtextstream.h>
#include <tqptrlist.h>
#include <tqdir.h>
#include <iostream>
#include <cstdlib>
#include "upgradewizard.h"
#include "errordialog.h"
DistroEntry::DistroEntry(TQString *d_field)
{
dist_field = d_field;
supported_field = false;
name_field = NULL;
version_field = NULL;
date_field = NULL;
desc_field = NULL;
release_file_url = NULL;
release_notes_url = NULL;
upgrade_tool_url = NULL;
upgrade_tool_sig_url = NULL;
}
DistroEntry::~DistroEntry() {
free( dist_field );
free( name_field );
free( version_field );
free( date_field );
free( desc_field );
free( release_file_url );
free( release_notes_url );
free( upgrade_tool_url );
free( upgrade_tool_sig_url );
}
UpgradeWizard::UpgradeWizard(TQWidget* parent, const char* name, bool modal, WFlags fl)
: UpgradeWizardDlg(parent,name, modal,fl)
{
err_dlg = NULL;
for(int i=0; i<pageCount(); i++) {
TQWidget* p = page( i );
setHelpEnabled( p, false );
}
TQWidget *p = page( pageCount()-1 );
setBackEnabled( p, false );
textLabel3->hide();
p = page( pageCount()-2 );
setNextEnabled( p, false );
TQPushButton *fin = finishButton();
connect(fin, TQT_SIGNAL( clicked() ), this, TQT_SLOT( launchDistUpdater() ) );
}
UpgradeWizard::~UpgradeWizard()
{}
// ** FUNCTIONS ** //
void UpgradeWizard::removeDirectory(TQString directoryName)
{
// recursively delete a directory structure
// Mar-22-2007 Billy Pollifrone
TQDir dir(directoryName);
TQStringList files(dir.entryList());
for (TQStringList::Iterator i=files.begin(); i!=files.end(); i++) {
TQString fileName(*(i));
if (fileName == TQString(".") || fileName == TQString("..")) continue;
TQFileInfo fileInfo(directoryName, fileName);
if (fileInfo.isDir()) {
removeDirectory(fileInfo.absFilePath());
} else {
TQFile file(fileInfo.absFilePath());
file.remove();
}
}
dir.rmdir(directoryName);
}
void UpgradeWizard::removeOldUpgradeTool()
{
// remove old files from dist-upgrade when we check if there is a knew one since
// adept kills us before we have a chance on the same run.
// Mar-22-2007 Billy Pollifrone
TQString directoryName("/tmp/tde-root");
TQString directoryFilter("adept_*.tmp*");
TQDir dir(directoryName, directoryFilter);
TQStringList files(dir.entryList());
for (TQStringList::Iterator i=files.begin(); i!=files.end(); i++) {
TQString fileName(*(i));
TQFileInfo fileInfo(directoryName, fileName);
if (fileInfo.isDir()) {
removeDirectory(fileInfo.absFilePath());
} else {
TQFile file(fileInfo.absFilePath());
file.remove();
}
}
}
bool UpgradeWizard::checkForDistUpgrade(TQString url, bool developmentVersion) {
removeOldUpgradeTool();
std::cout << "UpgradeWizard::checkForDistUpgrade" << std::endl;
if (url == TQString("")) {
url = TQString("http://changelogs.ubuntu.com/meta-release");
}
bool upgrade_available = false;
TDEConfig* config = TDEGlobal::config();
config->setGroup("General Settings");
TQString upgradeURL;
upgradeURL = config->readEntry(TQString("upgradeURL"), url);
KURL metafile_url( upgradeURL );
TQString temp_file_location;
if( TDEIO::NetAccess::download( metafile_url, temp_file_location, NULL ) ) {
TQFile temp_file( temp_file_location );
temp_file.open( IO_ReadOnly );
TQTextIStream *temp_file_stream = new TQTextIStream( temp_file.readAll() );
// need to spawn a process to call lsb_release -c -s
// to find out which version of kubuntu we are using
TDEProcess *proc = new TDEProcess;
*proc << "lsb_release";
*proc << "-c" << "-s";
connect(proc, TQT_SIGNAL( receivedStdout( TDEProcess*, char *, int ) ),
this, TQT_SLOT( receiveDistroName( TDEProcess*, char *, int ) ) );
proc->start( TDEProcess::Block, TDEProcess::Stdout );
current_dist = 0;
TQPtrList<DistroEntry> *entry_list = parseMetafile( temp_file_stream, distro_name );
upgrade_dist = entry_list->last();
DistroEntry* entry;
// if current_dist hasn't been set in parseMetafile then we can't upgrade, since we don't know what we are
if (current_dist == 0) {
return false;
}
// find the distro version one newer than our current one
for( entry = entry_list->first(); entry; entry = entry_list->next() ) {
//std::cout << "current date: " << (*current_dist->date_field).toString().latin1() << std::endl;
//std::cout << "entry date: " << (*entry->date_field).toString().latin1() << std::endl;
if( *entry->date_field > *current_dist->date_field /*&& entry->supported_field == true*/ ) {
upgrade_dist = entry;
upgrade_available = true;
//std::cout << "entry date: " << (*entry->name_field).latin1() << std::endl;
break;
}
}
// if there isn't one newer, find the current one
if (!upgrade_available) {
for( entry = entry_list->first(); entry; entry = entry_list->next() ) {
//std::cout << "current date: " << (*current_dist->date_field).toString().latin1() << std::endl;
//std::cout << "entry date: " << (*entry->date_field).toString().latin1() << std::endl;
if( *entry->date_field >= *current_dist->date_field && developmentVersion /*&& entry->supported_field == true*/ ) {
upgrade_dist = entry;
upgrade_available = true;
//std::cout << "entry date: " << (*entry->name_field).latin1() << std::endl;
break;
}
}
}
// DistroEntry *entry = NULL;
/*Debugging
for( entry = entry_list->first(); entry; entry = entry_list->next() ) {
std::cout << "current date: " << (*current_dist->date_field).toString().latin1() << std::endl;
std::cout << "entry date: " << (*entry->date_field).toString().latin1() << std::endl;
std::cout << "Dist: " << *entry->dist_field->latin1() << std::endl;
std::cout << "Name: " << *entry->name_field->latin1() << std::endl;
std::cout << "Version: " << *entry->version_field->latin1() << std::endl;
std::cout << "Date: " << entry->date_field->toString( TQString( "ddd, dd MMM yyyy hh:mm:ss UTC" ) ).latin1() << std::endl;
//std::cout << "Supported: " << entry->supported_field.latin1() << std::endl;
std::cout << "Description: " << *entry->desc_field->latin1() << std::endl;
std::cout << "Release-File: " << entry->release_file_url->prettyURL().latin1() << std::endl;
if( entry->release_notes_url != NULL ) {
std::cout << "ReleaseNotes: " << entry->release_notes_url->prettyURL().latin1() << std::endl;
}
if( entry->upgrade_tool_url != NULL ) {
std::cout << "UpgradeTool: " << entry->upgrade_tool_url->prettyURL().latin1() << std::endl;
}
if( entry->upgrade_tool_sig_url != NULL ) {
std::cout << "UpgradeToolSignature: " << entry->upgrade_tool_sig_url->prettyURL().latin1() << std::endl;
}
std::cout << std::endl;
}
*/
temp_file.close();
TDEIO::NetAccess::removeTempFile( temp_file_location );
}
return upgrade_available;
}
TQPtrList<DistroEntry> *UpgradeWizard::parseMetafile( TQTextIStream *text_stream,
TQString my_distro_name )
{
TQPtrList<DistroEntry> *metafile_entries = new TQPtrList<DistroEntry>();
DistroEntry *entry = NULL;
while( !text_stream->atEnd() ) {
TQStringList line = TQStringList::split( TQChar(':'), text_stream->readLine() );
if( !line.isEmpty() ) {
TQString first = line.first();
if( TQString::compare( first, TQString( "Dist" ) ) == 0 ) {
// we've encountered a new entry:
// first save the old one
if( entry != NULL ) {
// if this entry is for the current version we are running,
// then add it at the start of the list
if( TQString::compare( *entry->dist_field, my_distro_name ) == 0) {
current_dist = entry;
metafile_entries->prepend( entry );
} else {
metafile_entries->append( entry );
}
}
// now create a new entry
line.pop_front();
entry = new DistroEntry( new TQString( line.first().stripWhiteSpace() ) );
}
else if( TQString::compare( first, TQString( "Name" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
entry->name_field = new TQString( line.first().stripWhiteSpace() );
}
}
else if( TQString::compare( first, TQString( "Version" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
entry->version_field = new TQString( line.first().stripWhiteSpace() );
}
}
else if( TQString::compare( first, TQString( "Date" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
TQString temp = line.join( TQChar(' ') ).stripWhiteSpace();
// get the day(verbal)
line = TQStringList::split( TQChar(' '), temp );
TQString day_verbal = line.first();
day_verbal.truncate(3);
// get the date
line.pop_front();
TQString date = line.first();
// get the month(verbal)
line.pop_front();
TQString month_verbal = line.first();
// get the year
line.pop_front();
TQString year = line.first();
// get the time
line.pop_front();
TQString time = line.first() + ":";
line.pop_front();
time += line.first() + ":";
line.pop_front();
time += line.first();
TQDate the_date( TQDate::fromString( day_verbal + " " + month_verbal + " " + date + " " + year) );
TQTime the_time( TQTime::fromString( time ) );
entry->date_field = new TQDateTime( the_date, the_time );
}
}
else if( TQString::compare( first, TQString( "Supported" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
entry->supported_field = line.first().stripWhiteSpace().toInt();
}
}
else if( TQString::compare( first, TQString( "Description" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
entry->desc_field = new TQString( line.first().stripWhiteSpace() );
}
}
else if( TQString::compare( first, TQString( "Release-File" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
TQString http_part = line.first().stripWhiteSpace() + ":";
line.pop_front();
TQString complete_url = http_part + line.first().stripWhiteSpace();
entry->release_file_url = new KURL( complete_url );
}
}
else if( TQString::compare( first, TQString( "ReleaseNotes" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
TQString http_part = line.first().stripWhiteSpace() + ":";
line.pop_front();
TQString complete_url = http_part + line.first().stripWhiteSpace();
entry->release_notes_url = new KURL( complete_url );
}
}
else if( TQString::compare( first, TQString( "UpgradeTool" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
TQString http_part = line.first().stripWhiteSpace() + ":";
line.pop_front();
TQString complete_url = http_part + line.first().stripWhiteSpace();
entry->upgrade_tool_url = new KURL( complete_url );
}
}
else if( TQString::compare( first, TQString( "UpgradeToolSignature" ) ) == 0 ) {
if( entry != NULL ) {
line.pop_front();
TQString http_part = line.first().stripWhiteSpace() + ":";
line.pop_front();
TQString complete_url = http_part + line.first().stripWhiteSpace();
entry->upgrade_tool_sig_url = new KURL( complete_url );
}
}
}
}
// add the last one
// if this entry is for the current version we are running,
// then add it at the start of the list
if( TQString::compare( *entry->dist_field, my_distro_name ) == 0 ) {
current_dist = entry;
metafile_entries->prepend( entry );
} else {
metafile_entries->append( entry );
}
return metafile_entries;
}
// ** SLOTS ** //
void UpgradeWizard::receiveDistroName( TDEProcess*, char *buffer, int buflen ) {
distro_name = TQString::fromAscii( buffer, buflen-1 );
}
void UpgradeWizard::launchDistUpdater() {
TQDir dir;
dir.mkdir(upgrade_tool_location+"-extract");
KTar tarFile(upgrade_tool_location, TQString("application/x-gzip"));
tarFile.open(IO_ReadOnly);
//KArchiveDirectory* tarDirectory = tarFile.directory();
//tarDirectory->copyTo(upgrade_tool_location+"-extract");
tarFile.directory()->copyTo(upgrade_tool_location+"-extract", true);
TDEProcess *proc = new TDEProcess;
proc->setWorkingDirectory(upgrade_tool_location+"-extract");
*proc << "python" << upgrade_tool_location+"-extract/dist-upgrade.py";
*proc << "--frontend" << "DistUpgradeViewKDE";
proc->start( TDEProcess::DontCare );
// don't kill adept, it stops the app from running
// parentWidget()->close();
}
void UpgradeWizard::fetchReleaseAnnounce() {
TQString temp_file_location;
bool result = false;
if (upgrade_dist->release_notes_url == NULL) {
kdDebug() << "No release notes URL, so I'm skipping the fetch." << endl;
} else {
KURL my_url(*upgrade_dist->release_notes_url);
result = TDEIO::NetAccess::download(my_url, temp_file_location, NULL );
}
if( result ) {
emit killErrorDialog();
err_dlg = NULL;
textBrowser1->mimeSourceFactory()->setExtensionType( TQString("tmp"), "text/plain" );
textBrowser1->setSource( temp_file_location );
TQWidget *p = page( pageCount()-2 );
setNextEnabled( p, true );
} else {
if(err_dlg == NULL ) {
err_dlg = new ErrorDialog( this, i18n( "Could not download the release announcement. Please check that your Internet connection is active." ), 0, 1 );
connect( err_dlg->retryButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( fetchReleaseAnnounce() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), err_dlg, TQT_SLOT( close() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( close() ) );
connect( this, TQT_SIGNAL( killErrorDialog() ), err_dlg, TQT_SLOT( close() ) );
err_dlg->show();
}
}
}
void UpgradeWizard::fetchUpgradeTool() {
// download the upgrade tool
KURL my_url(*upgrade_dist->upgrade_tool_url);
bool result = TDEIO::NetAccess::download( my_url, upgrade_tool_location, NULL );
// uncomment this to use for testing if you don't want to d/l the file every time
//bool result = TDEIO::NetAccess::download( "/home/vladi/edgy.tar.gz", upgrade_tool_location, NULL );
if( result ) {
emit killErrorDialog();
err_dlg = NULL;
fetchUpgradeToolSig();
} else {
if(err_dlg == NULL ) {
err_dlg = new ErrorDialog( this, i18n( "Could not download the upgrade tool. Please check that your Internet connection is active." ), 0, 1 );
connect( err_dlg->retryButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( fetchUpgradeTool() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), err_dlg, TQT_SLOT( close() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( close() ) );
connect( this, TQT_SIGNAL( killErrorDialog() ), err_dlg, TQT_SLOT( close() ) );
err_dlg->show();
}
}
}
void UpgradeWizard::fetchUpgradeToolSig() {
bool result = TDEIO::NetAccess::download( *upgrade_dist->upgrade_tool_sig_url, upgrade_tool_sig_location, NULL );
if( result) {
emit killErrorDialog();
err_dlg = NULL;
verifyUpgradeTool();
} else {
if(err_dlg == NULL ) {
err_dlg = new ErrorDialog( this, i18n( "Could not download the upgrade tool's GPG signature. Please check that your Internet connection is active." ), 0, 1 );
connect( err_dlg->retryButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( fetchUpgradeToolSig() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), err_dlg, TQT_SLOT( close() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( close() ) );
connect( this, TQT_SIGNAL( killErrorDialog() ), err_dlg, TQT_SLOT( close() ) );
err_dlg->show();
}
}
}
void UpgradeWizard::verifyUpgradeTool() {
// spawn a process to call gpg and verify the signature
TDEProcess *proc = new TDEProcess;
*proc << "gpg";
*proc << "--keyring" << "/etc/apt/trusted.gpg" << "--verify" << upgrade_tool_sig_location << upgrade_tool_location;
proc->start( TDEProcess::Block, TDEProcess::Stdout );
// signature verification successful if gpg exist status = 0
if( proc->exitStatus() == 0 ) {
emit killErrorDialog();
err_dlg = NULL;
// remove the signature file
TDEIO::file_delete( KURL( upgrade_tool_sig_location ), false );
TQWidget *p = page( pageCount()-1 );
setFinishEnabled( p, true );
textLabel3->show();
} else {
if(err_dlg == NULL ) {
err_dlg = new ErrorDialog( this, i18n( "Could not verify the integrity of the upgrader application. This program will now exit." ), 0, 1 );
//connect( err_dlg->retryButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( verify_upgrade_tool() ) );
err_dlg->retryButton->setEnabled( false );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), err_dlg, TQT_SLOT( close() ) );
connect( err_dlg->exitButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( close() ) );
connect( this, TQT_SIGNAL( killErrorDialog() ), err_dlg, TQT_SLOT( close() ) );
err_dlg->show();
}
}
}
void UpgradeWizard::back()
{
TQWizard::back();
}
void UpgradeWizard::next()
{
TQWizard::next();
// page 1: d/l release announcement
// and display it on page1
if( indexOf( currentPage() ) == 1 ) {
fetchReleaseAnnounce();
}
else if( indexOf( currentPage() ) == 2 ) {
// remove the temp file used to store the release announcement
TDEIO::file_delete( KURL( textBrowser1->source() ), false );
// download the tool, its signature, and verify
fetchUpgradeTool();
}
}
#include "upgradewizard.moc"