/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; ihide(); 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 *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 *UpgradeWizard::parseMetafile( TQTextIStream *text_stream, TQString my_distro_name ) { TQPtrList *metafile_entries = new TQPtrList(); 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"