Imported Upstream version 17.6.0 upstream/17.6.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:16:03 +0000 (16:16 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:16:03 +0000 (16:16 +0900)
53 files changed:
VERSION.cmake
package/libzypp.changes
po/de.po
tests/zypp/MediaSetAccess_test.cc
tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt [new file with mode: 0644]
tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt [new file with mode: 0644]
zypp/KeyRing.cc
zypp/KeyRing.h
zypp/MediaSetAccess.cc
zypp/MediaSetAccess.h
zypp/PublicKey.cc
zypp/PublicKey.h
zypp/RepoInfo.cc
zypp/RepoInfo.h
zypp/RepoManager.cc
zypp/ZConfig.cc
zypp/ZConfig.h
zypp/ZYppCallbacks.h
zypp/media/MediaAccess.cc
zypp/media/MediaAccess.h
zypp/media/MediaCD.cc
zypp/media/MediaCD.h
zypp/media/MediaCIFS.cc
zypp/media/MediaCIFS.h
zypp/media/MediaCurl.cc
zypp/media/MediaCurl.h
zypp/media/MediaDIR.cc
zypp/media/MediaDIR.h
zypp/media/MediaDISK.cc
zypp/media/MediaDISK.h
zypp/media/MediaException.cc
zypp/media/MediaException.h
zypp/media/MediaHandler.cc
zypp/media/MediaHandler.h
zypp/media/MediaISO.cc
zypp/media/MediaISO.h
zypp/media/MediaManager.cc
zypp/media/MediaManager.h
zypp/media/MediaMultiCurl.cc
zypp/media/MediaMultiCurl.h
zypp/media/MediaNFS.cc
zypp/media/MediaNFS.h
zypp/media/MediaPlugin.cc
zypp/media/MediaPlugin.h
zypp/parser/yum/RepomdFileReader.cc
zypp/repo/Downloader.cc
zypp/repo/MediaInfoDownloader.cc
zypp/repo/PackageProvider.cc
zypp/repo/SUSEMediaVerifier.cc
zypp/target/rpm/BinHeader.cc
zypp/target/rpm/BinHeader.h
zypp/target/rpm/RpmHeader.cc
zypp/target/rpm/RpmHeader.h

index 7fb4ad1..41fd524 100644 (file)
@@ -60,9 +60,9 @@
 #
 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)
 #=======
index 315cea9..22c23f3 100644 (file)
@@ -1,4 +1,17 @@
 -------------------------------------------------------------------
+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
index e0d04b2..c9b585f 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -4647,7 +4647,7 @@ msgstr "%%posttrans script '%1%' wird ausgeführt"
 #: 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"
index 9160f11..8a21c51 100644 (file)
@@ -279,6 +279,34 @@ BOOST_AUTO_TEST_CASE(msa_remote_tests)
   //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();
 }
 
diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt b/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt
new file mode 100644 (file)
index 0000000..87949e6
--- /dev/null
@@ -0,0 +1,15 @@
+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.   
diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt b/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt
new file mode 100644 (file)
index 0000000..32a8037
--- /dev/null
@@ -0,0 +1,29 @@
+<?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>
index d9e0c9a..d8d49f3 100644 (file)
@@ -79,6 +79,18 @@ namespace zypp
   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
   {
     ///////////////////////////////////////////////////////////////////
index b3212fb..7e3fcc3 100644 (file)
@@ -70,6 +70,8 @@ namespace zypp
       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
@@ -96,6 +98,23 @@ namespace zypp
      */
     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
index 940c26a..9a6a239 100644 (file)
@@ -109,10 +109,11 @@ IMPL_PTR_TYPE(MediaSetAccess);
   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);
     }
   };
@@ -158,6 +159,7 @@ IMPL_PTR_TYPE(MediaSetAccess);
   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;
   }
@@ -171,6 +173,20 @@ IMPL_PTR_TYPE(MediaSetAccess);
     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);
@@ -189,18 +205,17 @@ IMPL_PTR_TYPE(MediaSetAccess);
     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 )
index b4074a3..1255a72 100644 (file)
@@ -173,6 +173,15 @@ namespace zypp
       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
@@ -192,13 +201,13 @@ namespace zypp
       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.
index 83db0d5..6c37082 100644 (file)
@@ -319,6 +319,9 @@ namespace zypp
   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;
@@ -541,6 +544,9 @@ namespace zypp
   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(); }
 
index 6ad5c67..9f00378 100644 (file)
@@ -193,6 +193,9 @@ namespace zypp
     /** 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() ); }
@@ -316,6 +319,7 @@ namespace zypp
     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(); }
index 4bc5a25..c167ed3 100644 (file)
 */
 #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;
 
