/* rpackage.cc - wrapper for accessing package information * * Copyright (c) 2000-2003 Conectiva S/A * 2002 Michael Vogt * * Author: Alfredo K. Kojima * Michael Vogt * * Portions Taken from Gnome APT * Copyright (C) 1998 Havoc Pennington * * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "config.h" #include "rpackage.h" #include "rpackagelister.h" #include "pkg_acqfile.h" #include "i18n.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_LUA #include #endif #include "raptoptions.h" static char descrBuffer[8192]; static char *parseDescription(string descr); RPackage::RPackage(RPackageLister *lister, pkgDepCache *depcache, pkgRecords *records, pkgCache::PkgIterator &pkg) : _lister(lister), _records(records), _depcache(depcache), _notify(true), _boolFlags(0) { _package = new pkgCache::PkgIterator(pkg); pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandVersion != NULL) _defaultCandVer = State.CandVersion; } RPackage::~RPackage() { delete _package; } #if 0 void RPackage::addVirtualPackage(pkgCache::PkgIterator dep) { _virtualPackages.push_back(dep); _provides.push_back(dep.Name()); } #endif const char *RPackage::section() { const char *s = _package->Section(); if (s != NULL) return s; else return _("Unknown"); } const char *RPackage::srcPackage() { static string _srcPkg; pkgCache::VerIterator ver = _package->VersionList(); pkgRecords::Parser &rec=_records->Lookup(ver.FileList()); _srcPkg = rec.SourcePkg().empty()?name():rec.SourcePkg(); return _srcPkg.c_str();; } const char *RPackage::summary() { static string _summary; pkgCache::VerIterator ver = _package->VersionList(); if (!ver.end()) { pkgRecords::Parser & parser = _records->Lookup(ver.FileList()); _summary = parser.ShortDesc(); return _summary.c_str(); } return ""; } const char *RPackage::maintainer() { static string _maintainer; pkgCache::VerIterator ver = _package->VersionList(); if (!ver.end()) { pkgRecords::Parser & parser = _records->Lookup(ver.FileList()); _maintainer = parser.Maintainer(); return _maintainer.c_str(); } return ""; } const char *RPackage::vendor() { return "dunno"; } const char *RPackage::installedVersion() { if ((*_package)->CurrentVer == 0) return NULL; return _package->CurrentVer().VerStr(); } const char *RPackage::availableVersion() { pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandidateVer == 0) return NULL; return State.CandidateVerIter(*_depcache).VerStr(); } const char *RPackage::priority() { pkgCache::VerIterator ver = _package->VersionList(); if (ver != 0) return ver.PriorityType(); else return NULL; } #ifndef HAVE_RPM const char *RPackage::installedFiles() { static string filelist; string s; filelist.erase(filelist.begin(), filelist.end()); string f = "/var/lib/dpkg/info/" + string(name()) + ".list"; if (FileExists(f)) { ifstream in(f.c_str()); if (!in != 0) return ""; while (in.eof() == false) { getline(in, s); filelist += s + "\n"; } in >> filelist; return filelist.c_str(); } filelist = _("The list of installed files is only available for installed packages"); return filelist.c_str(); } #else const char *RPackage::installedFiles() { return ""; } #endif const char *RPackage::description() { static string _description; pkgCache::VerIterator ver = _package->VersionList(); if (!ver.end()) { pkgRecords::Parser & parser = _records->Lookup(ver.FileList()); _description = parseDescription(parser.LongDesc()); return _description.c_str(); } else { return ""; } } long RPackage::installedSize() { pkgCache::VerIterator ver = _package->CurrentVer(); if (!ver.end()) return ver->InstalledSize; else return -1; } long RPackage::availableInstalledSize() { pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandidateVer == 0) return -1; return State.CandidateVerIter(*_depcache)->InstalledSize; } long RPackage::availablePackageSize() { pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandidateVer == 0) return -1; return State.CandidateVerIter(*_depcache)->Size; } int RPackage::getFlags() { int flags = 0; pkgDepCache::StateCache &state = (*_depcache)[*_package]; pkgCache::VerIterator ver = _package->CurrentVer(); if (state.Install()) flags |= FInstall; if (state.iFlags & pkgDepCache::ReInstall) { flags |= FReInstall; } else if (state.NewInstall()) { // Order matters here. flags |= FNewInstall; } else if (state.Upgrade()) { flags |= FUpgrade; } else if (state.Downgrade()) { flags |= FDowngrade; } else if (state.Delete()) { flags |= FRemove; if (state.iFlags & pkgDepCache::Purge) flags |= FPurge; } else if (state.Keep()) { flags |= FKeep; } if (!ver.end()) { flags |= FInstalled; if (state.Upgradable() && state.CandidateVer != NULL) { flags |= FOutdated; if (state.Keep()) flags |= FHeld; } if (state.Downgrade()) flags |= FDowngrade; } if (state.NowBroken()) flags |= FNowBroken; if (state.InstBroken()) flags |= FInstBroken; if ((*_package)->Flags & (pkgCache::Flag::Important | pkgCache::Flag::Essential)) flags |= FImportant; if ((*_package)->CurrentState == pkgCache::State::ConfigFiles) flags |= FResidualConfig; if (state.CandidateVer == 0 || !state.CandidateVerIter(*_depcache).Downloadable()) flags |= FNotInstallable; return flags | _boolFlags; } #if 0 bool RPackage::isWeakDep(pkgCache::DepIterator &dep) { if (dep->Type != pkgCache::Dep::Suggests && dep->Type != pkgCache::Dep::Recommends) return false; else return true; } bool RPackage::enumWDeps(const char *&type, const char *&what, bool &satisfied) { pkgCache::VerIterator ver; pkgDepCache::StateCache & state = (*_depcache)[*_package]; if (state.Keep() || state.Held()) { ver = (*_depcache)[*_package].InstVerIter(*_depcache); if (ver.end()) ver = _package->VersionList(); } else { ver = _package->VersionList(); } if (ver.end()) return false; _wdepI = ver.DependsList(); // uninitialized but doesn't matter, they just have to be equal _wdepStart = _wdepEnd; return nextWDeps(type, what, satisfied); } bool RPackage::nextWDeps(const char *&type, const char *&what, bool &satisfied) { static char buffer[32]; while (1) { if (_wdepStart == _wdepEnd) { if (_wdepI.end()) return false; _wdepI.GlobOr(_wdepStart, _wdepEnd); snprintf(buffer, sizeof(buffer), "%s", _wdepEnd.DepType()); } else { _wdepStart++; snprintf(buffer, sizeof(buffer), "| %s", _wdepEnd.DepType()); } satisfied = false; if (!isWeakDep(_wdepEnd)) continue; if (((*_depcache)[_wdepStart] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) satisfied = true; type = buffer; pkgCache::PkgIterator depPkg = _wdepStart.TargetPkg(); what = depPkg.Name(); break; } return true; } #endif vector RPackage::enumRDeps() { vector deps; DepInformation dep; pkgCache::VerIterator Cur; for(pkgCache::DepIterator D = _package->RevDependsList(); D.end() != true; D++) { // clear old values dep.isOr=dep.isVirtual=false; dep.name=dep.version=dep.versionComp=NULL; // check target and or-depends status pkgCache::PkgIterator Trg = D.TargetPkg(); if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) { dep.version = _("or dependency"); dep.versionComp = ""; } //FIXME: HACK ALARM, we need a "RDepends" type, so we use the last // one in pkg-dep dep.type = (pkgCache::Dep::DepType)(pkgCache::Dep::Obsoletes+1); dep.name = D.ParentPkg().Name(); if(Trg->VersionList == 0) dep.isVirtual=true; deps.push_back(dep); } return deps; } #if 0 bool RPackage::enumRDeps(const char *&dep, const char *&what) { _rdepI = _package->RevDependsList(); _vpackI = 0; return nextRDeps(dep, what); } bool RPackage::nextRDeps(const char *&dep, const char *&what) { while (_rdepI.end()) { if ((unsigned)_vpackI == _virtualPackages.size()) return false; _rdepI = _virtualPackages[_vpackI].RevDependsList(); _vpackI++; } what = _rdepI.TargetPkg().Name(); dep = _rdepI.ParentPkg().Name(); _rdepI++; return true; } #endif #if 0 bool RPackage::enumAvailDeps(const char *&type, const char *&what, const char *&pkg, const char *&which, char *&summary, bool &satisfied) { pkgCache::VerIterator ver; // pkgDepCache::StateCache & state = (*_depcache)[*_package]; //ver = _package->VersionList(); ver = (*_depcache)[*_package].CandidateVerIter(*_depcache); if (ver.end()) return false; _depI = ver.DependsList(); // uninitialized but doesn't matter, they just have to be equal _depStart = _depEnd; return nextDeps(type, what, pkg, which, summary, satisfied); } vector RPackage::getInstalledDeps() { vector < RPackage *>deps; pkgCache::VerIterator ver; ver = (*_depcache)[*_package].InstVerIter(*_depcache); if (ver.end()) ver = _package->VersionList(); if (ver.end()) return deps; _depI = ver.DependsList(); // uninitialized but doesn't matter, they just have to be equal pkgCache::DepIterator depIter = _depI; while (!depIter.end()) { pkgCache::PkgIterator depPkg = depIter.TargetPkg(); string name = depPkg.Name(); deps.push_back(_lister->getPackage(name)); depIter++; } return deps; } #endif /* Mostly taken from apt-get.cc:ShowBroken() */ string RPackage::showWhyInstBroken() { pkgCache::DepIterator depI; pkgCache::VerIterator Ver; bool First = true; ostringstream out; pkgDepCache::StateCache & State = (*_depcache)[*_package]; Ver = State.CandidateVerIter(*_depcache); // check if there is actually something to install if (Ver == 0) { ioprintf(out, _ ("\nPackage %s has no available version, but exists in the database.\n" "This typically means that the package was mentioned in a dependency and " "never uploaded, has been obsoleted or is not available with the contents " "of sources.list\n"), _package->Name()); return out.str(); } for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;) { // Compute a single dependency element (glob or) pkgCache::DepIterator Start; pkgCache::DepIterator End; D.GlobOr(Start, End); if (_depcache->IsImportantDep(End) == false) continue; if (((*_depcache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) continue; bool FirstOr = true; while (1) { /* Show a summary of the target package if possible. In the case of virtual packages we show nothing */ pkgCache::PkgIterator Targ = Start.TargetPkg(); if (Targ->ProvidesList == 0) { ioprintf(out, " "); pkgCache::VerIterator Ver = (*_depcache)[Targ].InstVerIter(*_depcache); // add minimal version information string requiredVersion; if(Start.TargetVer() != 0) requiredVersion = "("+string(Start.CompType())+string(Start.TargetVer())+")"; if (Ver.end() == false) { if (FirstOr == false) // TRANSLATORS: dependency error message, example: // "apt 0.5.4 but 0.5.3 is to be installed" ioprintf(out, _("\t%s %s but %s is to be installed"), Start.TargetPkg().Name(), requiredVersion.c_str(), Ver.VerStr()); else // TRANSLATORS: dependency error message, example: // "Depends: apt 0.5.4 but 0.5.3 is to be installed" ioprintf(out, _(" %s: %s %s but %s is to be installed"), End.DepType(), Start.TargetPkg().Name(), requiredVersion.c_str(), Ver.VerStr()); } else { if ((*_depcache)[Targ].CandidateVerIter(*_depcache).end() == true) { if (Targ->ProvidesList == 0) if (FirstOr == false) // TRANSLATORS: dependency error message, example: // "apt 0.5.4 but it is not installable" ioprintf(out, _("\t%s %s but it is not installable"), Start.TargetPkg().Name(), requiredVersion.c_str()); else // TRANSLATORS: dependency error message, example: // "Depends: apt 0.5.4 but it is not installable", ioprintf(out, "%s: %s %s but it is not installable", End.DepType(), Start.TargetPkg().Name(), requiredVersion.c_str()); else if (FirstOr == false) // TRANSLATORS: dependency error message, example: // "apt but it is a virtual package" ioprintf(out, _("\t%s but it is a virtual package"), Start.TargetPkg().Name()); else // TRANSLATORS: dependency error message, example: // "Depends: apt but it is a virtual package" ioprintf(out, _("%s: %s but it is a virtual package"), End.DepType(), Start.TargetPkg().Name()); } else if (FirstOr == false) // TRANSLATORS: dependency error message, example: // "apt but it is not going to be installed" ioprintf(out, _("\t%s but it is not going to be installed"), Start.TargetPkg().Name()); else // TRANSLATORS: dependency error message, example: // "Depends: apt but it is not going to be installed" ioprintf(out, _("%s: %s but it is not going to be installed"), End.DepType(), Start.TargetPkg().Name()); } } else { // virtual pkgs if (FirstOr == false) ioprintf(out, "\t%s", Start.TargetPkg().Name()); else ioprintf(out, " %s: %s", End.DepType(), Start.TargetPkg().Name()); // Show a quick summary of the version requirements if (Start.TargetVer() != 0) ioprintf(out, " (%s %s)", Start.CompType(), Start.TargetVer()); } First = false; FirstOr = false; if (Start != End) ioprintf(out, _(" or")); ioprintf(out, "\n"); if (Start == End) break; Start++; } } return out.str(); } vector RPackage::enumDeps(bool useCanidateVersion) { vector deps; DepInformation dep; pkgCache::VerIterator Cur; if(!useCanidateVersion) Cur = (*_depcache)[*_package].InstVerIter(*_depcache); if(useCanidateVersion || Cur.end()) Cur = (*_depcache)[*_package].CandidateVerIter(*_depcache); // no information found if(Cur.end()) return deps; for(pkgCache::DepIterator D = Cur.DependsList(); D.end() != true; D++) { // clear old values dep.isOr=dep.isVirtual=dep.isSatisfied=false; dep.name=dep.version=dep.versionComp=NULL; // check target and or-depends status pkgCache::PkgIterator Trg = D.TargetPkg(); if ((D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) dep.isOr=true; // common information dep.type = (pkgCache::Dep::DepType)D->Type; dep.name = Trg.Name(); // satisfied if (((*_depcache)[D] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) dep.isSatisfied = true; if (Trg->VersionList == 0) { dep.isVirtual = true; } else { dep.version=D.TargetVer(); dep.versionComp=D.CompType(); } deps.push_back(dep); } return deps; } bool RPackage::dependsOn(const char *pkgname) { vector deps = enumDeps(); for(unsigned int i=0;igetCache()->list(); for (pkgCache::VerFileIterator i = Ver.FileList(); i.end() == false; i++) { pkgIndexFile *Index; if (Sources->FindIndex(i.File(),Index) == false) continue; if (_config->FindB("Debug::pkgAcquire::Auth", false)) { std::cerr << "Checking index: " << Index->Describe() << "(Trusted=" << Index->IsTrusted() << ")\n"; } if (Index->IsTrusted()) return true; } return false; } #else // with apt-authentication we always trust that the package come from // a trusted source bool RPackage::isTrusted() { return true; }; #endif bool RPackage::wouldBreak() { int flags = getFlags(); if ((flags & FRemove) || (!(flags & FInstalled) && (flags & FKeep))) return false; return flags & FInstBroken; } void RPackage::setNotify(bool flag) { _notify = flag; } void RPackage::setKeep() { _depcache->MarkKeep(*_package, false); if (_notify) _lister->notifyChange(this); setReInstall(false); } void RPackage::setInstall() { _depcache->MarkInstall(*_package, true); pkgDepCache::StateCache & State = (*_depcache)[*_package]; // FIXME: can't we get rid of it here? // if there is something wrong, try to fix it if (!State.Install() || _depcache->BrokenCount() > 0) { pkgProblemResolver Fix(_depcache); Fix.Clear(*_package); Fix.Protect(*_package); Fix.Resolve(true); } #ifdef WITH_LUA _lua->SetDepCache(_depcache); _lua->SetGlobal("package", ((pkgCache::Package *) * _package)); _lua->RunScripts("Scripts::Synaptic::SetInstall", true); _lua->ResetGlobals(); _lua->ResetCaches(); #endif if (_notify) _lister->notifyChange(this); } void RPackage::setReInstall(bool flag) { _depcache->SetReInstall(*_package, flag); if (_notify) _lister->notifyChange(this); } void RPackage::setRemove(bool purge) { pkgProblemResolver Fix(_depcache); Fix.Clear(*_package); Fix.Protect(*_package); Fix.Remove(*_package); Fix.InstallProtect(); Fix.Resolve(true); _depcache->SetReInstall(*_package, false); _depcache->MarkDelete(*_package, purge); if (_notify) _lister->notifyChange(this); } string RPackage::getChangelogFile(pkgAcquire *fetcher) { string prefix; string srcpkg = srcPackage(); string descr("Changelog for "); descr+=name(); string src_section=section(); if(src_section.find('/')!=src_section.npos) src_section=string(src_section, 0, src_section.find('/')); else src_section="main"; prefix+=srcpkg[0]; if(srcpkg.size()>3 && srcpkg[0]=='l' && srcpkg[1]=='i' && srcpkg[2]=='b') prefix=std::string("lib")+srcpkg[3]; string verstr; if(availableVersion() != NULL) verstr = availableVersion(); if(verstr.find(':')!=verstr.npos) verstr=string(verstr, verstr.find(':')+1); char uri[512]; snprintf(uri,512,"http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog", src_section.c_str(), prefix.c_str(), srcpkg.c_str(), srcpkg.c_str(), verstr.c_str()); //cout << "uri is: " << uri << endl; // no need to translate this, the changelog is in english anyway string filename = RTmpDir()+"/tmp_cl"; ofstream out(filename.c_str()); out << "Failed to fetch the changelog for " << name() << endl; out << "URI was: " << uri << endl; out.close(); new pkgAcqFileSane(fetcher, uri, descr, name(), filename); fetcher->Run(); return filename; } string RPackage::getCanidateOrigin() { for(pkgCache::VerIterator Ver = _package->VersionList(); Ver.end() == false; Ver++) { // we always take the first available version pkgCache::VerFileIterator VF = Ver.FileList(); if(!VF.end()) { return VF.File().Site(); } } return ""; } void RPackage::setPinned(bool flag) { struct stat stat_buf; string File =RStateDir() + "/preferences"; _boolFlags = flag ? (_boolFlags | FPinned) : (_boolFlags & FPinned); if (flag) { // pkg already in pin-file if (_roptions->getPackageLock(name())) return; // write to pin-file ofstream out(File.c_str(), ios::app); out << "Package: " << name() << endl; // if the package is not installed, we pin it to the available version // and prevent installation of this package this way if(installedVersion() != NULL) out << "Pin: version " << installedVersion() << endl; else out << "Pin: version " << " 0.0 " << endl; out << "Pin-Priority: " << _config->FindI("Synaptic::DefaultPinPriority", 1001) << endl << endl; } else { // delete package from pinning file stat(File.c_str(), &stat_buf); // create a tmp_pin file in the internal dir string filename = RTmpDir()+"/tmp_pin"; FILE *out = fopen(filename.c_str(),"w"); if (out == NULL) cerr << "error opening tmpfile: " << filename << endl; FileFd Fd(File, FileFd::ReadOnly); pkgTagFile TF(&Fd); if (_error->PendingError() == true) return; pkgTagSection Tags; while (TF.Step(Tags) == true) { string Name = Tags.FindS("Package"); if (Name.empty() == true) { _error-> Error(_ ("Invalid record in the preferences file, no Package header")); return; } if (Name != name()) { TFRewriteData tfrd; tfrd.Tag = 0; tfrd.Rewrite = 0; tfrd.NewTag = 0; TFRewrite(out, Tags, TFRewritePackageOrder, &tfrd); fprintf(out, "\n"); } } fflush(out); rename(filename.c_str(), File.c_str()); chmod(File.c_str(), stat_buf.st_mode); fclose(out); } } // FIXME: this function is broken right now (and it never really wasn't :/ bool RPackage::isShallowDependency(RPackage *pkg) { #if 0 pkgCache::DepIterator rdepI; // check whether someone else depends on a virtual pkg of this for (int i = -1; i < (int)pkg->_virtualPackages.size(); i++) { if (i < 0) { rdepI = pkg->_package->RevDependsList(); } else { pkgCache::PkgIterator it = pkg->_virtualPackages[i]; rdepI = it.RevDependsList(); } while (!rdepI.end()) { // check whether the dependant is installed if (rdepI.ParentPkg().CurrentVer().end()) { // not installed // XXX check whether its marked for install rdepI++; continue; } // check whether the dependant isn't the own package if (rdepI.ParentPkg() == *_package) { rdepI++; continue; } // XXX should check for dependencies that depend on // dependencies of the same package return false; } } #endif return true; } // format: first version, second archives vector > RPackage::getAvailableVersions() { string VerTag; vector > versions; // Get available Versions. for (pkgCache::VerIterator Ver = _package->VersionList(); Ver.end() == false; Ver++) { // We always take the first available version. pkgCache::VerFileIterator VF = Ver.FileList(); if (!VF.end()) { pkgCache::PkgFileIterator File = VF.File(); if (File->Archive != 0) versions.push_back(pair < string, string > (Ver.VerStr(), File.Archive())); else versions.push_back(pair < string, string > (Ver.VerStr(), File.Site())); } } return versions; } bool RPackage::setVersion(string verTag) { pkgVersionMatch Match(verTag, pkgVersionMatch::Version); pkgCache::VerIterator Ver = Match.Find(*_package); if (Ver.end() == true) return false; _depcache->SetCandidateVersion(Ver); _boolFlags |= FOverrideVersion; return true; } void RPackage::unsetVersion() { //cout << "set version to " << _defaultCandVer << endl; setVersion(_defaultCandVer); _boolFlags &= ~FOverrideVersion; } vector RPackage::provides() { vector provides; pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandidateVer == 0) return provides; for (pkgCache::PrvIterator Prv = State.CandidateVerIter(*_depcache).ProvidesList(); Prv.end() != true; Prv++) { provides.push_back(Prv.Name()); } return provides; } /* mvo: actually shallow = false does not make a lot of sense as it * will remove packages very brutally (like removing libc6) */ void RPackage::setRemoveWithDeps(bool shallow, bool purge) { setRemove(); // remove packages that this one depends on, including this pkgCache::DepIterator deps = _package->VersionList().DependsList(); pkgCache::DepIterator start, end; deps.GlobOr(start, end); while (1) { if (start == end) { deps++; if (deps.end()) break; deps.GlobOr(start, end); } else { start++; } if (!_depcache->IsImportantDep(start)) continue; pkgCache::PkgIterator depPkg = start.TargetPkg(); // get the real package, in case this is a virtual pkg // mvo: does this actually work :) ? if (depPkg->VersionList == 0) { if (depPkg->ProvidesList != 0) { depPkg = depPkg.ProvidesList().OwnerPkg(); } else { continue; } } RPackage *depackage = _lister->getPackage(depPkg); //cout << "testing(RPackage): " << depackage->name() << endl; if (!depackage) continue; // skip important packages if (depackage->getFlags() & FImportant) continue; // skip dependencies that are dependants of other packages // if shallow=true if (shallow && !isShallowDependency(depackage)) { continue; } // set this package for removal depackage->setRemove(purge); } } // description parser stuff static char *debParser(string descr) { unsigned int i; string::size_type nlpos=0; nlpos = descr.find('\n'); // delete first line if (nlpos != string::npos) descr.erase(0, nlpos + 2); // del "\n " too while (nlpos < descr.length()) { nlpos = descr.find('\n', nlpos); if (nlpos == string::npos) break; i = nlpos; // del char after '\n' (always " ") i++; descr.erase(i, 1); // delete lines likes this: " .", makeing it a \n if (descr[i] == '.') { descr.erase(i, 1); nlpos++; continue; } // skip ws while (descr[++i] == ' '); // // not a list, erase nl // if(!(descr[i] == '*' || descr[i] == '-' || descr[i] == 'o')) // descr.erase(nlpos,1); nlpos++; } strcpy(descrBuffer, descr.c_str()); return descrBuffer; } static char *rpmParser(string descr) { string::size_type pos = descr.find('\n'); // delete first line if (pos != string::npos) descr.erase(0, pos + 2); // del "\n " too strcpy(descrBuffer, descr.c_str()); return descrBuffer; } static char *stripWsParser(string descr) { const char *end; const char *p; p = descr.c_str(); end = p + descr.size(); // mvo: hackish, but works int state = 0; char *pp = (char *)descrBuffer; while (p != end) { switch (state) { case 0: if (*p == '\n') state = 1; else *pp++ = *p; break; case 1: if (*p == ' ') state = 2; else { *pp++ = *p; state = 0; } break; case 2: if (!(*p == '\n' || *p == '.')) { *pp++ = ' '; *pp++ = *p; } state = 0; break; } p++; } *pp = '\0'; return descrBuffer; } static char *parseDescription(string descr) { if (descr.size() > sizeof(descrBuffer)) return "Description Too Long"; #ifdef HAVE_RPM int parser = _config->FindI("Synaptic::descriptionParser", NO_PARSER); #else int parser = _config->FindI("Synaptic::descriptionParser", DEB_PARSER); #endif switch (parser) { case DEB_PARSER: return debParser(descr); case STRIP_WS_PARSER: return stripWsParser(descr); case RPM_PARSER: return rpmParser(descr); case NO_PARSER: default: strcpy(descrBuffer, descr.c_str()); return descrBuffer; } } string RPackage::component() { string res; #ifdef WITH_APT_AUTH // the apt-secure patch breaks File.Component const char *s = _package->Section(); if(s == NULL) return ""; string src_section(s); if(src_section.find('/')!=src_section.npos) src_section=string(src_section, 0, src_section.find('/')); else src_section="main"; res = src_section; #else pkgCache::VerIterator Ver; pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandidateVer == 0) { //cout << "CanidateVer == 0" << endl; return ""; } Ver = State.CandidateVerIter(*_depcache); pkgCache::VerFileIterator VF = Ver.FileList(); pkgCache::PkgFileIterator File = VF.File(); if(File.Component() == NULL) { //cout << "File.Component() == NULL" << endl; return ""; } res = File.Component(); #endif return res; } string RPackage::label() { string res; pkgCache::VerIterator Ver; pkgDepCache::StateCache & State = (*_depcache)[*_package]; if (State.CandidateVer == 0) { //cout << "CanidateVer == 0" << endl; return ""; } Ver = State.CandidateVerIter(*_depcache); pkgCache::VerFileIterator VF = Ver.FileList(); pkgCache::PkgFileIterator File = VF.File(); if(File.Label() == NULL) { //cout << "File.Component() == NULL" << endl; return ""; } res = File.Label(); return res; } // class that finds out what do display to get user void RPackageStatus::init() { char *status_short[N_STATUS_COUNT] = { "install", "reinstall", "upgrade", "downgrade", "remove", "purge", "available", "available-locked", "installed-updated", "installed-outdated", "installed-locked", "broken", "new" }; memcpy(PackageStatusShortString, status_short, sizeof(status_short)); char *status_long[N_STATUS_COUNT] = { _("Marked for installation"), _("Marked for re-installation"), _("Marked for upgrade"), _("Marked for downgrade"), _("Marked for removal"), _("Marked for complete removal"), _("Not installed"), _("Not installed (locked)"), _("Installed"), _("Installed (upgradable)"), _("Installed (locked to the current version)"), _("Broken"), _("Not installed (new in repository)") }; memcpy(PackageStatusLongString, status_long, sizeof(status_long)); // check for unsupported stuff if(_config->FindB("Synaptic::mark-unsupported",true)) { string s, labels, components; markUnsupported = true; // read supported labels labels = _config->Find("Synaptic::supported-label", "Debian Debian-Security"); stringstream sst1(labels); while(!sst1.eof()) { sst1 >> s; supportedLabels.push_back(s); } // read supported components components = _config->Find("Synaptic::supported-components", "main updates/main"); stringstream sst2(components); while(!sst2.eof()) { sst2 >> s; supportedComponents.push_back(s); } } } bool RPackageStatus::isSupported(RPackage *pkg) { bool res = true; if(markUnsupported) { bool sc, sl; sc=sl=false; string component = pkg->component(); string label = pkg->label(); for(unsigned int i=0;igetFlags(); int ret = NotInstalled; if (pkg->wouldBreak()) { ret = IsBroken; } else if (flags & RPackage::FNewInstall) { ret = ToInstall; } else if (flags & RPackage::FUpgrade) { ret = ToUpgrade; } else if (flags & RPackage::FReInstall) { ret = ToReInstall; } else if (flags & RPackage::FDowngrade) { ret = ToDowngrade; } else if (flags & RPackage::FPurge) { ret = ToPurge; } else if (flags & RPackage::FRemove) { ret = ToRemove; } else if (flags & RPackage::FInstalled) { if (flags & RPackage::FPinned) ret = InstalledLocked; else if (flags & RPackage::FOutdated) ret = InstalledOutdated; else ret = InstalledUpdated; } else { if (flags & RPackage::FPinned) ret = NotInstalledLocked; else if (flags & RPackage::FNew) ret = IsNew; else ret = NotInstalled; } return ret; } // vim:ts=3:sw=3:et