0.7.1
[fapman] / aaptinterface.cpp
index 7ff8033..bda25dc 100644 (file)
@@ -45,6 +45,8 @@ AAptInterface::AAptInterface(QObject* parent = 0) : QObject(parent)
        iLastListUpdate.setTime_t(0);
        iLastDpkgUpdate.setTime_t(0);
 
+       iDataReadBuffer = new char[KDataReadBufferSize];
+
        iProcAptGetUpdate = new QProcess(this);
        iProcAptGetSimulate = new QProcess(this);
        iProcAptGetInstall = new QProcess(this);
@@ -84,12 +86,6 @@ AAptInterface::AAptInterface(QObject* parent = 0) : QObject(parent)
        QFile logfile(KLogFile);
        logfile.remove();
 
-       // clear files left from old versions
-       QFile f1("/root/.fapman/dates.cache");
-       f1.remove();
-       QFile f2("/root/.fapman/lastupdate");
-       f2.remove();
-
        readRepositoryInfo();
 }
 
@@ -103,6 +99,33 @@ AAptInterface::~AAptInterface()
                iProcAptGetInstall->kill();
        if( iProcAptGetClean->state() != QProcess::NotRunning )
                iProcAptGetClean->kill();
+
+       // qprocesses are automatically deleted by their parent
+
+       QHashIterator<QString, Package*> a( iPackagesAvailable );
+       while (a.hasNext())
+       {
+               a.next();
+               delete a.value();
+       }
+       iPackagesAvailable.clear();
+
+       QHashIterator<QString, Package*> i( iPackagesInstalled );
+       while (i.hasNext())
+       {
+               i.next();
+               delete i.value();
+       }
+       iPackagesInstalled.clear();
+
+       for(int x=0; x<iRepositories.count(); x++) {
+               if( iRepositories.at(x) )
+                       delete iRepositories.at(x);
+       }
+       iRepositories.clear();
+
+       delete[] iDataReadBuffer;
+       iDataReadBuffer=0;
 }
 
 void AAptInterface::addQueuedOperation(interfaceMode mode_)
@@ -214,7 +237,7 @@ void AAptInterface::cleanAfterError()
        iProcessPackageVersions.clear();
 }
 
-bool AAptInterface::running()
+bool AAptInterface::running() const
 {
        if( iMode == ModeNone )
                return false;
@@ -281,6 +304,8 @@ bool AAptInterface::startAptGetUpdate()
        iNeedDpkgRefresh = true;
        iNeedDateRefresh = true;
 
+       iMainWindow->openNetworkConnection();
+
        if( iUiDimmer ) {
                iUiDimmer->setProgress(0);
                iUiDimmer->updateText("Updating catalogs");
@@ -357,6 +382,8 @@ bool AAptInterface::startAptGetInstall()
 
        iProcAptGetInstallOutput.clear();
 
+       iMainWindow->openNetworkConnection();
+
        qDebug() << "running apt-get install";
 
        QString runBinary = "/usr/bin/apt-get";
@@ -522,7 +549,7 @@ QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
        } else if( output.contains("E: Broken packages") ) {
                msg = "Your system has broken packages or you are trying to install conflicting packages. See the log for details.";
        } else if( output.contains("E: Handler silently failed") ) {
-               msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category";
+               msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category. Disabling OVI store repositories might help.";
        } else if( iTerminated ) {
                msg = "The operation was cancelled by user";
        } else if( output.contains("Temporary failure resolving") || output.contains("Could not resolve host") ) {
@@ -535,6 +562,10 @@ QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
                msg = "Some of your packages have unmet dependencies which could not be fixed. See the log for details.";
        } else if( output.contains("E: The method driver") ) {
                msg = "Apt failed to find a suitable method driver. One or more of your repositories might have an invalid URL.";
+       } else if( output.contains("E: Invalid record in the preferences file") ) {
+               msg = "Invalid record in the apt preferences file.";
+       } else if( output.contains("E: Malformed line") && output.contains("in source list") ) {
+               msg = "Malformed line in sources list. Check your repository settings.";
        }
 
        return msg;
@@ -746,15 +777,26 @@ void AAptInterface::uiUpdaterAptGetUpdate()
                return;
 
        QStringList lines = QString( data.trimmed() ).split('\n');
+       QString infoline;
 
        for( int i=0; i<lines.count(); i++ )
        {
                if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
-                       iCatalogCounter++;
+               {
+                       iCatalogCounter++;                      
+               }
+               infoline = lines.at(i).trimmed();
        }
+       //if( infoline.isEmpty() )
+               //infoline = "arstus";
+
        //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
        //qDebug() << iCatalogCounter << iCatalogsTotal;
-       iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
+
+       //iUiDimmer->updateText("Updating catalogs<br><font size=\"-1\">" + infoline + "</font>");
+
+       if( iCatalogsTotal > 0 )
+               iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
 }
 
 void AAptInterface::uiUpdaterAptGetInstall()
