#include <iostream>
#include <vector>
-//#include "zypp/base/Logger.h"
-
#include "zypp/base/Gettext.h"
#include "zypp/base/String.h"
#include "zypp/base/Regex.h"
#include "zypp/TmpPath.h"
#include "zypp/PathInfo.h"
#include "zypp/base/Exception.h"
-#include "zypp/base/Logger.h"
+#include "zypp/base/LogTools.h"
#include "zypp/Date.h"
-#include "zypp/TmpPath.h"
-#include <ctime>
+/** \todo Fix duplicate define in PublicKey/KeyRing */
+#define GPG_BINARY "/usr/bin/gpg2"
using std::endl;
///////////////////////////////////////////////////////////////////
namespace zypp
-{ /////////////////////////////////////////////////////////////////
-
- /////////////////////////////////////////////////////////////////
- //
- // CLASS NAME : PublicKey::Impl
- //
- /** PublicKey implementation. */
- struct PublicKey::Impl
+{
+ ///////////////////////////////////////////////////////////////////
+ namespace
{
- Impl()
- {}
+ inline bool isExpired( const Date & expires_r )
+ { return( expires_r && expires_r < Date::now() ); }
- Impl( const Pathname & keyfile )
+ inline int hasDaysToLive( const Date & expires_r )
{
- PathInfo info( keyfile );
- MIL << "Takeing pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1") << endl;
+ if ( expires_r )
+ {
+ Date exp( expires_r - Date::now() );
+ int ret = exp / Date::day;
+ if ( exp < 0 ) ret -= 1;
+ return ret;
+ }
+ return INT_MAX;
+ }
- if ( !info.isExist() )
- ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
+ inline std::string expiresDetail( const Date & expires_r )
+ {
+ str::Str str;
+ if ( ! expires_r )
+ {
+ // translators: an annotation to a gpg keys expiry date
+ str << _("does not expire");
+ }
+ else if ( isExpired( expires_r ) )
+ {
+ // translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12"
+ str << ( str::Format(_("expired: %1%") ) % expires_r.printDate() );
+ }
+ else
+ {
+ // translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12"
+ str << ( str::Format(_("expires: %1%") ) % expires_r.printDate() );
+ }
+ return str;
+ }
+
+ inline std::string expiresDetailVerbose( const Date & expires_r )
+ {
+ if ( !expires_r )
+ { // translators: an annotation to a gpg keys expiry date
+ return _("(does not expire)");
+ }
+ std::string ret( expires_r.asString() );
+ int ttl( hasDaysToLive( expires_r ) );
+ if ( ttl <= 90 )
+ {
+ ret += " ";
+ if ( ttl < 0 )
+ { // translators: an annotation to a gpg keys expiry date
+ ret += _("(EXPIRED)");
+ }
+ else if ( ttl == 0 )
+ { // translators: an annotation to a gpg keys expiry date
+ ret += _("(expires within 24h)");
+ }
+ else
+ { // translators: an annotation to a gpg keys expiry date
+ ret += str::form( PL_("(expires in %d day)", "(expires in %d days)", ttl ), ttl );
+ }
+ }
+ return ret;
+ }
+
+ } //namespace
+ ///////////////////////////////////////////////////////////////////
- if ( copy( keyfile, _data_file.path() ) != 0 )
- ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " + _data_file.path().asString() ));
+ ///////////////////////////////////////////////////////////////////
+ /// \class PublicSubkeyData::Impl
+ /// \brief PublicSubkeyData implementation.
+ ///////////////////////////////////////////////////////////////////
+ struct PublicSubkeyData::Impl
+ {
+ std::string _id;
+ Date _created;
+ Date _expires;
- readFromFile();
+ public:
+ /** Offer default Impl. */
+ static shared_ptr<Impl> nullimpl()
+ {
+ static shared_ptr<Impl> _nullimpl( new Impl );
+ return _nullimpl;
}
- Impl( const filesystem::TmpFile & sharedfile )
- : _data_file( sharedfile )
- { readFromFile(); }
+ private:
+ friend Impl * rwcowClone<Impl>( const Impl * rhs );
+ /** clone for RWCOW_pointer */
+ Impl * clone() const
+ { return new Impl( *this ); }
+ };
- public:
- /** Offer default Impl. */
- static shared_ptr<Impl> nullimpl()
- {
- static shared_ptr<Impl> _nullimpl( new Impl );
- return _nullimpl;
- }
+ ///////////////////////////////////////////////////////////////////
+ /// class PublicSubkeyData
+ ///////////////////////////////////////////////////////////////////
+
+ PublicSubkeyData::PublicSubkeyData()
+ : _pimpl( Impl::nullimpl() )
+ {}
+
+ PublicSubkeyData::~PublicSubkeyData()
+ {}
+
+ PublicSubkeyData::operator bool() const
+ { return !_pimpl->_id.empty(); }
+
+ std::string PublicSubkeyData::id() const
+ { return _pimpl->_id; }
+
+ Date PublicSubkeyData::created() const
+ { return _pimpl->_created; }
+
+ Date PublicSubkeyData::expires() const
+ { return _pimpl->_expires; }
+
+ bool PublicSubkeyData::expired() const
+ { return isExpired( _pimpl->_expires ); }
+
+ int PublicSubkeyData::daysToLive() const
+ { return hasDaysToLive( _pimpl->_expires ); }
+
+ std::string PublicSubkeyData::asString() const
+ {
+ return str::Str() << id() << " " << created().printDate() << " [" << expiresDetail( expires() ) << "]";
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class PublicKeyData::Impl
+ /// \brief PublicKeyData implementation.
+ ///////////////////////////////////////////////////////////////////
+ struct PublicKeyData::Impl
+ {
+ std::string _id;
+ std::string _name;
+ std::string _fingerprint;
+ Date _created;
+ Date _expires;
- std::string asString() const
+ std::vector<PublicSubkeyData> _subkeys;
+
+ public:
+ bool hasSubkeyId( const std::string & id_r ) const
+ {
+ bool ret = false;
+ for ( const PublicSubkeyData & sub : _subkeys )
{
- return str::form( "[%s-%s] [%s] [%s] [TTL %d]",
- id().c_str(), str::hexstring(created(),8).substr(2).c_str(),
- name().c_str(),
- fingerprint().c_str(),
- daysToLive() );
+ if ( sub.id() == id_r )
+ {
+ ret = true;
+ break;
+ }
}
+ return ret;
+ }
+
+ public:
+ /** Offer default Impl. */
+ static shared_ptr<Impl> nullimpl()
+ {
+ static shared_ptr<Impl> _nullimpl( new Impl );
+ return _nullimpl;
+ }
+
+ private:
+ friend Impl * rwcowClone<Impl>( const Impl * rhs );
+ /** clone for RWCOW_pointer */
+ Impl * clone() const
+ { return new Impl( *this ); }
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// class PublicKeyData
+ ///////////////////////////////////////////////////////////////////
- std::string id() const
- { return _id; }
+ PublicKeyData::PublicKeyData()
+ : _pimpl( Impl::nullimpl() )
+ {}
+
+ PublicKeyData::~PublicKeyData()
+ {}
+
+ PublicKeyData::operator bool() const
+ { return !_pimpl->_fingerprint.empty(); }
+
+ std::string PublicKeyData::id() const
+ { return _pimpl->_id; }
+
+ std::string PublicKeyData::name() const
+ { return _pimpl->_name; }
+
+ std::string PublicKeyData::fingerprint() const
+ { return _pimpl->_fingerprint; }
- std::string name() const
- { return _name; }
+ Date PublicKeyData::created() const
+ { return _pimpl->_created; }
- std::string fingerprint() const
- { return _fingerprint; }
+ Date PublicKeyData::expires() const
+ { return _pimpl->_expires; }
+
+ bool PublicKeyData::expired() const
+ { return isExpired( _pimpl->_expires ); }
+
+ int PublicKeyData::daysToLive() const
+ { return hasDaysToLive( _pimpl->_expires ); }
+
+ std::string PublicKeyData::expiresAsString() const
+ { return expiresDetailVerbose( _pimpl->_expires ); }
+
+ std::string PublicKeyData::gpgPubkeyVersion() const
+ { return _pimpl->_id.empty() ? _pimpl->_id : str::toLower( _pimpl->_id.substr(8,8) ); }
+
+ std::string PublicKeyData::gpgPubkeyRelease() const
+ { return _pimpl->_created ? str::hexstring( _pimpl->_created ).substr(2) : std::string(); }
+
+ std::string PublicKeyData::asString() const
+ {
+ str::Str str;
+ str << "[" << _pimpl->_id << "-" << gpgPubkeyRelease();
+ for ( auto && sub : _pimpl->_subkeys )
+ str << ", " << sub.id();
+ return str << "] [" << _pimpl->_name.c_str() << "] [" << expiresDetail( _pimpl->_expires ) << "]";
+ }
+
+ bool PublicKeyData::hasSubkeys() const
+ { return !_pimpl->_subkeys.empty(); }
+
+ Iterable<PublicKeyData::SubkeyIterator> PublicKeyData::subkeys() const
+ { return makeIterable( &(*_pimpl->_subkeys.begin()), &(*_pimpl->_subkeys.end()) ); }
+
+ bool PublicKeyData::providesKey( const std::string & id_r ) const
+ { return( id_r == _pimpl->_id || _pimpl->hasSubkeyId( id_r ) ); }
+
+ std::ostream & dumpOn( std::ostream & str, const PublicKeyData & obj )
+ {
+ str << "[" << obj.name() << "]" << endl;
+ str << " fpr " << obj.fingerprint() << endl;
+ str << " id " << obj.id() << endl;
+ str << " cre " << Date::ValueType(obj.created()) << ' ' << obj.created() << endl;
+ str << " exp " << Date::ValueType(obj.expires()) << ' ' << obj.expiresAsString() << endl;
+ str << " ttl " << obj.daysToLive() << endl;
+ for ( auto && sub : obj._pimpl->_subkeys )
+ str << " sub " << sub << endl;
+ str << " rpm " << obj.gpgPubkeyVersion() << "-" << obj.gpgPubkeyRelease() << endl;
+ return str;
+ }
- std::string gpgPubkeyVersion() const
- { return _id.empty() ? _id : str::toLower( _id.substr(8,8) ); }
+ bool operator==( const PublicKeyData & lhs, const PublicKeyData & rhs )
+ { return ( lhs.fingerprint() == rhs.fingerprint() && lhs.created() == rhs.created() ); }
- std::string gpgPubkeyRelease() const
- { return _created ? str::hexstring( _created ).substr(2) : std::string(); }
- Date created() const
- { return _created; }
+ ///////////////////////////////////////////////////////////////////
+ /// \class PublicKeyScanner::Impl
+ /// \brief PublicKeyScanner implementation.
+ ///////////////////////////////////////////////////////////////////
+ struct PublicKeyScanner::Impl
+ {
+ enum { pNONE, pPUB, pSIG, pFPR, pUID, pSUB } _parseEntry;
+ std::vector<std::string> _words;
+ PublicKeyData::Impl * _keyDataPtr;
- Date expires() const
- { return _expires; }
+ Impl()
+ : _parseEntry( pNONE )
+ , _keyDataPtr( nullptr )
+ {}
- std::string expiresAsString() const
+ void scan( std::string & line_r, std::list<PublicKeyData> & keys_r )
+ {
+ // pub:-:1024:17:A84EDAE89C800ACA:971961473:1214043198::-:SuSE Package Signing Key <build@suse.de>:
+ // fpr:::::::::79C179B2E1C820C1890F9994A84EDAE89C800ACA:
+ // sig:::17:A84EDAE89C800ACA:1087899198:::::[selfsig]::13x:
+ // sig:::17:9E40E310000AABA4:980442706::::[User ID not found]:10x:
+ // sig:::1:77B2E6003D25D3D9:980443247::::[User ID not found]:10x:
+ // sig:::17:A84EDAE89C800ACA:1318348291:::::[selfsig]::13x:
+ // sub:-:2048:16:197448E88495160C:971961490:1214043258::: [expires: 2008-06-21]
+ // sig:::17:A84EDAE89C800ACA:1087899258:::::[keybind]::18x:
+ if ( line_r.empty() )
+ return;
+
+ // quick check for interesting entries, no parsing in subkeys
+ _parseEntry = pNONE;
+ switch ( line_r[0] )
{
- if ( !_expires )
- { // translators: an annotation to a gpg keys expiry date
- return _("(does not expire)");
- }
- std::string ret( _expires.asString() );
- int ttl( daysToLive() );
- if ( ttl <= 90 )
- {
- ret += " ";
- if ( ttl < 0 )
- { // translators: an annotation to a gpg keys expiry date
- ret += _("(EXPIRED)");
- }
- else if ( ttl == 0 )
- { // translators: an annotation to a gpg keys expiry date
- ret += _("(expires within 24h)");
+ case 'p':
+ if ( line_r[1] == 'u' && line_r[2] == 'b' && line_r[3] == ':' )
+ {
+ _parseEntry = pPUB;
+ keys_r.push_back( PublicKeyData() ); // reset upon new key
+ _keyDataPtr = keys_r.back()._pimpl.get();
}
- else
- { // translators: an annotation to a gpg keys expiry date
- ret += str::form( _PL("(expires in %d day)", "(expires in %d days)", ttl ), ttl );
- }
- }
- return ret;
+ break;
+
+ case 'f':
+ if ( line_r[1] == 'p' && line_r[2] == 'r' && line_r[3] == ':' )
+ _parseEntry = pFPR;
+ break;
+
+ case 'u':
+ if ( line_r[1] == 'i' && line_r[2] == 'd' && line_r[3] == ':' )
+ _parseEntry = pUID;
+ break;
+
+ case 's':
+ if ( line_r[1] == 'i' && line_r[2] == 'g' && line_r[3] == ':' )
+ _parseEntry = pSIG;
+ else if ( line_r[1] == 'u' && line_r[2] == 'b' && line_r[3] == ':' )
+ _parseEntry = pSUB;
+ break;
+
+ default:
+ return;
}
+ if ( _parseEntry == pNONE )
+ return;
+ if ( ! ( _keyDataPtr->_subkeys.empty() || _parseEntry == pSUB ) )
+ return; // collecting subkeys only
- Pathname path() const
- { return _data_file.path(); }
+ if ( line_r[line_r.size()-1] == '\n' )
+ line_r.erase( line_r.size()-1 );
+ //DBG << line_r << endl;
+
+ _words.clear();
+ str::splitFields( line_r, std::back_inserter(_words), ":" );
- bool expired() const
+ switch ( _parseEntry )
{
- Date exp( expires() );
- return( exp && exp < Date::now() );
+ case pPUB:
+ _keyDataPtr->_id = _words[4];
+ _keyDataPtr->_name = str::replaceAll( _words[9], "\\x3a", ":" );
+ _keyDataPtr->_created = Date(str::strtonum<Date::ValueType>(_words[5]));
+ _keyDataPtr->_expires = Date(str::strtonum<Date::ValueType>(_words[6]));
+ break;
+
+ case pSIG:
+ // Update creation/modification date from signatures type "13x".
+ if ( ( _words.size() > 10 && _words[10] == "13x" && !_words[9].empty() && _words[9] != "[User ID not found]" )
+ || ( _words.size() > 12 && _words[12] == "13x" /* [selfsig] */) )
+ {
+ Date cdate(str::strtonum<Date::ValueType>(_words[5]));
+ if ( _keyDataPtr->_created < cdate )
+ _keyDataPtr->_created = cdate;
+ }
+ break;
+
+ case pFPR:
+ if ( _keyDataPtr->_fingerprint.empty() )
+ _keyDataPtr->_fingerprint = _words[9];
+ break;
+
+ case pUID:
+ if ( ! _words[9].empty() && _words[9] != "[User ID not found]" )
+ _keyDataPtr->_name = str::replaceAll( _words[9], "\\x3a", ":" );
+ break;
+
+ case pSUB:
+ _keyDataPtr->_subkeys.push_back( PublicSubkeyData() );
+ {
+ PublicSubkeyData::Impl * subPtr = _keyDataPtr->_subkeys.back()._pimpl.get();
+ subPtr->_id = _words[4];
+ subPtr->_created = Date(str::strtonum<Date::ValueType>(_words[5]));
+ subPtr->_expires = Date(str::strtonum<Date::ValueType>(_words[6]));
+ }
+ break;
+
+ case pNONE:
+ break; // intentionally no default:
}
+ }
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ // class PublicKeyScanner
+ ///////////////////////////////////////////////////////////////////
+
+ PublicKeyScanner::PublicKeyScanner()
+ : _pimpl( new Impl )
+ {}
+
+ PublicKeyScanner::~PublicKeyScanner()
+ {}
- int daysToLive() const
+ void PublicKeyScanner::scan( std::string line_r )
+ { _pimpl->scan( line_r, _keys ); }
+
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class PublicKey::Impl
+ /// \brief PublicKey implementation.
+ ///////////////////////////////////////////////////////////////////
+ struct PublicKey::Impl
+ {
+ Impl()
+ {}
+
+ Impl( const Pathname & keyFile_r )
+ : _dontUseThisPtrDirectly( new filesystem::TmpFile )
+ {
+ PathInfo info( keyFile_r );
+ MIL << "Taking pubkey from " << keyFile_r << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyFile_r, "sha1") << endl;
+
+ if ( !info.isExist() )
+ ZYPP_THROW(Exception("Can't read public key from " + keyFile_r.asString() + ", file not found"));
+
+ if ( filesystem::hardlinkCopy( keyFile_r, path() ) != 0 )
+ ZYPP_THROW(Exception("Can't copy public key data from " + keyFile_r.asString() + " to " + path().asString() ));
+
+ readFromFile();
+ }
+
+ Impl( const filesystem::TmpFile & sharedFile_r )
+ : _dontUseThisPtrDirectly( new filesystem::TmpFile( sharedFile_r ) )
+ { readFromFile(); }
+
+ Impl( const filesystem::TmpFile & sharedFile_r, const PublicKeyData & keyData_r )
+ : _dontUseThisPtrDirectly( new filesystem::TmpFile( sharedFile_r ) )
+ , _keyData( keyData_r )
+ {
+ if ( ! keyData_r )
{
- Date exp( expires() );
- if ( ! expires() )
- return INT_MAX;
- exp -= Date::now();
- return exp < 0 ? exp / Date::day - 1 : exp / Date::day;
+ WAR << "Invalid PublicKeyData supplied: scanning from file" << endl;
+ readFromFile();
}
+ }
+
+ Impl( const PublicKeyData & keyData_r )
+ : _keyData( keyData_r )
+ {}
+
+ public:
+ const PublicKeyData & keyData() const
+ { return _keyData; }
+
+ Pathname path() const
+ { return( /*the one and only intended use*/_dontUseThisPtrDirectly ? _dontUseThisPtrDirectly->path() : Pathname() ); }
+
+ const std::list<PublicKeyData> & hiddenKeys() const
+ { return _hiddenKeys; }
protected:
+ std::string _initHomeDir() ///< readFromFile helper to prepare the 'gpg --homedir'
+ { Pathname ret( zypp::myTmpDir() / "PublicKey" ); filesystem::assert_dir( ret ); return ret.asString(); }
void readFromFile()
{
- PathInfo info( _data_file.path() );
+ PathInfo info( path() );
MIL << "Reading pubkey from " << info.path() << " of size " << info.size() << " and sha1 " << filesystem::checksum(info.path(), "sha1") << endl;
- static filesystem::TmpDir dir;
+ static std::string tmppath( _initHomeDir() );
+ std::string datapath( path().asString() );
+
const char* argv[] =
{
- "gpg",
+ GPG_BINARY,
"-v",
"--no-default-keyring",
"--fixed-list-mode",
"--with-fingerprint",
"--with-colons",
"--homedir",
- dir.path().asString().c_str(),
+ tmppath.c_str(),
"--quiet",
"--no-tty",
"--no-greeting",
"--batch",
- "--status-fd",
- "1",
- _data_file.path().asString().c_str(),
+ "--status-fd", "1",
+ datapath.c_str(),
NULL
};
+ ExternalProgram prog( argv, ExternalProgram::Discard_Stderr, false, -1, true );
- ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
-
- std::string line;
- bool sawpub = false;
- bool sawsig = false;
+ PublicKeyScanner scanner;
+ for ( std::string line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
+ {
+ scanner.scan( line );
+ }
+ int ret = prog.close();
- // pub:-:1024:17:A84EDAE89C800ACA:971961473:1214043198::-:SuSE Package Signing Key <build@suse.de>:
- // fpr:::::::::79C179B2E1C820C1890F9994A84EDAE89C800ACA:
- // sig:::17:A84EDAE89C800ACA:1087899198:::::[selfsig]::13x:
- // sig:::17:9E40E310000AABA4:980442706::::[User ID not found]:10x:
- // sig:::1:77B2E6003D25D3D9:980443247::::[User ID not found]:10x:
- // sub:-:2048:16:197448E88495160C:971961490:1214043258::: [expires: 2008-06-21]
- // sig:::17:A84EDAE89C800ACA:1087899258:::::[keybind]::18x:
+ switch ( scanner._keys.size() )
+ {
+ case 0:
+ if ( ret == 129 )
+ ZYPP_THROW( Exception( std::string("Can't read public key data: ") + GPG_BINARY + " is not installed!" ) );
+ else
+ ZYPP_THROW( BadKeyException( "File " + path().asString() + " doesn't contain public key data" , path() ) );
+ break;
+
+ case 1:
+ // ok.
+ _keyData = scanner._keys.back();
+ _hiddenKeys.clear();
+ break;
+
+ default:
+ WAR << "File " << path().asString() << " contains multiple keys: " << scanner._keys << endl;
+ _keyData = scanner._keys.back();
+ scanner._keys.pop_back();
+ _hiddenKeys.swap( scanner._keys );
+ break;
+ }
- for ( line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
- {
- // trim trailing NL.
- if ( line.empty() )
- continue;
- if ( line[line.size()-1] == '\n' )
- line.erase( line.size()-1 );
-
- // split at ':'
- std::vector<std::string> words;
- str::splitFields( line, std::back_inserter(words), ":" );
- if( words.empty() )
- continue;
-
- if ( words[0] == "pub" )
- {
- if ( sawpub )
- continue;
- sawpub = true;
- // take default from pub
- _id = words[4];
- _name = words[9];
- _created = Date(str::strtonum<Date::ValueType>(words[5]));
- _expires = Date(str::strtonum<Date::ValueType>(words[6]));
-
- }
- else if ( words[0] == "sig" )
- {
- if ( sawsig || words[words.size()-2] != "13x" )
- continue;
- sawsig = true;
- // update creation and expire dates from 1st signature type "13x"
- if ( ! words[5].empty() )
- _created = Date(str::strtonum<Date::ValueType>(words[5]));
- if ( ! words[6].empty() )
- _expires = Date(str::strtonum<Date::ValueType>(words[6]));
- }
- else if ( words[0] == "fpr" )
- {
- _fingerprint = words[9];
- }
- else if ( words[0] == "uid" )
- {
- if ( ! words[9].empty() )
- _name = words[9];
- }
- }
- prog.close();
-
- if ( _id.size() == 0 )
- ZYPP_THROW( BadKeyException( "File " + _data_file.path().asString() + " doesn't contain public key data" , _data_file.path() ) );
-
- //replace all escaped semicolon with real ':'
- str::replaceAll( _name, "\\x3a", ":" );
-
- MIL << "Read pubkey from " << info.path() << ": " << asString() << endl;
+ MIL << "Read pubkey from " << info.path() << ": " << _keyData << endl;
}
private:
- filesystem::TmpFile _data_file;
+ shared_ptr<filesystem::TmpFile> _dontUseThisPtrDirectly; // shared_ptr ok because TmpFile itself is a refernce type (no COW)
+ PublicKeyData _keyData;
+ std::list<PublicKeyData> _hiddenKeys;
- std::string _id;
- std::string _name;
- std::string _fingerprint;
- Date _created;
- Date _expires;
+ public:
+ /** Offer default Impl. */
+ static shared_ptr<Impl> nullimpl()
+ {
+ static shared_ptr<Impl> _nullimpl( new Impl );
+ return _nullimpl;
+ }
private:
friend Impl * rwcowClone<Impl>( const Impl * rhs );
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
- //
- // METHOD NAME : PublicKey::PublicKey
- // METHOD TYPE : Ctor
- //
+ // class PublicKey
+ ///////////////////////////////////////////////////////////////////
PublicKey::PublicKey()
: _pimpl( Impl::nullimpl() )
{}
PublicKey::PublicKey( const Pathname & file )
- : _pimpl( new Impl(file) )
+ : _pimpl( new Impl( file ) )
{}
PublicKey::PublicKey( const filesystem::TmpFile & sharedfile )
- : _pimpl( new Impl(sharedfile) )
+ : _pimpl( new Impl( sharedfile ) )
+ {}
+
+ PublicKey::PublicKey( const filesystem::TmpFile & sharedfile, const PublicKeyData & keyData_r )
+ : _pimpl( new Impl( sharedfile, keyData_r ) )
+ {}
+
+ PublicKey::PublicKey( const PublicKeyData & keyData_r )
+ : _pimpl( new Impl( keyData_r ) )
{}
- ///////////////////////////////////////////////////////////////////
- //
- // METHOD NAME : PublicKey::~PublicKey
- // METHOD TYPE : Dtor
- //
PublicKey::~PublicKey()
{}
- ///////////////////////////////////////////////////////////////////
- //
- // Forward to implementation:
- //
- ///////////////////////////////////////////////////////////////////
+ const PublicKeyData & PublicKey::keyData() const
+ { return _pimpl->keyData(); }
- std::string PublicKey::asString() const
- { return _pimpl->asString(); }
+ Pathname PublicKey::path() const
+ { return _pimpl->path(); }
+
+ const std::list<PublicKeyData> & PublicKey::hiddenKeys() const
+ { return _pimpl->hiddenKeys(); }
std::string PublicKey::id() const
- { return _pimpl->id(); }
+ { return keyData().id(); }
std::string PublicKey::name() const
- { return _pimpl->name(); }
+ { return keyData().name(); }
std::string PublicKey::fingerprint() const
- { return _pimpl->fingerprint(); }
-
- std::string PublicKey::gpgPubkeyVersion() const
- { return _pimpl->gpgPubkeyVersion(); }
-
- std::string PublicKey::gpgPubkeyRelease() const
- { return _pimpl->gpgPubkeyRelease(); }
+ { return keyData().fingerprint(); }
Date PublicKey::created() const
- { return _pimpl->created(); }
+ { return keyData().created(); }
Date PublicKey::expires() const
- { return _pimpl->expires(); }
-
- std::string PublicKey::expiresAsString() const
- { return _pimpl->expiresAsString(); }
+ { return keyData().expires(); }
bool PublicKey::expired() const
- { return _pimpl->expired(); }
+ { return keyData().expired(); }
int PublicKey::daysToLive() const
- { return _pimpl->daysToLive(); }
+ { return keyData().daysToLive(); }
- Pathname PublicKey::path() const
- { return _pimpl->path(); }
+ std::string PublicKey::expiresAsString() const
+ { return keyData().expiresAsString(); }
- bool PublicKey::operator==( PublicKey b ) const
- {
- return ( b.id() == id()
- && b.fingerprint() == fingerprint()
- && b.created() == created() );
- }
+ std::string PublicKey::gpgPubkeyVersion() const
+ { return keyData().gpgPubkeyVersion(); }
- bool PublicKey::operator==( std::string sid ) const
- {
- return sid == id();
- }
+ std::string PublicKey::gpgPubkeyRelease() const
+ { return keyData().gpgPubkeyRelease(); }
+
+ std::string PublicKey::asString() const
+ { return keyData().asString(); }
+
+ bool PublicKey::operator==( const PublicKey & rhs ) const
+ { return rhs.keyData() == keyData(); }
+
+ bool PublicKey::operator==( const std::string & sid ) const
+ { return sid == id(); }
std::ostream & dumpOn( std::ostream & str, const PublicKey & obj )
- {
- str << "[" << obj.name() << "]" << endl;
- str << " fpr " << obj.fingerprint() << endl;
- str << " id " << obj.id() << endl;
- str << " cre " << obj.created() << endl;
- str << " exp " << obj.expiresAsString() << endl;
- str << " ttl " << obj.daysToLive() << endl;
- str << " rpm " << obj.gpgPubkeyVersion() << "-" << obj.gpgPubkeyRelease() << endl;
- str << "]";
- return str;
- }
+ { return dumpOn( str, obj.keyData() ); }
/////////////////////////////////////////////////////////////////
} // namespace zypp