From 4494239cc6d519b0b6219387ecd684b42b5c2d79 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 25 Nov 2009 23:20:12 +0100 Subject: add config setting for User-Agent in http and https to the Acquire group, thanks Timothy J. Miller! (Closes: #355782) --- doc/examples/configure-index | 3 +++ 1 file changed, 3 insertions(+) (limited to 'doc/examples') diff --git a/doc/examples/configure-index b/doc/examples/configure-index index 27118fb7e..16e864d89 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -191,6 +191,7 @@ Acquire Max-Age "86400"; // 1 Day age on index files No-Store "false"; // Prevent the cache from storing archives Dl-Limit "7"; // 7Kb/sec maximum download rate + User-Agent "Debian APT-HTTP/1.3"; }; // HTTPS method configuration: @@ -204,6 +205,8 @@ Acquire CaPath "/etc/ssl/certs"; Verify-Host" "true"; AllowRedirect "true"; + + User-Agent "Debian APT-CURL/1.0"; }; ftp -- cgit v1.2.3-70-g09d2 From c0d438474bac961897f9e9472356222f79350c39 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 25 Nov 2009 23:29:57 +0100 Subject: add https options which default to the ones from http for the https method as this is more sane than using only the http options without a possibility to override these for https. --- debian/changelog | 2 + doc/apt.conf.5.xml | 8 ++-- doc/examples/configure-index | 33 ++++++++++---- methods/https.cc | 100 +++++++++++++++++++------------------------ 4 files changed, 76 insertions(+), 67 deletions(-) (limited to 'doc/examples') diff --git a/debian/changelog b/debian/changelog index ed67aaac2..1bd34e522 100644 --- a/debian/changelog +++ b/debian/changelog @@ -24,6 +24,7 @@ apt (0.7.25) UNRELEASED; urgency=low * doc/po4a.conf: activate translation of guide.sgml and offline.sgml * doc/apt.conf.5.xml: - provide a few more details about APT::Immediate-Configure + - briefly document the behaviour of the new https options * doc/sources.list.5.xml: - add note about additional apt-transport-methods * doc/apt-mark.8.xml: @@ -66,6 +67,7 @@ apt (0.7.25) UNRELEASED; urgency=low * methods/http{,s}.cc - add config setting for User-Agent to the Acquire group, thanks Timothy J. Miller! (Closes: #355782) + - add https options which default to http ones (Closes: #557085) [ Chris Leick ] * doc/ various manpages: diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 726bca2cc..d7ad51cfb 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -284,9 +284,11 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; https - HTTPS URIs. Cache-control and proxy options are the same as for - http method. - Pipeline-Depth option is not supported yet. + HTTPS URIs. Cache-control, Timeout, AllowRedirect, Dl-Limit and + proxy options are the same as for http method and will also + default to the options from the http method if they are not + explicitly set for https. Pipeline-Depth option is not + supported yet. CaInfo suboption specifies place of file that holds info about trusted certificates. diff --git a/doc/examples/configure-index b/doc/examples/configure-index index 16e864d89..7e86b3d4a 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -194,19 +194,34 @@ Acquire User-Agent "Debian APT-HTTP/1.3"; }; - // HTTPS method configuration: - // - uses the http proxy config - // - uses the http cache-control values - // - uses the http Dl-Limit values - https + + + // HTTPS method configuration: uses the http + // - proxy config + // - cache-control values + // - Dl-Limit, Timout, ... values + // if not set explicit for https + // + // see /usr/share/doc/apt/examples/apt-https-method-example.conf.gz + // for more examples + https { Verify-Peer "false"; SslCert "/etc/apt/some.pem"; - CaPath "/etc/ssl/certs"; - Verify-Host" "true"; - AllowRedirect "true"; + CaPath "/etc/ssl/certs"; + Verify-Host" "true"; + AllowRedirect "true"; + + Timeout "120"; + AllowRedirect "true"; + + // Cache Control. Note these do not work with Squid 2.0.2 + No-Cache "false"; + Max-Age "86400"; // 1 Day age on index files + No-Store "false"; // Prevent the cache from storing archives + Dl-Limit "7"; // 7Kb/sec maximum download rate - User-Agent "Debian APT-CURL/1.0"; + User-Agent "Debian APT-CURL/1.0"; }; ftp diff --git a/methods/https.cc b/methods/https.cc index e8d7bb5c6..18ecfd3d2 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -1,4 +1,4 @@ -// -*- mode: cpp; mode: fold -*- +//-*- mode: cpp; mode: fold -*- // Description /*{{{*/ // $Id: http.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $ /* ###################################################################### @@ -56,54 +56,38 @@ HttpsMethod::progress_callback(void *clientp, double dltotal, double dlnow, return 0; } -void HttpsMethod::SetupProxy() -{ - URI ServerName = Queue->Uri; - - // Determine the proxy setting - string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host); - if (!SpecificProxy.empty()) - { - if (SpecificProxy == "DIRECT") - Proxy = ""; - else - Proxy = SpecificProxy; - } - else - { - string DefProxy = _config->Find("Acquire::http::Proxy"); - if (!DefProxy.empty()) - { - Proxy = DefProxy; - } - else - { - char* result = getenv("http_proxy"); - Proxy = result ? result : ""; - } - } - - // Parse no_proxy, a , separated list of domains - if (getenv("no_proxy") != 0) - { - if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true) - Proxy = ""; - } - - // Determine what host and port to use based on the proxy settings - string Host; - if (Proxy.empty() == true || Proxy.Host.empty() == true) - { - } - else - { - if (Proxy.Port != 0) - curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port); - curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str()); - } -} - - +void HttpsMethod::SetupProxy() { /*{{{*/ + URI ServerName = Queue->Uri; + + // Determine the proxy setting - try https first, fallback to http and use env at last + string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host, + _config->Find("Acquire::http::Proxy::" + ServerName.Host)); + + if (UseProxy.empty() == true) + UseProxy = _config->Find("Acquire::https::Proxy", _config->Find("Acquire::http::Proxy")); + + // User want to use NO proxy, so nothing to setup + if (UseProxy == "DIRECT") + return; + + if (UseProxy.empty() == false) { + // Parse no_proxy, a comma (,) separated list of domains we don't want to use + // a proxy for so we stop right here if it is in the list + if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true) + return; + } else { + const char* result = getenv("http_proxy"); + UseProxy = result == NULL ? "" : result; + } + + // Determine what host and port to use based on the proxy settings + if (UseProxy.empty() == false) { + Proxy = UseProxy; + if (Proxy.Port != 1) + curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port); + curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str()); + } +} /*}}}*/ // HttpsMethod::Fetch - Fetch an item /*{{{*/ // --------------------------------------------------------------------- /* This adds an item to the pipeline. We keep the pipeline at a fixed @@ -189,12 +173,15 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_SSLVERSION, final_version); // cache-control - if(_config->FindB("Acquire::http::No-Cache",false) == false) + if(_config->FindB("Acquire::https::No-Cache", + _config->FindB("Acquire::http::No-Cache",false)) == false) { // cache enabled - if (_config->FindB("Acquire::http::No-Store",false) == true) + if (_config->FindB("Acquire::https::No-Store", + _config->FindB("Acquire::http::No-Store",false)) == true) headers = curl_slist_append(headers,"Cache-Control: no-store"); - ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::http::Max-Age",0)); + ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::https::Max-Age", + _config->FindI("Acquire::http::Max-Age",0))); headers = curl_slist_append(headers, ss.str().c_str()); } else { // cache disabled by user @@ -204,7 +191,8 @@ bool HttpsMethod::Fetch(FetchItem *Itm) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // speed limit - int dlLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024; + int dlLimit = _config->FindI("Acquire::https::Dl-Limit", + _config->FindI("Acquire::http::Dl-Limit",0))*1024; if (dlLimit > 0) curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, dlLimit); @@ -215,12 +203,14 @@ bool HttpsMethod::Fetch(FetchItem *Itm) "Debian APT-CURL/1.0 ("VERSION")"))); // set timeout - int timeout = _config->FindI("Acquire::http::Timeout",120); + int timeout = _config->FindI("Acquire::https::Timeout", + _config->FindI("Acquire::http::Timeout",120)); curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); // set redirect options and default to 10 redirects - bool AllowRedirect = _config->FindI("Acquire::https::AllowRedirect", true); + bool AllowRedirect = _config->FindB("Acquire::https::AllowRedirect", + _config->FindB("Acquire::http::AllowRedirect",true)); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, AllowRedirect); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10); -- cgit v1.2.3-70-g09d2 From 45df0ad2aab7d019cec855ba2cfe7ecdd0f8c7c8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 26 Nov 2009 22:23:08 +0100 Subject: [BREAK] add possibility to download and use multiply Translation files, configurable with Acquire::Languages accessable with APT::Configuration::getLanguages() and as always with documentation in apt.conf. The commit also includes a very very simple testapp. --- apt-pkg/aptconfiguration.cc | 136 +++++++++++++++++++++++++++++++++++++++ apt-pkg/aptconfiguration.h | 27 ++++++++ apt-pkg/deb/debindexfile.cc | 29 +++++---- apt-pkg/deb/debindexfile.h | 5 +- apt-pkg/deb/deblistparser.cc | 17 ++++- apt-pkg/deb/debmetaindex.cc | 17 ++++- apt-pkg/deb/debrecords.cc | 12 +++- apt-pkg/indexfile.cc | 61 ++++++------------ apt-pkg/pkgcache.cc | 26 +++++--- debian/changelog | 2 + doc/apt.conf.5.xml | 24 ++++++- doc/examples/configure-index | 9 +++ test/libapt/getlanguages_test.cc | 91 ++++++++++++++++++++++++++ test/libapt/makefile | 13 ++++ 14 files changed, 391 insertions(+), 78 deletions(-) create mode 100644 test/libapt/getlanguages_test.cc create mode 100644 test/libapt/makefile (limited to 'doc/examples') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 45ae9bed5..899004d9f 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -87,4 +87,140 @@ const Configuration::getCompressionTypes(bool const &Cached) { return types; } /*}}}*/ +// GetLanguages - Return Vector of Language Codes /*{{{*/ +// --------------------------------------------------------------------- +/* return a vector of language codes in the prefered order. + the special word "environment" will be replaced with the long and the short + code of the local settings and it will be insured that this will not add + duplicates. So in an german local the setting "environment, de_DE, en, de" + will result in "de_DE, de, en". + The special word "none" is the stopcode for the not-All code vector */ +std::vector const Configuration::getLanguages(bool const &All, + bool const &Cached, char const * const Locale) { + using std::string; + + // The detection is boring and has a lot of cornercases, + // so we cache the results to calculated it only once. + std::vector static allCodes; + std::vector static codes; + + // we have something in the cache + if (codes.empty() == false || allCodes.empty() == false) { + if (Cached == true) { + if(All == true && allCodes.empty() == false) + return allCodes; + else + return codes; + } else { + allCodes.clear(); + codes.clear(); + } + } + + // get the environment language code + // we extract both, a long and a short code and then we will + // check if we actually need both (rare) or if the short is enough + string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : Locale); + size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2; + size_t const lenLong = (envMsg.find('.') != string::npos) ? envMsg.find('.') : (lenShort + 3); + + string envLong = envMsg.substr(0,lenLong); + string const envShort = envLong.substr(0,lenShort); + bool envLongIncluded = true, envShortIncluded = false; + + // first cornercase: LANG=C, so we use only "en" Translation + if (envLong == "C") { + codes.push_back("en"); + return codes; + } + + if (envLong != envShort) { + // to save the servers from unneeded queries, we only try also long codes + // for languages it is realistic to have a long code translation file... + char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL }; + for (char const **l = needLong; *l != NULL; l++) + if (envShort.compare(*l) == 0) { + envLongIncluded = false; + break; + } + } + + // we don't add the long code, but we allow the user to do so + if (envLongIncluded == true) + envLong.clear(); + + // FIXME: Remove support for the old APT::Acquire::Translation + // it was undocumented and so it should be not very widthly used + string const oldAcquire = _config->Find("APT::Acquire::Translation",""); + if (oldAcquire.empty() == false && oldAcquire != "environment") { + if (oldAcquire != "none") + codes.push_back(oldAcquire); + return codes; + } + + // Support settings like Acquire::Translation=none on the command line to + // override the configuration settings vector of languages. + string const forceLang = _config->Find("Acquire::Languages",""); + if (forceLang.empty() == false) { + if (forceLang == "environment") { + if (envLongIncluded == false) + codes.push_back(envLong); + if (envShortIncluded == false) + codes.push_back(envShort); + return codes; + } else if (forceLang != "none") + codes.push_back(forceLang); + return codes; + } + + std::vector const lang = _config->FindVector("Acquire::Languages"); + // the default setting -> "environment, en" + if (lang.empty() == true) { + if (envLongIncluded == false) + codes.push_back(envLong); + if (envShortIncluded == false) + codes.push_back(envShort); + if (envShort != "en") + codes.push_back("en"); + return codes; + } + + // the configs define the order, so add the environment + // then needed and ensure the codes are not listed twice. + bool noneSeen = false; + for (std::vector::const_iterator l = lang.begin(); + l != lang.end(); l++) { + if (*l == "environment") { + if (envLongIncluded == true && envShortIncluded == true) + continue; + if (envLongIncluded == false) { + envLongIncluded = true; + if (noneSeen == false) + codes.push_back(envLong); + allCodes.push_back(envLong); + } + if (envShortIncluded == false) { + envShortIncluded = true; + if (noneSeen == false) + codes.push_back(envShort); + allCodes.push_back(envShort); + } + continue; + } else if (*l == "none") { + noneSeen = true; + continue; + } else if ((envLongIncluded == true && *l == envLong) || + (envShortIncluded == true && *l == envShort)) + continue; + + if (noneSeen == false) + codes.push_back(*l); + allCodes.push_back(*l); + } + if (All == true) + return allCodes; + else + return codes; +} + /*}}}*/ } diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index 6a123adce..f2f04a39b 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -39,6 +39,33 @@ public: /*{{{*/ * \return a vector of (all) Language Codes in the prefered usage order */ std::vector static const getCompressionTypes(bool const &Cached = true); + + /** \brief Returns a vector of Language Codes + * + * Languages can be defined with their two or five chars long code. + * This methods handles the various ways to set the prefered codes, + * honors the environment and ensures that the codes are not listed twice. + * + * The special word "environment" will be replaced with the long and the short + * code of the local settings and it will be insured that this will not add + * duplicates. So in an german local the setting "environment, de_DE, en, de" + * will result in "de_DE, de, en". + * + * Another special word is "none" which separates the prefered from all codes + * in this setting. So setting and method can be used to get codes the user want + * to see or to get all language codes APT (should) have Translations available. + * + * \param All return all codes or only codes for languages we want to use + * \param Cached saves the result so we need to calculated it only once + * this parameter should ony be used for testing purposes. + * \param Locale don't get the locale from the system but use this one instead + * this parameter should ony be used for testing purposes. + * + * \return a vector of (all) Language Codes in the prefered usage order + */ + std::vector static const getLanguages(bool const &All = false, + bool const &Cached = true, char const * const Locale = 0); + /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index ed7633803..5beb83665 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -319,10 +319,11 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) : - pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section) -{ -} +debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section, + char const * const Translation) : + pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section), + Language(Translation) +{} /*}}}*/ // TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/ // --------------------------------------------------------------------- @@ -355,8 +356,8 @@ string debTranslationsIndex::IndexURI(const char *Type) const bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const { if (TranslationsAvailable()) { - string TranslationFile = "Translation-" + LanguageCode(); - new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()), + string const TranslationFile = string("Translation-").append(Language); + new pkgAcqIndexTrans(Owner, IndexURI(Language), Info(TranslationFile.c_str()), TranslationFile); } @@ -375,7 +376,7 @@ string debTranslationsIndex::Describe(bool Short) const snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str()); else snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(), - IndexFile(LanguageCode().c_str()).c_str()); + IndexFile(Language).c_str()); return S; } /*}}}*/ @@ -397,20 +398,20 @@ string debTranslationsIndex::Info(const char *Type) const return Info; } /*}}}*/ -bool debTranslationsIndex::HasPackages() const +bool debTranslationsIndex::HasPackages() const /*{{{*/ { if(!TranslationsAvailable()) return false; - return FileExists(IndexFile(LanguageCode().c_str())); + return FileExists(IndexFile(Language)); } - + /*}}}*/ // TranslationsIndex::Exists - Check if the index is available /*{{{*/ // --------------------------------------------------------------------- /* */ bool debTranslationsIndex::Exists() const { - return FileExists(IndexFile(LanguageCode().c_str())); + return FileExists(IndexFile(Language)); } /*}}}*/ // TranslationsIndex::Size - Return the size of the index /*{{{*/ @@ -419,7 +420,7 @@ bool debTranslationsIndex::Exists() const unsigned long debTranslationsIndex::Size() const { struct stat S; - if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0) + if (stat(IndexFile(Language).c_str(),&S) != 0) return 0; return S.st_size; } @@ -430,7 +431,7 @@ unsigned long debTranslationsIndex::Size() const bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const { // Check the translation file, if in use - string TranslationFile = IndexFile(LanguageCode().c_str()); + string TranslationFile = IndexFile(Language); if (TranslationsAvailable() && FileExists(TranslationFile)) { FileFd Trans(TranslationFile,FileFd::ReadOnly); @@ -462,7 +463,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const /* */ pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const { - string FileName = IndexFile(LanguageCode().c_str()); + string FileName = IndexFile(Language); pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; File++) diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index b0012c96b..c0e8d7d8e 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -77,12 +77,13 @@ class debTranslationsIndex : public pkgIndexFile string URI; string Dist; string Section; + const char * const Language; string Info(const char *Type) const; string IndexFile(const char *Type) const; string IndexURI(const char *Type) const; - inline string TranslationFile() const {return "Translation-" + LanguageCode();}; + inline string TranslationFile() const {return string("Translation-").append(Language);}; public: @@ -99,7 +100,7 @@ class debTranslationsIndex : public pkgIndexFile virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; - debTranslationsIndex(string URI,string Dist,string Section); + debTranslationsIndex(string URI,string Dist,string Section, char const * const Language); }; class debSourcesIndex : public pkgIndexFile diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 517b771a5..16e6ee332 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -129,10 +130,11 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) only describe package properties */ string debListParser::Description() { - if (DescriptionLanguage().empty()) + string const lang = DescriptionLanguage(); + if (lang.empty()) return Section.FindS("Description"); else - return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()); + return Section.FindS(string("Description-").append(lang).c_str()); } /*}}}*/ // ListParser::DescriptionLanguage - Return the description lang string /*{{{*/ @@ -142,7 +144,16 @@ string debListParser::Description() assumed to describe original description. */ string debListParser::DescriptionLanguage() { - return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : ""; + if (Section.FindS("Description").empty() == false) + return ""; + + std::vector const lang = APT::Configuration::getLanguages(); + for (std::vector::const_iterator l = lang.begin(); + l != lang.end(); l++) + if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false) + return *l; + + return ""; } /*}}}*/ // ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/ diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index f3ab6960c..8f28f053b 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include using namespace std; @@ -170,13 +171,19 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const new indexRecords (Dist)); // Queue the translations + std::vector const lang = APT::Configuration::getLanguages(true); for (vector::const_iterator I = SectionEntries.begin(); I != SectionEntries.end(); I++) { if((*I)->IsSrc) continue; - debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section); - i.GetIndexes(Owner); + + for (vector::const_iterator l = lang.begin(); + l != lang.end(); l++) + { + debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()); + i.GetIndexes(Owner); + } } return true; @@ -202,6 +209,7 @@ vector *debReleaseIndex::GetIndexFiles() return Indexes; Indexes = new vector ; + std::vector const lang = APT::Configuration::getLanguages(true); for (vector::const_iterator I = SectionEntries.begin(); I != SectionEntries.end(); I++) { if ((*I)->IsSrc) @@ -209,7 +217,10 @@ vector *debReleaseIndex::GetIndexFiles() else { Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted())); - Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section)); + + for (vector::const_iterator l = lang.begin(); + l != lang.end(); l++) + Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str())); } } diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 8ed0bb7eb..5b8538a46 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include /*}}}*/ @@ -109,13 +110,18 @@ string debRecordParser::ShortDesc() string debRecordParser::LongDesc() { string orig, dest; - char *codeset = nl_langinfo(CODESET); if (!Section.FindS("Description").empty()) orig = Section.FindS("Description").c_str(); - else - orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str(); + else + { + vector const lang = APT::Configuration::getLanguages(); + for (vector::const_iterator l = lang.begin(); + orig.empty() && l != lang.end(); l++) + orig = Section.FindS(string("Description-").append(*l).c_str()); + } + char const * const codeset = nl_langinfo(CODESET); if (strcmp(codeset,"UTF-8") != 0) { UTF8ToCodeset(codeset, orig, &dest); orig = dest; diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 08f71feb0..37be87055 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -8,9 +8,9 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#include #include #include +#include #include #include @@ -66,28 +66,20 @@ string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &Record, return string(); } /*}}}*/ -// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/ +// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgIndexFile::TranslationsAvailable() -{ - const string Translation = _config->Find("APT::Acquire::Translation"); - - if (Translation.compare("none") != 0) - return CheckLanguageCode(LanguageCode().c_str()); - else - return false; +bool pkgIndexFile::TranslationsAvailable() { + return (APT::Configuration::getLanguages().empty() != true); } /*}}}*/ -// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/ +// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/ // --------------------------------------------------------------------- -/* */ -/* common cases: de_DE, de_DE@euro, de_DE.UTF-8, de_DE.UTF-8@euro, - de_DE.ISO8859-1, tig_ER - more in /etc/gdm/locale.conf -*/ - -bool pkgIndexFile::CheckLanguageCode(const char *Lang) +/* No intern need for this method anymore as the check for correctness + is already done in getLanguages(). Note also that this check is + rather bad (doesn't take three character like ast into account). + TODO: Remove method with next API break */ +__attribute__ ((deprecated)) bool pkgIndexFile::CheckLanguageCode(const char *Lang) { if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_')) return true; @@ -98,31 +90,14 @@ bool pkgIndexFile::CheckLanguageCode(const char *Lang) return false; } /*}}}*/ -// IndexFile::LanguageCode - Return the Language Code /*{{{*/ +// IndexFile::LanguageCode - Return the Language Code /*{{{*/ // --------------------------------------------------------------------- -/* return the language code */ -string pkgIndexFile::LanguageCode() -{ - const string Translation = _config->Find("APT::Acquire::Translation"); - - if (Translation.compare("environment") == 0) - { - string lang = std::setlocale(LC_MESSAGES,NULL); - - // we have a mapping of the language codes that contains all the language - // codes that need the country code as well - // (like pt_BR, pt_PT, sv_SE, zh_*, en_*) - const char *need_full_langcode[] = { "pt","sv","zh","en", NULL }; - for(const char **s = need_full_langcode;*s != NULL; s++) - if(lang.find(*s) == 0) - return lang.substr(0,5); - - if(lang.size() > 2) - return lang.substr(0,2); - else - return lang; - } - else - return Translation; +/* As we have now possibly more than one LanguageCode this method is + supersided by a) private classmembers or b) getLanguages(). + TODO: Remove method with next API break */ +__attribute__ ((deprecated)) string pkgIndexFile::LanguageCode() { + if (TranslationsAvailable() == false) + return ""; + return APT::Configuration::getLanguages()[0]; } /*}}}*/ diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index b0ce6e598..997ff51fe 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -22,11 +22,11 @@ // Include Files /*{{{*/ #include #include -#include #include #include #include #include +#include #include @@ -674,14 +674,22 @@ string pkgCache::PkgFileIterator::RelStr() */ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const { - pkgCache::DescIterator DescDefault = DescriptionList(); - pkgCache::DescIterator Desc = DescDefault; - for (; Desc.end() == false; Desc++) - if (pkgIndexFile::LanguageCode() == Desc.LanguageCode()) - break; - if (Desc.end() == true) - Desc = DescDefault; - return Desc; + std::vector const lang = APT::Configuration::getLanguages(); + for (std::vector::const_iterator l = lang.begin(); + l != lang.end(); l++) + { + pkgCache::DescIterator DescDefault = DescriptionList(); + pkgCache::DescIterator Desc = DescDefault; + + for (; Desc.end() == false; Desc++) + if (*l == Desc.LanguageCode()) + break; + if (Desc.end() == true) + Desc = DescDefault; + return Desc; + } + + return DescriptionList(); }; /*}}}*/ diff --git a/debian/changelog b/debian/changelog index 0cfb5ff30..07d9c0303 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,8 @@ apt (0.7.25) UNRELEASED; urgency=low Closes: #552606 [ David Kalnischkies ] + * [BREAK] add possibility to download and use multiply + Translation files, configurable with Acquire::Translation * apt-pkg/packagemanager.cc: - better debug output for ImmediateAdd with depth and why - improve the message shown for failing immediate configuration diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index d7ad51cfb..777630e14 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -142,7 +142,7 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; Default release to install packages from if more than one version available. Contains release name, codename or release version. Examples: 'stable', 'testing', 'unstable', 'lenny', 'squeeze', '4.0', '5.0*'. See also &apt-preferences;. - + Ignore-Hold Ignore Held packages; This global option causes the problem resolver to ignore held packages in its decision making. @@ -392,6 +392,27 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; these warnings are most of the time false negatives. Future versions will maybe include a way to really prefer uncompressed files to support the usage of local mirrors. + + Languages + The Languages subsection controls which Translation files are downloaded + and in which order APT tries to display the Description-Translations. APT will try to display the first + available Description for the Language which is listed at first. Languages can be defined with their + short or long Languagecodes. Note that not all archives provide Translation + files for every Language - especially the long Languagecodes are rare, so please + inform you which ones are available before you set here impossible values. + The default list includes "environment" and "en". "environment" has a special meaning here: + It will be replaced at runtime with the languagecodes extracted from the LC_MESSAGES enviroment variable. + It will also ensure that these codes are not included twice in the list. If LC_MESSAGES + is set to "C" only the Translation-en file (if available) will be used. + To force apt to use no Translation file use the setting Acquire::Languages=none. "none" + is another special meaning code which will stop the search for a fitting Translation file. + This can be used by the system administrator to let APT know that it should download also this files without + actually use them if not the environment specifies this languages. So the following example configuration will + result in the order "en, de" in an english and in "de, en" in a german localization. Note that "fr" is downloaded, + but not used if APT is not used in a french localization, in such an environment the order would be "fr, de, en". + Acquire::Languages { "environment"; "de"; "en"; "none"; "fr"; }; + + @@ -983,6 +1004,7 @@ is commented. --> + diff --git a/doc/examples/configure-index b/doc/examples/configure-index index 7e86b3d4a..05826feaa 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -273,6 +273,15 @@ Acquire Order { "gz"; "lzma"; "bz2"; }; }; + + Languages + { + "environment"; + "de"; + "en"; + "none"; + "fr"; + }; }; // Directory layout diff --git a/test/libapt/getlanguages_test.cc b/test/libapt/getlanguages_test.cc new file mode 100644 index 000000000..f3629df68 --- /dev/null +++ b/test/libapt/getlanguages_test.cc @@ -0,0 +1,91 @@ +#include +#include + +#include +#include +#include + +#include + +// simple helper to quickly output a vector of strings +void dumpVector(std::vector vec) { + for (std::vector::const_iterator v = vec.begin(); + v != vec.end(); v++) + std::cout << *v << std::endl; +} + +int main(int argc,char *argv[]) +{ + std::vector vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + assert(vec.size() == 2); + assert(vec[0] == "de"); + assert(vec[1] == "en"); + + // Special: Check if the cache is actually in use + vec = APT::Configuration::getLanguages(false, true, "en_GB.UTF-8"); + assert(vec.size() == 2); + assert(vec[0] == "de"); + assert(vec[1] == "en"); + + vec = APT::Configuration::getLanguages(false, false, "en_GB.UTF-8"); + assert(vec.size() == 2); + assert(vec[0] == "en_GB"); + assert(vec[1] == "en"); + + vec = APT::Configuration::getLanguages(false, false, "pt_PR.UTF-8"); + assert(vec.size() == 3); + assert(vec[0] == "pt_PR"); + assert(vec[1] == "pt"); + assert(vec[2] == "en"); + + vec = APT::Configuration::getLanguages(false, false, "ast_DE.UTF-8"); // bogus, but syntactical correct + assert(vec.size() == 2); + assert(vec[0] == "ast"); + assert(vec[1] == "en"); + + vec = APT::Configuration::getLanguages(false, false, "C"); + assert(vec.size() == 1); + assert(vec[0] == "en"); + + _config->Set("Acquire::Languages::1", "environment"); + _config->Set("Acquire::Languages::2", "en"); + vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + assert(vec.size() == 2); + assert(vec[0] == "de"); + assert(vec[1] == "en"); + + _config->Set("Acquire::Languages::3", "de"); + vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + assert(vec.size() == 2); + assert(vec[0] == "de"); + assert(vec[1] == "en"); + + _config->Set("Acquire::Languages::1", "none"); + vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + assert(vec.size() == 0); + vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + assert(vec[0] == "en"); + assert(vec[1] == "de"); + + _config->Set("Acquire::Languages::1", "fr"); + _config->Set("Acquire::Languages", "de_DE"); + vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + assert(vec.size() == 1); + assert(vec[0] == "de_DE"); + + _config->Set("Acquire::Languages", "none"); + vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + assert(vec.size() == 0); + + _config->Set("Acquire::Languages", ""); + //FIXME: Remove support for this deprecated setting + _config->Set("APT::Acquire::Translation", "ast_DE"); + vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + assert(vec.size() == 1); + assert(vec[0] == "ast_DE"); + _config->Set("APT::Acquire::Translation", "none"); + vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + assert(vec.size() == 0); + + return 0; +} diff --git a/test/libapt/makefile b/test/libapt/makefile new file mode 100644 index 000000000..f61a95f3d --- /dev/null +++ b/test/libapt/makefile @@ -0,0 +1,13 @@ +# -*- make -*- +BASE=../.. +SUBDIR=test/libapt +BASENAME=_libapt_test + +# Bring in the default rules +include ../../buildlib/defaults.mak + +# Program for testing getLanguageCode +PROGRAM = getLanguages${BASENAME} +SLIBS = -lapt-pkg +SOURCE = getlanguages_test.cc +include $(PROGRAM_H) -- cgit v1.2.3-70-g09d2 From 02dceb31f77f0812c76334a1758631c7cf9544a3 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 2 Jan 2010 00:22:31 +0100 Subject: add configuration PDiffs::Limit-options (FileLimit and SizeLimit) to not download too many or too big patches (Closes: #554349) --- apt-pkg/acquire-item.cc | 62 ++++++++++++++++++++++++++++++++++---------- debian/changelog | 3 +++ doc/apt.conf.5.xml | 9 ++++++- doc/examples/configure-index | 5 +++- 4 files changed, 64 insertions(+), 15 deletions(-) (limited to 'doc/examples') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 10e80eb56..4f0abbb91 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -219,19 +219,19 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ if(TF.Step(Tags) == true) { - string local_sha1; bool found = false; DiffInfo d; string size; - string tmp = Tags.FindS("SHA1-Current"); + string const tmp = Tags.FindS("SHA1-Current"); std::stringstream ss(tmp); - ss >> ServerSha1; + ss >> ServerSha1 >> size; + unsigned long const ServerSize = atol(size.c_str()); FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); SHA1Summation SHA1; SHA1.AddFD(fd.Fd(), fd.Size()); - local_sha1 = string(SHA1.Result()); + string const local_sha1 = SHA1.Result(); if(local_sha1 == ServerSha1) { @@ -248,20 +248,56 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ std::clog << "SHA1-Current: " << ServerSha1 << std::endl; // check the historie and see what patches we need - string history = Tags.FindS("SHA1-History"); + string const history = Tags.FindS("SHA1-History"); std::stringstream hist(history); - while(hist >> d.sha1 >> size >> d.file) + while(hist >> d.sha1 >> size >> d.file) { - d.size = atoi(size.c_str()); // read until the first match is found + // from that point on, we probably need all diffs if(d.sha1 == local_sha1) found=true; - // from that point on, we probably need all diffs - if(found) + else if (found == false) + continue; + + if(Debug) + std::clog << "Need to get diff: " << d.file << std::endl; + available_patches.push_back(d); + } + + if (available_patches.empty() == false) + { + // patching with too many files is rather slow compared to a fast download + unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0); + if (fileLimit != 0 && fileLimit < available_patches.size()) + { + if (Debug) + std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit + << ") so fallback to complete download" << std::endl; + return false; + } + + // see if the patches are too big + found = false; // it was true and it will be true again at the end + d = *available_patches.begin(); + string const firstPatch = d.file; + unsigned long patchesSize = 0; + std::stringstream patches(Tags.FindS("SHA1-Patches")); + while(patches >> d.sha1 >> size >> d.file) + { + if (firstPatch == d.file) + found = true; + else if (found == false) + continue; + + patchesSize += atol(size.c_str()); + } + unsigned long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); + if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) { - if(Debug) - std::clog << "Need to get diff: " << d.file << std::endl; - available_patches.push_back(d); + if (Debug) + std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100 + << ") so fallback to complete download" << std::endl; + return false; } } } @@ -270,7 +306,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ if(found) { // queue the diffs - string::size_type last_space = Description.rfind(" "); + string::size_type const last_space = Description.rfind(" "); if(last_space != string::npos) Description.erase(last_space, Description.size()-last_space); new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, diff --git a/debian/changelog b/debian/changelog index e36813148..1454eed3c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -31,6 +31,9 @@ apt (0.7.26) UNRELEASED; urgency=low - instruct debiandoc to build files with utf-8 encoding * buildlib/tools.m4: - fix some warning from the buildtools + * apt-pkg/acquire-item.cc: + - add configuration PDiffs::Limit-options to not download + too many or too big patches (Closes: #554349) -- Michael Vogt Thu, 10 Dec 2009 22:02:38 +0100 diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 734ae1fe7..fd50e377f 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -221,7 +221,14 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; PDiffs Try to download deltas called PDiffs for Packages or Sources files instead of downloading whole ones. True - by default. + by default. + Two sub-options to limit the use of PDiffs are also available: + With FileLimit can be specified how many PDiff files + are downloaded at most to patch a file. SizeLimit + on the other hand is the maximum precentage of the size of all patches + compared to the size of the targeted file. If one of these limits is + exceeded the complete file is downloaded instead of the patches. + Queue-Mode diff --git a/doc/examples/configure-index b/doc/examples/configure-index index 0a20e8f2b..be461aaad 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -176,7 +176,10 @@ Acquire Source-Symlinks "true"; PDiffs "true"; // try to get the IndexFile diffs - + PDiffs::FileLimit "4"; // don't use diffs if we would need more than 4 diffs + PDiffs::SizeLimit "50"; // don't use diffs if size of all patches excess + // 50% of the size of the original file + // HTTP method configuration http { -- cgit v1.2.3-70-g09d2 From c24f6ce22cd6720004addad2e3382b3caa6b1b7c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 4 Jan 2010 13:45:14 +0100 Subject: add TrustedParts so in the future new keyrings can just be dropped into /etc/apt/trusted.gpg.d/ which eliminates the need to have gpg installed to add keys to APTs trusted keyring (with apt-key) (Closes #304846) - Thanks to Timo Weingärtner & Peter Palfrader for providing different patchs/ideas for this! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmdline/apt-key | 37 +++++++++++++++-- debian/apt.dirs | 1 + debian/changelog | 4 ++ doc/apt-key.8.xml | 24 ++++++++--- doc/apt.ent | 13 ++++++ doc/examples/configure-index | 7 +--- methods/gpgv.cc | 98 +++++++++++++++++++++++++------------------- 7 files changed, 126 insertions(+), 58 deletions(-) (limited to 'doc/examples') diff --git a/cmdline/apt-key b/cmdline/apt-key index 24010edf3..1950723f3 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -5,10 +5,8 @@ unset GREP_OPTIONS # We don't use a secret keyring, of course, but gpg panics and # implodes if there isn't one available - GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg --trustdb-name /etc/apt/trustdb.gpg" -GPG="$GPG_CMD --keyring /etc/apt/trusted.gpg" - +GPG="$GPG_CMD" MASTER_KEYRING="" ARCHIVE_KEYRING_URI="" @@ -115,7 +113,7 @@ update() { usage() { - echo "Usage: apt-key [command] [arguments]" + echo "Usage: apt-key [--keyring file] [command] [arguments]" echo echo "Manage apt's list of trusted keys" echo @@ -129,8 +127,39 @@ usage() { echo " apt-key finger - list fingerprints" echo " apt-key adv - pass advanced options to gpg (download key)" echo + echo "If no specific keyring file is given the command applies to all keyring files." } +# Determine on which keyring we want to work +if [ "$1" = "--keyring" ]; then + echo "keyfile given" + shift + TRUSTEDFILE="$1" + if [ -r "$TRUSTEDFILE" ]; then + GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE" + else + echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable" + exit 1 + fi + shift +else + echo "generate list" + TRUSTEDFILE="/etc/apt/trusted.gpg" + if [ -r "$TRUSTEDFILE" ]; then + GPG="$GPG --keyring $TRUSTEDFILE" + fi + GPG="$GPG --primary-keyring $TRUSTEDFILE" + TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + if [ -d "$TRUSTEDPARTS" ]; then + echo "parts active" + for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do + echo "part -> $trusted" + GPG="$GPG --keyring $trusted" + done + fi +fi +echo "COMMAND: $GPG" + command="$1" if [ -z "$command" ]; then usage diff --git a/debian/apt.dirs b/debian/apt.dirs index fb6716c35..66556e453 100644 --- a/debian/apt.dirs +++ b/debian/apt.dirs @@ -5,6 +5,7 @@ etc/apt etc/apt/apt.conf.d etc/apt/preferences.d etc/apt/sources.list.d +etc/apt/trusted.gpg.d etc/logrotate.d var/cache/apt/archives/partial var/lib/apt/lists/partial diff --git a/debian/changelog b/debian/changelog index f70c5735f..fca8d3ccb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -41,6 +41,10 @@ apt (0.7.26) UNRELEASED; urgency=low the keyring so we don't need to ship our own version * cmdline/apt-key: - errors out if wget is not installed (Closes: #545754) + - add --keyring option as we have now possibly many + * methods/gpgv.cc: + - pass all keyrings (TrustedParts) to gpgv instead of + using only one trusted.gpg keyring (Closes: #304846) -- Michael Vogt Thu, 10 Dec 2009 22:02:38 +0100 diff --git a/doc/apt-key.8.xml b/doc/apt-key.8.xml index 7b0691b5e..8f445b7f9 100644 --- a/doc/apt-key.8.xml +++ b/doc/apt-key.8.xml @@ -26,7 +26,8 @@ apt-key - command/ + + command @@ -135,11 +136,24 @@ + Options +Note that options need to be defined before the commands described in the previous section. + + --keyring filename + With this option it is possible to specify a specific keyring + file the command should operate on. The default is that a command is executed + on the trusted.gpg file as well as on all parts in the + trusted.gpg.d directory, through trusted.gpg + is the primary keyring which means that e.g. new keys are added to this one. + + + + + Files - /etc/apt/trusted.gpg - Keyring of local trusted keys, new keys will be added here. - + + &file-trustedgpg; /etc/apt/trustdb.gpg Local trust database of archive keys. @@ -153,8 +167,6 @@ Keyring of Debian archive removed trusted keys. - - diff --git a/doc/apt.ent b/doc/apt.ent index 0b341ec14..da43d8f3d 100644 --- a/doc/apt.ent +++ b/doc/apt.ent @@ -353,3 +353,16 @@ Configuration Item: Dir::State::Lists (implicit partial). "> + +/etc/apt/trusted.gpg + Keyring of local trusted keys, new keys will be added here. + Configuration Item: Dir::Etc::Trusted. + + + /etc/apt/trusted.gpg.d/ + File fragments for the trusted keys, additional keyrings can + be stored here (by other packages or the administrator). + Configuration Item Dir::Etc::TrustedParts. + +"> diff --git a/doc/examples/configure-index b/doc/examples/configure-index index be461aaad..87cf97ffe 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -90,11 +90,6 @@ APT TrustCDROM "false"; // consider the CDROM always trusted }; - GPGV - { - TrustedKeyring "/etc/apt/trusted.gpg"; - }; - // Some general options Ignore-Hold "false"; Clean-Installed "true"; @@ -320,6 +315,8 @@ Dir "/" SourceParts "sources.list.d"; VendorList "vendors.list"; VendorParts "vendors.list.d"; + Trusted "trusted.gpg"; + TrustedParts "trusted.gpg.d"; }; // Locations of binaries diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 150c1d315..e3e849827 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -1,10 +1,9 @@ #include #include #include +#include #include -#include -#include #include #include #include @@ -45,42 +44,47 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, vector &WorthlessSigners, vector &NoPubKeySigners) { + bool const Debug = _config->FindB("Debug::Acquire::gpgv", false); // setup a (empty) stringstream for formating the return value std::stringstream ret; ret.str(""); - if (_config->FindB("Debug::Acquire::gpgv", false)) - { - std::cerr << "inside VerifyGetSigners" << std::endl; - } + if (Debug == true) + std::clog << "inside VerifyGetSigners" << std::endl; + pid_t pid; int fd[2]; FILE *pipein; int status; - struct stat buff; - string gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); - string pubringpath = _config->Find("APT::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg"); - if (_config->FindB("Debug::Acquire::gpgv", false)) + string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); + // FIXME: remove support for deprecated APT::GPGV setting + string const trustedFile = _config->FindFile("Dir::Etc::Trusted", + _config->Find("APT::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg").c_str()); + string const trustedPath = _config->FindDir("Dir::Etc::TrustedParts", "/etc/apt/trusted.gpg.d"); + if (Debug == true) { - std::cerr << "gpgv path: " << gpgvpath << std::endl; - std::cerr << "Keyring path: " << pubringpath << std::endl; + std::clog << "gpgv path: " << gpgvpath << std::endl; + std::clog << "Keyring file: " << trustedFile << std::endl; + std::clog << "Keyring path: " << trustedPath << std::endl; } - if (stat(pubringpath.c_str(), &buff) != 0) + vector keyrings = GetListOfFilesInDir(trustedPath, "gpg", false); + if (FileExists(trustedFile) == true) + keyrings.push_back(trustedFile); + + if (keyrings.empty() == true) { - ioprintf(ret, _("Couldn't access keyring: '%s'"), strerror(errno)); + // TRANSLATOR: %s is the trusted keyring parts directory + ioprintf(ret, _("No keyring installed in %s."), trustedPath.c_str()); return ret.str(); } + if (pipe(fd) < 0) - { return "Couldn't create pipe"; - } pid = fork(); if (pid < 0) - { return string("Couldn't spawn new process") + strerror(errno); - } else if (pid == 0) { const char *Args[400]; @@ -90,8 +94,16 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, Args[i++] = "--status-fd"; Args[i++] = "3"; Args[i++] = "--ignore-time-conflict"; - Args[i++] = "--keyring"; - Args[i++] = pubringpath.c_str(); + for (vector::const_iterator K = keyrings.begin(); + K != keyrings.end(); ++K) + { + Args[i++] = "--keyring"; + Args[i++] = K->c_str(); + if(i >= 395) { + std::clog << _("E: Too many keyrings should be passed to gpgv. Exiting.") << std::endl; + exit(111); + } + } Configuration::Item const *Opts; Opts = _config->Tree("Acquire::gpgv::Options"); @@ -104,7 +116,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, continue; Args[i++] = Opts->Value.c_str(); if(i >= 395) { - std::cerr << _("E: Argument list from Acquire::gpgv::Options too long. Exiting.") << std::endl; + std::clog << _("E: Argument list from Acquire::gpgv::Options too long. Exiting.") << std::endl; exit(111); } } @@ -113,14 +125,14 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, Args[i++] = outfile; Args[i++] = NULL; - if (_config->FindB("Debug::Acquire::gpgv", false)) + if (Debug == true) { - std::cerr << "Preparing to exec: " << gpgvpath; + std::clog << "Preparing to exec: " << gpgvpath; for(unsigned int j=0;Args[j] != NULL; j++) - std::cerr << " " << Args[j]; - std::cerr << std::endl; + std::clog << " " << Args[j]; + std::clog << std::endl; } - int nullfd = open("/dev/null", O_RDONLY); + int const nullfd = open("/dev/null", O_RDONLY); close(fd[0]); // Redirect output to /dev/null; we read from the status fd dup2(nullfd, STDOUT_FILENO); @@ -159,8 +171,8 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, break; *(buffer+bufferoff) = '\0'; bufferoff = 0; - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Read: " << buffer << std::endl; + if (Debug == true) + std::clog << "Read: " << buffer << std::endl; // Push the data into three separate vectors, which // we later concatenate. They're kept separate so @@ -168,33 +180,33 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, // it will be better. if (strncmp(buffer, GNUPGBADSIG, sizeof(GNUPGBADSIG)-1) == 0) { - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got BADSIG! " << std::endl; + if (Debug == true) + std::clog << "Got BADSIG! " << std::endl; BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } if (strncmp(buffer, GNUPGNOPUBKEY, sizeof(GNUPGNOPUBKEY)-1) == 0) { - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got NO_PUBKEY " << std::endl; + if (Debug == true) + std::clog << "Got NO_PUBKEY " << std::endl; NoPubKeySigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0) { - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got NODATA! " << std::endl; + if (Debug == true) + std::clog << "Got NODATA! " << std::endl; BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0) { - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got KEYEXPIRED! " << std::endl; + if (Debug == true) + std::clog << "Got KEYEXPIRED! " << std::endl; WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0) { - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got REVKEYSIG! " << std::endl; + if (Debug == true) + std::clog << "Got REVKEYSIG! " << std::endl; WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0) @@ -204,17 +216,17 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, while (*p && isxdigit(*p)) p++; *p = 0; - if (_config->FindB("Debug::Acquire::gpgv", false)) - std::cerr << "Got GOODSIG, key ID:" << sig << std::endl; + if (Debug == true) + std::clog << "Got GOODSIG, key ID:" << sig << std::endl; GoodSigners.push_back(string(sig)); } } fclose(pipein); waitpid(pid, &status, 0); - if (_config->FindB("Debug::Acquire::gpgv", false)) + if (Debug == true) { - std::cerr << "gpgv exited\n"; + std::clog << "gpgv exited\n"; } if (WEXITSTATUS(status) == 0) @@ -305,7 +317,7 @@ bool GPGVMethod::Fetch(FetchItem *Itm) if (_config->FindB("Debug::Acquire::gpgv", false)) { - std::cerr << "gpgv succeeded\n"; + std::clog << "gpgv succeeded\n"; } return true; -- cgit v1.2.3-70-g09d2 From 930f51811cd36a695c07f0b8414b118ce28dda04 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 4 Jan 2010 13:54:57 +0100 Subject: finally merge the rest of the patchset from Arnaud Ebalard with the CRL and Issuers options for https, thanks! (Closes: #485963) --- debian/changelog | 3 +++ doc/examples/apt-https-method-example.conf | 21 +++++++++++++++++++++ methods/https.cc | 14 ++++++++++++++ 3 files changed, 38 insertions(+) (limited to 'doc/examples') diff --git a/debian/changelog b/debian/changelog index fca8d3ccb..cdf477cfd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -45,6 +45,9 @@ apt (0.7.26) UNRELEASED; urgency=low * methods/gpgv.cc: - pass all keyrings (TrustedParts) to gpgv instead of using only one trusted.gpg keyring (Closes: #304846) + * methods/https.cc: + - finally merge the rest of the patchset from Arnaud Ebalard + with the CRL and Issuers options, thanks! (Closes: #485963) -- Michael Vogt Thu, 10 Dec 2009 22:02:38 +0100 diff --git a/doc/examples/apt-https-method-example.conf b/doc/examples/apt-https-method-example.conf index 0067171bd..cc7889044 100644 --- a/doc/examples/apt-https-method-example.conf +++ b/doc/examples/apt-https-method-example.conf @@ -36,6 +36,8 @@ to access its content. - The certificate presented by both server have (as expected) a CN that matches their respective DNS names. + - We have CRL available for both dom1.tld and dom2.tld PKI, and intend + to use them. - It somtimes happens that we had other more generic https available repository to our list. We want the checks to be performed against a common list of anchors (like the one provided by ca-certificates @@ -56,10 +58,13 @@ Acquire::https::CaInfo "/etc/ssl/certs/ca-certificates.pem"; // Use a specific anchor and associated CRL. Enforce issuer of // server certificate using its cert. Acquire::https::secure.dom1.tld::CaInfo "/etc/apt/certs/ca-dom1-crt.pem"; +Acquire::https::secure.dom1.tld::CrlFile "/etc/apt/certs/ca-dom1-crl.pem"; +Acquire::https::secure.dom1.tld::IssuerCert "/etc/apt/certs/secure.dom1-issuer-crt.pem"; // Like previous for anchor and CRL, but also provide our // certificate and keys for client authentication. Acquire::https::secure.dom2.tld::CaInfo "/etc/apt/certs/ca-dom2-crt.pem"; +Acquire::https::secure.dom2.tld::CrlFile "/etc/apt/certs/ca-dom2-crl.pem"; Acquire::https::secure.dom2.tld::SslCert "/etc/apt/certs/my-crt.pem"; Acquire::https::secure.dom2.tld::SslKey "/etc/apt/certs/my-key.pem"; @@ -97,6 +102,22 @@ Acquire::https::secure.dom2.tld::SslKey "/etc/apt/certs/my-key.pem"; used for the https entries in the sources.list file that use that repository (with the same name). + Acquire::https[::repo.domain.tld]::CrlFile "/path/to/all/crl.pem"; + + Like previous knob but for passing the list of CRL files (in PEM + format) to be used to verify revocation status. Again, if the + option is defined with no specific mirror (probably makes little + sense), this CRL information is used for all defined https entries + in sources.list file. In a mirror specific context, it only applies + to that mirror. + + Acquire::https[::repo.domain.tld]::IssuerCert "/path/to/issuer/cert.pem"; + + Allows to constrain the issuer of the server certificate (for all + https mirrors or a specific one) to a specific issuer. If the + server certificate has not been issued by this certificate, + connection fails. + Acquire::https[::repo.domain.tld]::Verify-Peer "true"; When authenticating the server, if the certificate verification fails diff --git a/methods/https.cc b/methods/https.cc index 5d8e63f47..35c23db20 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -151,6 +151,13 @@ bool HttpsMethod::Fetch(FetchItem *Itm) default_verify = 0; curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verify); + // Also enforce issuer of server certificate using its cert + string issuercert = _config->Find("Acquire::https::IssuerCert",""); + knob = "Acquire::https::"+remotehost+"::IssuerCert"; + issuercert = _config->Find(knob.c_str(),issuercert.c_str()); + if(issuercert != "") + curl_easy_setopt(curl, CURLOPT_ISSUERCERT,issuercert.c_str()); + // For client authentication, certificate file ... string pem = _config->Find("Acquire::https::SslCert",""); knob = "Acquire::https::"+remotehost+"::SslCert"; @@ -177,6 +184,13 @@ bool HttpsMethod::Fetch(FetchItem *Itm) final_version = CURL_SSLVERSION_SSLv3; curl_easy_setopt(curl, CURLOPT_SSLVERSION, final_version); + // CRL file + string crlfile = _config->Find("Acquire::https::CrlFile",""); + knob = "Acquire::https::"+remotehost+"::CrlFile"; + crlfile = _config->Find(knob.c_str(),crlfile.c_str()); + if(crlfile != "") + curl_easy_setopt(curl, CURLOPT_CRLFILE, crlfile.c_str()); + // cache-control if(_config->FindB("Acquire::https::No-Cache", _config->FindB("Acquire::http::No-Cache",false)) == false) -- cgit v1.2.3-70-g09d2