@@ -785,7 +827,7 @@ void AAptInterface::uiUpdaterAptGetInstall()
                        if( pkg!=0 ) {
                                iAptGetCurrentDownloadFileName = pkg->fileName();
                                iAptGetCurrentFileTotalSize = pkg->size()/1024;
-                               pkgname += QString(" (%1 kB)").arg(iAptGetCurrentFileTotalSize);
+                               pkgname += QString(" (%L1 kB)").arg(iAptGetCurrentFileTotalSize);
                        }
                        iAptGetDownloadCount++;
                        oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
@@ -847,7 +889,7 @@ void AAptInterface::uiUpdaterAptGetInstall()
 
 void AAptInterface::progressCheckTimerCallback()
 {
-       if( iAptGetCurrentDownloadFileName=="" )
+       if( iAptGetCurrentDownloadFileName.isEmpty() )
                return;
 
        qint64 prevsize = iAptGetCurrentFileDownloadSize;
@@ -904,7 +946,7 @@ QByteArray AAptInterface::readLogFile()
                own.close();
        }
 
-       if( log=="" )
+       if( log.isEmpty() )
                log = "The log is empty";
 
        return log;
@@ -957,6 +999,7 @@ void AAptInterface::readRepositoryInfo()
                                        //qDebug() << r->toListFileNames();
                                } else {
                                        delete r;
+                                       r=0;
                                }
                        }
                }
@@ -972,7 +1015,7 @@ void AAptInterface::readRepositoryInfo()
                while(!names.atEnd() && c<iRepositories.count())
                {
                        QString line = names.readLine().trimmed();
-                       if( line.trimmed()!="" )
+                       if( !line.trimmed().isEmpty() )
                        iRepositories.at(c)->setName( line.trimmed() );
                        c++;
                }
@@ -980,8 +1023,10 @@ void AAptInterface::readRepositoryInfo()
                return;
        }
 
-       if( ownFound )
+       if( ownFound ) {
+               qDebug() << "own repo lists found";
                return;
+       }
 
        QFile ham( KHamRepoListFile );
        if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
@@ -992,20 +1037,26 @@ void AAptInterface::readRepositoryInfo()
                        Repository* r = new Repository();
                        if( r->setFromString(line) ) {
                                iRepositories.append(r);
+
+#ifdef Q_WS_MAEMO_5
+                               // disable the ovi repository by default
+                               if( line.contains("https://downloads.maemo.nokia.com/fremantle1.2/ovi/") ) {
+                                       r->setEnabled(false);
+                               }
+#endif
                        } else {
                                delete r;
+                               r=0;
                        }
                }
                ham.close();
+               qDebug() << "system repo list loaded";
        }
