using std::string;
-static debListParser::WordList PrioList[] = {
+static const debListParser::WordList PrioList[] = {
{"required",pkgCache::State::Required},
{"important",pkgCache::State::Important},
{"standard",pkgCache::State::Standard},
// ---------------------------------------------------------------------
/* This is to return the name of the package this section describes */
string debListParser::Package() {
- string const Result = Section.FindS("Package");
+ string Result = Section.FindS("Package");
+
+ // Normalize mixed case package names to lower case, like dpkg does
+ // See Bug#807012 for details
+ std::transform(Result.begin(), Result.end(), Result.begin(), tolower_ascii);
+
if(unlikely(Result.empty() == true))
_error->Error("Encountered a section with no Package: header");
return Result;
}
else if (likely(value.size() == 32))
{
- if (likely(value.find_first_not_of("0123456789abcdefABCDEF") == string::npos))
- return MD5SumValue(value);
+ MD5SumValue sumvalue;
+ if (sumvalue.Set(value))
+ return sumvalue;
+
_error->Error("Malformed Description-md5 line; includes invalid character '%s'", value.c_str());
return MD5SumValue();
}
char *J = S;
for (; Start != End; ++Start)
{
- if (isspace(*Start) != 0)
+ if (isspace_ascii(*Start) != 0)
continue;
*J++ = tolower_ascii(*Start);
bool const &ParseRestrictionsList)
{
// Strip off leading space
- for (;Start != Stop && isspace(*Start) != 0; ++Start);
+ for (;Start != Stop && isspace_ascii(*Start) != 0; ++Start);
// Parse off the package name
const char *I = Start;
- for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
+ for (;I != Stop && isspace_ascii(*I) == 0 && *I != '(' && *I != ')' &&
*I != ',' && *I != '|' && *I != '[' && *I != ']' &&
*I != '<' && *I != '>'; ++I);
Package.assign(Start,I - Start);
// We don't want to confuse library users which can't handle MultiArch
- string const arch = _config->Find("APT::Architecture");
if (StripMultiArch == true) {
+ string const arch = _config->Find("APT::Architecture");
size_t const found = Package.rfind(':');
if (found != string::npos &&
(strcmp(Package.c_str() + found, ":any") == 0 ||
}
// Skip white space to the '('
- for (;I != Stop && isspace(*I) != 0 ; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0 ; I++);
// Parse a version
if (I != Stop && *I == '(')
{
// Skip the '('
- for (I++; I != Stop && isspace(*I) != 0 ; I++);
+ for (I++; I != Stop && isspace_ascii(*I) != 0 ; I++);
if (I + 3 >= Stop)
return 0;
I = ConvertRelation(I,Op);
// Skip whitespace
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
Start = I;
I = (const char*) memchr(I, ')', Stop - I);
if (I == NULL || Start == I)
// Skip trailing whitespace
const char *End = I;
- for (; End > Start && isspace(End[-1]); End--);
+ for (; End > Start && isspace_ascii(End[-1]); End--);
Ver.assign(Start,End-Start);
I++;
}
// Skip whitespace
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
- if (ParseArchFlags == true)
+ if (unlikely(ParseArchFlags == true))
{
+ string const arch = _config->Find("APT::Architecture");
APT::CacheFilter::PackageArchitectureMatchesSpecification matchesArch(arch, false);
// Parse an architecture
while (I != Stop)
{
// look for whitespace or ending ']'
- for (;End != Stop && !isspace(*End) && *End != ']'; ++End);
+ for (;End != Stop && !isspace_ascii(*End) && *End != ']'; ++End);
if (unlikely(End == Stop))
return 0;
}
I = End;
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
}
if (NegArch == true)
}
// Skip whitespace
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
}
- if (ParseRestrictionsList == true)
+ if (unlikely(ParseRestrictionsList == true))
{
// Parse a restrictions formula which is in disjunctive normal form:
// (foo AND bar) OR (blub AND bla)
for (;End != Stop && *End != '>'; ++End);
I = ++End;
// skip whitespace
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
} else {
bool applies2 = true;
// all the conditions inside a restriction list have to be
{
// look for whitespace or ending '>'
// End now points to the character after the current term
- for (;End != Stop && !isspace(*End) && *End != '>'; ++End);
+ for (;End != Stop && !isspace_ascii(*End) && *End != '>'; ++End);
if (unlikely(End == Stop))
return 0;
if (*End++ == '>') {
I = End;
// skip whitespace
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
break;
}
I = End;
// skip whitespace
- for (;I != Stop && isspace(*I) != 0; I++);
+ for (;I != Stop && isspace_ascii(*I) != 0; I++);
}
if (applies2) {
applies1 = true;
if (I == Stop || *I == ',' || *I == '|')
{
if (I != Stop)
- for (I++; I != Stop && isspace(*I) != 0; I++);
+ for (I++; I != Stop && isspace_ascii(*I) != 0; I++);
return I;
}
}
else
{
- string Arch = Package.substr(found+1, string::npos);
- Package = Package.substr(0, found);
// Such dependencies are not supposed to be accepted …
// … but this is probably the best thing to do anyway
- if (Arch == "native")
- Arch = _config->Find("APT::Architecture");
- if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false)
+ if (Package.substr(found + 1) == "native")
+ Package = Package.substr(0, found) + ':' + Ver.Cache()->NativeArch();
+
+ if (NewDepends(Ver, Package, "any", Version, Op | pkgCache::Dep::ArchSpecific, Type) == false)
return false;
}
/* */
bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
{
+ /* it is unlikely, but while parsing dependencies, we might have already
+ picked up multi-arch implicit provides which we do not want to duplicate here */
+ bool hasProvidesAlready = false;
+ std::string const spzName = Ver.ParentPkg().FullName(false);
+ {
+ for (pkgCache::PrvIterator Prv = Ver.ProvidesList(); Prv.end() == false; ++Prv)
+ {
+ if (Prv.IsMultiArchImplicit() == false || (Prv->Flags & pkgCache::Flag::ArchSpecific) == 0)
+ continue;
+ if (spzName != Prv.OwnerPkg().FullName(false))
+ continue;
+ hasProvidesAlready = true;
+ break;
+ }
+ }
+
+ string const Arch = Ver.Arch();
const char *Start;
const char *Stop;
if (Section.Find("Provides",Start,Stop) == true)
{
string Package;
string Version;
- string const Arch = Ver.Arch();
unsigned int Op;
- while (1)
+ do
{
- Start = ParseDepends(Start,Stop,Package,Version,Op);
+ Start = ParseDepends(Start,Stop,Package,Version,Op, false, false, false);
const size_t archfound = Package.rfind(':');
if (Start == 0)
return _error->Error("Problem parsing Provides line");
if (Op != pkgCache::Dep::NoOp && Op != pkgCache::Dep::Equals) {
_error->Warning("Ignoring Provides line with non-equal DepCompareOp for package %s", Package.c_str());
} else if (archfound != string::npos) {
- string OtherArch = Package.substr(archfound+1, string::npos);
- Package = Package.substr(0, archfound);
- if (NewProvides(Ver, Package, OtherArch, Version, pkgCache::Flag::ArchSpecific) == false)
+ std::string spzArch = Package.substr(archfound + 1);
+ if (spzArch != "any")
+ {
+ if (NewProvides(Ver, Package.substr(0, archfound), spzArch, Version, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
+ return false;
+ }
+ if (NewProvides(Ver, Package, "any", Version, pkgCache::Flag::ArchSpecific) == false)
return false;
} else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) {
- if (NewProvidesAllArch(Ver, Package, Version, 0) == false)
- return false;
+ if (APT::Configuration::checkArchitecture(Arch))
+ if (NewProvidesAllArch(Ver, Package, Version, 0) == false)
+ return false;
} else {
+ if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
+ {
+ if (NewProvides(Ver, Package + ":any", "any", Version, pkgCache::Flag::MultiArchImplicit) == false)
+ return false;
+ }
if (NewProvides(Ver, Package, Arch, Version, 0) == false)
return false;
}
+ if (archfound == std::string::npos)
+ {
+ std::string const spzName = Package + ':' + Ver.ParentPkg().Arch();
+ pkgCache::PkgIterator const spzPkg = Ver.Cache()->FindPkg(spzName, "any");
+ if (spzPkg.end() == false)
+ {
+ if (NewProvides(Ver, spzName, "any", Version, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
+ return false;
+ }
+ }
+ } while (Start != Stop);
+ }
- if (Start == Stop)
- break;
+ if (APT::Configuration::checkArchitecture(Arch))
+ {
+ if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
+ {
+ string const Package = string(Ver.ParentPkg().Name()).append(":").append("any");
+ if (NewProvides(Ver, Package, "any", Ver.VerStr(), pkgCache::Flag::MultiArchImplicit) == false)
+ return false;
+ }
+ else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
+ {
+ if (NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr(), pkgCache::Flag::MultiArchImplicit) == false)
+ return false;
}
}
- if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
+ if (hasProvidesAlready == false)
{
- string const Package = string(Ver.ParentPkg().Name()).append(":").append("any");
- return NewProvides(Ver, Package, "any", Ver.VerStr(), pkgCache::Flag::MultiArchImplicit);
+ pkgCache::PkgIterator const spzPkg = Ver.Cache()->FindPkg(spzName, "any");
+ if (spzPkg.end() == false)
+ {
+ if (NewProvides(Ver, spzName, "any", Ver.VerStr(), pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
+ return false;
+ }
}
- else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
- return NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr(), pkgCache::Flag::MultiArchImplicit);
-
return true;
}
/*}}}*/
// ListParser::GrabWord - Matches a word and returns /*{{{*/
// ---------------------------------------------------------------------
/* Looks for a word in a list of words - for ParseStatus */
-bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
+bool debListParser::GrabWord(string Word,const WordList *List,unsigned char &Out)
{
for (unsigned int C = 0; List[C].Str != 0; C++)
{