@@ -490,6 +501,102 @@ namespace zypp
     _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!
index 0e3fde3..85a3979 100644 (file)
@@ -400,6 +400,8 @@ namespace zypp
       /** (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
index 3256d2e..fca1f42 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <solv/solvversion.h>
 
+#include "zypp/base/String.h"
 #include "zypp/base/InputStream.h"
 #include "zypp/base/LogTools.h"
 #include "zypp/base/Gettext.h"
@@ -38,6 +39,7 @@
 #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"
index 0adf08e..2a063c3 100644 (file)
@@ -909,7 +909,13 @@ namespace zypp
   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)
index e5c42a1..bc6d176 100644 (file)
@@ -149,6 +149,11 @@ namespace zypp
        */
       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
@@ -517,7 +522,7 @@ namespace zypp
       class Impl;
       /** Dtor */
       ~ZConfig();
-    private:
+  private:
       friend class Impl;
       /** Default ctor. */
       ZConfig();
index 667e8a4..e920126 100644 (file)
@@ -12,6 +12,7 @@
 #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"
index f119b00..f56f260 100644 (file)
@@ -337,13 +337,13 @@ MediaAccess::release( const std::string & ejectDev )
 // 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
@@ -470,7 +470,7 @@ void MediaAccess::getFile( const Url &from, const Pathname &to )
   try {
     media.open( u );
     media.attach();
-    media._handler->provideFileCopy( base, to );
+    media._handler->provideFileCopy( base, to, 0 );
     media.release();
   }
   catch (const MediaException & excpt_r)
index 4555b4a..4bf4af2 100644 (file)
@@ -219,7 +219,7 @@ namespace zypp {
         * \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
@@ -386,7 +386,7 @@ namespace zypp {
              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)
index 68a71af..fbe2c75 100644 (file)
@@ -720,9 +720,9 @@ namespace zypp
   //
   //  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 );
   }
 
   ///////////////////////////////////////////////////////////////////