+
 }
 
 bool AAptInterface::writeRepositories()
 {
-#ifndef Q_WS_MAEMO_5   // for simulator
-       return true;
-#endif
-
        iNeedListRefresh = true;
 
        QFile own( KOwnRepoFile );
@@ -1044,10 +1095,6 @@ bool AAptInterface::writeRepositories()
 
 bool AAptInterface::needRepoRefresh()
 {
-#ifndef Q_WS_MAEMO_5   // for simulator
-       return false;
-#endif
-
        if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
                iNeedRepoRefresh = false;
                iSettings->qsettings()->setValue("need_repo_refresh", false);
@@ -1137,7 +1184,7 @@ void AAptInterface::startPkgListRead()
        quint64 totaldatasize = 0;
        quint64 currentreaddata = 0;
        quint64 lastupdatedata = 0;
-       quint64 updateinterval = 1000000;
+       quint64 updateinterval = 2000000;
        if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
                for( int i=0; i<files.count(); i++ )
                {
@@ -1183,14 +1230,13 @@ void AAptInterface::startPkgListRead()
 
                                while (!db.atEnd() && !iTerminated) {
                                        Package* newpkg = ReadNextPackage(db, currentreaddata);
-                                       //qDebug() << "read" << currentreaddata << "of" << totaldatasize;
                                        if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
                                                iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
                                                lastupdatedata = currentreaddata;
                                                QApplication::processEvents();
                                        }
                                        pkgcount_apt++;
-                                       if( newpkg )//&& !newpkg->name().isEmpty() )
+                                       if( newpkg )
                                        {
                                                newpkg->addRepository( currentRepo );
 
@@ -1216,10 +1262,7 @@ void AAptInterface::startPkgListRead()
                                                                newpkg=0;
                                                        }
                                                }
-                                       }/* else if( newpkg ) {
-                                               delete newpkg;
-                                               newpkg = 0;
-                                       }*/
+                                       }
                                }
                                db.close();
                        }
@@ -1303,6 +1346,7 @@ void AAptInterface::startPkgListRead()
        }
 
        readBlacklist();
+       readPinnedPackages();
 
        communicateStatusToUi(true, "Operation finished", "Package data read");
        iCanCancel = false;
@@ -1316,15 +1360,19 @@ Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
        Package* pkg = new Package("", this);
 
        bool pkgready = false;
+
+       // this is faster than directly reading to QByteArray...
+       QByteArray line;
        while( !pkgready && !f.atEnd() ) {
-               QByteArray line = f.readLine();
+               f.readLine(iDataReadBuffer,KDataReadBufferSize);
+               line = iDataReadBuffer;
                currentreaddata += line.size();
                if( processPackageDataLine(pkg,line) ) {
                        pkgready = true;
                }
        }
 
