#
SET(LIBZYPP_MAJOR "17")
SET(LIBZYPP_COMPATMINOR "2")
-SET(LIBZYPP_MINOR "5")
-SET(LIBZYPP_PATCH "2")
+SET(LIBZYPP_MINOR "6")
+SET(LIBZYPP_PATCH "0")
#
-# LAST RELEASED: 17.5.2 (2)
+# LAST RELEASED: 17.6.0 (2)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
-------------------------------------------------------------------
+Fri Aug 3 11:11:25 CEST 2018 - ma@suse.de
+
+- RepoInfo::provideKey: add report telling where we look for missing
+ keys.
+- Support listing gpgkey URLs in repo files (bsc#1088037)
+- Add new report to request user approval for importing a package key
+- Handle http error 502 Bad Gateway in curl backend (bsc #1070851)
+ (fixes openSUSE/zypper#177)
+- Add filesize check for downloads with known size (bsc#408814)
+- Removed superfluous space in translation (bsc#1102019)
+- version 17.6.0 (2)
+
+-------------------------------------------------------------------
Thu Jul 19 12:57:21 CEST 2018 - ma@suse.de
- Prevent the system from sleeping during a commit
#: zypp/target/RpmPostTransCollector.cc:160
#, c-format, boost-format
msgid "Executing %posttrans scripts"
-msgstr "%p osttrans scripts werden ausgeführt"
+msgstr "%posttrans scripts werden ausgeführt"
#: zypp/target/TargetImpl.cc:310
msgid " executed"
//file should be removed once the ManagedFile goes out of scope
BOOST_CHECK(check_file_exists(fPath) == false);
+ BOOST_CHECK(setaccess.doesFileExist("/test-big.txt"));
+ BOOST_CHECK(setaccess.doesFileExist("dir/test-big.txt"));
+
+ {
+ // providing a file with wrong filesize should throw
+ OnMediaLocation locPlain("dir/test-big.txt");
+ locPlain.setDownloadSize( zypp::ByteCount(500, zypp::ByteCount::B) );
+ BOOST_CHECK_THROW(setaccess.provideFile(locPlain), media::MediaFileSizeExceededException);
+
+ // using the correct file size should NOT throw
+ locPlain.setDownloadSize( zypp::ByteCount(7135, zypp::ByteCount::B) );
+ Pathname file = setaccess.provideFile( locPlain );
+ BOOST_CHECK(check_file_exists(file) == true);
+ }
+
+ {
+ // test the maximum filesize again with metalink downloads
+ // providing a file with wrong filesize should throw
+ OnMediaLocation locMeta("/test-big.txt");
+ locMeta.setDownloadSize( zypp::ByteCount(500, zypp::ByteCount::B) );
+ BOOST_CHECK_THROW(setaccess.provideFile(locMeta), media::MediaFileSizeExceededException);
+
+ // using the correct file size should NOT throw
+ locMeta.setDownloadSize( zypp::ByteCount(7135, zypp::ByteCount::B) );
+ Pathname file = setaccess.provideFile( locMeta );
+ BOOST_CHECK(check_file_exists(file) == true);
+ }
+
web.stop();
}
--- /dev/null
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<metalink version="3.0"
+ xmlns="http://www.metalinker.org/"
+ generator="http://metalinks.sourceforge.net/"
+ >
+<files>
+ <file name="test-big.txt">
+ <size>7135</size>
+ <verification>
+ <hash type="md4">818dcbb0bbb033aa8b8c9ddd269648d2</hash>
+ <hash type="md5">f69a3e53751eb3249c3c36c50290b8da</hash>
+ <hash type="sha1">edf0cf52765c9b5cfeddfd83b62f8517b119ca77</hash>
+ <hash type="sha256">b0343a8ee06d97c9786b65bcb64c49fbb7e1d517159fac4633ba56f7a521fef0</hash>
+ <hash type="sha384">202d21693dabe53ff5f2305d6b78844ffaa3b566b9644d61ca087cab752965b16d6a188def7a9463b5f17fdc50b3d105</hash>
+ <hash type="sha512">caf260dd5420a6a6df6a558eac69a901cd3e43dbfd37b54e0fb176940f3e09c3f96c7faa22e505777106ebf056c471be7556c8cba80331d6efdb9e763e66190b</hash>
+ <hash type="ripemd160">77fc06ff936163cfb6c1b0c68cb47a295a5bf8e3</hash>
+ <hash type="tiger192">2fcd624ba2ad1adb2ff23af58049b6f7b062754eadd031b1</hash>
+ <hash type="crc32">011209ae</hash>
+ <hash type="ed2k">818dcbb0bbb033aa8b8c9ddd269648d2</hash>
+ <pieces length="262144" type="sha1">
+ <hash piece="0">edf0cf52765c9b5cfeddfd83b62f8517b119ca77</hash>
+ </pieces>
+ </verification>
+ <resources>
+ <url type="http">http://localhost:10002/dir/test-big.txt</url>
+ </resources>
+ </file>
+</files>
+</metalink>
bool KeyRingReport::askUserToAcceptVerificationFailed( const std::string & file, const PublicKey & key, const KeyContext & keycontext )
{ return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); }
+ bool KeyRingReport::askUserToAcceptPackageKey(const PublicKey &key_r, const KeyContext &keycontext_r)
+ {
+ UserData data(ACCEPT_PACKAGE_KEY_REQUEST);
+ data.set("PublicKey", key_r);
+ data.set("KeyContext", keycontext_r);
+ report(data);
+
+ if ( data.hasvalue("TrustKey") )
+ return data.get<bool>("TrustKey");
+ return false;
+ }
+
namespace
{
///////////////////////////////////////////////////////////////////
KEY_TRUST_AND_IMPORT
};
+ constexpr static const char * ACCEPT_PACKAGE_KEY_REQUEST = "KeyRingReport/AcceptPackageKey";
+
/**
* Ask user to trust and/or import the key to trusted keyring.
* \see KeyTrust
*/
virtual bool askUserToAcceptVerificationFailed( const std::string &file, const PublicKey &key, const KeyContext &keycontext = KeyContext() );
+ /**
+ * Ask user to trust and/or import the package key to trusted keyring, using ReportBase::report
+ *
+ * The UserData object will have the following fields:
+ * "PublicKey" The PublicKey to be accepted
+ * "KeyContext" The KeyContext
+ *
+ * Userdata accepted:
+ * "TrustKey" bool user can either trust or not trust the key
+ *
+ * \see KeyTrust
+ * \sa ReportBase::report
+ * \note this is a non virtual function and will use ReportBase::report to send the report.
+ *
+ */
+ bool askUserToAcceptPackageKey( const PublicKey &key_r, const KeyContext &keycontext_r = KeyContext() );
+
};
struct KeyRingSignals : public callback::ReportBase
struct ProvideFileOperation
{
Pathname result;
+ ByteCount expectedFileSize;
void operator()( media::MediaAccessId media, const Pathname &file )
{
media::MediaManager media_mgr;
- media_mgr.provideFile(media, file);
+ media_mgr.provideFile(media, file, expectedFileSize);
result = media_mgr.localPath(media, file);
}
};
Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile )
{
ProvideFileOperation op;
+ op.expectedFileSize = resource.downloadSize();
provide( boost::ref(op), resource, options, deltafile );
return op.result;
}
return op.result;
}
+ Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
+ {
+ try
+ {
+ if ( doesFileExist( file, media_nr ) )
+ return provideFile( file, media_nr, PROVIDE_NON_INTERACTIVE );
+ }
+ catch ( const media::MediaFileNotFoundException & excpt_r )
+ { ZYPP_CAUGHT( excpt_r ); }
+ catch ( const media::MediaNotAFileException & excpt_r )
+ { ZYPP_CAUGHT( excpt_r ); }
+ return Pathname();
+ }
+
ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options)
{
Url url(file_url);
return tmpFile;
}
- Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr )
+ ManagedFile MediaSetAccess::provideOptionalFileFromUrl( const Url & file_url )
{
try
{
- if ( doesFileExist( file, media_nr ) )
- return provideFile( file, media_nr, PROVIDE_NON_INTERACTIVE );
+ return provideFileFromUrl( file_url, PROVIDE_NON_INTERACTIVE );
}
catch ( const media::MediaFileNotFoundException & excpt_r )
{ ZYPP_CAUGHT( excpt_r ); }
catch ( const media::MediaNotAFileException & excpt_r )
{ ZYPP_CAUGHT( excpt_r ); }
- return Pathname();
+ return ManagedFile();
}
bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
Pathname provideFile(const Pathname & file, unsigned media_nr = 1, ProvideFileOptions options = PROVIDE_DEFAULT );
/**
+ * Provides an optional \a file from media \a media_nr.
+ *
+ * Like \ref provideFile (NON_INTERACTIVE), but return an empty \ref Pathname
+ * rather than throwing a \ref MediaException if the file is not present on
+ * the media.
+ */
+ Pathname provideOptionalFile( const Pathname & file, unsigned media_nr = 1 );
+
+ /**
* Provides \a file from \a url.
*
* \param absolute url to the file
static ManagedFile provideFileFromUrl( const Url & file_url, ProvideFileOptions options = PROVIDE_DEFAULT );
/**
- * Provides an optional \a file from media \a media_nr.
+ * Provides an optional \a file from \a url.
*
- * Like \ref provideFile (NON_INTERACTIVE), but return an empty \ref Pathname
+ * Like \ref provideFileFromUrl( NON_INTERACTIVE ), but return an empty \ref Pathname
* rather than throwing a \ref MediaException if the file is not present on
* the media.
*/
- Pathname provideOptionalFile( const Pathname & file, unsigned media_nr = 1 );
+ static ManagedFile provideOptionalFileFromUrl( const Url & file_url );
/**
* Release file from media.
std::string PublicKeyData::gpgPubkeyRelease() const
{ return _pimpl->_created ? str::hexstring( _pimpl->_created ).substr(2) : std::string(); }
+ std::string PublicKeyData::rpmName() const
+ { return str::Format( "gpg-pubkey-%1%-%2%" ) % gpgPubkeyVersion() % gpgPubkeyRelease(); }
+
std::string PublicKeyData::asString() const
{
str::Str str;
std::string PublicKey::asString() const
{ return keyData().asString(); }
+ std::string PublicKey::rpmName() const
+ { return keyData().rpmName(); }
+
bool PublicKey::operator==( const PublicKey & rhs ) const
{ return rhs.keyData() == keyData(); }
/** Gpg-pubkey release as computed by rpm (hexencoded \ref created) */
std::string gpgPubkeyRelease() const;
+ /** Gpg-pubkey name as computed by rpm*/
+ std::string rpmName () const;
+
/** Gpg-pubkey \ref Edition built from version and release.*/
Edition gpgPubkeyEdition() const
{ return Edition( gpgPubkeyVersion(), gpgPubkeyRelease() ); }
std::string gpgPubkeyVersion() const; //!< \see \ref PublicKeyData
std::string gpgPubkeyRelease() const; //!< \see \ref PublicKeyData
std::string asString() const; //!< \see \ref PublicKeyData
+ std::string rpmName () const;
Edition gpgPubkeyEdition() const ///!< \see \ref PublicKeyData
{ return keyData().gpgPubkeyEdition(); }
*/
#include <iostream>
#include <vector>
+#include <fstream>
#include "zypp/base/LogTools.h"
#include "zypp/base/DefaultIntegral.h"
#include "zypp/parser/xml/XmlEscape.h"
+#include "zypp/ManagedFile.h"
+#include "zypp/PublicKey.h"
+#include "zypp/MediaSetAccess.h"
#include "zypp/RepoInfo.h"
#include "zypp/Glob.h"
#include "zypp/TriBool.h"
#include "zypp/base/InputStream.h"
#include "zypp/parser/xml/Reader.h"
+
+#include "zypp/base/StrMatcher.h"
+#include "zypp/KeyRing.h"
+#include "zypp/TmpPath.h"
+#include "zypp/ZYppFactory.h"
+#include "zypp/ZYppCallbacks.h"
+
using std::endl;
using zypp::xml::escape;
_pimpl->gpgKeyUrls().raw().push_back( url_r );
}
+ Pathname RepoInfo::provideKey(const std::string &keyID_r, const Pathname &targetDirectory_r)
+ {
+ MIL << "Check for " << keyID_r << " at " << targetDirectory_r << endl;
+ std::string keyIDStr( keyID_r.size() > 8 ? keyID_r.substr( keyID_r.size()-8 ) : keyID_r ); // print short ID in Jobreports
+ filesystem::TmpDir tmpKeyRingDir;
+ KeyRing tempKeyRing(tmpKeyRingDir.path());
+
+ // translator: %1% is a gpg key ID like 3DBDC284
+ // %2% is a cache directories path
+ JobReport::info( str::Format(_("Looking for gpg key ID %1% in cache %2%.") ) % keyIDStr % targetDirectory_r );
+ filesystem::dirForEach(targetDirectory_r,
+ StrMatcher(".key", Match::STRINGEND),
+ [&tempKeyRing]( const Pathname & dir_r, const std::string & str_r ){
+ try {
+
+ // deprecate a month old keys
+ PathInfo fileInfo ( dir_r/str_r );
+ if ( Date::now() - fileInfo.mtime() > Date::month ) {
+ //if unlink fails, the file will be overriden in the next step, no need
+ //to show a error
+ filesystem::unlink( dir_r/str_r );
+ } else {
+ tempKeyRing.multiKeyImport(dir_r/str_r, true);
+ }
+ } catch (const KeyRingException& e) {
+ ZYPP_CAUGHT(e);
+ ERR << "Error importing cached key from file '"<<dir_r/str_r<<"'."<<endl;
+ }
+ return true;
+ });
+
+ // no key in the cache is what we are looking for, lets download
+ // all keys specified in gpgkey= entries
+ if ( !tempKeyRing.isKeyTrusted(keyID_r) ) {
+ if ( ! gpgKeyUrlsEmpty() ) {
+ // translator: %1% is a gpg key ID like 3DBDC284
+ // %2% is a repositories name
+ JobReport::info( str::Format(_("Looking for gpg key ID %1% in repository %2%.") ) % keyIDStr % asUserString() );
+ for ( const Url &url : gpgKeyUrls() ) {
+ try {
+ JobReport::info( " gpgkey=" + url.asString() );
+ ManagedFile f = MediaSetAccess::provideOptionalFileFromUrl( url );
+ if ( f->empty() )
+ continue;
+
+ PublicKey key(f);
+ if ( !key.isValid() )
+ continue;
+
+ // import all keys into our temporary keyring
+ tempKeyRing.multiKeyImport(f, true);
+
+ } catch ( const std::exception & e ) {
+ //ignore and continue to next url
+ ZYPP_CAUGHT(e);
+ MIL << "Key import from url:'"<<url<<"' failed." << endl;
+ }
+ }
+ }
+ else {
+ // translator: %1% is a repositories name
+ JobReport::info( str::Format(_("Repository %1% does not define additional 'gpgkey=' URLs.") ) % asUserString() );
+ }
+ }
+
+ filesystem::assert_dir( targetDirectory_r );
+
+ //now write all keys into their own files in cache, override existing ones to always have
+ //up to date key data
+ for ( const auto & key: tempKeyRing.trustedPublicKeyData()) {
+ MIL << "KEY ID in KEYRING: " << key.id() << endl;
+
+ Pathname keyFile = targetDirectory_r/(str::Format("%1%.key") % key.rpmName()).asString();
+
+ std::ofstream fout( keyFile.c_str(), std::ios_base::out | std::ios_base::trunc );
+
+ if (!fout)
+ ZYPP_THROW(Exception(str::form("Cannot open file %s",keyFile.c_str())));
+
+ tempKeyRing.dumpTrustedPublicKey( key.id(), fout );
+ }
+
+ // key is STILL not known, we give up
+ if ( !tempKeyRing.isKeyTrusted(keyID_r) ) {
+ return Pathname();
+ }
+
+ PublicKeyData keyData( tempKeyRing.trustedPublicKeyData( keyID_r ) );
+ if ( !keyData ) {
+ ERR << "Error when exporting key from temporary keychain." << endl;
+ return Pathname();
+ }
+
+ return targetDirectory_r/(str::Format("%1%.key") % keyData.rpmName()).asString();
+ }
+
void RepoInfo::addBaseUrl( const Url & url_r )
{
for ( const auto & url : _pimpl->baseUrls().raw() ) // Raw unique!
/** (leagcy API) Set the gpgkey URL defined for this repo */
void setGpgKeyUrl( const Url &gpgkey );
+ /** downloads all configured gpg keys into the defined directory */
+ Pathname provideKey(const std::string &keyID_r, const Pathname &targetDirectory_r );
/**
* \short Whether packages downloaded from this repository will be kept in local cache
#include <solv/solvversion.h>
+#include "zypp/base/String.h"
#include "zypp/base/InputStream.h"
#include "zypp/base/LogTools.h"
#include "zypp/base/Gettext.h"
#include "zypp/MediaSetAccess.h"
#include "zypp/ExternalProgram.h"
#include "zypp/ManagedFile.h"
+#include "zypp/KeyManager.h"
#include "zypp/parser/RepoFileReader.h"
#include "zypp/parser/ServiceFileReader.h"
Pathname ZConfig::repoCachePath() const
{
return ( _pimpl->cfg_cache_path.empty()
- ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path );
+ ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path );
+ }
+
+ Pathname ZConfig::pubkeyCachePath() const
+ {
+ return ( _pimpl->cfg_cache_path.empty()
+ ? Pathname("/var/cache/zypp/pubkeys") : _pimpl->cfg_cache_path/"pubkeys" );
}
void ZConfig::setRepoCachePath(const zypp::filesystem::Pathname &path_r)
*/
void setRepoCachePath ( const Pathname &path_r );
+ /**
+ * Path where the pubkey caches
+ */
+ Pathname pubkeyCachePath() const;
+
/**
* Path where the repo metadata is downloaded and kept (repoCachePath()/raw).
* \ingroup g_ZC_REPOCACHE
class Impl;
/** Dtor */
~ZConfig();
- private:
+ private:
friend class Impl;
/** Default ctor. */
ZConfig();
#ifndef ZYPP_ZYPPCALLBACKS_H
#define ZYPP_ZYPPCALLBACKS_H
+#include "zypp/base/Gettext.h"
#include "zypp/base/EnumClass.h"
#include "zypp/Callback.h"
#include "zypp/UserData.h"
// filename is interpreted relative to the attached url
// and a path prefix is preserved to destination
void
-MediaAccess::provideFile( const Pathname & filename ) const
+MediaAccess::provideFile(const Pathname & filename , const ByteCount &expectedFileSize) const
{
if ( !_handler ) {
ZYPP_THROW(MediaNotOpenException("provideFile(" + filename.asString() + ")"));
}
- _handler->provideFile( filename );
+ _handler->provideFile( filename, expectedFileSize );
}
void
try {
media.open( u );
media.attach();
- media._handler->provideFileCopy( base, to );
+ media._handler->provideFileCopy( base, to, 0 );
media.release();
}
catch (const MediaException & excpt_r)
* \throws MediaException
*
**/
- void provideFile( const Pathname & filename ) const;
+ void provideFile( const Pathname & filename, const ByteCount &expectedFileSize ) const;
/**
* Remove filename below attach point IFF handler downloads files
ZYPP_THROW(MediaBadFilenameException(_file.asString()));
} else if ( _media ) {
try {
- _media->provideFile( _file );
+ _media->provideFile( _file, 0 );
_local_file = _media->localPath( _file );
}
catch (const MediaException & excpt_r)
//
// DESCRIPTION : Asserted that media is attached.
//
- void MediaCD::getFile( const Pathname & filename ) const
+ void MediaCD::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
{
- MediaHandler::getFile( filename );
+ MediaHandler::getFile( filename, expectedFileSize_r );
}
///////////////////////////////////////////////////////////////////
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile(const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
//
// DESCRIPTION : Asserted that media is attached.
//
- void MediaCIFS::getFile (const Pathname & filename) const
+ void MediaCIFS::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
{
- MediaHandler::getFile( filename );
+ MediaHandler::getFile( filename, expectedFileSize_r );
}
///////////////////////////////////////////////////////////////////
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
struct ProgressData
{
ProgressData( CURL *_curl, time_t _timeout = 0, const Url & _url = Url(),
+ ByteCount expectedFileSize_r = 0,
callback::SendReport<DownloadProgressReport> *_report = nullptr )
: curl( _curl )
, url( _url )
, timeout( _timeout )
, reached( false )
+ , fileSizeExceeded ( false )
, report( _report )
+ , _expectedFileSize( expectedFileSize_r )
{}
CURL *curl;
Url url;
time_t timeout;
bool reached;
+ bool fileSizeExceeded;
callback::SendReport<DownloadProgressReport> *report;
+ ByteCount _expectedFileSize;
time_t _timeStart = 0; ///< Start total stats
time_t _timeLast = 0; ///< Start last period(~1sec)
if ( timeout )
reached = ( (now - _timeRcv) > timeout );
+ // check if the downloaded data is already bigger than what we expected
+ fileSizeExceeded = _expectedFileSize > 0 && _expectedFileSize < static_cast<ByteCount::SizeType>(_dnlNow);
+
// percentage:
if ( _dnlTotal )
_dnlPercent = int(_dnlNow * 100 / _dnlTotal);
int reportProgress() const
{
+ if ( fileSizeExceeded )
+ return 1;
if ( reached )
return 1; // no-data timeout
if ( report && !(*report)->progress( _dnlPercent, url, _drateTotal, _drateLast ) )
///////////////////////////////////////////////////////////////////
-void MediaCurl::getFile( const Pathname & filename ) const
+void MediaCurl::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
{
// Use absolute file name to prevent access of files outside of the
// hierarchy below the attach point.
- getFileCopy(filename, localPath(filename).absolutename());
+ getFileCopy(filename, localPath(filename).absolutename(), expectedFileSize_r);
}
///////////////////////////////////////////////////////////////////
-void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target) const
+void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target, const ByteCount &expectedFileSize_r ) const
{
callback::SendReport<DownloadProgressReport> report;
{
try
{
- doGetFileCopy(filename, target, report);
+ doGetFileCopy(filename, target, report, expectedFileSize_r);
retry = false;
}
// retry with proper authentication data
///////////////////////////////////////////////////////////////////
-void MediaCurl::evaluateCurlCode( const Pathname &filename,
+void MediaCurl::evaluateCurlCode(const Pathname &filename,
CURLcode code,
- bool timeout_reached ) const
+ bool timeout_reached) const
{
if ( code != 0 )
{
url = _url;
else
url = getFileUrl(filename);
+
std::string err;
{
switch ( code )
));
}
+ case 502: // bad gateway (bnc #1070851)
case 503: // service temporarily unavailable (bnc #462545)
ZYPP_THROW(MediaTemporaryProblemException(url));
case 504: // gateway timeout
///////////////////////////////////////////////////////////////////
-void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaCurl::doGetFileCopy(const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
{
Pathname dest = target.absolutename();
if( assert_dir( dest.dirname() ) )
}
try
{
- doGetFileCopyFile(filename, dest, file, report, options);
+ doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
}
catch (Exception &e)
{
///////////////////////////////////////////////////////////////////
-void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaCurl::doGetFileCopyFile(const Pathname & filename , const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
{
DBG << filename.asString() << endl;
}
// Set callback and perform.
- ProgressData progressData(_curl, _settings.timeout(), url, &report);
+ ProgressData progressData(_curl, _settings.timeout(), url, expectedFileSize_r, &report);
if (!(options & OPTION_NO_REPORT_START))
report->start(url, dest);
if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) {
// which holds whether the timeout was reached or not,
// otherwise it would be a user cancel
try {
- evaluateCurlCode( filename, ret, progressData.reached);
+
+ if ( progressData.fileSizeExceeded )
+ ZYPP_THROW(MediaFileSizeExceededException(url, progressData._expectedFileSize));
+
+ evaluateCurlCode( filename, ret, progressData.reached );
}
catch ( const MediaException &e ) {
// some error, we are not sure about file existence, rethrw
switch ( it->type ) {
case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
case filesystem::FT_FILE:
- getFile( filename );
+ getFile( filename, 0 );
break;
case filesystem::FT_DIR: // newer directory.yast contain at least directory info
if ( recurse_r ) {
return "";
}
+/**
+ * MediaMultiCurl needs to reset the expected filesize in case a metalink file is downloaded
+ * otherwise this function should not be called
+ */
+void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize)
+{
+ ProgressData *data = reinterpret_cast<ProgressData *>(clientp);
+ if ( data ) {
+ data->_expectedFileSize = expectedFileSize;
+ }
+}
+
///////////////////////////////////////////////////////////////////
bool MediaCurl::authenticate(const string & availAuthTypes, bool firstTry) const
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
* \throws MediaException
*
*/
- virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename) const;
+ virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, const ByteCount &expectedFileSize_r) const override;
/**
*
* \throws MediaException
*
*/
- virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
+ virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, const ByteCount &expectedFileSize_r, RequestOptions options = OPTION_NONE ) const;
virtual bool checkAttachPoint(const Pathname &apoint) const;
*
* \throws MediaException If there is a problem
*/
- void evaluateCurlCode( const zypp::Pathname &filename, CURLcode code, bool timeout ) const;
+ void evaluateCurlCode(const zypp::Pathname &filename, CURLcode code, bool timeout) const;
- void doGetFileCopyFile( const Pathname & srcFilename, const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
+ void doGetFileCopyFile( const Pathname & srcFilename, const Pathname & dest, FILE *file, callback::SendReport<DownloadProgressReport> & _report, const ByteCount &expectedFileSize_r, RequestOptions options = OPTION_NONE ) const;
+
+ static void resetExpectedFileSize ( void *clientp, const ByteCount &expectedFileSize );
private:
/**
//
// DESCRIPTION : Asserted that media is attached.
//
- void MediaDIR::getFile( const Pathname & filename ) const
+ void MediaDIR::getFile(const Pathname & filename , const ByteCount &expectedFileSize_r) const
{
- MediaHandler::getFile( filename );
+ MediaHandler::getFile( filename, expectedFileSize_r );
}
///////////////////////////////////////////////////////////////////
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
//
// DESCRIPTION : Asserted that media is attached.
//
- void MediaDISK::getFile (const Pathname & filename) const
+ void MediaDISK::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
{
- MediaHandler::getFile( filename );
+ MediaHandler::getFile( filename, expectedFileSize_r );
}
///////////////////////////////////////////////////////////////////
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile(const Pathname & filename, const ByteCount &expectedFileSize_r ) const override;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
return str;
}
+ std::ostream &MediaFileSizeExceededException::dumpOn(std::ostream &str) const
+ {
+ str << form(_("Downloaded data exceeded the expected filesize '%s' of '%s'."), _expectedFileSize.asString().c_str(), _url.c_str() );
+ if ( !_msg.empty() )
+ str << endl << _msg;
+ return str;
+ }
+
std::ostream & MediaTemporaryProblemException::dumpOn( std::ostream & str ) const
{
str << form(_("Location '%s' is temporarily unaccessible."), _url.c_str() );
#include "zypp/base/Exception.h"
#include "zypp/Pathname.h"
#include "zypp/Url.h"
+#include "zypp/ByteCount.h"
///////////////////////////////////////////////////////////////////
namespace zypp
std::string _msg;
};
+ class MediaFileSizeExceededException : public MediaException
+ {
+ public:
+ MediaFileSizeExceededException(const Url & url_r, const ByteCount &cnt_r, const std::string & msg = "")
+ : MediaException(msg)
+ , _url(url_r.asString())
+ , _msg(msg)
+ , _expectedFileSize(cnt_r)
+ {}
+ virtual ~MediaFileSizeExceededException() throw() {};
+ protected:
+ virtual std::ostream & dumpOn( std::ostream & str ) const;
+ std::string _url;
+ std::string _msg;
+ ByteCount _expectedFileSize;
+ };
+
/** For HTTP 503 and similar. */
class MediaTemporaryProblemException : public MediaException
{
//
// DESCRIPTION :
//
-void MediaHandler::provideFileCopy( Pathname srcFilename,
- Pathname targetFilename ) const
+void MediaHandler::provideFileCopy(Pathname srcFilename,
+ Pathname targetFilename , const ByteCount &expectedFileSize_r) const
{
if ( !isAttached() ) {
INT << "Media not_attached on provideFileCopy(" << srcFilename
ZYPP_THROW(MediaNotAttachedException(url()));
}
- getFileCopy( srcFilename, targetFilename ); // pass to concrete handler
+ getFileCopy( srcFilename, targetFilename, expectedFileSize_r ); // pass to concrete handler
DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl;
}
-void MediaHandler::provideFile( Pathname filename ) const
+void MediaHandler::provideFile(Pathname filename , const ByteCount &expectedFileSize_r) const
{
if ( !isAttached() ) {
INT << "Error: Not attached on provideFile(" << filename << ")" << endl;
ZYPP_THROW(MediaNotAttachedException(url()));
}
- getFile( filename ); // pass to concrete handler
+ getFile( filename, expectedFileSize_r ); // pass to concrete handler
DBG << "provideFile(" << filename << ")" << endl;
}
// look for directory.yast
Pathname dirFile = dirname + "directory.yast";
- getFile( dirFile );
+ getFile( dirFile, 0 );
DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
// using directory.yast
// DESCRIPTION : Asserted that media is attached.
// Default implementation of pure virtual.
//
-void MediaHandler::getFile( const Pathname & filename ) const
+void MediaHandler::getFile(const Pathname & filename , const ByteCount &) const
{
PathInfo info( localPath( filename ) );
if( info.isFile() ) {
}
-void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const
+void MediaHandler::getFileCopy (const Pathname & srcFilename, const Pathname & targetFilename , const ByteCount &expectedFileSize_r) const
{
- getFile(srcFilename);
+ getFile(srcFilename, expectedFileSize_r);
if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) {
ZYPP_THROW(MediaWriteException(targetFilename));
* \throws MediaException
*
**/
- virtual void getFile( const Pathname & filename ) const = 0;
+ virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const;
/**
* Call concrete handler to provide a file under a different place
* \throws MediaException
*
**/
- virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename ) const;
+ virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, const ByteCount &expectedFileSize_r ) const;
/**
* \throws MediaException
*
**/
- void provideFile( Pathname filename ) const;
+ void provideFile( Pathname filename, const ByteCount &expectedFileSize_r ) const;
/**
* Call concrete handler to provide a copy of a file under a different place
* \throws MediaException
*
**/
- void provideFileCopy( Pathname srcFilename, Pathname targetFilename) const;
+ void provideFileCopy( Pathname srcFilename, Pathname targetFilename, const ByteCount &expectedFileSize_r ) const;
/**
* Use concrete handler to provide directory denoted
}
// ---------------------------------------------------------------
- void MediaISO::getFile(const Pathname &filename) const
+ void MediaISO::getFile(const Pathname &filename, const ByteCount &expectedFileSize_r) const
{
- MediaHandler::getFile(filename);
+ MediaHandler::getFile(filename, expectedFileSize_r);
}
// ---------------------------------------------------------------
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev = "" );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
return path;
}
- // ---------------------------------------------------------------
void
MediaManager::provideFile(MediaAccessId accessId,
- const Pathname &filename ) const
+ const Pathname &filename,
+ const ByteCount &expectedFileSize ) const
{
MutexLock glock(g_Mutex);
ref.checkDesired(accessId);
- ref.handler->provideFile(filename);
+ ref.handler->provideFile(filename, expectedFileSize);
+ }
+
+ // ---------------------------------------------------------------
+ void
+ MediaManager::provideFile(MediaAccessId accessId,
+ const Pathname &filename ) const
+ {
+ provideFile( accessId, filename, 0);
}
// ---------------------------------------------------------------
*
* \param accessId The media access id to use.
* \param filename The filename to provide, relative to localRoot().
+ * \param expectedFileSize The expected filesize, download will stop if it is exceeded
*
* \throws MediaNotOpenException in case of invalid access id.
* \throws MediaNotAttachedException in case, that the media is not attached.
*/
void
+ provideFile(MediaAccessId accessId,
+ const Pathname &filename,
+ const ByteCount &expectedFileSize) const;
+
+ void
provideFile(MediaAccessId accessId,
const Pathname &filename ) const;
worker->evaluateCurlCode(Pathname(), cc, false);
}
}
+
+ if ( _filesize > 0 && _fetchedgoodsize > _filesize ) {
+ ZYPP_THROW(MediaFileSizeExceededException(_baseurl, _filesize));
+ }
}
// send report
if (_report)
{
int percent = _totalsize ? (100 * (_fetchedgoodsize + _fetchedsize)) / (_totalsize + _fetchedsize) : 0;
+
double avg = 0;
if (now > _starttime)
avg = _fetchedsize / (now - _starttime);
}
if (ismetalink)
{
+ // this is a metalink file change the expected filesize
+ MediaCurl::resetExpectedFileSize( clientp, ByteCount( 2, ByteCount::MB) );
// we're downloading the metalink file. Just trigger aliveCallbacks
curl_easy_setopt(_curl, CURLOPT_PROGRESSFUNCTION, &MediaCurl::aliveCallback);
return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow);
return MediaCurl::progressCallback(clientp, dltotal, dlnow, ultotal, ulnow);
}
-void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, RequestOptions options ) const
+void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname & target, callback::SendReport<DownloadProgressReport> & report, const ByteCount &expectedFileSize_r, RequestOptions options ) const
{
Pathname dest = target.absolutename();
if( assert_dir( dest.dirname() ) )
curl_easy_setopt(_curl, CURLOPT_PRIVATE, file);
try
{
- MediaCurl::doGetFileCopyFile(filename, dest, file, report, options);
+ MediaCurl::doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
}
catch (Exception &ex)
{
}
try
{
- multifetch(filename, file, &urls, &report, &bl);
+ multifetch(filename, file, &urls, &report, &bl, expectedFileSize_r);
}
catch (MediaCurlException &ex)
{
ZYPP_RETHROW(ex);
}
}
+ catch (MediaFileSizeExceededException &ex) {
+ ZYPP_RETHROW(ex);
+ }
catch (Exception &ex)
{
// something went wrong. fall back to normal download
file = fopen(destNew.c_str(), "w+e");
if (!file)
ZYPP_THROW(MediaWriteException(destNew));
- MediaCurl::doGetFileCopyFile(filename, dest, file, report, options | OPTION_NO_REPORT_START);
+ MediaCurl::doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options | OPTION_NO_REPORT_START);
}
}
if (!_multi)
ZYPP_THROW(MediaCurlInitException(baseurl));
}
+
multifetchrequest req(this, filename, baseurl, _multi, fp, report, blklist, filesize);
req._timeout = _settings.timeout();
req._connect_timeout = _settings.connectTimeout();
MediaMultiCurl(const Url &url_r, const Pathname & attach_point_hint_r);
~MediaMultiCurl();
- virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, RequestOptions options = OPTION_NONE ) const;
+ virtual void doGetFileCopy( const Pathname & srcFilename, const Pathname & targetFilename, callback::SendReport<DownloadProgressReport> & _report, const ByteCount &expectedFileSize_r, RequestOptions options = OPTION_NONE ) const override;
void multifetch(const Pathname &filename, FILE *fp, std::vector<Url> *urllist, callback::SendReport<DownloadProgressReport> *report = 0, MediaBlockList *blklist = 0, off_t filesize = off_t(-1)) const;
//
// DESCRIPTION : Asserted that media is attached.
//
- void MediaNFS::getFile (const Pathname & filename) const
+ void MediaNFS::getFile (const Pathname & filename, const ByteCount &expectedFileSize_r) const
{
- MediaHandler::getFile( filename );;
+ MediaHandler::getFile( filename, expectedFileSize_r );
}
///////////////////////////////////////////////////////////////////
virtual void attachTo (bool next = false);
virtual void releaseFrom( const std::string & ejectDev );
- virtual void getFile( const Pathname & filename ) const;
+ virtual void getFile( const Pathname & filename, const ByteCount &expectedFileSize_r ) const;
virtual void getDir( const Pathname & dirname, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist,
const Pathname & dirname, bool dots = true ) const;
void MediaPlugin::releaseFrom( const std::string & ejectDev_r )
{}
- void MediaPlugin::getFile( const Pathname & filename_r ) const
+ void MediaPlugin::getFile(const Pathname & filename_r , const ByteCount expectedFileSize_r) const
{}
void MediaPlugin::getDir( const Pathname & dirname_r, bool recurse_r ) const
protected:
virtual void attachTo( bool next_r = false );
virtual void releaseFrom( const std::string & ejectDev_r );
- virtual void getFile( const Pathname & filename_r ) const;
+ virtual void getFile( const Pathname & filename_r, const ByteCount expectedFileSize_r ) const;
virtual void getDir( const Pathname & dirname_r, bool recurse_r ) const;
virtual void getDirInfo( std::list<std::string> & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const;
virtual void getDirInfo( filesystem::DirContent & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const;
return true;
}
+ // xpath: /repomd/size
+ if ( reader_r->name() == "size" )
+ {
+ string size_value = reader_r.nodeText().asString();
+ zypp::ByteCount size = zypp::ByteCount( str::strtonum<ByteCount::SizeType>( size_value ) );
+ _location.setDownloadSize( size );
+ return true;
+ }
+
//! \todo xpath: /repomd/open-checksum (?)
}
Pathname keypath = masterIndex_r.extend( ".key" );
// always download them, even if repoGpgCheck is disabled
- enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ) );
- enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ) );
+ enqueue( OnMediaLocation( sigpath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
+ enqueue( OnMediaLocation( keypath, 1 ).setOptional( true ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ) );
start( destdir_r, media_r );
reset();
WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
}
- enqueue( OnMediaLocation( masterIndex_r, 1 ), checker ? checker : FileChecker(NullFileChecker()) );
+ enqueue( OnMediaLocation( masterIndex_r, 1 ).setDownloadSize( ByteCount( 20, ByteCount::MB ) ), checker ? checker : FileChecker(NullFileChecker()) );
start( destdir_r, media_r );
reset();
const ProgressData::ReceiverFnc & progressrcv )
{
Fetcher fetcher;
- fetcher.enqueue( OnMediaLocation("/media.1/media").setOptional(true) );
+
+ //hardcode the max filesize to 20MB, to prevent unlimited data downloads but this limit will
+ //never be reached in a sane setup
+ fetcher.enqueue( OnMediaLocation("/media.1/media").setOptional(true).setDownloadSize( ByteCount(20, ByteCount::MB ) ) );
fetcher.start( dest_dir, media, progressrcv );
// ready, go!
fetcher.reset();
#include "zypp/Target.h"
#include "zypp/target/rpm/RpmDb.h"
#include "zypp/FileChecker.h"
+#include "zypp/target/rpm/RpmHeader.h"
using std::endl;
//@{
void rpmSigFileChecker( const Pathname & file_r ) const
{
- const RepoInfo & info = _package->repoInfo();
+ RepoInfo info = _package->repoInfo();
if ( info.pkgGpgCheck() )
{
UserData userData( "pkgGpgCheck" );
userData.set( "ResObject", roptr ); // a type for '_package->asKind<ResObject>()'...
/*legacy:*/userData.set( "Package", roptr->asKind<Package>() );
userData.set( "Localpath", file_r );
- RpmDb::CheckPackageResult res = packageSigCheck( file_r, info.pkgGpgCheckIsMandatory(), userData );
- // publish the checkresult, even if it is OK. Apps may want to report something...
- report()->pkgGpgCheck( userData );
+ RpmDb::CheckPackageResult res = RpmDb::CHK_NOKEY;
+ while ( res == RpmDb::CHK_NOKEY ) {
+ res = packageSigCheck( file_r, info.pkgGpgCheckIsMandatory(), userData );
+
+ // publish the checkresult, even if it is OK. Apps may want to report something...
+ report()->pkgGpgCheck( userData );
+
+ if ( res == RpmDb::CHK_NOKEY ) {
+ // if the check fails because we don't know the key
+ // we try to resolv it with gpgkey urls from the
+ // repository, if available
+
+ target::rpm::RpmHeader::constPtr hr = target::rpm::RpmHeader::readPackage( file_r );
+ if ( !hr ) {
+ // we did not find any information about the key in the header
+ // this should never happen
+ WAR << "Unable to read package header from " << hr << endl;
+ break;
+ }
+
+ std::string keyID = hr->signatureKeyID();
+ if ( keyID.length() > 0 ) {
+ const ZConfig &conf = ZConfig::instance();
+ Pathname cacheDir = conf.repoManagerRoot() / conf.pubkeyCachePath();
+
+ Pathname myKey = info.provideKey ( keyID, cacheDir );
+ if ( myKey.empty() )
+ // if we did not find any keys, there is no point in checking again, break
+ break;
+
+ callback::SendReport<KeyRingReport> report;
+
+ PublicKey key;
+ try {
+ key = PublicKey( myKey );
+ } catch ( const Exception &e ) {
+ ZYPP_CAUGHT(e);
+ break;
+ }
+
+ if ( !key.isValid() ) {
+ ERR << "Key [" << keyID << "] from cache: " << cacheDir << " is not valid" << endl;
+ break;
+ }
+
+ MIL << "Key [" << keyID << "] " << key.name() << " loaded from cache" << endl;
+
+ KeyContext context;
+ context.setRepoInfo( info );
+ if ( ! report->askUserToAcceptPackageKey( key, context ) ) {
+ break;
+ }
+
+ MIL << "User wants to import key [" << keyID << "] " << key.name() << " from cache" << endl;
+ KeyRing_Ptr theKeyRing = getZYpp()->keyRing();
+ try {
+ theKeyRing->importKey( key, true );
+ } catch ( const KeyRingException &e ) {
+ ZYPP_CAUGHT(e);
+ ERR << "Failed to import key: "<<keyID;
+ break;
+ }
+ } else {
+ // we did not find any information about the key in the header
+ // this should never happen
+ WAR << "packageSigCheck returned without setting providing missing key information" << endl;
+ break;
+ }
+ }
+ }
if ( res != RpmDb::CHK_OK )
{
return true;
Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
- ref->provideFile (media_file);
+ ref->provideFile (media_file, 0);
media_file = ref->localPath(media_file);
std::ifstream str(media_file.asString().c_str());
std::string vendor;
#include "zypp/base/Logger.h"
#include "zypp/base/NonCopyable.h"
+#include "zypp/base/String.h"
+#include "zypp/AutoDispose.h"
#include "zypp/target/rpm/BinHeader.h"
return "";
}
+string BinHeader::format(const char *fmt) const
+{
+ zypp::AutoDispose<char *> form(headerFormat(_h, fmt, NULL), free);
+ if ( !form )
+ return std::string();
+
+ return std::string(form);
+}
+
///////////////////////////////////////////////////////////////////
//
//
int int_val( tag tag_r ) const;
std::string string_val( tag tag_r ) const;
+ std::string format ( const char * fmt) const;
public:
return string_val( RPMTAG_SOURCERPM );
}
+std::string RpmHeader::signatureKeyID() const
+{
+ std::string sigInfo = format("%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|");
+
+ //no signature, return empty string
+ if ( sigInfo == "(none)" )
+ return std::string();
+
+ std::vector<std::string> words;
+ str::split( sigInfo, std::back_inserter(words), ",");
+ if ( words.size() < 3)
+ return std::string();
+
+ const std::string &keyId = words[2];
+ if ( !str::startsWith(keyId, " Key ID "))
+ return std::string();
+
+ return str::toUpper( words[2].substr(8) );
+}
+
///////////////////////////////////////////////////////////////////
//
//
std::string tag_posttransprog()const;
std::string tag_sourcerpm() const;
+ /**
+ * Uses headerFormat to query the signature info from the header.
+ * \note Query copied from Yum misc/checksig.py
+ */
+ std::string signatureKeyID() const;
+
/** just the list of names */
std::list<std::string> tag_filenames() const;