index 4cd3527..03cee50 100644 (file)
@@ -45,7 +45,7 @@ namespace zypp {
 
        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;
index a6396e0..f1d490e 100644 (file)
@@ -350,9 +350,9 @@ namespace zypp {
     //
     // 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 );
     }
 
     ///////////////////////////////////////////////////////////////////
index 44f44a6..29bb9c7 100644 (file)
@@ -35,7 +35,7 @@ namespace zypp {
 
       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;
index 0457ac8..1d16827 100644 (file)
@@ -184,19 +184,24 @@ namespace zypp {
     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)
@@ -240,6 +245,9 @@ namespace zypp {
        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);
@@ -260,6 +268,8 @@ namespace zypp {
 
       int reportProgress() const
       {
+        if ( fileSizeExceeded )
+          return 1;
        if ( reached )
          return 1;     // no-data timeout
        if ( report && !(*report)->progress( _dnlPercent, url, _drateTotal, _drateLast ) )
@@ -965,16 +975,16 @@ Url MediaCurl::getFileUrl( const Pathname & filename_r ) const
 
 ///////////////////////////////////////////////////////////////////
 
-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;
 
@@ -986,7 +996,7 @@ void MediaCurl::getFileCopy( const Pathname & filename , const Pathname & target
   {
     try
     {
-      doGetFileCopy(filename, target, report);
+      doGetFileCopy(filename, target, report, expectedFileSize_r);
       retry = false;
     }
     // retry with proper authentication data
@@ -1051,9 +1061,9 @@ bool MediaCurl::getDoesFileExist( const Pathname & filename ) const
 
 ///////////////////////////////////////////////////////////////////
 
-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 )
   {
@@ -1062,6 +1072,7 @@ void MediaCurl::evaluateCurlCode( const Pathname &filename,
       url = _url;
     else
       url = getFileUrl(filename);
+
     std::string err;
     {
       switch ( code )
@@ -1098,6 +1109,7 @@ void MediaCurl::evaluateCurlCode( const Pathname &filename,
                            ));
           }
 
+          case 502: // bad gateway (bnc #1070851)
           case 503: // service temporarily unavailable (bnc #462545)
             ZYPP_THROW(MediaTemporaryProblemException(url));
           case 504: // gateway timeout
@@ -1370,7 +1382,7 @@ bool MediaCurl::detectDirIndex() const
 
 ///////////////////////////////////////////////////////////////////
 
-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() ) )
@@ -1422,7 +1434,7 @@ void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & targ
     }
     try
     {
-      doGetFileCopyFile(filename, dest, file, report, options);
+      doGetFileCopyFile(filename, dest, file, report, expectedFileSize_r, options);
     }
     catch (Exception &e)
     {
@@ -1484,7 +1496,7 @@ void MediaCurl::doGetFileCopy( const Pathname & filename , const Pathname & targ
 
 ///////////////////////////////////////////////////////////////////
 
-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;
 
@@ -1524,7 +1536,7 @@ void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname &
     }
 
     // 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 ) {
@@ -1568,7 +1580,11 @@ void MediaCurl::doGetFileCopyFile( const Pathname & filename , const Pathname &
       // 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
@@ -1598,7 +1614,7 @@ void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const
       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 ) {
@@ -1688,6 +1704,18 @@ string MediaCurl::getAuthHint() const
   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
index d7b6100..209ff06 100644 (file)
@@ -53,7 +53,7 @@ class MediaCurl : public MediaHandler
 
     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;
@@ -82,14 +82,14 @@ class MediaCurl : public MediaHandler
      * \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;
@@ -147,9 +147,11 @@ class MediaCurl : public MediaHandler
      *
      * \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:
     /**
index 4f8288e..0169d2f 100644 (file)
@@ -130,9 +130,9 @@ namespace zypp {
     //
     // 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 );
     }
 
     ///////////////////////////////////////////////////////////////////
index 2f99de8..988c5bf 100644 (file)
@@ -31,7 +31,7 @@ namespace zypp {
 
        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;
index c9f2260..0abfaa2 100644 (file)
@@ -353,9 +353,9 @@ namespace zypp {
     //
     // 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 );
     }
 
     ///////////////////////////////////////////////////////////////////
index 8427611..8b2dc9e 100644 (file)
@@ -37,7 +37,7 @@ namespace zypp {
 
        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;
index 6108b82..81c8ad4 100644 (file)
@@ -190,6 +190,14 @@ namespace zypp
       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() );
index f5d919b..1ffea3f 100644 (file)
@@ -20,6 +20,7 @@
 #include "zypp/base/Exception.h"
 #include "zypp/Pathname.h"
 #include "zypp/Url.h"
+#include "zypp/ByteCount.h"
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
@@ -486,6 +487,23 @@ 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
     {
index 2e20218..5a52ada 100644 (file)
@@ -991,8 +991,8 @@ MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch)
 //
 //     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
@@ -1000,18 +1000,18 @@ void MediaHandler::provideFileCopy( Pathname 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;
 }
 
@@ -1176,7 +1176,7 @@ void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist,
 
   // look for directory.yast
   Pathname dirFile = dirname + "directory.yast";
-  getFile( dirFile );
+  getFile( dirFile, 0 );
   DBG << "provideFile(" << dirFile << "): " << "OK" << endl;
 
   // using directory.yast
@@ -1232,7 +1232,7 @@ ostream & operator<<( ostream & str, const MediaHandler & obj )
 //     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() ) {
@@ -1246,9 +1246,9 @@ void MediaHandler::getFile( const Pathname & filename ) const
 }
 
 
-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));
index 9fd8782..a34f01f 100644 (file)
@@ -358,7 +358,7 @@ class MediaHandler {
         * \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
@@ -371,7 +371,7 @@ class MediaHandler {
         * \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;
 
 
        /**
@@ -571,7 +571,7 @@ class MediaHandler {
         * \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
@@ -584,7 +584,7 @@ class MediaHandler {
         * \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
index e49de6b..a24d9a1 100644 (file)
@@ -272,9 +272,9 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
-    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);
     }
 
     // ---------------------------------------------------------------
index 7828e8b..032a3b4 100644 (file)
@@ -43,7 +43,7 @@ namespace zypp
 
        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;
index b753b51..e098ada 100644 (file)
@@ -668,10 +668,10 @@ namespace zypp
       return path;
     }
 
-    // ---------------------------------------------------------------
     void
     MediaManager::provideFile(MediaAccessId   accessId,
-                              const Pathname &filename ) const
+                              const Pathname &filename,
+                              const ByteCount &expectedFileSize ) const
     {
       MutexLock glock(g_Mutex);
 
@@ -679,7 +679,15 @@ namespace zypp
 
       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);
     }
 
     // ---------------------------------------------------------------
index b2e0ed4..cb035fd 100644 (file)
@@ -748,6 +748,7 @@ namespace zypp
        *
        * \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.
@@ -760,6 +761,11 @@ namespace zypp
        */
 
       void
+      provideFile(MediaAccessId accessId,
+                  const Pathname &filename,
+                  const ByteCount &expectedFileSize) const;
+
+      void
       provideFile(MediaAccessId   accessId,
                   const Pathname &filename ) const;
 
index 9f9a65d..f01dabe 100644 (file)
@@ -1119,12 +1119,17 @@ multifetchrequest::run(std::vector<Url> &urllist)
                  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);
@@ -1274,6 +1279,8 @@ int MediaMultiCurl::progressCallback( void *clientp, double dltotal, double dlno
     }
   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);
@@ -1282,7 +1289,7 @@ int MediaMultiCurl::progressCallback( void *clientp, double dltotal, double dlno
   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() ) )
@@ -1338,7 +1345,7 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
   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)
     {
@@ -1428,7 +1435,7 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
            }
          try
            {
-             multifetch(filename, file, &urls, &report, &bl);
+             multifetch(filename, file, &urls, &report, &bl, expectedFileSize_r);
            }
          catch (MediaCurlException &ex)
            {
@@ -1436,6 +1443,9 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
              ZYPP_RETHROW(ex);
            }
        }