-       if( pkg->name() != "" && pkg->isInstalled() ) {
+       if( !pkg->name().isEmpty() && pkg->isInstalled() ) {
                QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
                if( f.exists() )
                        pkg->setDate( f.lastModified() );
@@ -1332,7 +1380,8 @@ Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
 
        pkg->updateStatus();
 
-       if( pkg->name() == "" ) {
+       if( pkg->name().isEmpty() ) {
+               qDebug() << "null name package!";
                delete pkg;
                pkg = 0;
        }
@@ -1341,12 +1390,37 @@ Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
 
 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
 {
-       if( !line.startsWith(' ') && !line.startsWith('\t') )
-               line = line.trimmed();
-       if( line.trimmed()=="" )
+       if( line.isEmpty() || line=="\n" )
+       {
                return true;
+       }
+
+       else if( iMultiLine == MultiLineDesc ) {
+               if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
+                       if( line.trimmed()!="." )
+                               pkg->appendDescLong( line.trimmed() + "\n" );
+                       else
+                               pkg->appendDescLong( "\n" );
+               } else {
+                       iMultiLine = MultiLineNone;
+               }
+       }
+       else if( iMultiLine == MultiLineIcon ) {
+               if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
+                       pkg->appendIconData( line.trimmed() );
+               } else {
+                       iMultiLine = MultiLineNone;
+               }
+       }
+       else if( iMultiLine == MultiLineUpgradeDesc ) {
+               if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
+                       pkg->appendUpgradeDescription( line.trimmed() + "\n" );
+               } else {
+                       iMultiLine = MultiLineNone;
+               }
+       }
 
-       if( line.startsWith("Package:") )
+       else if( line.startsWith("Package:") )
        {
                pkg->setName( line.mid(8).trimmed() );
                iMultiLine=MultiLineNone;
@@ -1394,18 +1468,10 @@ bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
        {
                pkg->appendPreDepends( line.mid(12).trimmed() );
        }
-       else if( line.startsWith("Provides:") )
-       {
-               pkg->appendProvides( line.mid(9).trimmed() );
-       }
        else if( line.startsWith("Replaces:") )
        {
                pkg->appendReplaces( line.mid(9).trimmed() );
        }
-       else if( line.startsWith("Breaks:") )
-       {
-               pkg->appendBreaks( line.mid(7).trimmed() );
-       }
        else if( line.startsWith("Recommends:") )
        {
                pkg->appendRecommends( line.mid(11).trimmed() );
@@ -1414,33 +1480,20 @@ bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
        {
                pkg->appendSuggests( line.mid(9).trimmed() );
        }
-
-       if( iMultiLine == MultiLineDesc ) {
-               if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
-                       if( line.trimmed()!="." )
-                               pkg->appendDescLong( line.trimmed() + "\n" );
-                       else
-                               pkg->appendDescLong( "\n" );
-               } else {
-                       iMultiLine = MultiLineNone;
-               }
+       else if( line.startsWith("Provides:") )
+       {
+               pkg->appendProvides( line.mid(9).trimmed() );
        }
-       else if( iMultiLine == MultiLineIcon ) {
-               if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
-                       pkg->appendIconData( line.trimmed() );
-               } else {
-                       iMultiLine = MultiLineNone;
-               }
+       else if( line.startsWith("Breaks:") )
+       {
+               pkg->appendBreaks( line.mid(7).trimmed() );
        }
-       else if( iMultiLine == MultiLineUpgradeDesc ) {
-               if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
-                       pkg->appendUpgradeDescription( line.trimmed() + "\n" );
-               } else {
-                       iMultiLine = MultiLineNone;
-               }
+       else if( line.startsWith("Maintainer:") )
+       {
+               pkg->setMaintainer( line.mid(11).trimmed() );
        }
 
-       if( line.startsWith("Description:") )
+       else if( line.startsWith("Description:") )
        {
                pkg->setDescShort( line.mid(12).trimmed() );
                iMultiLine = MultiLineDesc;
@@ -1550,20 +1603,23 @@ void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList
                return;
        }
 
-       QStringList newlist;
        bool removed = false;
 
        for( int i=0; i<iBlacklist.count(); i++ )
        {
                if( oldstate == BlacklistSelect::BlacklistAll )
                {
-                       if( !(iBlacklist.at(i) == pkg->name()) ) {
-                               newlist << iBlacklist.at(i);
-                       } else removed = true;
+                       if( iBlacklist.at(i) == pkg->name() ) {
+                               iBlacklist.removeAt(i);
+                               i--;
+                               removed = true;
+                       }
                } else if( oldstate == BlacklistSelect::BlacklistThis ) {
-                       if( !(iBlacklist.at(i) == (pkg->name()+" "+pkg->version())) ) {
-                               newlist << iBlacklist.at(i);
-                       } else removed = true;
+                       if( iBlacklist.at(i) == (pkg->name()+" "+pkg->version()) ) {
+                               iBlacklist.removeAt(i);
+                               i--;
+                               removed = true;
+                       }
                }
        }
 
@@ -1572,7 +1628,6 @@ void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList
        else
                qDebug() << "blacklist:" << pkg->name() << "not in saved list";
 
-       iBlacklist = newlist;
 }
 
 
@@ -1602,9 +1657,11 @@ void AAptInterface::startFetchDates()
                QApplication::processEvents();
        }
 
+       iMainWindow->openNetworkConnection();
+
        QNetworkAccessManager* nam = new QNetworkAccessManager(this);
 
-       if( iSettings->qsettings()->value("use_proxies").toBool() && iSettings->qsettings()->value("http_proxy").toString()!="" )
+       if( iSettings->qsettings()->value("use_proxies").toBool() && !iSettings->qsettings()->value("http_proxy").toString().isEmpty() )
        {
                 QNetworkProxy proxy = Settings::createProxyFromString( iSettings->qsettings()->value("http_proxy").toString() );
                 nam->setProxy(proxy);
@@ -1622,7 +1679,7 @@ void AAptInterface::startFetchDates()
                i.next();
                if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
                {
-                       Repository* repo = 0;
+                       const Repository* repo = 0;
                        for( int x=0; x<i.value()->repositories().count(); x++ ) {
                                if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
                                {
@@ -1651,7 +1708,7 @@ void AAptInterface::startFetchDates()
        {
                fe.next();
 
-               if( updProgress >=10 ) {
+               if( updProgress >=20 ) {
                        iUiDimmer->setProgress( count*100/fetchable.count() );
                        updProgress=0;
                }
@@ -1659,13 +1716,13 @@ void AAptInterface::startFetchDates()
                if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
                {
                        QString url;
-                       Repository* repo = 0;
+                       const Repository* repo = 0;
                        QString fullFilename = "unknown_filename";
                        for( int x=0; x<fe.value()->repositories().count(); x++ ) {
                                if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
                                {
                                        repo = fe.value()->repositories().at(x);
-                                       if( fe.value()->fullFileNames().count()>x )
+                                       if( repo && fe.value()->fullFileNames().count()>x )
                                                fullFilename = fe.value()->fullFileNames().at(x);
                                        break;
                                }
@@ -1686,7 +1743,7 @@ void AAptInterface::startFetchDates()
                                                QApplication::processEvents(QEventLoop::WaitForMoreEvents);
                                        }
                                } else {
-                                       while( iDateRequestsWaiting>50 ) {
+                                       while( iDateRequestsWaiting>5 ) {
                                                QApplication::processEvents(QEventLoop::WaitForMoreEvents);
                                        }
                                }
@@ -1708,7 +1765,7 @@ void AAptInterface::startFetchDates()
                }
        }
        while( iDateRequestsWaiting>0 ) {
-               if( updProgress >=10 ) {
+               if( updProgress >=20 ) {
                        iUiDimmer->setProgress( count*100/fetchable.count() );
                        updProgress=0;
                }
@@ -1717,6 +1774,7 @@ void AAptInterface::startFetchDates()
                updProgress++;
        }
        delete nam;
+       nam=0;
 
        if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
                iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
@@ -1767,10 +1825,10 @@ void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
 {
        iDateRequestsWaiting--;
        iDateRequestsReceived++;
-       //qDebug() << "reply" << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
        iNetworkError = reply->error();
+       QDateTime dateModified = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
 
-       if( reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid() )
+       if( reply->error() == QNetworkReply::NoError && dateModified.isValid() )
        {
                QString pkgname = reply->url().fragment();
                //qDebug() << pkgname;
@@ -1780,7 +1838,7 @@ void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
 
                Package* pkg = iPackagesAvailable.value(pkgname, 0);
                if( pkg ) {
-                       pkg->setDate( reply->header(QNetworkRequest::LastModifiedHeader).toDateTime() );
+                       pkg->setDate( dateModified );
                } else {
                        qDebug() << "warning: unknown packagename in reply:" << pkgname;
                }
@@ -1856,9 +1914,43 @@ bool AAptInterface::dateCacheExists()
        return f.exists();
 }
 
-bool AAptInterface::loadInstallFiles(QStringList files_)
+void AAptInterface::readPinnedPackages()
 {
-       qDebug() << files_;
+       QFile f(KAptPreferencesFile);
+       if( !f.exists() )
+               return;
 
-       return false;
+       bool warnAllPinned = false;
+       if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
+       {
+               qDebug() << "apt preferences exist: reading pinned packages";
+               int pinned_packages = 0;
+               while( !f.atEnd() )
+               {
+                       QString line = f.readLine().trimmed();
+
+                       if( line=="Package: *" || line=="Package:*")
+                               warnAllPinned = true;
+
+                       if( line.startsWith("Package:") ) {
+                               pinned_packages++;
+                               QString pkg = line.mid(8).trimmed();
+                               Package* pkg_i = iPackagesInstalled.value(pkg,0);
+                               if( pkg_i ) {
+                                       pkg_i->setPinned(true);
+                               }
+                               Package* pkg_a = iPackagesAvailable.value(pkg,0);
+                               if( pkg_a ) {
+                                       pkg_a->setPinned(true);
+                               }
+                       }
+               }
+               f.close();
+               qDebug() << "read" << pinned_packages << "pinned packages";
+       }
+
+       if( warnAllPinned ) {
+               iMainWindow->notifyDialog("Warning","You have pinned packages with '*' in apt preferences. It is strongly recommended to "
+                                                                 "remove such settings as they can result in unexpected behavior of Faster Application Manager.");
+       }
 }