+      catch (MediaFileSizeExceededException &ex) {
+        ZYPP_RETHROW(ex);
+      }
       catch (Exception &ex)
        {
          // something went wrong. fall back to normal download
@@ -1455,7 +1465,7 @@ void MediaMultiCurl::doGetFileCopy( const Pathname & filename , const Pathname &
          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);
        }
     }
 
@@ -1513,6 +1523,7 @@ void MediaMultiCurl::multifetch(const Pathname & filename, FILE *fp, std::vector
       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();
index e5d8212..0c2e1ee 100644 (file)
@@ -45,7 +45,7 @@ public:
   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;
 
index 626651c..15b7db6 100644 (file)
@@ -206,9 +206,9 @@ namespace zypp {
     //
     // 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 );
     }
 
     ///////////////////////////////////////////////////////////////////
index eea5daf..bcc084c 100644 (file)
@@ -40,7 +40,7 @@ namespace zypp {
        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;
index 76b75b3..fcb9f09 100644 (file)
@@ -39,7 +39,7 @@ namespace zypp
     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
index 2b68ace..fd47dc9 100644 (file)
@@ -36,7 +36,7 @@ namespace zypp
       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;
index 55954b9..5d8a1ab 100644 (file)
@@ -156,6 +156,15 @@ namespace zypp
         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 (?)
     }
 
index 2f36b03..332b72b 100644 (file)
@@ -52,8 +52,8 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
   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();
 
@@ -91,7 +91,7 @@ void Downloader::defaultDownloadMasterIndex( MediaSetAccess & media_r, const Pat
     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();
 
index 4974fe6..e1c37ca 100644 (file)
@@ -27,7 +27,10 @@ void downloadMediaInfo( const Pathname &dest_dir,
                         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();
index ef62861..99039dd 100644 (file)
@@ -31,6 +31,7 @@
 #include "zypp/Target.h"
 #include "zypp/target/rpm/RpmDb.h"
 #include "zypp/FileChecker.h"
+#include "zypp/target/rpm/RpmHeader.h"
 
 using std::endl;
 
@@ -202,7 +203,7 @@ namespace zypp
       //@{
       void rpmSigFileChecker( const Pathname & file_r ) const
       {
-       const RepoInfo & info = _package->repoInfo();
+       RepoInfo info = _package->repoInfo();
        if ( info.pkgGpgCheck() )
        {
          UserData userData( "pkgGpgCheck" );
@@ -210,10 +211,77 @@ namespace zypp
          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 )
          {
index c06ca8d..3d920e3 100644 (file)
@@ -51,7 +51,7 @@ bool SUSEMediaVerifier::isDesiredMedia(const media::MediaAccessRef &ref)
     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;
index 95350c8..af78692 100644 (file)
@@ -23,6 +23,8 @@ typedef rpmuint32_t rpm_count_t;
 
 #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"
 
@@ -371,6 +373,15 @@ std::string BinHeader::string_val( tag tag_r ) const
   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);
+}
+
 ///////////////////////////////////////////////////////////////////
 //
 //
index 1dc636c..3a9a04a 100644 (file)
@@ -88,6 +88,7 @@ public:
   int int_val( tag tag_r ) const;
 
   std::string string_val( tag tag_r ) const;
+  std::string format ( const char * fmt) const;
 
 public:
 
index 95ab82b..b698088 100644 (file)
@@ -876,6 +876,26 @@ std::string RpmHeader::tag_sourcerpm() const
   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) );
+}
+
 ///////////////////////////////////////////////////////////////////
 //
 //
index 697b2cb..72645a7 100644 (file)
@@ -161,6 +161,12 @@ public:
   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;